Old Global Defines - mhightower83/Arduino-ESP8266-misc GitHub Wiki

Update

This python script may be a better way to do this gist mhightower83/prebuild-v2.py The script comments describe how to use it. I'll update this Wiki later.

Another alternative

Support for adding compiler command-line options to a Sketch has been added to some boards. A sketch file build_opt.h is used to hold the command-line options. It must not contain any "C" code and must not be referenced by any #include statements. There are no dependencies to cause a rebuild. If you change build_opt.h, you may need to restart the Arduino IDE to get your sketch built correctly. Also, you may want to address the issue of Overzealous Caching of core.a

While having non "C" code in a .h is a bit odd, the file having a .h extension allows you to edit it with the Arduino-IDE. Personally I would prefer encapsualting the command in a "C" block comment.

Sketch Specific Build Properties

This method of Global Defines appears to be working again with Arduino IDE 1.8.13, Arduino ESP8266 Core v3, and GNU C++ compiler v10. Specifically, it was dependencies that broke some time ago as tools changed (no idea which one) and I just now see they are working again.

Something changed in either the Arduino IDE or Arduino ESP8266 core, build dependency no longer works for the Global defines. You will need to restart the IDE for edits to take effect. This was probably a variation on Overzealous Caching of core.a see above.

Note, This an advanced user topic

Editorial Note: While I think the setup and use of this, is easy and straightforward. I may be wrong. If you are new to programming and just getting started with Arduino, I think it is unlikely, that you will need this. At least not yet. :) On the other hand, if you managed to find this Wiki, you may have been searching for this capability. Enjoy!

While this discussion is specific to the ESP8266 board option installed on the Arduino IDE, this method should be adaptable to other board options; however, that discussion is beyond the scope of this page.

What is this for?

This tweak enables a Sketch to have a unique set of build properties, that apply to all library and core modules built. This is done by adding the file platform.local.txt1 to the platform folder.

Implementation Objectives

  • Allows you to keep a .h file in your Sketch directory, that will be used to store global defines. This file will be implicitly included with every module built for your Sketch. Do not directly include it in any of your sketch files or in any other source files. The default file name for this is globals.h.
  • Allows you to keep, project specific compiler build flags, in a file in your Sketch directory. The default file name for this is compiler_flags.txt. An effort was made, to get build dependencies to track this file. (seems to work)
  • Allows for global global defines that are applied to all Arduino IDE Sketches. The default path/file for this is include/ide_globals.h in the Sketchbook directory. This file will be implicitly included with every module built. Note, it should not be directly specified in any of the source files.
  • All these features are optional. No need to create empty/dummy files, when not used.
  • The initial addition of platform.local.txt should not change anything, beyond a few additional lines lost in the message area spew, during a Verify/Compile.
  • No build changes from the normal until you create one of the special files.

Setup/Install

Prerequisites:

  • A current version of the Arduino IDE. This was tested with 1.8.5. The "key=value" properties, {build.source.path}, was not available or correct in some earlier versions.
  • ESP8266 3rd Party Board support installed.

To get started you need to find the right folder to save platform.local.txt in. You can locate that folder by doing the following steps.

  • Select a board from the ESP8266 list.
  • Set preferences for a verbose compile,
    • From the Arduino IDE select Edit->File->Preferences.
    • Find the selection: "Show verbose output during: [] compilation [] upload"
    • Check the box for "compilation"
  • Open a new sketch.
  • Run Verify, (Sketch->Verify/Compile).
  • Scroll up to the top of the Arduino IDE message area.
  • Look for the text "Using core 'esp8266' from platform in folder" and make note of the path. This line will be near the top, before "Detecting libraries used...". This is the location you need to remember for saving platform.local.txt.

A sample of Arduino IDE message area text:

  C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs ...
  C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine ...
  Using board 'generic' from platform in folder: C:\Users\mhightower83\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0
> Using core 'esp8266' from platform in folder: C:\Users\mhightower83\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0
  Detecting libraries used...
  ...

