diff --git a/pkgs/os-specific/darwin/gen-frameworks.py b/pkgs/os-specific/darwin/gen-frameworks.py deleted file mode 100755 index ec2a6c7c16ec..000000000000 --- a/pkgs/os-specific/darwin/gen-frameworks.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env nix-shell -#!nix-shell -i python -p python3 swiftPackages.swift-unwrapped - -""" -Generate a frameworks.nix for a macOS SDK. - -You may point this tool at an Xcode bundled SDK, but more ideal is using the -SDK from Nixpkgs. For example: - -SDK_PATH="$(nix-build --no-link -A darwin.apple_sdk_11_0.MacOSX-SDK)" -./gen-frameworks.py "$SDK_PATH" > ./new-frameworks.nix -""" - -import json -import os -import subprocess -import sys - -ALLOWED_LIBS = ["simd"] - -HEADER = """\ -# This file is generated by gen-frameworks.nix. -# Do not edit, put overrides in apple_sdk.nix instead. -{ libs, frameworks }: with libs; with frameworks; -{ -""" - -FOOTER = """\ -} -""" - - -def eprint(*args): - print(*args, file=sys.stderr) - - -def name_from_ident(ident): - return ident.get("swift", ident.get("clang")) - - -def scan_sdk(sdk): - # Find frameworks by scanning the SDK frameworks directory. - frameworks = [ - framework.removesuffix(".framework") - for framework in os.listdir(f"{sdk}/System/Library/Frameworks") - if not framework.startswith("_") - ] - frameworks.sort() - - # Determine the longest name for padding output. - width = len(max(frameworks, key=len)) - - output = HEADER - - for framework in frameworks: - deps = [] - - # Use Swift to scan dependencies, because a module may have both Clang - # and Swift parts. Using Clang only imports the Clang module, whereas - # using Swift will usually import both Clang + Swift overlay. - # - # TODO: The above is an assumption. Not sure if it's possible a Swift - # module completely shadows a Clang module. (Seems unlikely) - # - # TODO: Handle "module 'Foobar' is incompatible with feature 'swift'" - # - # If there were a similar Clang invocation for scanning, we could fix - # the above todos, but that doesn't appear to exist. - eprint(f"# scanning {framework}") - result = subprocess.run( - [ - "swiftc", - "-scan-dependencies", - # We provide a source snippet via stdin. - "-", - # Use the provided SDK. - "-sdk", - sdk, - # This search path is normally added automatically by the - # compiler based on the SDK, but we have a patch in place that - # removes that for SDKs in /nix/store, because our xcbuild stub - # SDK doesn't have the directory. - # (swift-prevent-sdk-dirs-warning.patch) - "-I", - f"{sdk}/usr/lib/swift", - # For some reason, 'lib/swift/shims' from both the SDK and - # Swift compiler are picked up, causing redefinition errors. - # This eliminates the latter. - "-resource-dir", - f"{sdk}/usr/lib/swift", - ], - input=f"import {framework}".encode(), - stdout=subprocess.PIPE, - ) - if result.returncode != 0: - eprint(f"# Scanning {framework} failed (exit code {result.returncode})") - result.stdout = b"" - - # Parse JSON output. - if len(result.stdout) != 0: - data = json.loads(result.stdout) - - # Entries in the modules list come in pairs. The first is an - # identifier (`{ swift: "foobar" }` or `{ clang: "foobar" }`), and - # the second metadata for that module. Here we look for the pair - # that matches the framework we're scanning (and ignore the rest). - modules = data["modules"] - for i in range(0, len(modules), 2): - ident, meta = modules[i : i + 2] - - # NOTE: We may match twice, for a Swift module _and_ for a - # Clang module. So matching here doesn't break from the loop, - # and deps is appended to. - if name_from_ident(ident) == framework: - dep_idents = meta["directDependencies"] - deps += [name_from_ident(ident) for ident in dep_idents] - # List unfiltered deps in progress output. - eprint(ident, "->", dep_idents) - - # Filter out modules that are not separate derivations. - # Also filter out duplicates (when a Swift overlay imports the Clang module) - allowed = frameworks + ALLOWED_LIBS - deps = set([dep for dep in deps if dep in allowed]) - - # Filter out self-references. (Swift overlay importing Clang module.) - if framework in deps: - deps.remove(framework) - - # Generate a Nix attribute line. - if len(deps) != 0: - deps = list(deps) - deps.sort() - deps = " ".join(deps) - output += f" {framework.ljust(width)} = {{ inherit {deps}; }};\n" - else: - output += f" {framework.ljust(width)} = {{}};\n" - - output += FOOTER - sys.stdout.write(output) - - -if __name__ == "__main__": - if len(sys.argv) != 2: - eprint(f"Usage: {sys.argv[0]} ") - sys.exit(64) - - scan_sdk(sys.argv[1])