@@ -2652,21 +2652,44 @@ def safe_copy(src, dst):
26522652 if dst == '/dev/null' : return
26532653 shutil .copyfile (src , dst )
26542654
2655- def clang_preprocess (filename ):
2656- # TODO: REMOVE HACK AND PASS PREPROCESSOR FLAGS TO CLANG.
2657- return subprocess .check_output ([CLANG_CC , '-DFETCH_DEBUG=1' , '-E' , '-P' , '-C' , '-x' , 'c' , filename ])
2658-
2659- def read_and_preprocess (filename ):
2660- f = open (filename , 'r' ).read ()
2661- pos = 0
2662- include_pattern = re .compile ('^#include\s*["<](.*)[">]\s?$' , re .MULTILINE )
2663- while (1 ):
2664- m = include_pattern .search (f , pos )
2665- if not m :
2666- return f
2667- included_file = open (os .path .join (os .path .dirname (filename ), m .groups (0 )[0 ]), 'r' ).read ()
2655+ def find_lines_with_preprocessor_directives (file ):
2656+ return filter (lambda x : '#if' in x or '#elif' in x , open (file , 'r' ).readlines ())
2657+
2658+ def run_c_preprocessor_on_file (src , dst ):
2659+ # Run LLVM's C preprocessor on the given file, expanding #includes and variables found in src/setting.js.
2660+ # Historically, .js file preprocessing only expands variables found in #if etc. statements, and .js
2661+ # code uses some setting names as variables as well. For example, pthread-main.js has a variable
2662+ # TOTAL_MEMORY, which is also a Setting name. Therefore detect to only expand those Setting names that
2663+ # are referred to if and #elif defines - but that expansion is done globally in the file, so it will
2664+ # preclude one from doing things like
2665+ #
2666+ # var TOTAL_MEMORY = {{{ TOTAL_MEMORY }}};
2667+ # if TOTAL_MEMORY > 65536
2668+ #
2669+ # Still, this should give a good balance to be compatible with existing behavior.
2670+
2671+ # Find the #if lines that we'll allow expanding.
2672+ whitelisted_defines = find_lines_with_preprocessor_directives (src )
2673+
2674+ def any_string_contains (string_list , substr ):
2675+ for s in string_list :
2676+ if substr in s :
2677+ return True
2678+ return False
2679+
2680+ defines = []
2681+ for s in Settings .attrs :
2682+ if any_string_contains (whitelisted_defines , s ):
2683+ d = '-D' + s + '=' + str (Settings .attrs [s ])
2684+ logging .debug ('Expanding #define ' + d + ' when preprocessing file ' + src )
2685+ defines += [d ]
2686+
2687+ response_filename = response_file .create_response_file (defines , TEMP_DIR )
2688+ preprocessed = subprocess .check_output ([CLANG_CC , '-E' , '-P' , '-C' , '-x' , 'c' , '@' + response_filename , src ])
2689+ try_delete (response_filename )
26682690
2669- f = f [:m .start (0 )] + included_file + f [m .end (0 ):]
2691+ if dst : open (dst , 'w' ).write (preprocessed )
2692+ return preprocessed
26702693
26712694# Generates a suitable fetch-worker.js script from the given input source JS file (which is an asm.js build output),
26722695# and writes it out to location output_file. fetch-worker.js is the root entry point for a dedicated filesystem web
@@ -2696,7 +2719,7 @@ def make_fetch_worker(source_file, output_file):
26962719 func_code = src [loc :end_loc ]
26972720 function_prologue = function_prologue + '\n ' + func_code
26982721
2699- fetch_worker_src = function_prologue + '\n ' + clang_preprocess (path_from_root ('src' , 'fetch-worker.js' ))
2722+ fetch_worker_src = function_prologue + '\n ' + run_c_preprocessor_on_file (path_from_root ('src' , 'fetch-worker.js' ), dst = None )
27002723 open (output_file , 'w' ).write (fetch_worker_src )
27012724
27022725
0 commit comments