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))
Beispiel #5
0
    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