For this sample, we would save the platform.local.txt file to:

C:\Users\mhightower83\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0

Summary of files to be added or optional:

  • In platform folder platform.local.txt
  • In Sketch's folder globals.h, Optional
  • In Sketch's folder compiler_flags.txt, Optional
  • In Sketchbook folder include/ide_globals.h, Optional

Copy and paste into your editor the platform.local.txt text shown below. At this time, you should also replace YourUserId with your UsedID. This the string that aids in selecting your home directory. This is usually the UserID. Then save as platform.local.txt to the platform folder you made note of, earlier.

custom.userid value is used to complete the formation of a path to your include directory. This will be the include directory, you create later, in your Sketchbook to hold ide_globals.h. There should be no ill effect from not initially creating the include directory.

Link to a copy of platform.local.txt

View file content
##
#                    Attention!
#
# Replace YourUserId below with your Login UserID. This value should results
# in "custom.ideglobal.source.path" pointing to your include directory,
# which is located at the top level of your Sketchbook directory.
# If you are not using default file names or locations, make updates as need.

custom.userid=YourUserId
custom.ideglbl_h.name=ide_globals.h
custom.globals_h.name=globals.h
custom.flags_txt.name=compiler_flags.txt

#----- This Section can be deleted, it served as a reminder to ---------------
#----- edit "custom.userid=YourUserId".
#----- Starts Here ---------------
recipe.hooks.prebuild.01.pattern.windows=cmd /c if z{custom.userid} == zYourUserId (echo You need to edit platform.local.txt and change, custom.userid=YourUserId, to be equal to your UserID. )
recipe.hooks.prebuild.01.pattern.linux=bash -c "if [ z{custom.userid} = zYourUserId ]; then echo You\ need\ to\ edit\ platform.local.txt\ and\ change,\ custom.userid=YourUserId,\ to\ be\ equal\ to\ your\ UserID.; fi;"
#----- Stops Here ---------------
#
#------------- There is usually no need to edit below this line --------------
#

custom.ideglobal.path.linux=/home/{custom.userid}/Arduino/include/
custom.ideglobal.path.windows=C:\Users\{custom.userid}\Documents\Arduino\include\
custom.source.path.linux={build.source.path}/
custom.source.path.windows={build.source.path}\
custom.ideglbl_h.source.pathname={custom.ideglobal.path}{custom.ideglbl_h.name}
custom.globals_h.source.pathname={custom.source.path}{custom.globals_h.name}
custom.flags_txt.source.pathname={custom.source.path}{custom.flags_txt.name}

custom.build.path.linux={build.path}/custom/
custom.build.path.windows={build.path}\custom\
custom.globals_h.build.pathname={custom.build.path}{custom.globals_h.name}
custom.ideglbl_h.build.pathname={custom.build.path}{custom.ideglbl_h.name}
custom.flags_txt.build.pathname={custom.build.path}{custom.flags_txt.name}


compiler.global_flags=-include "{custom.ideglbl_h.build.pathname}" -include "{custom.globals_h.build.pathname}" -include "{custom.flags_txt.build.pathname}.h" @{custom.flags_txt.build.pathname}
assembler.global_flags=-include "{custom.flags_txt.build.pathname}.h" @{custom.flags_txt.build.pathname}

compiler.c.extra_flags={compiler.global_flags}
compiler.S.extra_flags={compiler.global_flags}
compiler.cpp.extra_flags={compiler.global_flags}


#
# Here we handle the copying of global files, from their respective locations,
# to the build tree. With attention to newness as needed.
# compiler_flags.txt needs more attention because .txt files are not
# tracked by the build dependencies. This is addressed by managing a ghost
# file by its name with a .h extension. compiler_flags.txt's time stamp is
# tracked and its ghost image is updated as needed.
# ref https://stackoverflow.com/a/8055430 for && vs & usage in Windows cmd

