Add support for global build defines and options (#8504) · esp8266/Arduino@d1d4212 (original) (raw)

``

1

`+

How to specify global build defines and options

`

``

2

`+

===============================================

`

``

3

+

``

4

`+

To create globally usable macro definitions for a Sketch, create a file

`

``

5


with a name based on your Sketch’s file name followed by ``.globals.h``

``

6

`+

in the Sketch folder. For example, if the main Sketch file is named

`

``

7


``LowWatermark.ino``, its global ``.h`` file would be

``

8


``LowWatermark.ino.globals.h``. This file will be implicitly included

``

9

`+

with every module built for your Sketch. Do not directly include it in

`

``

10

`+

any of your sketch files or in any other source files. There is no need

`

``

11

`+

to create empty/dummy files, when not used.

`

``

12

+

``

13


This global ``.h`` also supports embedding compiler command-line options

``

14

`+

in a unique “C” block comment. Compiler options are placed in a “C”

`

``

15


block comment starting with ``/*@create-file:build.opt@``. This

``

16

`+

signature line must be alone on a single line. The block comment ending

`

``

17


``*/`` should also be alone on a single line. In between, place your

``

18

`+

compiler command-line options just as you would have for the GCC @file

`

``

19

`+

command option.

`

``

20

+

``

21


Actions taken in processing comment block to create ``build.opt`` \* for

``

22

`+

each line, white space is trimmed * blank lines are skipped * lines

`

``

23


starting with ``*``, ``//``, or ``#`` are skipped \* the remaining

``

24


results are written to build tree\ ``/core/build.opt`` \* multiple

``

25


``/*@create-file:build.opt@`` ``*/`` comment blocks are not allowed \*

``

26


``build.opt`` is finished with a ``-include ...`` command, which

``

27

`+

references the global .h its contents were extracted from.

`

``

28

+

``

29


Example Sketch: ``LowWatermark.ino``

``

30

+

``

31

`+

.. code:: cpp

`

``

32

+

``

33

`+

#include <umm_malloc/umm_malloc.h> // has prototype for umm_free_heap_size_min()

`

``

34

+

``

35

`+

void setup() {

`

``

36

`+

Serial.begin(115200);

`

``

37

`+

delay(200);

`

``

38

`+

#ifdef MYTITLE1

`

``

39

`+

Serial.printf("\r\n" MYTITLE1 MYTITLE2 "\r\n");

`

``

40

`+

#else

`

``

41

`+

Serial.println("ERROR: MYTITLE1 not present");

`

``

42

`+

#endif

`

``

43

`+

Serial.printf("Heap Low Watermark %u\r\n", umm_free_heap_size_min());

`

``

44

`+

}

`

``

45

+

``

46

`+

void loop() {}

`

``

47

+

``

48


Global ``.h`` file: ``LowWatermark.ino.globals.h``

``

49

+

``

50

`+

.. code:: cpp

`

``

51

+

``

52

`+

/*@create-file:build.opt@

`

``

53

`+

// An embedded build.opt file using a "C" block comment. The starting signature

`

``

54

`+

// must be on a line by itself. The closing block comment pattern should be on a

`

``

55

`+

// line by itself. Each line within the block comment will be space trimmed and

`

``

56

`+

// written to build.opt, skipping blank lines and lines starting with '//', '*'

`

``

57

`+

// or '#'.

`

``

58

+

``

59

`+

`

``

60

`+

this line is ignored

`

``

61

`+

-DMYTITLE1=""Running on ""

`

``

62

`+

-O3

`

``

63

`+

//-fanalyzer

`

``

64

`+

-DUMM_STATS_FULL=1

`

``

65

`+

*/

`

``

66

+

``

67

`+

#ifndef LOWWATERMARK_INO_GLOBALS_H

`

``

68

`+

#define LOWWATERMARK_INO_GLOBALS_H

`

``

69

+

``

70

`+

#if !defined(ASSEMBLER)

`

``

71

`+

// Defines kept away from assembler modules

`

``

72

`+

// i.e. Defines for .cpp, .ino, .c ... modules

`

``

73

`+

#endif

`

``

74

+

``

75

`+

#if defined(__cplusplus)

`

``

76

`+

// Defines kept private to .cpp and .ino modules

`

``

77

`+

//#pragma message("__cplusplus has been seen")

`

``

78

`+

#define MYTITLE2 "Empty"

`

``

79

`+

#endif

`

``

80

+

``

81

`+

#if !defined(__cplusplus) && !defined(ASSEMBLER)

`

``

82

`+

// Defines kept private to .c modules

`

``

83

`+

#define MYTITLE2 "Full"

`

``

84

`+

#endif

`

``

85

+

``

86

`+

#if defined(ASSEMBLER)

`

``

87

`+

// Defines kept private to assembler modules

`

``

88

`+

#endif

`

``

89

+

``

90

`+

#endif

`

``

91

+

``

92

`+

Aggressively cache compiled core

`

``

93

`+

================================

`

``

94

+

``

95

`+

This feature appeared with the release of Arduino IDE 1.8.2. The feature

`

``

96

`+

“Aggressively Cache Compiled core” refers to sharing a single copy of

`

``

97


``core.a`` across all Arduino IDE Sketch windows. This feature is on by

``

98


default. ``core.a`` is an archive file containing the compiled objects

``

99


of ``./core/esp8266/*``. Created after your 1ST successful compilation.

``

100

`+

All other open sketch builds use this shared file. When you close all

`

``

101

`+

Arduino IDE windows, the core archive file is deleted.

`

``

102

+

``

103

`+

This feature is not compatible with using global defines or compiler

`

``

104

`+

command-line options. Without mediation, bad builds could result, when

`

``

105


left enabled. When ``#define`` changes require rebuilding ``core.a`` and

``

106

`+

multiple Sketches are open, they can no longer reliably share one cached

`

``

107


``core.a``. In a simple case: The 1st Sketch to be built has its version

``

108


of ``core.a`` cached. Other sketches will use this cached version for

``

109

`+

their builds.

`

``

110

+

``

111

`+

There are two solutions to this issue: 1. Turn off the “Aggressively

`

``

112


Cache Compiled core” feature, by setting ``compiler.cache_core=false``.

``

113

`+

  1. Rely on the not ideal fail-safe, aggressive cache workaround built

`

``

114

`+

into the script.

`

``

115

+

``

116

`+

Using “compiler.cache_core=false”

`

``

117

`+


`

``

118

+

``

119

`+

There are two ways to turn off the “Aggressively Cache Compiled core”

`

``

120

`+

feature: This can be done with the Arduino IDE command-line or a text

`

``

121

`+

editor.

`

``

122

+

``

123

`+

Using the Arduino IDE command-line from a system command line, enter the

`

``

124

`+

following:

`

``

125

+

``

126

`+

::

`

``

127

+

``

128

`+

arduino --pref compiler.cache_core=false --save-prefs

`

``

129

+

``

130

`+

For the text editor, you need to find the location of

`

``

131


``preferences.txt``. From the Arduino IDE, go to *File->Preferences*.

``

132


Make note of the path to ``prefereces.txt``. You *cannot* edit the file

``

133

`+

while the Arduino IDE is running. Close all Arduino IDE windows and edit

`

``

134


the file ``preferences.txt``. Change ``compiler.cache_core=true`` to

``

135


``compiler.cache_core=false`` and save. Then each sketch will maintain

``

136


its *own* copy of ``core.a`` built with the customization expressed by

``

137


their respective ``build.opt`` file.

``

138

+

``

139

`+

The “workaround”

`

``

140

`+


`

``

141

+

``

142

`+

When the “Aggressively Cache Compiled core” feature is enabled and the

`

``

143

`+

global define file is detected, a workaround will turn on and stay on.

`

``

144

`+

When you switch between Sketch windows, core will be recompiled and the

`

``

145

`+

cache updated. The workaround logic is reset when Arduino IDE is

`

``

146

`+

completely shutdown and restarted.

`

``

147

+

``

148

`+

The workaround is not perfect. These issues may be of concern: 1. Dirty

`

``

149

`+

temp space. Arduino build cache files left over from a previous run or

`

``

150

`+

boot. 2. Arduino command-line options: * override default

`

``

151

`+

preferences.txt file. * override a preference, specifically

`

``

152


``compiler.cache_core``. 3. Multiple versions of the Arduino IDE running

``

153

+

``

154

`+

Dirty temp space

`

``

155

+

``

156

`+

A minor concern, the workaround is always on. Not an issue for build

`

``

157


accuracy, but ``core.a`` maybe rebuild more often than necessary.

``

158

+

``

159

`+

Some operating systems are better at cleaning up their temp space than

`

``

160

`+

others at reboot after a crash. At least for Windows®, you may need to

`

``

161

`+

manually delete the Arduino temp files and directories after a crash.

`

``

162

`+

Otherwise, the workaround logic may be left on. There is no harm in the

`

``

163

`+

workaround being stuck on, the build will be correct; however, the core

`

``

164

`+

files will occasionally be recompiled when not needed.

`

``

165

+

``

166

`+

For some Windows® systems the temp directory can be found near

`

``

167


``C:\Users\<user id>\AppData\Local\Temp\arduino*``. Note ``AppData`` is

``

168

`+

a hidden directory. For help with this do an Internet search on

`

``

169


``windows disk cleanup``. Or, type ``disk cleanup`` in the Windows®

``

170

`+

taskbar search box.

`

``

171

+

``

172

`+

With Linux, this problem could occur after an Arduino IDE crash. The

`

``

173

`+

problem would be cleared after a reboot. Or you can manually cleanup the

`

``

174


``/tmp/`` directory before restarting the Arduino IDE.

``

175

+

``

176

`+

Arduino command-line option overrides

`

``

177

+

``

178


The script needs to know the working value of ``compiler.cache_core``

``

179

`+

that the Arduino IDE uses when building. This script can learn the state

`

``

180

`+

through documented locations; however, the Arduino IDE has two

`

``

181

`+

command-line options that can alter the results the Arduino IDE uses

`

``

182

`+

internally. And, the Arduino IDE does not provide a means for a script

`

``

183

`+

to learn the override value.

`

``

184

+

``

185

`+

These two command-line options are the problem:

`

``

186

+

``

187

`+

::

`

``

188

+

``

189

`+

./arduino --preferences-file other-preferences.txt

`

``

190

`+

./arduino --pref compiler.cache_core=false

`

``

191

+

``

192


Hints for discovering the value of ``compiler.cache_core``, can be

``

193


provided by specifying ``mkbuildoptglobals.extra_flags=...`` in

``

194


``platform.local.txt``.

``

195

+

``

196

`+

Examples of hints:

`

``

197

+

``

198

`+

::

`

``

199

+

``

200

`+

mkbuildoptglobals.extra_flags=--preferences_sketch # assume file preferences.txt in the sketch folder

`

``

201

`+

mkbuildoptglobals.extra_flags=--preferences_sketch "pref.txt" # is relative to the sketch folder

`

``

202

`+

mkbuildoptglobals.extra_flags=--no_cache_core

`

``

203

`+

mkbuildoptglobals.extra_flags=--cache_core

`

``

204

`+

mkbuildoptglobals.extra_flags=--preferences_file "other-preferences.txt" # relative to IDE or full path

`

``

205

+

``

206

`+

If required, remember to quote file or file paths.

`

``

207

+

``

208

`+

Multiple versions of the Arduino IDE running

`

``

209

+

``

210

`+

You can run multiple Arduino IDE windows as long as you run one version

`

``

211

`+

of the Arduino IDE at a time. When testing different versions,

`

``

212

`+

completely exit one before starting the next version. For example,

`

``

213

`+

Arduino IDE 1.8.19 and Arduino IDE 2.0 work with different temp and

`

``

214

`+

build paths. With this combination, the workaround logic sometimes fails

`

``

215

`+

to enable.

`

``

216

+

``

217

`+

At the time of this writing, when Arduino IDE 2.0 rc5 exits, it leaves

`

``

218

`+

the temp space dirty. This keeps the workaround active the next time the

`

``

219

`+

IDE is started. If this is an issue, manually delete the temp files.

`

``

220

+

``

221

`+

Custom build environments

`

``

222

`+

=========================

`

``

223

+

``

224

`+

Some custom build environments may have already addressed this issue by

`

``

225

`+

other means. If you have a custom build environment that does not

`

``

226

`+

require this feature and would like to turn it off, you can add the

`

``

227


following lines to the ``platform.local.txt`` used in your build

``

228

`+

environment:

`

``

229

+

``

230

`+

::

`

``

231

+

``

232

`+

recipe.hooks.prebuild.2.pattern=

`

``

233

`+

build.opt.flags=

`

``

234

+

``

235

`+

Other build confusion

`

``

236

`+

=====================

`

``

237

+

``

238

`+

  1. Renaming a file does not change the last modified timestamp, possibly

`

``

239

`+

causing issues when adding a file by renaming and rebuilding. A good

`

``

240

`+

example of this problem would be to have then fixed a typo in file

`

``

241


 name ``LowWatermark.ino.globals.h``. You need to touch (update

``

242

`+

timestamp) the file so a “rebuild all” is performed.

`

``

243

+

``

244


2. When a ``.h`` file is renamed in the sketch folder, a copy of the old

``

245

`+

file remains in the build sketch folder. This can create confusion if

`

``

246


 you missed an edit in updating an ``#include`` in one or more of your

``

247

`+

modules. That module will continue to use the stale version of the

`

``

248


 ``.h`` until you restart the IDE or other major changes that would

``

249

`+

cause the IDE to delete and recopy the contents from the source

`

``

250

`+

Sketch directory. Changes on the IDE Tools board settings may cause a

`

``

251

`+

complete rebuild, clearing the problem. This may be the culprit for

`

``

252

`+

“What! It built fine last night!”

`