1
+ # Copyright 2014-present PlatformIO <contact@platformio.org>
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import shutil
16
+ from os import SEEK_CUR , SEEK_END
17
+ from os .path import basename , isfile , join
18
+
19
+ from SCons .Script import Builder
20
+
21
+ Import ("env" )
22
+
23
+ board = env .BoardConfig ()
24
+
25
+ #
26
+ # Embedded files helpers
27
+ #
28
+
29
+
30
+ def extract_files (cppdefines , files_type ):
31
+ result = []
32
+ files = env .GetProjectOption ("board_build.%s" % files_type , "" ).splitlines ()
33
+ if files :
34
+ result .extend ([join ("$PROJECT_DIR" , f .strip ()) for f in files if f ])
35
+ else :
36
+ files_define = "COMPONENT_" + files_type .upper ()
37
+ for define in cppdefines :
38
+ if files_define not in define :
39
+ continue
40
+
41
+ value = define [1 ]
42
+ if not isinstance (define , tuple ):
43
+ print ("Warning! %s macro cannot be empty!" % files_define )
44
+ return []
45
+
46
+ if not isinstance (value , str ):
47
+ print (
48
+ "Warning! %s macro must contain "
49
+ "a list of files separated by ':'" % files_define
50
+ )
51
+ return []
52
+
53
+ for f in value .split (":" ):
54
+ if not f :
55
+ continue
56
+ result .append (join ("$PROJECT_DIR" , f ))
57
+
58
+ for f in result :
59
+ if not isfile (env .subst (f )):
60
+ print ('Warning! Could not find file "%s"' % basename (f ))
61
+
62
+ return result
63
+
64
+
65
+ def remove_config_define (cppdefines , files_type ):
66
+ for define in cppdefines :
67
+ if files_type in define :
68
+ env .ProcessUnFlags ("-D%s" % "=" .join (str (d ) for d in define ))
69
+ return
70
+
71
+
72
+ def prepare_file (source , target , env ):
73
+ filepath = source [0 ].get_abspath ()
74
+ shutil .copy (filepath , filepath + ".piobkp" )
75
+
76
+ with open (filepath , "rb+" ) as fp :
77
+ fp .seek (- 1 , SEEK_END )
78
+ if fp .read (1 ) != "\0 " :
79
+ fp .seek (0 , SEEK_CUR )
80
+ fp .write (b"\0 " )
81
+
82
+
83
+ def revert_original_file (source , target , env ):
84
+ filepath = source [0 ].get_abspath ()
85
+ if isfile (filepath + ".piobkp" ):
86
+ shutil .move (filepath + ".piobkp" , filepath )
87
+
88
+
89
+ def embed_files (files , files_type ):
90
+ for f in files :
91
+ filename = basename (f ) + ".txt.o"
92
+ file_target = env .TxtToBin (join ("$BUILD_DIR" , filename ), f )
93
+ env .Depends ("$PIOMAINPROG" , file_target )
94
+ if files_type == "embed_txtfiles" :
95
+ env .AddPreAction (file_target , prepare_file )
96
+ env .AddPostAction (file_target , revert_original_file )
97
+ env .AppendUnique (PIOBUILDFILES = [env .File (join ("$BUILD_DIR" , filename ))])
98
+
99
+
100
+ def transform_to_asm (target , source , env ):
101
+ files = [join ("$BUILD_DIR" , s .name + ".S" ) for s in source ]
102
+ return files , source
103
+
104
+
105
+ env .Append (
106
+ BUILDERS = dict (
107
+ TxtToBin = Builder (
108
+ action = env .VerboseAction (
109
+ " " .join (
110
+ [
111
+ "xtensa-lx106-elf-objcopy" ,
112
+ "--input-target" ,
113
+ "binary" ,
114
+ "--output-target" ,
115
+ "elf32-xtensa-le" ,
116
+ "--binary-architecture" ,
117
+ "xtensa" ,
118
+ "--rename-section" ,
119
+ ".data=.rodata.embedded" ,
120
+ "$SOURCE" ,
121
+ "$TARGET" ,
122
+ ]
123
+ ),
124
+ "Converting $TARGET" ,
125
+ ),
126
+ suffix = ".txt.o" ,
127
+ ),
128
+ FileToAsm = Builder (
129
+ action = env .VerboseAction (
130
+ " " .join (
131
+ [
132
+ join (
133
+ env .PioPlatform ().get_package_dir ("tool-cmake" ) or "" ,
134
+ "bin" ,
135
+ "cmake" ,
136
+ ),
137
+ "-DDATA_FILE=$SOURCE" ,
138
+ "-DSOURCE_FILE=$TARGET" ,
139
+ "-DFILE_TYPE=$FILE_TYPE" ,
140
+ "-P" ,
141
+ join (
142
+ env .PioPlatform ().get_package_dir ("framework-esp8266-rtos-sdk" ) or "" ,
143
+ "tools" ,
144
+ "cmake" ,
145
+ "scripts" ,
146
+ "data_file_embed_asm.cmake" ,
147
+ ),
148
+ ]
149
+ ),
150
+ "Generating assembly for $TARGET" ,
151
+ ),
152
+ emitter = transform_to_asm ,
153
+ single_source = True ,
154
+ ),
155
+ )
156
+ )
157
+
158
+
159
+ flags = env .get ("CPPDEFINES" )
160
+ for files_type in ("embed_txtfiles" , "embed_files" ):
161
+ if (
162
+ "COMPONENT_" + files_type .upper () not in env .Flatten (flags )
163
+ and "build." + files_type not in board
164
+ ):
165
+ continue
166
+
167
+ files = extract_files (flags , files_type )
168
+ if "esp8266-rtos-sdk" in env .subst ("$PIOFRAMEWORK" ):
169
+ env .Requires (
170
+ join ("$BUILD_DIR" , "${PROGNAME}.elf" ),
171
+ env .FileToAsm (
172
+ files ,
173
+ FILE_TYPE = "TEXT" if files_type == "embed_txtfiles" else "BINARY" ,
174
+ ),
175
+ )
176
+ else :
177
+ embed_files (files , files_type )
178
+ remove_config_define (flags , files_type )
179
+
0 commit comments