|
@@ -4,21 +4,21 @@
|
4
|
4
|
import os,subprocess,re,json,hashlib
|
5
|
5
|
|
6
|
6
|
#
|
7
|
|
-# The dumbest preprocessor in the world
|
8
|
|
-# Extract macro name from an header file and store them in an array
|
9
|
|
-# No processing is done here, so they are raw values here and it does not match what actually enabled
|
10
|
|
-# in the file (since you can have #if SOMETHING_UNDEFINED / #define BOB / #endif)
|
11
|
|
-# But it's useful to filter the useful macro spit out by the preprocessor from noise from the system
|
12
|
|
-# headers.
|
|
7
|
+# Return all macro names in a header as an array, so we can take
|
|
8
|
+# the intersection with the preprocessor output, giving a decent
|
|
9
|
+# reflection of all enabled options that (probably) came from the
|
|
10
|
+# configuration files. We end up with the actual configured state,
|
|
11
|
+# better than what the config files say. You can then use the
|
|
12
|
+# resulting config.ini to produce more exact configuration files.
|
13
|
13
|
#
|
14
|
14
|
def extract_defines(filepath):
|
15
|
15
|
f = open(filepath, encoding="utf8").read().split("\n")
|
16
|
16
|
a = []
|
17
|
17
|
for line in f:
|
18
|
|
- sline = line.strip(" \t\n\r")
|
|
18
|
+ sline = line.strip()
|
19
|
19
|
if sline[:7] == "#define":
|
20
|
20
|
# Extract the key here (we don't care about the value)
|
21
|
|
- kv = sline[8:].strip().split(' ')
|
|
21
|
+ kv = sline[8:].strip().split()
|
22
|
22
|
a.append(kv[0])
|
23
|
23
|
return a
|
24
|
24
|
|
|
@@ -51,7 +51,7 @@ def compute_build_signature(env):
|
51
|
51
|
# Definitions from these files will be kept
|
52
|
52
|
files_to_keep = [ 'Marlin/Configuration.h', 'Marlin/Configuration_adv.h' ]
|
53
|
53
|
|
54
|
|
- build_dir=os.path.join(env['PROJECT_BUILD_DIR'], env['PIOENV'])
|
|
54
|
+ build_dir = os.path.join(env['PROJECT_BUILD_DIR'], env['PIOENV'])
|
55
|
55
|
|
56
|
56
|
# Check if we can skip processing
|
57
|
57
|
hashes = ''
|
|
@@ -77,14 +77,14 @@ def compute_build_signature(env):
|
77
|
77
|
complete_cfg = run_preprocessor(env)
|
78
|
78
|
|
79
|
79
|
# Dumb #define extraction from the configuration files
|
80
|
|
- real_defines = {}
|
|
80
|
+ conf_defines = {}
|
81
|
81
|
all_defines = []
|
82
|
82
|
for header in files_to_keep:
|
83
|
83
|
defines = extract_defines(header)
|
84
|
84
|
# To filter only the define we want
|
85
|
|
- all_defines = all_defines + defines
|
|
85
|
+ all_defines += defines
|
86
|
86
|
# To remember from which file it cames from
|
87
|
|
- real_defines[header.split('/')[-1]] = defines
|
|
87
|
+ conf_defines[header.split('/')[-1]] = defines
|
88
|
88
|
|
89
|
89
|
r = re.compile(r"\(+(\s*-*\s*_.*)\)+")
|
90
|
90
|
|
|
@@ -116,16 +116,16 @@ def compute_build_signature(env):
|
116
|
116
|
resolved_defines = {}
|
117
|
117
|
for key in defines:
|
118
|
118
|
# Remove all boards now
|
119
|
|
- if key[0:6] == "BOARD_" and key != "BOARD_INFO_NAME":
|
|
119
|
+ if key.startswith("BOARD_") and key != "BOARD_INFO_NAME":
|
120
|
120
|
continue
|
121
|
121
|
# Remove all keys ending by "_NAME" as it does not make a difference to the configuration
|
122
|
|
- if key[-5:] == "_NAME" and key != "CUSTOM_MACHINE_NAME":
|
|
122
|
+ if key.endswith("_NAME") and key != "CUSTOM_MACHINE_NAME":
|
123
|
123
|
continue
|
124
|
|
- # Remove all keys ending by "_T_DECLARED" as it's a copy of not important system stuff
|
125
|
|
- if key[-11:] == "_T_DECLARED":
|
|
124
|
+ # Remove all keys ending by "_T_DECLARED" as it's a copy of extraneous system stuff
|
|
125
|
+ if key.endswith("_T_DECLARED"):
|
126
|
126
|
continue
|
127
|
127
|
# Remove keys that are not in the #define list in the Configuration list
|
128
|
|
- if not (key in all_defines) and key != "DETAILED_BUILD_VERSION" and key != "STRING_DISTRIBUTION_DATE":
|
|
128
|
+ if key not in all_defines + [ 'DETAILED_BUILD_VERSION', 'STRING_DISTRIBUTION_DATE' ]:
|
129
|
129
|
continue
|
130
|
130
|
|
131
|
131
|
# Don't be that smart guy here
|
|
@@ -136,13 +136,13 @@ def compute_build_signature(env):
|
136
|
136
|
data = {}
|
137
|
137
|
data['__INITIAL_HASH'] = hashes
|
138
|
138
|
# First create a key for each header here
|
139
|
|
- for header in real_defines:
|
|
139
|
+ for header in conf_defines:
|
140
|
140
|
data[header] = {}
|
141
|
141
|
|
142
|
142
|
# Then populate the object where each key is going to (that's a O(N^2) algorithm here...)
|
143
|
143
|
for key in resolved_defines:
|
144
|
|
- for header in real_defines:
|
145
|
|
- if key in real_defines[header]:
|
|
144
|
+ for header in conf_defines:
|
|
145
|
+ if key in conf_defines[header]:
|
146
|
146
|
data[header][key] = resolved_defines[key]
|
147
|
147
|
|
148
|
148
|
# Append the source code version and date
|
|
@@ -155,6 +155,9 @@ def compute_build_signature(env):
|
155
|
155
|
except:
|
156
|
156
|
pass
|
157
|
157
|
|
|
158
|
+ #
|
|
159
|
+ # Produce a JSON file for CONFIGURATION_EMBEDDING or CONFIG_DUMP > 0
|
|
160
|
+ #
|
158
|
161
|
with open(marlin_json, 'w') as outfile:
|
159
|
162
|
json.dump(data, outfile, separators=(',', ':'))
|
160
|
163
|
|
|
@@ -163,10 +166,12 @@ def compute_build_signature(env):
|
163
|
166
|
|
164
|
167
|
# Generate a C source file for storing this array
|
165
|
168
|
with open('Marlin/src/mczip.h','wb') as result_file:
|
166
|
|
- result_file.write(b'#ifndef NO_CONFIGURATION_EMBEDDING_WARNING\n')
|
167
|
|
- result_file.write(b' #warning "Generated file \'mc.zip\' is embedded (Define NO_CONFIGURATION_EMBEDDING_WARNING to suppress this warning.)"\n')
|
168
|
|
- result_file.write(b'#endif\n')
|
169
|
|
- result_file.write(b'const unsigned char mc_zip[] PROGMEM = {\n ')
|
|
169
|
+ result_file.write(
|
|
170
|
+ b'#ifndef NO_CONFIGURATION_EMBEDDING_WARNING\n'
|
|
171
|
+ + b' #warning "Generated file \'mc.zip\' is embedded (Define NO_CONFIGURATION_EMBEDDING_WARNING to suppress this warning.)"\n'
|
|
172
|
+ + b'#endif\n'
|
|
173
|
+ + b'const unsigned char mc_zip[] PROGMEM = {\n '
|
|
174
|
+ )
|
170
|
175
|
count = 0
|
171
|
176
|
for b in open(os.path.join(build_dir, 'mc.zip'), 'rb').read():
|
172
|
177
|
result_file.write(b' 0x%02X,' % b)
|