Beispiel #1
0
def _lipo_exec_files(exec_files, target_archs, strip_bitcode, source_path,
                     destination_path):
    """Strips executable files if needed and copies them to the destination."""
    # Find all architectures from the set of files we might have to lipo.
    exec_archs = lipo.find_archs_for_binaries(
        [os.path.join(source_path, f) for f in exec_files])

    # Ensure directory for remote execution
    if not os.path.exists(destination_path):
        os.makedirs(destination_path)

    # Copy or lipo each file as needed, from source to destination.
    for exec_file in exec_files:
        exec_file_source_path = os.path.join(source_path, exec_file)
        exec_file_destination_path = os.path.join(destination_path, exec_file)
        if len(exec_archs) == 1 or target_archs == exec_archs:
            # If there is no need to lipo, copy and mark as executable.
            shutil.copy(exec_file_source_path, exec_file_destination_path)
            os.chmod(exec_file_destination_path, 0o755)
        else:
            lipo.invoke_lipo(exec_file_source_path, target_archs,
                             exec_file_destination_path)
        if strip_bitcode:
            bitcode_strip.invoke(exec_file_destination_path,
                                 exec_file_destination_path)
Beispiel #2
0
def _lipo_exec_files(exec_files, target_archs, strip_bitcode, source_path,
                     destination_path):
    """Strips executable files if needed and copies them to the destination."""
    # Find all architectures from the set of files we might have to lipo.
    _, exec_archs = lipo.find_archs_for_binaries(
        [os.path.join(source_path, f) for f in exec_files])

    # Copy or lipo each file as needed, from source to destination.
    for exec_file in exec_files:
        exec_file_source_path = os.path.join(source_path, exec_file)
        exec_file_destination_path = os.path.join(destination_path, exec_file)
        file_archs = exec_archs[exec_file_source_path]

        archs_to_keep = target_archs & file_archs

        # On M1 hardware, thin x86_64 libraries do not need lipo when archs_to_keep
        # is empty.
        if len(file_archs
               ) == 1 or archs_to_keep == file_archs or not archs_to_keep:
            # If there is no need to lipo, copy and mark as executable.
            shutil.copy(exec_file_source_path, exec_file_destination_path)
            os.chmod(exec_file_destination_path, 0o755)
        else:
            lipo.invoke_lipo(exec_file_source_path, archs_to_keep,
                             exec_file_destination_path)
        if strip_bitcode:
            bitcode_strip.invoke(exec_file_destination_path,
                                 exec_file_destination_path)
Beispiel #3
0
def main():
    parser = codesigningtool.generate_arg_parser()
    parser.add_argument(
        "--framework_binary",
        type=str,
        required=True,
        action="append",
        help="path to a binary file scoped to one of the imported frameworks")
    parser.add_argument("--slice",
                        type=str,
                        required=True,
                        action="append",
                        help="binary slice "
                        "expected to represent the target architectures")
    parser.add_argument("--strip_bitcode",
                        action="store_true",
                        default=False,
                        help="strip "
                        "bitcode from the imported frameworks.")
    parser.add_argument(
        "--framework_file",
        type=str,
        action="append",
        help="path to a file "
        "scoped to one of the imported frameworks, distinct from the binary files"
    )
    parser.add_argument("--temp_path",
                        type=str,
                        required=True,
                        help="temporary path to copy "
                        "all framework files to")
    parser.add_argument(
        "--output_zip",
        type=str,
        required=True,
        help="path to save the zip file "
        "containing a codesigned, lipoed version of the imported framework")
    args = parser.parse_args()

    all_binary_archs = args.slice
    framework_archs = lipo.find_archs_for_binaries(args.framework_binary)

    if not framework_archs:
        return 1

    # Delete any existing stale framework files, if any exist.
    if os.path.exists(args.temp_path):
        shutil.rmtree(args.temp_path)
    if os.path.exists(args.output_zip):
        os.remove(args.output_zip)
    os.makedirs(args.temp_path)

    for framework_binary in args.framework_binary:
        # If the imported framework is single architecture, and therefore assumed
        # that it doesn't need to be lipoed, or if the binary architectures match
        # the framework architectures perfectly, treat as a copy instead of a lipo
        # operation.
        if len(framework_archs) == 1 or all_binary_archs == framework_archs:
            status_code = _copy_framework_file(framework_binary,
                                               executable=True,
                                               output_path=args.temp_path)
        else:
            slices_needed = framework_archs.intersection(all_binary_archs)
            if not slices_needed:
                print("Error: Precompiled framework does not share any binary "
                      "architectures with the binaries that were built.")
                return 1
            status_code = _strip_framework_binary(framework_binary,
                                                  args.temp_path,
                                                  slices_needed)
        if status_code:
            return 1

        # Strip bitcode from the output framework binary
        if args.strip_bitcode:
            output_binary = os.path.join(args.temp_path,
                                         os.path.basename(framework_binary))
            bitcode_strip.invoke(output_binary, output_binary)

    if args.framework_file:
        for framework_file in args.framework_file:
            status_code = _copy_framework_file(framework_file,
                                               executable=False,
                                               output_path=args.temp_path)
            if status_code:
                return 1

    # Attempt to sign the framework, check for an error when signing.
    status_code = codesigningtool.main(args)
    if status_code:
        return status_code

    _zip_framework(args.temp_path, args.output_zip)