1919
2020import re
2121from copy import copy
22- from os .path import join , dirname , splitext , basename , exists , isfile , relpath
22+ from os .path import join , dirname , splitext , basename , exists , isfile , relpath , sep
2323from os import makedirs , write , remove
2424from tempfile import mkstemp
2525from shutil import rmtree
@@ -270,6 +270,41 @@ def compile_cpp(self, source, object, includes):
270270 def correct_scatter_shebang (self , sc_fileref , cur_dir_name = None ):
271271 """Correct the shebang at the top of a scatter file.
272272
273+ The shebang line is the line at the top of the file starting with '#!'. If this line is present
274+ then the linker will execute the command on that line on the content of the scatter file prior
275+ to consuming the content into the link. Typically the shebang line will contain an instruction
276+ to run the C-preprocessor (either 'armcc -E' or 'armclang -E') which allows for macro expansion,
277+ inclusion of headers etc. Other options are passed to the preprocessor to specify aspects of the
278+ system such as the processor architecture and cpu type.
279+
280+ The build system (at this point) will have constructed what it considers to be a correct shebang
281+ line for this build. If this differs from the line in the scatter file then the scatter file
282+ will be rewritten by this function to contain the build-system-generated shebang line. Note
283+ that the rewritten file will be placed in the BUILD output directory.
284+
285+ Include processing
286+
287+ If the scatter file runs the preprocessor, and contains #include statements then the pre-processor
288+ include path specifies where the #include files are to be found. Typically, #include files
289+ are specified with a path relative to the location of the original scatter file. When the
290+ preprocessor runs, the system automatically passes the location of the scatter file into the
291+ include path through an implicit '-I' option to the preprocessor, and this works fine in the
292+ offline build system.
293+ Unfortunately this approach does not work in the online build, because the preprocessor
294+ command runs in a chroot. The true (non-chroot) path to the file as known by the build system
295+ looks something like this:
296+ /tmp/chroots/ch-eefd72fb-2bcb-4e99-9043-573d016618bb/extras/mbed-os.lib/...
297+ whereas the path known by the preprocessor will be:
298+ /extras/mbed-os.lib/...
299+ Consequently, the chroot path has to be explicitly passed to the preprocessor through an
300+ explicit -I/path/to/chroot/file option in the shebang line.
301+
302+ *** THERE IS AN ASSUMPTION THAT THE CHROOT PATH IS THE REAL FILE PATH WITH THE FIRST
303+ *** THREE ELEMENTS REMOVED. THIS ONLY HOLDS TRUE UNTIL THE ONLINE BUILD SYSTEM CHANGES
304+
305+ If the include path manipulation as described above does change, then any scatter file
306+ containing a #include statement is likely to fail on the online compiler.
307+
273308 Positional arguments:
274309 sc_fileref -- FileRef object of the scatter file
275310
@@ -285,21 +320,34 @@ def correct_scatter_shebang(self, sc_fileref, cur_dir_name=None):
285320 """
286321 with open (sc_fileref .path , "r" ) as input :
287322 lines = input .readlines ()
323+
324+ # If the existing scatter file has no shebang line, or the line that it does have
325+ # matches the desired line then the existing scatter file is used directly without rewriting.
288326 if (lines [0 ].startswith (self .SHEBANG ) or
289- not lines [0 ].startswith ("#!" )):
327+ not lines [0 ].startswith ("#!" )):
290328 return sc_fileref
291- else :
292- new_scatter = join (self .build_dir , ".link_script.sct" )
293- if cur_dir_name is None :
294- cur_dir_name = dirname (sc_fileref .path )
295- self .SHEBANG += " -I %s" % cur_dir_name
296- if self .need_update (new_scatter , [sc_fileref .path ]):
297- with open (new_scatter , "w" ) as out :
298- out .write (self .SHEBANG )
299- out .write ("\n " )
300- out .write ("" .join (lines [1 :]))
301-
302- return FileRef (".link_script.sct" , new_scatter )
329+
330+ new_scatter = join (self .build_dir , ".link_script.sct" )
331+ if cur_dir_name is None :
332+ cur_dir_name = dirname (sc_fileref .path )
333+
334+ # For a chrooted system, adjust the path to the scatter file to be a valid
335+ # chroot location by removing the first three elements of the path.
336+ if cur_dir_name .startswith ("/tmp/chroots" ):
337+ cur_dir_name = sep + join (* (cur_dir_name .split (sep )[4 :]))
338+
339+ # Add the relocated scatter file path to the include path.
340+ self .SHEBANG += " -I%s" % cur_dir_name
341+
342+ # Only rewrite if doing a full build...
343+ if self .need_update (new_scatter , [sc_fileref .path ]):
344+ with open (new_scatter , "w" ) as out :
345+ # Write the new shebang line...
346+ out .write (self .SHEBANG + "\n " )
347+ # ...followed by the unmolested remaining content from the original scatter file.
348+ out .write ("" .join (lines [1 :]))
349+
350+ return FileRef (".link_script.sct" , new_scatter )
303351
304352 def get_link_command (
305353 self ,
0 commit comments