def __init__(self, arch, input_xar, output_path, use_xml=None): self.output = os.path.realpath(output_path) self.returncode = 0 self.stdout = "" self.arch = arch self.input = input_xar self.is_executable = False self.contain_swift = False self.deployment_target = None self.force_optimize_swift = False self.is_compile_with_clang = env.compile_with_clang # zf: read from xar xml during super class initialization super(BitcodeBundle, self).__init__(input_xar) if use_xml: data = "" with open(use_xml, 'r') as file: data = file.read() self.xml = ET.fromstring(data) try: self.platform = self.subdoc.find("platform").text self.sdk_version = self.subdoc.find("sdkversion").text self.version = self.subdoc.find("version").text except AttributeError: env.error("Malformed Header for bundle") else: env.setVersion(self.version) env.setPlatform(self.platform) if env.translate_watchos and env.getPlatform( ) == "watchos" and arch == "armv7k": self.arch = "arm64_32"
def run(self): """Build Bitcode Bundle""" linker_inputs = [] linker = Ld(self.output, self.dir) linker.addArgs(["-arch", self.arch]) linker.addArgs(self.linkOptions) # gongjl ld add __LLVM __Bundle linker.addArgs(["-bitcode_bundle"]) # handle bitcode input bitcode_files = self.getFileNode("Bitcode") if len(bitcode_files) > 0: compiler_jobs = map(self.constructBitcodeJob, bitcode_files) linker_inputs.extend(compiler_jobs) # object input object_files = self.getFileNode("Object") if len(object_files) > 0: if env.getPlatform() == "watchos": env.error("Watch platform doesn't support object inputs") object_jobs = map(self.constructObjectJob, object_files) linker_inputs.extend(object_jobs) # run compilation env.map(self.run_job, linker_inputs) # run bundle compilation in sequential to avoid dead-lock bundle_files = self.getFileNode("Bundle") if len(bundle_files) > 0: bundle_jobs = map(self.constructBundleJob, bundle_files) map(self.run_job, bundle_jobs) linker_inputs.extend(bundle_jobs) # sort object inputs inputs = sorted([os.path.basename(x.output) for x in linker_inputs]) # handle LTO inputs LTO_inputs = self.getFileNode("LTO") if (len(LTO_inputs)) != 0: lto_input_files = [x.find("name").text for x in LTO_inputs] linker.addArgs(["-flto-codegen-only"]) linker.addArgs(["-object_path_lto", self.output + ".lto.o"]) linker.addArgs(ClangCC1Translator.compatibility_flags(self.arch)) # watchOS doesn't support inline asm. if env.getPlatform() == "watchos": linker.addArgs(["-mllvm", "-lto-module-no-asm"]) if self.is_translate_watchos: lto_input_files = self.rewriteLTOInputFiles(lto_input_files) linker.addArgs( ["-mllvm", "-aarch64-watch-bitcode-compatibility"]) inputs.extend(lto_input_files) # add inputs to a LinkFileList LinkFileList = os.path.join(self.dir, self.output + ".LinkFileList") with open(LinkFileList, 'w') as f: for i in inputs: f.write(os.path.join(self.dir, i)) f.write('\n') linker.addArgs(["-filelist", LinkFileList]) # version specific arguments if env.satifiesLinkerVersion("253.2"): linker.addArgs(["-ignore_auto_link"]) if env.satifiesLinkerVersion("253.3.1"): linker.addArgs(["-allow_dead_duplicates"]) # add libLTO.dylib if needed if env.liblto is not None: linker.addArgs(["-lto_library", env.liblto]) # handle dylibs dylibs_node = self.subdoc.find("dylibs") if dylibs_node is not None: for lib_node in dylibs_node.iter(): if lib_node.tag == "lib": lib_path = env.resolveDylibs(self.arch, lib_node.text) linker.addArgs([lib_path]) elif lib_node.tag == "weak": # allow weak framework to be missing. If they provide no # symbols, the link will succeed. lib_path = env.resolveDylibs(self.arch, lib_node.text, True) if lib_path is not None: linker.addArgs(["-weak_library", lib_path]) # add swift library search path, only when auto-link cannot be ignored. if self.contain_swift and not env.satifiesLinkerVersion("253.2"): swiftLibPath = env.getlibSwiftPath(self.arch) if swiftLibPath is not None: linker.addArgs(["-L", swiftLibPath]) # add libclang_rt if self.forceload_compiler_rt: linker.addArgs(["-force_load"]) linker.addArgs([env.getlibclang_rt(self.arch)]) # linking try: self.run_job(linker) except BitcodeBuildFailure as e: if self.contain_swift and self.is_translate_watchos and not self.force_optimize_swift: env.warning("Rebuild failing swift project with optimization") rebuild = BitcodeBundle(self.arch, self.input, self.output) rebuild.force_optimize_swift = True rebuild.is_compile_with_clang = True return rebuild.run() else: raise e else: return self
def is_translate_watchos(self): return env.translate_watchos and env.getPlatform() == "watchos"
def constructBitcodeJob(self, xml_node): """construct a single bitcode workload""" name = xml_node.find("name").text output_name = name + ".o" if xml_node.find("clang") is not None: clang = Clang(name, output_name, self.dir) options = [ x.text if x.text is not None else "" for x in xml_node.find("clang").findall("cmd") ] options = ClangCC1Translator.upgrade(options, self.arch) if self.is_translate_watchos: options = ClangCC1Translator.translate_triple(options) if clang_option_verifier.verify(options): clang.addArgs(options) else: env.error(u"Clang option verification " "failed for bitcode {} ({})".format( name, clang_option_verifier.error_msg)) if env.getPlatform() == "watchos": clang.addArgs(["-fno-gnu-inline-asm"]) # gongjl build bitcode and cmd clang.addArgs(["-fembed-bitcode=all"]) return clang elif xml_node.find("swift") is not None: # swift uses extension to distinguish input type # we need to move the file to have .bc extension first self.contain_swift = True if self.is_compile_with_clang: clang = Clang(name, output_name, self.dir) options = [ x.text if x.text is not None else "" for x in xml_node.find("swift").findall("cmd") ] options = SwiftArgTranslator.upgrade(options, self.arch) if swift_option_verifier.verify(options): options = SwiftArgTranslator.translate_to_clang(options) if self.force_optimize_swift: options = ClangCC1Translator.add_optimization(options) if self.is_translate_watchos: options = ClangCC1Translator.translate_triple(options) clang.addArgs(options) else: env.error(u"Swift option verification " "failed for bitcode {} ({})".format( name, clang_option_verifier.error_msg)) return clang else: bcname = name + ".bc" shutil.move(os.path.join(self.dir, name), os.path.join(self.dir, bcname)) swift = Swift(bcname, output_name, self.dir) options = [ x.text if x.text is not None else "" for x in xml_node.find("swift").findall("cmd") ] if swift_option_verifier.verify(options): if self.force_optimize_swift: options = SwiftArgTranslator.add_optimization(options) if self.is_translate_watchos: options = SwiftArgTranslator.translate_triple(options) swift.addArgs(options) else: env.error(u"Swift option verification " "failed for bitcode {} ({})".format( name, swift_option_verifier.error_msg)) return swift else: env.error("Cannot figure out bitcode kind: {}".format(name))
def run(self): """Build Bitcode Bundle""" linker_inputs = [] linker = Ld(self.output, self.dir) linker.addArgs(["-arch", self.arch]) linker.addArgs(self.linkOptions) # handle bitcode input bitcode_files = self.getFileNode("Bitcode") if len(bitcode_files) > 0: compiler_jobs = map(self.constructBitcodeJob, bitcode_files) linker_inputs.extend(compiler_jobs) # object input object_files = self.getFileNode("Object") if len(object_files) > 0: if env.getPlatform() == "watchos": env.error("Watch platform doesn't support object inputs") object_jobs = map(self.constructObjectJob, object_files) linker_inputs.extend(object_jobs) # run compilation env.map(self.run_job, linker_inputs) # run bundle compilation in sequential to avoid dead-lock bundle_files = self.getFileNode("Bundle") if len(bundle_files) > 0: bundle_jobs = map(self.constructBundleJob, bundle_files) map(self.run_job, bundle_jobs) linker_inputs.extend(bundle_jobs) # sort object inputs inputs = sorted([os.path.basename(x.output) for x in linker_inputs]) # handle LTO inputs LTO_inputs = self.getFileNode("LTO") if (len(LTO_inputs)) != 0: inputs.extend([x.find("name").text for x in LTO_inputs]) linker.addArgs(["-flto-codegen-only"]) # add inputs to a LinkFileList LinkFileList = os.path.join(self.dir, self.output + ".LinkFileList") with open(LinkFileList, 'w') as f: for i in inputs: f.write(os.path.join(self.dir, i)) f.write('\n') linker.addArgs(["-filelist", LinkFileList]) # version specific arguments if env.satifiesLinkerVersion("253.2"): linker.addArgs(["-ignore_auto_link"]) if env.satifiesLinkerVersion("253.3.1"): linker.addArgs(["-allow_dead_duplicates"]) # add libLTO.dylib if needed if env.liblto is not None: linker.addArgs(["-lto_library", env.liblto]) # handle dylibs dylibs_node = self.subdoc.find("dylibs") if dylibs_node is not None: for lib_node in dylibs_node.iter(): if lib_node.tag == "lib": lib_path = env.resolveDylibs(self.arch, lib_node.text) linker.addArgs([lib_path]) elif lib_node.tag == "weak": # allow weak framework to be missing. If they provide no # symbols, the link will succeed. lib_path = env.resolveDylibs(self.arch, lib_node.text, True) if lib_path is not None: linker.addArgs(["-weak_library", lib_path]) # add swift library search path, only when auto-link cannot be ignored. if self.contain_swift and not env.satifiesLinkerVersion("253.2"): swiftLibPath = env.getlibSwiftPath(self.arch) if swiftLibPath is not None: linker.addArgs(["-L", swiftLibPath]) # add libclang_rt if self.forceload_compiler_rt: linker.addArgs(["-force_load"]) linker.addArgs([env.getlibclang_rt(self.arch)]) # linking self.run_job(linker) return self