1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5from argparse import ( 6 Action, 7 ArgumentParser, 8) 9import os 10import subprocess 11import sys 12import tempfile 13 14import buildconfig 15 16 17class CPPFlag(Action): 18 all_flags = [] 19 20 def __call__(self, parser, namespace, values, option_string=None): 21 if "windres" in buildconfig.substs["RC"].lower(): 22 if option_string == "-U": 23 return 24 if option_string == "-I": 25 option_string = "--include-dir" 26 27 self.all_flags.extend((option_string, values)) 28 29 30def generate_res(): 31 parser = ArgumentParser() 32 parser.add_argument( 33 "-D", action=CPPFlag, metavar="VAR[=VAL]", help="Define a variable" 34 ) 35 parser.add_argument("-U", action=CPPFlag, metavar="VAR", help="Undefine a variable") 36 parser.add_argument( 37 "-I", action=CPPFlag, metavar="DIR", help="Search path for includes" 38 ) 39 parser.add_argument("-o", dest="output", metavar="OUTPUT", help="Output file") 40 parser.add_argument("input", help="Input file") 41 args = parser.parse_args() 42 43 is_windres = "windres" in buildconfig.substs["RC"].lower() 44 45 verbose = os.environ.get("BUILD_VERBOSE_LOG") 46 47 # llvm-rc doesn't preprocess on its own, so preprocess manually 48 # Theoretically, not windres could be rc.exe, but configure won't use it 49 # unless you really ask for it, and it will still work with preprocessed 50 # output. 51 try: 52 if not is_windres: 53 fd, path = tempfile.mkstemp(suffix=".rc") 54 command = buildconfig.substs["CXXCPP"] + CPPFlag.all_flags 55 command.extend(("-DRC_INVOKED", args.input)) 56 57 cpu_arch_dict = {"x86_64": "_AMD64_", "x86": "_X86_", "aarch64": "_ARM64_"} 58 59 # add a preprocessor #define that specifies the CPU architecture 60 cpu_arch_ppd = cpu_arch_dict[buildconfig.substs["CPU_ARCH"]] 61 62 command.extend(("-D", cpu_arch_ppd)) 63 64 if verbose: 65 print("Executing:", " ".join(command)) 66 with os.fdopen(fd, "wb") as fh: 67 retcode = subprocess.run(command, stdout=fh).returncode 68 if retcode: 69 # Rely on the subprocess printing out any relevant error 70 return retcode 71 else: 72 path = args.input 73 74 command = [buildconfig.substs["RC"]] 75 if is_windres: 76 command.extend(("-O", "coff")) 77 78 # Even though llvm-rc doesn't preprocess, we still need to pass at least 79 # the -I flags. 80 command.extend(CPPFlag.all_flags) 81 82 if args.output: 83 if is_windres: 84 command.extend(("-o", args.output)) 85 else: 86 # Use win1252 code page for the input. 87 command.extend(("-c", "1252", "-Fo" + args.output)) 88 89 command.append(path) 90 91 if verbose: 92 print("Executing:", " ".join(command)) 93 retcode = subprocess.run(command).returncode 94 if retcode: 95 # Rely on the subprocess printing out any relevant error 96 return retcode 97 finally: 98 if path != args.input: 99 os.remove(path) 100 101 return 0 102 103 104if __name__ == "__main__": 105 sys.exit(generate_res()) 106