@@ -2652,21 +2652,44 @@ def safe_copy(src, dst):
2652
2652
if dst == '/dev/null' : return
2653
2653
shutil .copyfile (src , dst )
2654
2654
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 )
2668
2690
2669
- f = f [:m .start (0 )] + included_file + f [m .end (0 ):]
2691
+ if dst : open (dst , 'w' ).write (preprocessed )
2692
+ return preprocessed
2670
2693
2671
2694
# Generates a suitable fetch-worker.js script from the given input source JS file (which is an asm.js build output),
2672
2695
# 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):
2696
2719
func_code = src [loc :end_loc ]
2697
2720
function_prologue = function_prologue + '\n ' + func_code
2698
2721
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 )
2700
2723
open (output_file , 'w' ).write (fetch_worker_src )
2701
2724
2702
2725
0 commit comments