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