recipe.hooks.prebuild.11.pattern.linux=mkdir -p "{custom.build.path}"
recipe.hooks.prebuild.12.pattern.linux=bash -c "if [   -f {custom.ideglbl_h.source.pathname}  ]; then cp -u {custom.ideglbl_h.source.pathname} {custom.ideglbl_h.build.pathname}; fi;"
recipe.hooks.prebuild.13.pattern.linux=bash -c "if [   -f {custom.globals_h.source.pathname}  ]; then cp -u {custom.globals_h.source.pathname} {custom.globals_h.build.pathname}; fi;"
recipe.hooks.prebuild.14.pattern.linux=bash -c "if [   -f {custom.flags_txt.source.pathname}  ]; then if [ {custom.flags_txt.source.pathname} -nt {custom.flags_txt.build.pathname} ]; then cp -u {custom.flags_txt.source.pathname} {custom.flags_txt.build.pathname}; touch {custom.flags_txt.build.pathname}.h; fi; fi;"
recipe.hooks.prebuild.15.pattern.linux=bash -c "if [ ! -f {custom.ideglbl_h.source.pathname}  ]; then if [ -s {custom.ideglbl_h.build.pathname} ]; then rm {custom.ideglbl_h.build.pathname}; touch {custom.ideglbl_h.build.pathname}; fi; fi;"
recipe.hooks.prebuild.16.pattern.linux=bash -c "if [ ! -f {custom.globals_h.source.pathname}  ]; then if [ -s {custom.globals_h.build.pathname} ]; then rm {custom.globals_h.build.pathname}; touch {custom.globals_h.build.pathname}; fi; fi;"
recipe.hooks.prebuild.17.pattern.linux=bash -c "if [ ! -f {custom.flags_txt.source.pathname}  ]; then if [ -s {custom.flags_txt.build.pathname} ]; then rm {custom.flags_txt.build.pathname}; touch {custom.flags_txt.build.pathname} {custom.flags_txt.build.pathname}.h; fi; fi;"
recipe.hooks.prebuild.18.pattern.linux=bash -c "if [ ! -f {custom.ideglbl_h.build.pathname}   ]; then touch -t 170001010000 {custom.ideglbl_h.build.pathname}; fi;"
recipe.hooks.prebuild.19.pattern.linux=bash -c "if [ ! -f {custom.globals_h.build.pathname}   ]; then touch -t 170001010000 {custom.globals_h.build.pathname}; fi;"
recipe.hooks.prebuild.20.pattern.linux=bash -c "if [ ! -f {custom.flags_txt.build.pathname}   ]; then touch -t 170001010000 {custom.flags_txt.build.pathname}; fi;"
recipe.hooks.prebuild.21.pattern.linux=bash -c "if [ ! -f {custom.flags_txt.build.pathname}.h ]; then touch -t 170001010000 {custom.flags_txt.build.pathname}.h; fi;"

recipe.hooks.prebuild.11.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.build.path} (mkdir {custom.build.path} )"
recipe.hooks.prebuild.12.pattern.windows=cmd /v:on /e:on /c "if     exist {custom.ideglbl_h.source.pathname} (copy {custom.ideglbl_h.source.pathname} {custom.ideglbl_h.build.pathname} )"
recipe.hooks.prebuild.13.pattern.windows=cmd /v:on /e:on /c "if     exist {custom.globals_h.source.pathname} (copy {custom.globals_h.source.pathname} {custom.globals_h.build.pathname} )"
recipe.hooks.prebuild.14.pattern.windows=cmd /v:on /e:on /c "if     exist {custom.flags_txt.source.pathname} (fc /b {custom.flags_txt.source.pathname} {custom.flags_txt.build.pathname} ) >nul 2>&1 || (copy {custom.flags_txt.source.pathname} {custom.flags_txt.build.pathname} & type NUL> {custom.flags_txt.build.pathname}.h )"
recipe.hooks.prebuild.15.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.ideglbl_h.source.pathname} (for %f in ( {custom.ideglbl_h.build.pathname} ) do set size=%~zf) & (if not defined size set size=0) & (if !size! NEQ 0 type NUL> {custom.ideglbl_h.build.pathname} )"
recipe.hooks.prebuild.16.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.globals_h.source.pathname} (for %f in ( {custom.globals_h.build.pathname} ) do set size=%~zf) & (if not defined size set size=0) & (if !size! NEQ 0 type NUL> {custom.globals_h.build.pathname} )"
recipe.hooks.prebuild.17.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.flags_txt.source.pathname} (for %f in ( {custom.flags_txt.build.pathname} ) do set size=%~zf) & (if not defined size set size=0) & (if !size! NEQ 0 (type NUL> {custom.flags_txt.build.pathname} & type NUL> {custom.flags_txt.build.pathname}.h ) )"
recipe.hooks.prebuild.18.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.ideglbl_h.build.pathname}   (type NUL> {custom.ideglbl_h.build.pathname} )"
recipe.hooks.prebuild.19.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.globals_h.build.pathname}   (type NUL> {custom.globals_h.build.pathname} )"
recipe.hooks.prebuild.20.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.flags_txt.build.pathname}   (type NUL> {custom.flags_txt.build.pathname} )"
recipe.hooks.prebuild.21.pattern.windows=cmd /v:on /e:on /c "if not exist {custom.flags_txt.build.pathname}.h (type NUL> {custom.flags_txt.build.pathname}.h )"

Using features:

Global Defines Specific to a Sketch

To create global defines for your Sketch, you simply create a file by the name globals.h in your Sketch's directory and place your defines in it.

Example file contents for: globals.h

#ifndef GLOBALS_H
#define GLOBALS_H
/**
 * Defines, placed in this sketch's globals.h file, are unique to this sketch's
 * build. And will be used by all library and core modules for that build.
 * See link for more information:
 *   https://github.com/mhightower83/Arduino-ESP8266-misc/wiki/global-defines
 */
#if (__ASSEMBLER__ == 0)

#endif

#define USE_FLASH_FOR_STRINGS 1
#define LIB_USE_FLASH_FOR_STRINGS 1
#endif

Sketch Specific - Compiler Flags

To set compiler flags, specific to a Sketch, you create the file compiler_flags.txt, in your Sketch's directory and place your sketch specific compiler flag options in it. This file will be added to the GCC/G++ command line using the @file option. Thus, whatever you would have used in a GCC/G++ @file option should work here.

Example file contents for: compiler_flags.txt

-DCOMPILER_FLAGS_DOT_TXT="Exist"

Global Defines for All Sketches

For this, you need to create a folder, include, inside your Arduino Sketchbook folder. Then inside the include folder create the file ide_globals.h and place your global global defines in it. If you have not fixed-up custom.userid=YourUserId with a correct UserID, you must do so now for this option to work.

The Sketchbook directory is commonly named Arduino and is located in the users home directory, at least on Linux. On Windows maybe in the Document folder. To locate your Sketchbook folder:

  • Start the Arduino IDE
  • Select File->Preferences
  • Look for "Sketchbook location:"; it will appear as the first item in the Settings tab on the Preferences window.

Example file contents for: ide_globals.h

#ifndef IDE_GLOBALS_H
#define IDE_GLOBALS_H
/*
 * This file lives at ~YourUserId/Arduino/include/ide_global.h
 * Defines, placed here, are made available to all sketches and modules built.
 * See link for more information:
 *   https://github.com/mhightower83/Arduino-ESP8266-misc/wiki/global-defines
 *
 */

#endif

Credits, Inspirations, and Footnotes

This method contains inspirations from the following:

  1. Arduino IDE 1.5 3rd party Hardware specification, Old link - Has the specifics for creating a platform.local.txt file.
  2. Include global UserSettings.h file #15
  3. HOWTO: Store Project Settings
  4. Use recipe.hooks feature of the platform.txt file #41
  5. Added recipe.hooks feature to override gcc options
⚠️ **GitHub.com Fallback** ⚠️