diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml index 56bb4bf..c6c8692 100644 --- a/.github/workflows/automation.yml +++ b/.github/workflows/automation.yml @@ -20,21 +20,29 @@ jobs: with: determinate: true - uses: DeterminateSystems/flakehub-cache-action@main + - uses: DeterminateSystems/flakehub-push@main + with: + name: Cloudef/zig2nix + rolling: true + visibility: public + include-output-paths: true - uses: cachix/cachix-action@master with: name: zig2nix authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' skipAddingSubstituter: true - run: | - nix run .#update-versions > versions.json + nix flake update + nix run .#update-versions nix run .#update-templates - nix run .#test.all + nix run .#test-all nix run .#readme > README.md - uses: test-room-7/action-update-file@v2.0.0 with: branch: ${{ github.head_ref || github.ref_name }} file-path: | - versions.json + flake.lock + src/zig/versions.nix templates/** README.md commit-msg: Automatic update diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 93f8ddb..f7d3c73 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,5 +26,5 @@ jobs: - uses: DeterminateSystems/flakehub-cache-action@main - run: | nix run .#update-templates - nix run .#test.all + nix run .#test-all nix run .#readme diff --git a/README.md b/README.md index 4a3e871..8e359d4 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,8 @@ https://ziglang.org/ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -* Zig git: `git+05937b3+2025-03-05 @ 2025-03-05` -* Zig master: `0.14.0-dev.3462+edabcf619 @ 2025-03-04` -* Zig default: `0.13.0 @ 2024-06-07` +* Zig master: `0.15.0-dev.10+214750fcf @ 2025-03-08` +* Zig latest: `0.14.0 @ 2025-03-05` ## Examples @@ -35,17 +34,17 @@ nix run . ### Build zig from source ```bash -nix build github:Cloudef/zig2nix#zig.master.src +nix build github:Cloudef/zig2nix#zig-src-master +nix build github:Cloudef/zig2nix#zig-src-latest +nix build github:Cloudef/zig2nix#zig-src-0_8_0 ``` ### Running zig compiler directly ```bash -nix run github:Cloudef/zig2nix#env.master.bin.bare.zig -- version -nix run github:Cloudef/zig2nix#env.default.bin.bare.zig -- version -# Or simply these aliases nix run github:Cloudef/zig2nix#master -- version -nix run github:Cloudef/zig2nix -- version +nix run github:Cloudef/zig2nix#latest -- version +nix run github:Cloudef/zig2nix#0_8_0 -- version ``` #### Convenience zig for multimedia programs @@ -53,61 +52,38 @@ nix run github:Cloudef/zig2nix -- version > This sets (DY)LD_LIBRARY_PATH and PKG_CONFIG_PATH so that common libs are available ```bash -nix run github:Cloudef/zig2nix#env.master.bin.multimedia.zig -- version -nix run github:Cloudef/zig2nix#env.default.bin.multimedia.zig -- version +nix run github:Cloudef/zig2nix#multimedia-master -- version +nix run github:Cloudef/zig2nix#multimedia-latest -- version +nix run github:Cloudef/zig2nix#multimedia-0_8_0 -- version ``` ### Shell for building and running a Zig project ```bash -nix develop github:Cloudef/zig2nix#env.master.bin.bare -nix develop github:Cloudef/zig2nix#env.default.bin.bare -# Or simply these aliases nix develop github:Cloudef/zig2nix#master -nix develop github:Cloudef/zig2nix -``` - -#### Convenience shell for multimedia programs - -> This sets (DY)LD_LIBRARY_PATH and PKG_CONFIG_PATH so that common libs are available - -```bash -nix develop github:Cloudef/zig2nix#env.master.bin.multimedia -nix develop github:Cloudef/zig2nix#env.default.bin.multimedia +nix develop github:Cloudef/zig2nix#latest +nix develop github:Cloudef/zig2nix#0_8_0 ``` ### Convert zon file to json ```bash -nix run github:Cloudef/zig2nix#zon2json -- build.zig.zon +nix run github:Cloudef/zig2nix -- zon2json build.zig.zon ``` ### Convert build.zig.zon to a build.zig.zon2json-lock ```bash -nix run github:Cloudef/zig2nix#zon2json-lock -- build.zig.zon -# alternatively output to stdout -nix run github:Cloudef/zig2nix#zon2json-lock -- build.zig.zon - +nix run github:Cloudef/zig2nix -- zon2lock build.zig.zon ``` ### Convert build.zig.zon/2json-lock to a nix derivation ```bash # calls zon2json-lock if build.zig.zon2json-lock does not exist (requires network access) -nix run github:Cloudef/zig2nix#zon2nix -- build.zig.zon +nix run github:Cloudef/zig2nix -- zon2nix build.zig.zon # alternatively run against the lock file (no network access required) -nix run github:Cloudef/zig2nix#zon2nix -- build.zig.zon2json-lock -``` - -### Cross-compile nixpkgs using zig - -> This is very experimental, and many things may not compile. - -```bash -nix build github:Cloudef/zig2nix#env.master.bin.cross.x86_64-windows-gnu.zlib -nix build github:Cloudef/zig2nix#env.default.bin.cross.x86_64-windows-gnu.zlib -# Or simply this alias that uses env.master.bin -nix build github:Cloudef/zig2nix#zigCross.x86_64-windows-gnu.zlib +nix run github:Cloudef/zig2nix -- zon2nix build.zig.zon2json-lock ``` ## Crude documentation @@ -122,78 +98,58 @@ zig-env = { # Overrideable nixpkgs. nixpkgs ? self.inputs.nixpkgs, # Zig version to use. - zig ? zigv.default.bin, - # Additional runtime deps to inject into the helpers. - customRuntimeDeps ? [], - # Additional runtime libs to inject to the helpers. - # Gets included in LD_LIBRARY_PATH and DYLD_LIBRARY_PATH. - customRuntimeLibs ? [], - # Custom prelude in the flake app helper. - customAppHook ? "", - # Custom prelude in the flake shell helper. - customDevShellHook ? "", - # Enable Vulkan support. - enableVulkan ? false, - # Enable OpenGL support. - enableOpenGL ? false, - # Enable Wayland support. - enableWayland ? false, - # Enable X11 support. - enableX11 ? false, - # Enable Alsa support. - enableAlsa ? false, + zig ? zigv.latest, }: { ... }; #! --- Outputs of zig-env {} function. #! access: (zig-env {}).thing #! Tools for bridging zig and nix -zon2json-lock = zon2json-lock-base { inherit zig; }; -zon2nix = zon2nix-base { inherit zon2json-lock; }; -lib = zig2nix-lib { inherit zon2json zon2nix; }; +zig2nix = zig2nix-for-version zig; + +#! Translates zig and nix compatible targets +target = system: (exec-json "target" [ system ]); + +#! Reads zon file into a attribute set +fromZON = path: exec-json-path "zon2json" path []; +#! Creates derivation from zon2json-lock file +deriveLockFile = path: pkgs.callPackage (exec-path "zon2nix" path []); #! Returns true if target is nix flake compatible. #! -isFlakeTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; -in any (s: (systems.elaborate s).config == (nixTripleFromSystem target-system)) systems.flakeExposed; - +isFlakeTarget = any: pkgs.lib.any (s: (systems.elaborate s).config == (target any).config) systems.flakeExposed; #! Returns crossPkgs from nixpkgs for target string or system. #! This will always cross-compile the package. -crossPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; - crossPkgs = import nixpkgs { localSystem = system; crossSystem = { config = nixTripleFromSystem target-system; }; }; - this-system = (systems.elaborate system).config == nixTripleFromSystem target-system; +crossPkgsForTarget = any: let + crossPkgs = import nixpkgs { localSystem = system; crossSystem = { config = (target any).config; }; }; + this-system = (systems.elaborate system).config == (target any).config; in if this-system then pkgs else crossPkgs; #! Returns pkgs from nixpkgs for target string or system. #! This does not cross-compile and you'll get a error if package does not exist in binary cache. -binaryPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; - binaryPkgs = import nixpkgs { localSystem = { config = nixTripleFromSystem target-system; }; }; - this-system = (systems.elaborate system).config == nixTripleFromSystem target-system; +binaryPkgsForTarget = any: let + binaryPkgs = import nixpkgs { localSystem = { config = (target any).config; }; }; + this-system = (systems.elaborate system).config == (target any).config; in if this-system then pkgs else binaryPkgs; #! Returns either binaryPkgs or crossPkgs depending if the target is flake target or not. -pkgsForTarget = args': -if isFlakeTarget args' then binaryPkgsForTarget args' -else crossPkgsForTarget args'; +pkgsForTarget = any: +if isFlakeTarget any then binaryPkgsForTarget any +else crossPkgsForTarget any; #! Cross-compile nixpkgs using zig :) #! NOTE: This is an experimental feature, expect it not faring well -zigCrossPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; +zigCrossPkgsForTarget = any: let crossPkgs = pkgs.callPackage ./src/cross { - inherit zig zigPackage allTargetSystems; - inherit nixTripleFromSystem zigTripleFromSystem; - inherit mkZigSystemFromPlatform mkZigSystemFromString; - nixCrossPkgs = pkgsForTarget target-system; + inherit zig zigPackage target; + nixCrossPkgs = pkgsForTarget any; + nixBinaryPkgs = binaryPkgsForTarget any; localSystem = system; - crossSystem = { config = nixTripleFromSystem target-system; }; + crossSystem = { config = (target any).config; }; }; -in warn "zigCross: ${zigTripleFromSystem target-system}" crossPkgs; +in warn "zigCross: ${(target any).zig}" crossPkgs; #! Flake app helper (Without zig-env and root dir restriction). app-bare-no-root = deps: script: { @@ -217,13 +173,13 @@ app-bare = deps: script: app-bare-no-root deps '' #! Flake app helper (without root dir restriction). app-no-root = deps: script: app-bare-no-root (deps ++ _deps) '' - ${runtime.app} + ${shell-runtime deps} ${script} ''; #! Flake app helper. app = deps: script: app-bare (deps ++ _deps) '' - ${runtime.app} + ${shell-runtime deps} ${script} ''; @@ -234,7 +190,7 @@ mkShell = pkgs.callPackage ({ } @attrs: pkgs.mkShellNoCC (attrs // { nativeBuildInputs = optionals (attrs ? nativeBuildInputs) attrs.nativeBuildInputs ++ _deps; shellHook = '' - ${runtime.shell} + ${shell-runtime nativeBuildInputs} ${attrs.shellHook or ""} ''; })); @@ -251,11 +207,9 @@ packageForTarget = zigPackage; #! #! Additional attributes: #! zigTarget: Specify target for zig compiler, defaults to stdenv.targetPlatform of given target. -#! zigInheritStdenv: -#! By default if zigTarget is specified, nixpkgs stdenv compatible environment is not used. -#! Set this to true, if you want to specify zigTarget, but still use the derived stdenv compatible environment. #! zigPreferMusl: Prefer musl libc without specifying the target. -#! zigDisableWrap: makeWrapper will not be used. Might be useful if distributing outside nix. +#! zigWrapperBins: Binaries available to the binary during runtime (PATH) +#! zigWrapperLibs: Libraries available to the binary during runtime (LD_LIBRARY_PATH) #! zigWrapperArgs: Additional arguments to makeWrapper. #! zigBuildZon: Path to build.zig.zon file, defaults to build.zig.zon. #! zigBuildZonLock: Path to build.zig.zon2json-lock file, defaults to build.zig.zon2json-lock. @@ -274,96 +228,25 @@ bundle.aws.lambda = pkgs.callPackage ./src/bundle/lambda.nix { bundleZip = bundl #! access: `zig2nix.outputs.thing.${system}` #! Helper functions for building and running Zig projects. -inherit zig-env zig-hook; - -#! Prints available zig versions -apps.versions = with pkgs; test-app [ coreutils jq ] '' - printf 'git\nmaster\ndefault\n' - jq -r 'delpaths([["master"],["default"],["git"]]) | keys_unsorted | sort_by(split(".") | map(tonumber)) | reverse | .[]' ${./versions.json} -''; - +inherit zig-env; #! Versioned Zig packages. -#! nix build .#zig.master.bin -#! nix build .#zig.master.src -#! nix run .#zig.master.bin -#! nix run .#zig.master.src -packages.zig = zigv; - -#! Default zig package. -#! Latest released binary zig. -packages.default = zigv.default.bin; - -#! zon2json: Converts zon files to json -packages.zon2json = zon2json; - -#! zon2json-lock: Converts build.zig.zon to a build.zig.zon2json lock file -packages.zon2json-lock = default-env.zon2json-lock; - -#! zon2nix: Converts build.zig.zon and build.zig.zon2json-lock to nix deriviation -packages.zon2nix = default-env.zon2nix; - -#! Nixpkgs cross-compiled with zig -cross = env.pkgs.lib.genAttrs env.lib.allTargetTriples (t: env.zigCrossPkgsForTarget t); - -#! Cross-compile nixpkgs with master zig -packages.zigCross = packages.env.master.bin.cross; - -#! Run a version of a Zig compiler -#! nix run .#env."zig-version"."build"."type".zig -#! example: nix run .#env.master.src.bare.zig -#! example: nix run .#env.default.bin.multimedia.zig -zig = env.app-no-root [] ''zig "$@"''; - -#! nix run .#env."zig-version"."build"."type".zon2json-lock -#! example: nix run .#env.master.src.bare.zon2json-lock -#! example: nix run .#env.default.bin.multimedia.zon2json-lock -zon2json-lock = env.app-no-root [ env.zon2json-lock ] ''zon2json-lock "$@"''; - -#! nix run .#env."zig-version"."build"."type".zon2nix -#! example: nix run .#env.master.src.bare.zon2nix -#! example: nix run .#env.default.bin.multimedia.zon2nix -zon2nix = env.app-no-root [ env.zon2nix ] ''zon2nix "$@"''; - -#! Master zig -apps.master = apps.env.master.bin.bare.zig; - -#! Default zig -apps.default = apps.env.default.bin.bare.zig; - -#! Master dev shell -devShells.master = devShells.env.master.bin.bare; - -#! Default dev shell -devShells.default = devShells.env.default.bin.bare; +#! nix build .#zig-master +#! nix build .#zig-latest +#! nix run .#zig-0_13_0 +packages = mapAttrs' (k: v: nameValuePair ("zig-" + k) v) zigv; + +#! Develop shell for building and running Zig projects. +#! nix develop .#zig_version +#! example: nix develop .#master +#! example: nix develop .#default +devShells = flake-outputs.devShells // { + default = flake-outputs.devShells.latest; +}; #! --- Generic flake outputs. #! access: `zig2nix.outputs.thing` -#! Overlay for overriding Zig with specific version (source). -overlays.zig.src = mapAttrs (k: v: (final: prev: { - zig = v.src; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; -})) outputs.packages.${prev.system}.zig; - -#! Overlay for overriding Zig with specific version (binary). -overlays.zig.bin = mapAttrs (k: v: (final: prev: { - zig = v.bin; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; -})) outputs.packages.${prev.system}.zig; - -#! mitchellh/zig-overlay compatible overlay. -overlays.zig-overlay = final: prev: { - zigpkgs = mapAttrs (k: v: v.bin) outputs.packages.${prev.system}.zig; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; -}; - -#! Default overlay -overlays.default = overlays.zig.bin.default; - #! Default project template #! nix flake init -t templates templates.default = rec { diff --git a/tools/fixtures/1.zig.zon b/fixtures/1.zig.zon similarity index 100% rename from tools/fixtures/1.zig.zon rename to fixtures/1.zig.zon diff --git a/tools/fixtures/1.zig.zon2json-lock b/fixtures/1.zig.zon2json-lock similarity index 99% rename from tools/fixtures/1.zig.zon2json-lock rename to fixtures/1.zig.zon2json-lock index 8244f2d..6f683a6 100644 --- a/tools/fixtures/1.zig.zon2json-lock +++ b/fixtures/1.zig.zon2json-lock @@ -4,4 +4,4 @@ "url": "https://github.com/getty-zig/getty/archive/cb007b8ed148510de71ccc52143343b2e11413ff.tar.gz", "hash": "sha256-qALaXveW6cWkR7pPJxOqj7pTpECdXmJvzgq3TI9GPqM=" } -} +} \ No newline at end of file diff --git a/tools/fixtures/2.zig.zon b/fixtures/2.zig.zon similarity index 100% rename from tools/fixtures/2.zig.zon rename to fixtures/2.zig.zon diff --git a/fixtures/2.zig.zon2json-lock b/fixtures/2.zig.zon2json-lock new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/fixtures/2.zig.zon2json-lock @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tools/fixtures/3.zig.zon b/fixtures/3.zig.zon similarity index 100% rename from tools/fixtures/3.zig.zon rename to fixtures/3.zig.zon diff --git a/tools/fixtures/3.zig.zon2json-lock b/fixtures/3.zig.zon2json-lock similarity index 99% rename from tools/fixtures/3.zig.zon2json-lock rename to fixtures/3.zig.zon2json-lock index 1d96f7e..47a4c12 100644 --- a/tools/fixtures/3.zig.zon2json-lock +++ b/fixtures/3.zig.zon2json-lock @@ -5,4 +5,4 @@ "hash": "sha256-YUwb8yfz26Tfz4wyN13MBsdyA40ygJwfxHWt4eFMvQE=", "rev": "e2627e265d940db5ea58dffa63e490375bfc92e5" } -} +} \ No newline at end of file diff --git a/tools/fixtures/example/build.zig.zon b/fixtures/example/build.zig.zon similarity index 100% rename from tools/fixtures/example/build.zig.zon rename to fixtures/example/build.zig.zon diff --git a/tools/fixtures/example/build.zig.zon2json-lock b/fixtures/example/build.zig.zon2json-lock similarity index 99% rename from tools/fixtures/example/build.zig.zon2json-lock rename to fixtures/example/build.zig.zon2json-lock index 7503fd0..9912025 100644 --- a/tools/fixtures/example/build.zig.zon2json-lock +++ b/fixtures/example/build.zig.zon2json-lock @@ -5,4 +5,4 @@ "hash": "sha256-AmqqAZQh/FijlnkKChaqMks5rzGDhHZBW4WbH7tIz/U=", "rev": "db91954e18654eeebc54c900f44c704002e1866d" } -} +} \ No newline at end of file diff --git a/tools/fixtures/libxml2/build.zig.zon b/fixtures/libxml2/build.zig.zon similarity index 100% rename from tools/fixtures/libxml2/build.zig.zon rename to fixtures/libxml2/build.zig.zon diff --git a/flake.lock b/flake.lock index 45ac57d..65c598f 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1741337598, - "narHash": "sha256-dw3gBBVV6o38e5IReRLC3PZdoMql6hOhM9AMXZ5dc5E=", + "lastModified": 1741481966, + "narHash": "sha256-MrMsXesCo5Y79F5qjlybADozu60Zk91jVBi+FnoEiJU=", "owner": "nixos", "repo": "nixpkgs", - "rev": "cee01a7a06c7b3ac6bf0055dd08e10aed275e6ba", + "rev": "5c2eeaafda070b7c357b839f13bb53c1d4334001", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 4dfeb74..5878f43 100644 --- a/flake.nix +++ b/flake.nix @@ -12,48 +12,36 @@ #! Structures. - zig2nix-lib-base = pkgs.callPackage ./src/lib.nix {}; - # Use our own zig hook. # The nixpkgs one forces flags which can't be overridden. # Also -target is recommended over use of -Dcpu=baseline. # https://ziggit.dev/t/exe-files-not-interchangeable-among-identical-linux-systems/2708/6 # I would've reused the setup-hook.sh, but it breaks when cross-compiling. - zig-hook = { makeSetupHook, zig }: makeSetupHook { + zigHook = { makeSetupHook, zig }: makeSetupHook { name = "zig-hook"; propagatedBuildInputs = [ zig ]; substitutions.zig_default_flags = []; passthru = { inherit zig; }; } ./src/setup-hook.sh; - # Zig versions. + # Zig versions # - zigv = with zig2nix-lib-base; pkgs.callPackage ./versions.nix { - zigSystem = zigDoubleFromString system; - zigHook = zig-hook; - }; - - # Converts zon files to json - zon2json = with zig2nix-lib-base; let - target = resolveTargetTriple { target = system; musl = true; }; - in (pkgs.callPackage tools/zon2json/default.nix { zig = zigv.default.bin; }) { - zigBuildFlags = [ "-Dtarget=${target}" ]; + zigv = import ./src/zig/versions.nix { + inherit zigHook; + inherit (pkgs) callPackage; }; - # Converts build.zig.zon to a build.zig.zon2json lock file - zon2json-lock-base = { zig }: pkgs.callPackage tools/zon2json-lock.nix { - inherit zig zon2json; - }; - - # Converts build.zig.zon and build.zig.zon2json-lock to nix deriviation - zon2nix-base = { zon2json-lock }: pkgs.callPackage tools/zon2nix.nix { - inherit zon2json-lock; - }; - - # Tools for bridging zig and nix - zig2nix-lib = { zon2json, zon2nix }: with pkgs; zig2nix-lib-base // { - fromZON = path: fromJSON (readFile (runCommandLocal "fromZON" {} ''${zon2json}/bin/zon2json "${path}" > "$out"'')); - deriveLockFile = path: callPackage (runCommandLocal "deriveLockFile" {} ''${zon2nix}/bin/zon2nix ${path} > $out''); + # zig2nix bridge utility + # always compiled with zig-latest, but passes the correct zig to the PATH of the process + zig2nix-for-version = zig: let + pkg = pkgs.callPackage ./src/zig2nix/default.nix { + zig = zigv.latest; + zigBuildFlags = [ "-Dcpu=baseline" ]; + }; + in pkgs.writeShellApplication { + name = "zig2nix"; + runtimeInputs = [ zig ]; + text = ''${pkg}/bin/zig2nix "$@"''; }; #:! Helper function for building and running Zig projects. @@ -61,26 +49,7 @@ # Overrideable nixpkgs. nixpkgs ? self.inputs.nixpkgs, # Zig version to use. - zig ? zigv.default.bin, - # Additional runtime deps to inject into the helpers. - customRuntimeDeps ? [], - # Additional runtime libs to inject to the helpers. - # Gets included in LD_LIBRARY_PATH and DYLD_LIBRARY_PATH. - customRuntimeLibs ? [], - # Custom prelude in the flake app helper. - customAppHook ? "", - # Custom prelude in the flake shell helper. - customDevShellHook ? "", - # Enable Vulkan support. - enableVulkan ? false, - # Enable OpenGL support. - enableOpenGL ? false, - # Enable Wayland support. - enableWayland ? false, - # Enable X11 support. - enableX11 ? false, - # Enable Alsa support. - enableAlsa ? false, + zig ? zigv.latest, }: with pkgs.lib; let #! --- Outputs of zig-env {} function. #! access: (zig-env {}).thing @@ -89,69 +58,69 @@ pkgs = nixpkgs.outputs.legacyPackages.${system}; #! Tools for bridging zig and nix - zon2json-lock = zon2json-lock-base { inherit zig; }; - zon2nix = zon2nix-base { inherit zon2json-lock; }; - lib = zig2nix-lib { inherit zon2json zon2nix; }; + zig2nix = zig2nix-for-version zig; + + exec = cmd: args: pkgs.runCommandLocal cmd {} ''${zig2nix}/bin/zig2nix ${cmd} ${escapeShellArgs args} > $out''; + exec-path = cmd: path: args: pkgs.runCommandLocal cmd {} ''${zig2nix}/bin/zig2nix ${cmd} ${path} ${escapeShellArgs args} > $out''; + exec-json = cmd: args: fromJSON (readFile (exec cmd args)); + exec-json-path = cmd: path: args: fromJSON (readFile (exec-path cmd path args)); + + #! Translates zig and nix compatible targets + target = system: (exec-json "target" [ system ]); + + #! Reads zon file into a attribute set + fromZON = path: exec-json-path "zon2json" path []; + + #! Creates derivation from zon2json-lock file + deriveLockFile = path: pkgs.callPackage (exec-path "zon2nix" path []); + + # Provides small shell runtime + shell-runtime = pkgs.callPackage ./src/shell.nix { inherit system; }; #! Returns true if target is nix flake compatible. #! - isFlakeTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; - in any (s: (systems.elaborate s).config == (nixTripleFromSystem target-system)) systems.flakeExposed; + isFlakeTarget = any: pkgs.lib.any (s: (systems.elaborate s).config == (target any).config) systems.flakeExposed; #! Returns crossPkgs from nixpkgs for target string or system. #! This will always cross-compile the package. - crossPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; - crossPkgs = import nixpkgs { localSystem = system; crossSystem = { config = nixTripleFromSystem target-system; }; }; - this-system = (systems.elaborate system).config == nixTripleFromSystem target-system; + crossPkgsForTarget = any: let + crossPkgs = import nixpkgs { localSystem = system; crossSystem = { config = (target any).config; }; }; + this-system = (systems.elaborate system).config == (target any).config; in if this-system then pkgs else crossPkgs; #! Returns pkgs from nixpkgs for target string or system. #! This does not cross-compile and you'll get a error if package does not exist in binary cache. - binaryPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; - binaryPkgs = import nixpkgs { localSystem = { config = nixTripleFromSystem target-system; }; }; - this-system = (systems.elaborate system).config == nixTripleFromSystem target-system; + binaryPkgsForTarget = any: let + binaryPkgs = import nixpkgs { localSystem = { config = (target any).config; }; }; + this-system = (systems.elaborate system).config == (target any).config; in if this-system then pkgs else binaryPkgs; #! Returns either binaryPkgs or crossPkgs depending if the target is flake target or not. - pkgsForTarget = args': - if isFlakeTarget args' then binaryPkgsForTarget args' - else crossPkgsForTarget args'; - - # Solving platform specific spaghetti - runtimeForTargetSystem = pkgs.callPackage ./src/runtime.nix { - inherit (lib) mkZigSystemFromString; - inherit pkgsForTarget customAppHook customDevShellHook customRuntimeLibs; - inherit enableVulkan enableOpenGL enableWayland enableX11 enableAlsa; - }; + pkgsForTarget = any: + if isFlakeTarget any then binaryPkgsForTarget any + else crossPkgsForTarget any; # Package a Zig project - zigPackage = target: (crossPkgsForTarget target).callPackage (pkgs.callPackage ./src/package.nix { - inherit zig runtimeForTargetSystem; - inherit (lib) resolveTargetSystem zigTripleFromSystem fromZON deriveLockFile; + zigPackage = any: (crossPkgsForTarget any).callPackage (pkgs.callPackage ./src/package.nix { + inherit zig target fromZON deriveLockFile; }); #! Cross-compile nixpkgs using zig :) #! NOTE: This is an experimental feature, expect it not faring well - zigCrossPkgsForTarget = with lib; args': let - target-system = if isString args' then mkZigSystemFromString args' else args'; + zigCrossPkgsForTarget = any: let crossPkgs = pkgs.callPackage ./src/cross { - inherit zig zigPackage allTargetSystems; - inherit nixTripleFromSystem zigTripleFromSystem; - inherit mkZigSystemFromPlatform mkZigSystemFromString; - nixCrossPkgs = pkgsForTarget target-system; + inherit zig zigPackage target; + nixCrossPkgs = pkgsForTarget any; + nixBinaryPkgs = binaryPkgsForTarget any; localSystem = system; - crossSystem = { config = nixTripleFromSystem target-system; }; + crossSystem = { config = (target any).config; }; }; - in warn "zigCross: ${zigTripleFromSystem target-system}" crossPkgs; + in warn "zigCross: ${(target any).zig}" crossPkgs; - runtime = runtimeForTargetSystem system; - _deps = [ zig ] ++ customRuntimeDeps ++ runtime.build-bins; + _deps = [ zig zig2nix ]; in rec { - inherit lib pkgs pkgsForTarget crossPkgsForTarget zigCrossPkgsForTarget binaryPkgsForTarget; - inherit zig zon2json zon2json-lock zon2nix zig-hook; + inherit pkgs pkgsForTarget crossPkgsForTarget zigCrossPkgsForTarget binaryPkgsForTarget; + inherit zig zig2nix target fromZON deriveLockFile; #! Flake app helper (Without zig-env and root dir restriction). app-bare-no-root = deps: script: { @@ -175,13 +144,13 @@ #! Flake app helper (without root dir restriction). app-no-root = deps: script: app-bare-no-root (deps ++ _deps) '' - ${runtime.app} + ${shell-runtime deps} ${script} ''; #! Flake app helper. app = deps: script: app-bare (deps ++ _deps) '' - ${runtime.app} + ${shell-runtime deps} ${script} ''; @@ -192,7 +161,7 @@ } @attrs: pkgs.mkShellNoCC (attrs // { nativeBuildInputs = optionals (attrs ? nativeBuildInputs) attrs.nativeBuildInputs ++ _deps; shellHook = '' - ${runtime.shell} + ${shell-runtime nativeBuildInputs} ${attrs.shellHook or ""} ''; })); @@ -209,11 +178,9 @@ #! #! Additional attributes: #! zigTarget: Specify target for zig compiler, defaults to stdenv.targetPlatform of given target. - #! zigInheritStdenv: - #! By default if zigTarget is specified, nixpkgs stdenv compatible environment is not used. - #! Set this to true, if you want to specify zigTarget, but still use the derived stdenv compatible environment. #! zigPreferMusl: Prefer musl libc without specifying the target. - #! zigDisableWrap: makeWrapper will not be used. Might be useful if distributing outside nix. + #! zigWrapperBins: Binaries available to the binary during runtime (PATH) + #! zigWrapperLibs: Libraries available to the binary during runtime (LD_LIBRARY_PATH) #! zigWrapperArgs: Additional arguments to makeWrapper. #! zigBuildZon: Path to build.zig.zon file, defaults to build.zig.zon. #! zigBuildZonLock: Path to build.zig.zon2json-lock file, defaults to build.zig.zon2json-lock. @@ -228,364 +195,200 @@ bundle.aws.lambda = pkgs.callPackage ./src/bundle/lambda.nix { bundleZip = bundle.zip; }; }; - # Default zig env used for tests and automation. - default-env = zig-env { zig = zigv.default.bin; }; - test-env = zig-env { zig = zigv.master.bin; }; + test-env = zig-env { zig = zigv.master; }; test-app = test-env.app-bare; - # For the convenience flake outputs - multimedia-attrs = { - enableX11 = true; - enableWayland = true; - enableVulkan = true; - enableOpenGL = true; - enableAlsa = true; - }; - in rec { - # TODO: Convert this to the standard flake format - # Currently this uses invalid flake format - # See: nix flake check --help + test = removeAttrs (pkgs.callPackage src/test.nix { + inherit test-app; + inherit (test-env) zig zig2nix target deriveLockFile; + zig-env = test-env; + }) [ "override" "overrideDerivation" "overrideAttrs" ]; + flake-outputs = pkgs.callPackage (import ./src/zig/outputs.nix) { + inherit zigv zig-env; + }; + in with pkgs.lib; { #! --- Architecture dependent flake outputs. #! access: `zig2nix.outputs.thing.${system}` #! Helper functions for building and running Zig projects. - inherit zig-env zig-hook; - - #! Prints available zig versions - apps.versions = with pkgs; test-app [ coreutils jq ] '' - printf 'git\nmaster\ndefault\n' - jq -r 'delpaths([["master"],["default"],["git"]]) | keys_unsorted | sort_by(split(".") | map(tonumber)) | reverse | .[]' ${./versions.json} - ''; + inherit zig-env; #! Versioned Zig packages. - #! nix build .#zig.master.bin - #! nix build .#zig.master.src - #! nix run .#zig.master.bin - #! nix run .#zig.master.src - packages.zig = zigv; - - #! Default zig package. - #! Latest released binary zig. - packages.default = zigv.default.bin; - - #! zon2json: Converts zon files to json - packages.zon2json = zon2json; - - #! zon2json-lock: Converts build.zig.zon to a build.zig.zon2json lock file - packages.zon2json-lock = default-env.zon2json-lock; - - #! zon2nix: Converts build.zig.zon and build.zig.zon2json-lock to nix deriviation - packages.zon2nix = default-env.zon2nix; - - # Generate flake packages for all the zig versions. - packages.env = mapAttrs (k: v: let - pkgs-for = zig: let - env = zig-env { inherit zig; }; - in { - #! Nixpkgs cross-compiled with zig - cross = env.pkgs.lib.genAttrs env.lib.allTargetTriples (t: env.zigCrossPkgsForTarget t); - }; - in { - bin = pkgs-for v.bin; - src = pkgs-for v.src; - } - ) zigv; - - #! Cross-compile nixpkgs with master zig - packages.zigCross = packages.env.master.bin.cross; + #! nix build .#zig-master + #! nix build .#zig-latest + #! nix run .#zig-0_13_0 + packages = mapAttrs' (k: v: nameValuePair ("zig-" + k) v) zigv; # Generates flake apps for all the zig versions. - apps.env = mapAttrs (k: v: let - apps-for = zig: let - apps-for = attrs: let - env = zig-env ({ inherit zig; } // attrs); - in { - #! Run a version of a Zig compiler - #! nix run .#env."zig-version"."build"."type".zig - #! example: nix run .#env.master.src.bare.zig - #! example: nix run .#env.default.bin.multimedia.zig - zig = env.app-no-root [] ''zig "$@"''; - - #! nix run .#env."zig-version"."build"."type".zon2json-lock - #! example: nix run .#env.master.src.bare.zon2json-lock - #! example: nix run .#env.default.bin.multimedia.zon2json-lock - zon2json-lock = env.app-no-root [ env.zon2json-lock ] ''zon2json-lock "$@"''; - - #! nix run .#env."zig-version"."build"."type".zon2nix - #! example: nix run .#env.master.src.bare.zon2nix - #! example: nix run .#env.default.bin.multimedia.zon2nix - zon2nix = env.app-no-root [ env.zon2nix ] ''zon2nix "$@"''; - }; - in { - # Minimal environment - bare = apps-for {}; - # Environment for running multimedia programs - multimedia = apps-for multimedia-attrs; - }; - in { - bin = apps-for v.bin; - src = apps-for v.src; - } - ) zigv; - - #! Master zig - apps.master = apps.env.master.bin.bare.zig; - - #! Default zig - apps.default = apps.env.default.bin.bare.zig; - - # Develop shell for building and running Zig projects. - # nix develop .#env."zig-version"."build"."type" - # example: nix develop .#env.master.src.bare - # example: nix develop .#env.default.bin.multimedia - devShells.env = mapAttrs (k: v: let - shells-for = zig: let - shells-for = attrs: let - env = zig-env ({ inherit zig; } // attrs); - in env.mkShell {}; - in { - # Minimal environment - bare = shells-for {}; - # Environment for running multimedia programs - multimedia = shells-for multimedia-attrs; - }; - in { - bin = shells-for v.bin; - src = shells-for v.src; - } - ) zigv; - - #! Master dev shell - devShells.master = devShells.env.master.bin.bare; - - #! Default dev shell - devShells.default = devShells.env.default.bin.bare; - - # nix run .#update-versions - apps.update-versions = with pkgs; test-app [ curl jq coreutils ] '' - tmpdir="$(mktemp -d)" - trap 'rm -rf "$tmpdir"' EXIT - read -r rev _ < <(git ls-remote https://github.com/ziglang/zig.git HEAD) - url="https://github.com/ziglang/zig/archive/$rev.tar.gz" - curl -sSL "$url" -o "$tmpdir/git.tar.gz" - read -r size _ < <(wc -c "$tmpdir/git.tar.gz") - date="$(date +"%Y-%m-%d")" - cat < "$tmpdir/git.json" - { - "git": { - "version": "git+''${rev:0:7}+$date", - "date": "$date", - "docs": "https://ziglang.org/documentation/master/", - "stdDocs": "https://ziglang.org/documentation/master/std/", - "src": { - "tarball": "$url", - "shasum": "$(nix hash file --type sha256 --base16 "$tmpdir/git.tar.gz")", - "size": "$size" - } - } - } - EOF - curl -sSL https://ziglang.org/download/index.json |\ - jq 'with_entries(select(.key != "0.1.1" and .key != "0.2.0" and .key != "0.3.0" and .key != "0.4.0" and .key != "0.5.0" and .key != "0.6.0" and .key != "0.7.0" and .key != "0.7.1"))' > "$tmpdir"/versions.json - jq 'to_entries | {"default": ({"version": .[1].key} + .[1].value)}' "$tmpdir/versions.json" | cat "$tmpdir/git.json" - "$tmpdir/versions.json" | jq -s add + apps = flake-outputs.apps // { + default = flake-outputs.apps.zig2nix-latest; + + # Backwards compatibility + zon2json = flake-outputs.apps.zon2json-latest; + zon2json-lock = flake-outputs.apps.zon2json-lock-latest; + zon2nix = flake-outputs.apps.zon2nix-latest; + + # nix run .#update-versions + update-versions = test-app [ test-env.zig2nix ] '' + tmp="$(mktemp)" + trap 'rm -f "$tmp"' EXIT + zig2nix versions "$@" > "$tmp" + cp -f "$tmp" src/zig/versions.nix ''; - # nix run .#update-templates - apps.update-templates = with pkgs; test-app [ coreutils gnused ] '' - rm -rf templates/default - mkdir -p templates/default - sed 's#/[*]SED_ZIG_VER[*]/##' templates/flake.nix > templates/default/flake.nix - sed -i 's#@SED_ZIG_BIN@#default#' templates/default/flake.nix - cp -f templates/gitignore templates/default/.gitignore - cp -f .gitattributes templates/default/.gitattributes - (cd templates/default; ${packages.zig.default.bin}/bin/zig init) - - rm -rf templates/master - mkdir -p templates/master - # shellcheck disable=SC2016 - sed 's#/[*]SED_ZIG_VER[*]/# zig = zig2nix.outputs.packages.''${system}.zig.master.bin; #' templates/flake.nix > templates/master/flake.nix - sed -i 's#@SED_ZIG_BIN@#master#' templates/master/flake.nix - cp -f templates/gitignore templates/master/.gitignore - cp -f .gitattributes templates/master/.gitattributes - (cd templates/master; ${packages.zig.master.bin}/bin/zig init) - ''; - - apps.test = pkgs.callPackage src/test.nix { - inherit test-app; - inherit (test-env.lib) deriveLockFile resolveTargetSystem zigTripleFromSystem nixTripleFromSystem allFlakeTargetTriples; - inherit (test-env) zig zon2json-lock; - zig-env = test-env; - }; - - # nix run .#readme - apps.readme = let - project = "zig2nix flake"; - in with pkgs; test-app [ gawk gnused jq ] (replaceStrings ["`"] ["\\`"] '' - cat < templates/default/flake.nix + sed -i 's#@SED_ZIG_BIN@#default#' templates/default/flake.nix + cp -f templates/gitignore templates/default/.gitignore + cp -f .gitattributes templates/default/.gitattributes + (cd templates/default; ${zigv.latest}/bin/zig init) + (cd templates/default; nix flake check --override-input zig2nix ../..) + + rm -rf templates/master + mkdir -p templates/master + # shellcheck disable=SC2016 + sed 's#/[*]SED_ZIG_VER[*]/# zig = zig2nix.outputs.packages.''${system}.zig-master; #' templates/flake.nix > templates/master/flake.nix + sed -i 's#@SED_ZIG_BIN@#master#' templates/master/flake.nix + cp -f templates/gitignore templates/master/.gitignore + cp -f .gitattributes templates/master/.gitattributes + (cd templates/master; ${zigv.master}/bin/zig init) + (cd templates/master; nix flake check --override-input zig2nix ../..) + ''; - * Zig git: `${zigv.git.src.version} @ ${zigv.git.src.date}` - * Zig master: `${zigv.master.bin.version} @ ${zigv.master.bin.date}` - * Zig default: `${zigv.default.bin.version} @ ${zigv.default.bin.date}` + # nix run .#readme + readme = let + project = "zig2nix flake"; + in with pkgs; test-app [ gawk gnused ] (replaceStrings ["`"] ["\\`"] '' + cat < This sets (DY)LD_LIBRARY_PATH and PKG_CONFIG_PATH so that common libs are available + ```bash + nix flake init -t github:Cloudef/zig2nix#master + nix run . + # for more options check the flake.nix file + ``` - ```bash - nix run github:Cloudef/zig2nix#env.master.bin.multimedia.zig -- version - nix run github:Cloudef/zig2nix#env.default.bin.multimedia.zig -- version - ``` + ### Build zig from source - ### Shell for building and running a Zig project + ```bash + nix build github:Cloudef/zig2nix#zig-src-master + nix build github:Cloudef/zig2nix#zig-src-latest + nix build github:Cloudef/zig2nix#zig-src-0_8_0 + ``` - ```bash - nix develop github:Cloudef/zig2nix#env.master.bin.bare - nix develop github:Cloudef/zig2nix#env.default.bin.bare - # Or simply these aliases - nix develop github:Cloudef/zig2nix#master - nix develop github:Cloudef/zig2nix - ``` + ### Running zig compiler directly - #### Convenience shell for multimedia programs + ```bash + nix run github:Cloudef/zig2nix#master -- version + nix run github:Cloudef/zig2nix#latest -- version + nix run github:Cloudef/zig2nix#0_8_0 -- version + ``` - > This sets (DY)LD_LIBRARY_PATH and PKG_CONFIG_PATH so that common libs are available + #### Convenience zig for multimedia programs - ```bash - nix develop github:Cloudef/zig2nix#env.master.bin.multimedia - nix develop github:Cloudef/zig2nix#env.default.bin.multimedia - ``` + > This sets (DY)LD_LIBRARY_PATH and PKG_CONFIG_PATH so that common libs are available - ### Convert zon file to json + ```bash + nix run github:Cloudef/zig2nix#multimedia-master -- version + nix run github:Cloudef/zig2nix#multimedia-latest -- version + nix run github:Cloudef/zig2nix#multimedia-0_8_0 -- version + ``` - ```bash - nix run github:Cloudef/zig2nix#zon2json -- build.zig.zon - ``` + ### Shell for building and running a Zig project - ### Convert build.zig.zon to a build.zig.zon2json-lock + ```bash + nix develop github:Cloudef/zig2nix#master + nix develop github:Cloudef/zig2nix#latest + nix develop github:Cloudef/zig2nix#0_8_0 + ``` - ```bash - nix run github:Cloudef/zig2nix#zon2json-lock -- build.zig.zon - # alternatively output to stdout - nix run github:Cloudef/zig2nix#zon2json-lock -- build.zig.zon - - ``` + ### Convert zon file to json - ### Convert build.zig.zon/2json-lock to a nix derivation + ```bash + nix run github:Cloudef/zig2nix -- zon2json build.zig.zon + ``` - ```bash - # calls zon2json-lock if build.zig.zon2json-lock does not exist (requires network access) - nix run github:Cloudef/zig2nix#zon2nix -- build.zig.zon - # alternatively run against the lock file (no network access required) - nix run github:Cloudef/zig2nix#zon2nix -- build.zig.zon2json-lock - ``` + ### Convert build.zig.zon to a build.zig.zon2json-lock - ### Cross-compile nixpkgs using zig + ```bash + nix run github:Cloudef/zig2nix -- zon2lock build.zig.zon + ``` - > This is very experimental, and many things may not compile. + ### Convert build.zig.zon/2json-lock to a nix derivation - ```bash - nix build github:Cloudef/zig2nix#env.master.bin.cross.x86_64-windows-gnu.zlib - nix build github:Cloudef/zig2nix#env.default.bin.cross.x86_64-windows-gnu.zlib - # Or simply this alias that uses env.master.bin - nix build github:Cloudef/zig2nix#zigCross.x86_64-windows-gnu.zlib - ``` + ```bash + # calls zon2json-lock if build.zig.zon2json-lock does not exist (requires network access) + nix run github:Cloudef/zig2nix -- zon2nix build.zig.zon + # alternatively run against the lock file (no network access required) + nix run github:Cloudef/zig2nix -- zon2nix build.zig.zon2json-lock + ``` - ## Crude documentation + ## Crude documentation - Below is auto-generated dump of important outputs in this flake. + Below is auto-generated dump of important outputs in this flake. - ```nix - $(awk -f doc.awk flake.nix | sed "s/```/---/g") - ``` - EOF - ''); + ```nix + $(awk -f doc.awk flake.nix | sed "s/```/---/g") + ``` + EOF + ''); + } // mapAttrs' (name: value: nameValuePair ("test-" + name) value) test; + + #! Develop shell for building and running Zig projects. + #! nix develop .#zig_version + #! example: nix develop .#master + #! example: nix develop .#default + devShells = flake-outputs.devShells // { + default = flake-outputs.devShells.latest; + }; })); - welcome-template = description: '' - # ${description} - - Zig: https://ziglang.org/ + welcome-template = description: '' + # ${description} + - Zig: https://ziglang.org/ + + ## Build & Run - ## Build & Run + ``` + nix run . + ``` - ``` - nix run . - ``` + See flake.nix for more options. + ''; - See flake.nix for more options. - ''; - in outputs // rec { + in outputs // { #! --- Generic flake outputs. #! access: `zig2nix.outputs.thing` - #! Overlay for overriding Zig with specific version (source). - overlays.zig.src = mapAttrs (k: v: (final: prev: { - zig = v.src; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; - })) outputs.packages.${prev.system}.zig; - - #! Overlay for overriding Zig with specific version (binary). - overlays.zig.bin = mapAttrs (k: v: (final: prev: { - zig = v.bin; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; - })) outputs.packages.${prev.system}.zig; - - #! mitchellh/zig-overlay compatible overlay. - overlays.zig-overlay = final: prev: { - zigpkgs = mapAttrs (k: v: v.bin) outputs.packages.${prev.system}.zig; - # TODO: fix these to be for correct zig version - inherit (outputs.packages) zon2json zon2json-lock zon2nix; - }; - - #! Default overlay - overlays.default = overlays.zig.bin.default; - #! Default project template #! nix flake init -t templates templates.default = rec { diff --git a/src/bundle/loader/src/runtime.zig b/src/bundle/loader/src/runtime.zig index b63ebd5..3ec88fe 100644 --- a/src/bundle/loader/src/runtime.zig +++ b/src/bundle/loader/src/runtime.zig @@ -122,12 +122,14 @@ const SonameIterator = struct { }; while (self.iter.next()) |soname| { - var split = std.mem.splitScalar(u8, soname, '.'); - const base = split.first(); - - if (std.mem.count(u8, base, "ld-linux-") > 0) { + const trimmed = D: { + for (soname, 0..) |c, idx| if (std.ascii.isPrint(c)) break :D soname[idx..]; continue; - } + }; + if (trimmed.len > 0 and trimmed[0] == '/') continue; + + var split = std.mem.splitScalar(u8, trimmed, '.'); + const base = split.first(); const is_ignored = blk: { inline for (ignored) |ignore| { @@ -140,7 +142,7 @@ const SonameIterator = struct { continue; } - return if (as_base) base else soname; + return if (as_base) base else trimmed; } return null; @@ -200,8 +202,8 @@ fn setupLinux(allocator: std.mem.Allocator, bin: []const u8) !std.process.EnvMap // NixOS, Guix and GoboLinux are to my knowledge the only non-FHS Linux distros // However GoboLinux apparently has FHS compatibility, so it probably works OOB? switch (detectDistro(allocator)) { - .nixos => { - log.info("setting up a {s} runtime ...", .{@tagName(.nixos)}); + .nixos => |tag| { + log.info("setting up a {s} runtime ...", .{@tagName(tag)}); // packages that match a soname don't have to be included // this list only includes common libs for doing multimedia stuff on linux @@ -288,8 +290,8 @@ fn setupLinux(allocator: std.mem.Allocator, bin: []const u8) !std.process.EnvMap } } }, - .guix => { - log.info("setting up a {s} runtime ...", .{@tagName(.guix)}); + .guix => |tag| { + log.info("setting up a {s} runtime ...", .{@tagName(tag)}); // I'm not sure if this is okay, but guix seems to not be so opposed to global env like nix is // And this path at least in guix live cd has mostly everything neccessary diff --git a/src/bundle/zip.nix b/src/bundle/zip.nix index fda0145..ce754ec 100644 --- a/src/bundle/zip.nix +++ b/src/bundle/zip.nix @@ -85,13 +85,13 @@ in stdenvNoCC.mkDerivation (userAttrs // { nativeBuildInputs = [ zip ]; phases = [ "installPhase" ]; installPhase = '' - '' + optionalString (useLoader) '' + '' + optionalString useLoader '' cp -f ${loader}/bin/loader ${zipEntrypoint} '' + optionalString (!useLoader && (!packageAsRoot || tightly-packed)) '' ln -s ${entrypoint} ${zipEntrypoint} '' + optionalString (!useLoader && (packageAsRoot && !tightly-packed)) '' ln -s ./${removePrefix "${toString package}/" entrypoint} ${zipEntrypoint} - '' + optionalString (tightly-packed) '' + '' + optionalString tightly-packed '' zip -9 $out ${zipEntrypoint} '' + optionalString (!tightly-packed && !packageAsRoot) '' zip -9 --symlinks $out ${zipEntrypoint} diff --git a/src/cross/default.nix b/src/cross/default.nix index 11b2540..c64da41 100644 --- a/src/cross/default.nix +++ b/src/cross/default.nix @@ -1,31 +1,66 @@ { lib , path - , callPackage , localSystem , crossSystem , zig , zigPackage - , allTargetSystems - , nixTripleFromSystem - , zigTripleFromSystem - , mkZigSystemFromPlatform - , mkZigSystemFromString , nixCrossPkgs + , nixBinaryPkgs + , target + , writeText + , callPackage }: with builtins; with lib; -warn "toolchain: ${crossSystem.config}" +let + mkToolchain = callPackage ./toolchain.nix { + inherit zig zigPackage target; + }; + +in warn "toolchain: ${crossSystem.config}" import path { inherit localSystem crossSystem; - stdenvStages = callPackage ./stdenv.nix { - mkZigToolchain = callPackage ./toolchain.nix { - inherit zig zigPackage allTargetSystems; - inherit nixTripleFromSystem zigTripleFromSystem; - inherit mkZigSystemFromPlatform mkZigSystemFromString; - }; + stdenvStages = callPackage (import ./stdenv.nix) {}; + + config = { + replaceCrossStdenv = { buildPackages, baseStdenv }: baseStdenv.override (old: { + buildPlatform = old.buildPlatform // { + # Override nixpkgs's canExecute + # This is to prevent nixpkgs trying to execute x86 binaries on x86_64 for example + # We don't provide libc through nix, so there is no loader + canExecute = other: other.config == old.buildPlatform.config; + }; + + allowedRequisites = null; + cc = nixCrossPkgs.callPackage mkToolchain {}; + + preHook = let + libc = nixBinaryPkgs.stdenv.cc.libc; + builtin_libc = (target old.targetPlatform.config).libc; + libc-file = writeText "libc.txt" '' + include_dir=${getDev libc}/include + sys_include_dir=${getDev libc}/include + crt_dir=${getLib libc}/lib + msvc_lib_dir= + kernel32_lib_dir= + gcc_dir= + ''; + in '' + ${old.preHook} + export NIX_CC_USE_RESPONSE_FILE=0 + '' + optionalString (!builtin_libc) '' + export ZIG_LIBC=${libc-file} + ''; + + extraBuildInputs = []; + extraNativeBuildInputs = with buildPackages; old.extraNativeBuildInputs + # without proper `file` command, libtool sometimes fails + # to recognize 64-bit DLLs + ++ optional (hostPlatform.config == "x86_64-w64-mingw32") file; + }); }; overlays = [(self: super: { diff --git a/src/cross/stdenv.nix b/src/cross/stdenv.nix index 2b53084..1a55187 100644 --- a/src/cross/stdenv.nix +++ b/src/cross/stdenv.nix @@ -1,95 +1,149 @@ { - path - , mkZigToolchain + path, }: { - lib - , localSystem - , crossSystem - , config - , overlays - , crossOverlays ? [] + lib, + localSystem, + crossSystem, + config, + overlays, + crossOverlays ? [ ], }: -with builtins; -with lib; - let - prehook = prelude: '' - ${prelude} - export NIX_CC_USE_RESPONSE_FILE=0 - ''; - bootStages = import "${path}/pkgs/stdenv" { inherit lib localSystem overlays; crossSystem = localSystem; - crossOverlays = []; - # Ignore custom stdenvs when cross compiling for compatability - config = removeAttrs config [ "replaceStdenv" ]; + crossOverlays = [ ]; + + # Ignore custom stdenvs when cross compiling for compatibility + # Use replaceCrossStdenv instead. + config = builtins.removeAttrs config [ "replaceStdenv" ]; }; -in init bootStages ++ [ - (somePrevStage: last bootStages somePrevStage // { allowCustomOverrides = true; }) +in +lib.init bootStages +++ [ + + # Regular native packages + ( + somePrevStage: + lib.last bootStages somePrevStage + // { + # It's OK to change the built-time dependencies + allowCustomOverrides = true; + } + ) - # First replace native compiler with zig - # This gives us more deterministic environment - (vanillaPackages: warn "local: ${localSystem.config}" { + # Build tool Packages + (vanillaPackages: { inherit config overlays; selfBuild = false; - stdenv = (vanillaPackages.stdenv.override (old: { - targetPlatform = crossSystem; - allowedRequisites = null; - hasCC = true; - cc = vanillaPackages.callPackage mkZigToolchain { - inherit (old.cc) libc; + stdenv = + assert vanillaPackages.stdenv.buildPlatform == localSystem; + assert vanillaPackages.stdenv.hostPlatform == localSystem; + assert vanillaPackages.stdenv.targetPlatform == localSystem; + vanillaPackages.stdenv.override { + targetPlatform = crossSystem; + overrides = self: super: ( + removeAttrs vanillaPackages [ + "stdenv" "callPackage" "newScope" "pkgs" "system" "wrapBintools" "wrapCC" + "buildPlatform" "hostPlatform" "targetPlatform" "gccWithoutTargetLibc" + ] + ); }; - preHook = prehook old.preHook; - # Propagate everything to the next step as we do not need to bootstrap - # We exclude packages that would break nixpkgs cross-compiling setup - overrides = self: super: genAttrs (filter (a: ! any (b: hasPrefix b a) [ - "callPackage" "newScope" "pkgs" "stdenv" "system" "wrapBintools" "wrapCC" - ]) (attrNames vanillaPackages)) (x: vanillaPackages."${x}"); - })); # It's OK to change the built-time dependencies allowCustomOverrides = true; }) - # Then use zig as a cross-compiler as well - (buildPackages: let - adaptStdenv = if crossSystem.isStatic then buildPackages.stdenvAdapters.makeStatic else id; - in { - inherit config; - overlays = overlays ++ crossOverlays; - selfBuild = false; - stdenv = adaptStdenv (buildPackages.stdenv.override (old: rec { - buildPlatform = localSystem // { - # Override nixpkgs's canExecute - # This is to prevent nixpkgs trying to execute x86 binaries on x86_64 for example - # We don't provide libc through nix, so there is no loader - canExecute = other: other.config == localSystem.config; - }; - hostPlatform = crossSystem; - targetPlatform = crossSystem; + # Run Packages + ( + buildPackages: + let + adaptStdenv = if crossSystem.isStatic then buildPackages.stdenvAdapters.makeStatic else lib.id; + stdenvNoCC = adaptStdenv ( + buildPackages.stdenv.override (old: rec { + buildPlatform = localSystem; + hostPlatform = crossSystem; + targetPlatform = crossSystem; - # Prior overrides are surely not valid as packages built with this run on - # a different platform, and so are disabled. - overrides = _: _: {}; - allowedRequisites = null; - hasCC = true; - cc = buildPackages.callPackage mkZigToolchain { - inherit (old.cc) libc; - }; - preHook = prehook old.preHook; + # Prior overrides are surely not valid as packages built with this run on + # a different platform, and so are disabled. + overrides = _: _: { }; + extraBuildInputs = [ ]; # Old ones run on wrong platform + allowedRequisites = null; + + cc = null; + hasCC = false; + + extraNativeBuildInputs = + old.extraNativeBuildInputs + ++ lib.optionals (hostPlatform.isLinux && !buildPlatform.isLinux) [ buildPackages.patchelf ] + ++ lib.optional ( + let + f = + p: + !p.isx86 + || builtins.elem p.libc [ + "musl" + "wasilibc" + "relibc" + ] + || p.isiOS + || p.isGenode; + in + f hostPlatform && !(f buildPlatform) + ) buildPackages.updateAutotoolsGnuConfigScriptsHook; + }) + ); + in + { + inherit config; + overlays = overlays ++ crossOverlays; + selfBuild = false; + inherit stdenvNoCC; + stdenv = + let + inherit (stdenvNoCC) hostPlatform targetPlatform; + baseStdenv = stdenvNoCC.override { + # Old ones run on wrong platform + extraBuildInputs = lib.optionals hostPlatform.isDarwin [ + buildPackages.targetPackages.apple-sdk + ]; + + hasCC = !stdenvNoCC.targetPlatform.isGhcjs; + + cc = + if crossSystem.useiOSPrebuilt or false then + buildPackages.darwin.iosSdkPkgs.clang + else if crossSystem.useAndroidPrebuilt or false then + buildPackages."androidndkPkgs_${crossSystem.androidNdkVersion}".clang + else if + targetPlatform.isGhcjs + # Need to use `throw` so tryEval for splicing works, ugh. Using + # `null` or skipping the attribute would cause an eval failure + # `tryEval` wouldn't catch, wrecking accessing previous stages + # when there is a C compiler and everything should be fine. + then + throw "no C compiler provided for this platform" + else if crossSystem.isDarwin then + buildPackages.llvmPackages.libcxxClang + else if crossSystem.useLLVM or false then + buildPackages.llvmPackages.clang + else if crossSystem.useZig or false then + buildPackages.zig.cc + else if crossSystem.useArocc or false then + buildPackages.arocc + else + buildPackages.gcc; + + }; + in + if config ? replaceCrossStdenv then + config.replaceCrossStdenv { inherit buildPackages baseStdenv; } + else + baseStdenv; + } + ) - extraNativeBuildInputs = with buildPackages; old.extraNativeBuildInputs - ++ optionals (hostPlatform.isLinux && !buildPlatform.isLinux) [ patchelf ] - ++ optional - (let f = p: !p.isx86 || elem p.libc [ "musl" "wasilibc" "relibc" ] || p.isiOS || p.isGenode; - in f hostPlatform && !(f buildPlatform)) - updateAutotoolsGnuConfigScriptsHook - # without proper `file` command, libtool sometimes fails - # to recognize 64-bit DLLs - ++ optional (hostPlatform.config == "x86_64-w64-mingw32") file; - })); - }) ] diff --git a/src/cross/toolchain.nix b/src/cross/toolchain.nix index 8e9ea75..3b83721 100644 --- a/src/cross/toolchain.nix +++ b/src/cross/toolchain.nix @@ -8,12 +8,10 @@ , llvm , zig , zigPackage - , allTargetSystems - , nixTripleFromSystem - , zigTripleFromSystem - , mkZigSystemFromPlatform - , mkZigSystemFromString - , buildPlatform + , target + , wrapCCWith + , wrapBintoolsWith + , stdenv }: with lib; @@ -48,26 +46,26 @@ let # -Wl,-arch, -march, -mcpu, -mtune are not compatible # https://github.com/ziglang/zig/issues/4911 # this does not matter as -target encodes the needed information anyways - zigcc = target: let - support = zigPackage target { + zigcc = any: let + support = zigPackage any { name = "support"; src = cleanSource ./support; }; - pp_args = [ "-target" ''${target}'' ]; + pp_args = [ "-target" ''${any}'' ]; - system = mkZigSystemFromString target; + os = (target any).os; # Does not support the -c compiler flag - multiple-objects-supported = system.zig.kernel != "windows" && system.kernel.name != "darwin"; + multiple-objects-supported = os != "windows" && os != "darwin"; - libname = lib: if system.zig.kernel == "windows" then "${lib}.lib" else "lib${lib}.a"; + libname = lib: if os == "windows" then "${lib}.lib" else "lib${lib}.a"; # Has to be separate as these will be treated as inputs otherwise ... cc_args = [ # Symbol versioning hell ... "-Wl,--undefined-version" - ] ++ optionals (multiple-objects-supported) [ + ] ++ optionals multiple-objects-supported [ # Provides arc4random family functions # This is quite unfortunate, but zig ships recent glibc headers, but links against older glibc stubs # Thus compile fails as autotools detects we don't have arc4random but it's in the glibc headers @@ -75,7 +73,6 @@ let # https://github.com/spdk/spdk/issues/2637 "${support}/lib/${libname "arc4random"}" ]; - in cmd: writeShellApplication { name = "zig${cmd}"; runtimeInputs = [ zigtool ]; @@ -115,12 +112,18 @@ let shift;shift;; --target=*) shift;; + -B/nix*|-L/nix*) + shift;; -march=*|-mcpu=*|-mtune=*) shift;; -flto-partition=*) shift;; -static-libgcc) shift;; + --gcc-toolchain=*) + shift;; + -fstack-clash-protection) + shift;; ${concatStringsSep "|" sys_excluded}) shift;; -o) @@ -194,51 +197,38 @@ let text = ''exec zigtool ${cmd} "$@"''; }; - tools-for-target = t: let - local = zigTripleFromSystem (mkZigSystemFromPlatform buildPlatform); - z = t.z or local; - p = if t != null then "${t.n}-" else ""; - in '' - ln -sf ${llvm}/bin/llvm-install-name-tool $out/bin/${p}install_name_tool - ln -sf ${llvm}/bin/llvm-as $out/bin/${p}as - ln -sf ${llvm}/bin/llvm-dwp $out/bin/${p}dwp - ln -sf ${llvm}/bin/llvm-nm $out/bin/${p}nm - ln -sf ${llvm}/bin/llvm-objdump $out/bin/${p}objdump - ln -sf ${llvm}/bin/llvm-readelf $out/bin/${p}readelf - ln -sf ${llvm}/bin/llvm-size $out/bin/${p}size - ln -sf ${llvm}/bin/llvm-strip $out/bin/${p}strip - ln -sf ${zigcmd "ar"}/bin/ar $out/bin/${p}ar - ln -sf ${zigcmd "ranlib"}/bin/ranlib $out/bin/${p}ranlib - ln -sf ${zigcmd "dlltool"}/bin/dlltool $out/bin/${p}dlltool - ln -sf ${zigcmd "lib"}/bin/lib $out/bin/${p}lib - ln -sf ${zigcmd "objcopy"}/bin/objcopy $out/bin/${p}objcopy - ln -sf ${zigrc}/bin/zigrc $out/bin/${p}rc - ln -sf $out/bin/${p}rc $out/bin/${p}windres - ln -sf ${zigcc z "cc"}/bin/zigcc $out/bin/${p}clang - ln -sf ${zigcc z "c++"}/bin/zigc++ $out/bin/${p}clang++ - ln -sf $out/bin/${p}clang $out/bin/${p}gcc - ln -sf $out/bin/${p}clang++ $out/bin/${p}g++ - ln -sf $out/bin/${p}clang $out/bin/${p}cc - ln -sf $out/bin/${p}clang++ $out/bin/${p}c++ - ln -sf ${zigld}/bin/zigld $out/bin/${p}ld - ''; - - toolchain-universal = let - triples = map (s: { z = zigTripleFromSystem s; n = nixTripleFromSystem s; }) allTargetSystems; - in runCommandLocal "zig-toolchain-universal" {} '' + tools-for-target = any: let + z = (target any).zig; + in runCommandLocal "zig-toolchain-${(target any).config}-symlinks" {} '' mkdir -p "$out/bin" - ${concatStringsSep "\n" (map tools-for-target triples)} + ln -sf ${llvm}/bin/llvm-install-name-tool $out/bin/install_name_tool + ln -sf ${llvm}/bin/llvm-as $out/bin/as + ln -sf ${llvm}/bin/llvm-dwp $out/bin/dwp + ln -sf ${llvm}/bin/llvm-nm $out/bin/nm + ln -sf ${llvm}/bin/llvm-objdump $out/bin/objdump + ln -sf ${llvm}/bin/llvm-readelf $out/bin/readelf + ln -sf ${llvm}/bin/llvm-size $out/bin/size + ln -sf ${llvm}/bin/llvm-strip $out/bin/strip + ln -sf ${zigcmd "ar"}/bin/ar $out/bin/ar + ln -sf ${zigcmd "ranlib"}/bin/ranlib $out/bin/ranlib + ln -sf ${zigcmd "dlltool"}/bin/dlltool $out/bin/dlltool + ln -sf ${zigcmd "lib"}/bin/lib $out/bin/lib + ln -sf ${zigcmd "objcopy"}/bin/objcopy $out/bin/objcopy + ln -sf ${zigrc}/bin/zigrc $out/bin/rc + ln -sf $out/bin/rc $out/bin/windres + ln -sf ${zigcc z "cc"}/bin/zigcc $out/bin/clang + ln -sf ${zigcc z "c++"}/bin/zigc++ $out/bin/clang++ + ln -sf $out/bin/clang $out/bin/gcc + ln -sf $out/bin/clang++ $out/bin/g++ + ln -sf $out/bin/clang $out/bin/cc + ln -sf $out/bin/clang++ $out/bin/c++ + ln -sf ${zigld}/bin/zigld $out/bin/ld ''; - toolchain-local = runCommandLocal "zig-toolchain-local" {} '' - mkdir -p "$out/bin" - ${tools-for-target null} - ''; - - toolchain-unwrapped = libllvm: symlinkJoin { - name = "zig-toolchain"; + toolchain-unwrapped = { libllvm, targetPlatform }: symlinkJoin { + name = "zig-toolchain-${targetPlatform.config}"; inherit (zig) version; - paths = [ toolchain-local toolchain-universal ]; + paths = [ (tools-for-target targetPlatform.config) ]; passthru = { isClang = true; isLLVM = true; @@ -248,30 +238,18 @@ let in { - libc - , wrapCCWith - , wrapBintoolsWith - , libllvm + callPackage + , targetPlatform }: wrapCCWith { - inherit gnugrep coreutils libc; - cc = toolchain-unwrapped libllvm; + inherit gnugrep coreutils; + cc = callPackage toolchain-unwrapped {}; useCcForLibs = false; + libc = if (targetPlatform == stdenv.buildPlatform) then stdenv.cc.libc else null; bintools = wrapBintoolsWith { - inherit gnugrep coreutils libc; - bintools = toolchain-unwrapped libllvm; + inherit gnugrep coreutils; + libc = if (targetPlatform == stdenv.buildPlatform) then stdenv.cc.libc else null; + bintools = callPackage toolchain-unwrapped {}; }; - - # nix really wants us to use nixpkgs libc - # so make sure we don't pass extra garbage on the cc command line - extraBuildCommands = '' - rm -f $out/nix-support/cc-cflags - rm -f $out/nix-support/cc-ldflags - rm -f $out/nix-support/libc-crt1-cflags - rm -f $out/nix-support/libc-cflags - rm -f $out/nix-support/libc-ldflags - rm -f $out/nix-support/libcxx-cxxflags - rm -f $out/nix-support/libcxx-ldflags - ''; } diff --git a/src/lib.nix b/src/lib.nix deleted file mode 100644 index 26fe951..0000000 --- a/src/lib.nix +++ /dev/null @@ -1,162 +0,0 @@ -{ lib }: - -with builtins; -with lib; -with lib.attrsets; - -let - # only do simple conversion in this function - mk-triple = arch: kernel: vendor: abis: mergeAttrsList (map (abi: let - zig-arch = if isString arch then arch else arch.zig or (throw "invalid arch argument"); - - zig2nix-arch = { - x86 = "i686"; - arm = "armv7a"; - }.${zig-arch} or zig-arch; - - nix-arch = if isString arch then zig2nix-arch else arch.nix or zig2nix-arch; - - zig-kernel = if isString kernel then kernel else kernel.zig or (throw "invalid kernel argument"); - - zig2nix-kernel = { - macos = "darwin"; - freestanding = "none"; - }.${zig-kernel} or zig-kernel; - - nix-kernel = if isString kernel then zig2nix-kernel else kernel.nix or zig2nix-kernel; - - zig-abi = if isString abi then abi else abi.zig or (throw "invalid abi argument"); - nix-abi = if isString abi then zig-abi else abi.nix or zig-abi; - opt-nix-abi = if nix-abi != "none" then "-${nix-abi}" else ""; - in if vendor != null then { - "${zig-arch}-${zig-kernel}-${zig-abi}" = "${nix-arch}-${vendor}-${nix-kernel}${opt-nix-abi}"; - } else { - "${zig-arch}-${zig-kernel}-${zig-abi}" = "${nix-arch}-${nix-kernel}-${nix-abi}"; - }) abis); - - from-archs = kernel: vendor: archs: abis: mergeAttrsList (map (arch: mk-triple arch kernel vendor abis) archs); - - # nix unsupported archs: csky, armeb, thumb, gnux32, muslx32 - # broken archs: arm, aarch64_be (windows, unsupported arch), m68k (InvalidLlvmTriple), sparc, s390x (support lib) - # broken platforms: ios, watchos, tvos (no bundled sdk), risv64-gnu (gnu/stubs-lp64d.h) - # broken abis: gnuabin32 (support lib) - zig2nix-target = {} - // from-archs "linux" "unknown" [ "riscv64" ] [ "musl" ] - // from-archs "linux" "unknown" [ "x86_64" ] [ "gnu" "musl" ] - // from-archs "linux" "unknown" [ "x86" ] [ "gnu" "musl" ] - // from-archs "linux" "unknown" [ "aarch64" "aarch64_be" ] [ "gnu" "musl" ] - // from-archs "linux" "unknown" [ "arm" ] [ "gnueabi" "gnueabihf" "musleabi" "musleabihf" ] - // from-archs "linux" "unknown" [ "mips64el" "mips64" ] [ "gnuabi64" "musl" ] - // from-archs "linux" "unknown" [ "mipsel" "mips" ] [ "gnueabi" "gnueabihf" "musl" ] - // from-archs "linux" "unknown" [ "powerpc64" ] [ { zig = "gnu"; nix = "gnuabielfv2"; } "musl" ] - // from-archs "linux" "unknown" [ "powerpc64le" ] [ "gnu" "musl" ] - // from-archs "linux" "unknown" [ "powerpc" ] [ "gnueabi" "gnueabihf" "musl" ] - # // from-archs "linux" "unknown" [ "csky" ] [ "gnueabi" "gnueabihf" ] - # // from-archs "linux" "unknown" [ "s390x" ] [ "gnu" "musl" ] - # // from-archs "linux" "unknown" [ "sparc" "sparc64" ] [ "gnu" ] - // from-archs "windows" "pc" [ "x86" "x86_64" "aarch64" ] [ "msvc" ] - # maps to autotools mingw target triples - // from-archs { zig = "windows"; nix = "w64"; } null [ "x86" "x86_64" "aarch64" ] [ { zig = "gnu"; nix = "mingw32"; } ] - // from-archs "macos" "apple" [ "x86_64" "aarch64" ] [ "none" ] - # // from-archs "ios" "apple" [ "x86_64" "aarch64" ] [ "none" ] - # // from-archs "watchos" "apple" [ "x86_64" "aarch64" ] [ "none" ] - # // from-archs "tvos" "apple" [ "x86_64" "aarch64" ] [ "none" ] - // from-archs "wasi" "unknown" [ "wasm32" ] [ "musl" ] - // from-archs "freebsd" "unknown" [ "x86_64" ] [ "none" ]; - - allTargetTriples = attrNames zig2nix-target; - - nix2zig-target = mergeAttrsList (map (k: { - "${zig2nix-target.${k}}" = "${k}"; - }) allTargetTriples) // { - # map flake targets - "armv5tel-unknown-linux-gnueabi" = "arm-linux-gnueabi"; - "armv6l-unknown-linux-gnueabihf" = "arm-linux-gnueabihf"; - "armv7l-unknown-linux-gnueabihf" = "arm-linux-gnueabihf"; - "mipsel-unknown-linux-gnu" = "mipsel-linux-gnueabi"; - "powerpc64le-unknown-linux-gnu" = "powerpc64le-linux-gnu"; - }; - - # freebsd has no bundled libc yet - broken = [ "riscv64-linux" "x86_64-freebsd" "armv7l-linux" "armv6l-linux" ]; - allFlakeTargetTriples = map (f: nix2zig-target.${(systems.elaborate f).config}) (subtractLists broken systems.flakeExposed); - - normalized-target = s: let - n = concatStringsSep "-" (map (c: elemAt (splitString "." c) 0) (splitString "-" s)); - elaborated = (systems.elaborate n).config; - in - if (zig2nix-target.${n} or null) != null then n - else if (nix2zig-target.${n} or null) != null then nix2zig-target.${n} - else nix2zig-target.${elaborated} or (throw "invalid target string ${s}"); - - zig-meta = s: let - n0 = concatStringsSep "-" (map (c: elemAt (splitString "." c) 0) (splitString "-" s)); - n = if (zig2nix-target.${n0} or null) != null then s else normalized-target s; - parts = splitString "-" n; - meta = s: d: let - splitted = splitString "." s; - in { - base = elemAt splitted 0; - meta = if length splitted > 1 then elemAt splitted 1 else d; - }; - in rec { - cpu = elemAt parts 0; - kernel = elemAt parts 1; - abi = elemAt parts 2; - versionlessKernel = (meta kernel null).base; - kernelVersion = let - default = { - freebsd = "13"; - }.${versionlessKernel} or null; - in (meta kernel default).meta; - supportStaticLinking = any (p: p == versionlessKernel) [ "macos" "ios" "watchos" "tvos" ]; - }; -in rec { - mkZigSystemFromString = s: let - n = normalized-target s; - system = systems.parse.mkSystemFromString zig2nix-target.${n}; - in system // { zig = zig-meta s; }; - - mkZigSystemFromPlatform = p: let - system = mkZigSystemFromString p.config; - in { - darwin = let - sdkVer = - if (versionAtLeast p.darwinSdkVersion "10.13") then p.darwinSdkVersion - else warn "zig only supports macOS 10.13+, forcing SDK 11.0" "11.0"; - in mkZigSystemFromString "${system.zig.cpu}-${system.zig.kernel}.${sdkVer}-${system.zig.abi}"; - }.${system.kernel.name} or system; - - zigTripleFromSystem = system: "${system.zig.cpu}-${system.zig.kernel}-${system.zig.abi}"; - zigDoubleFromSystem = system: "${system.zig.cpu}-${system.zig.kernel}"; - zigTripleFromString = s: zigTripleFromSystem (mkZigSystemFromString s); - zigDoubleFromString = s: zigDoubleFromSystem (mkZigSystemFromString s); - - nixTripleFromSystem = s: zig2nix-target.${normalized-target (zigTripleFromSystem s)}; - nixDoubleFromSystem = systems.parse.doubleFromSystem; - nixTripleFromString = s: zig2nix-target.${normalized-target s}; - nixDoubleFromString = s: nixDoubleFromSystem (mkZigSystemFromString s); - - # helpers for resolving the final target and system for building a package from derivation attrs - resolveTargetSystem = { target ? null, platform ? null, musl ? false }: let - resolved = - if target != null then mkZigSystemFromString target - else if platform != null then mkZigSystemFromPlatform platform - else throw "either target or platform must be specified"; - in resolved // optionalAttrs (musl && resolved.zig.kernel == "linux") { - abi = resolved.abi // { - name = replaceStrings [ "gnu" "uclibc" ] [ "musl" "musl" ] resolved.abi.name; - }; - zig = resolved.zig // { - abi = replaceStrings [ "gnu" ] [ "musl" ] resolved.zig.abi; - }; - }; - - resolveTargetTriple = args: zigTripleFromSystem (resolveTargetSystem args); - - inherit allFlakeTargetTriples; - allFlakeTargetSystems = map (s: mkZigSystemFromString s) allFlakeTargetTriples; - - inherit allTargetTriples; - allTargetSystems = map (s: mkZigSystemFromString s) allTargetTriples; -} diff --git a/src/package.nix b/src/package.nix index 4bb3998..ca8048c 100644 --- a/src/package.nix +++ b/src/package.nix @@ -1,13 +1,12 @@ { lib , zig - , resolveTargetSystem - , zigTripleFromSystem , fromZON , deriveLockFile - , runtimeForTargetSystem , makeWrapper , removeReferencesTo + , pkg-config + , target }: { @@ -15,13 +14,12 @@ , stdenvNoCC # Specify target for zig compiler, defaults to stdenv.targetPlatform. , zigTarget ? null - # By default if zigTarget is specified, nixpkgs stdenv compatible environment is not used. - # Set this to true, if you want to specify zigTarget, but still use the derived stdenv compatible environment. - , zigInheritStdenv ? zigTarget == null # Prefer musl libc without specifying the target. , zigPreferMusl ? false - # makeWrapper will not be used. Might be useful if distributing outside nix. - , zigDisableWrap ? false + # Binaries available to the binary during runtime (PATH) + , zigWrapperBins ? [] + # Libraries available to the binary during runtime (LD_LIBRARY_PATH) + , zigWrapperLibs ? [] # Additional arguments to makeWrapper. , zigWrapperArgs ? [] # Path to build.zig.zon file, defaults to build.zig.zon. @@ -35,19 +33,20 @@ with builtins; with lib; let - target-system = resolveTargetSystem { - target = zigTarget; - platform = stdenvNoCC.targetPlatform; - musl = zigPreferMusl; - }; - - target-triple = zigTripleFromSystem target-system; zon = fromZON zigBuildZon; - runtime = runtimeForTargetSystem target-system; - wrapper-args = zigWrapperArgs - ++ optionals (length runtime.bins > 0) [ "--prefix" "PATH" ":" (makeBinPath runtime.bins) ] - ++ optionals (length runtime.libs > 0) [ "--prefix" runtime.env.LIBRARY_PATH ":" (makeLibraryPath runtime.libs) ]; + config = + if zigPreferMusl then + replaceStrings ["-gnu"] ["-musl"] stdenvNoCC.targetPlatform.config + else stdenvNoCC.targetPlatform.config; + + default-target = (target config).zig; + resolved-target = if zigTarget != null then zigTarget else default-target; + + wrapper-args = [] + ++ optionals (length zigWrapperBins > 0) [ "--prefix" "PATH" ":" (makeBinPath zigWrapperBins) ] + ++ optionals (length zigWrapperLibs > 0) [ "--prefix" "LD_LIBRARY_PATH" ":" (makeLibraryPath zigWrapperLibs) ] + ++ zigWrapperArgs; attrs = optionalAttrs (pathExists zigBuildZon && !userAttrs ? name && !userAttrs ? pname) { pname = zon.name; @@ -61,30 +60,22 @@ let }; default-flags = - if hasPrefix "git" zig.version || versionAtLeast zig.version "0.11" then + if versionAtLeast zig.version "0.11" then [ "-Doptimize=ReleaseSafe" ] else [ "-Drelease-safe=true" ]; - - stdenv-flags = optionals (zigInheritStdenv) (runtime.env.stdenvZigFlags or []); in stdenvNoCC.mkDerivation ( (removeAttrs attrs [ "stdenvNoCC" ]) // { zigBuildFlags = (attrs.zigBuildFlags or default-flags) - ++ [ "-Dtarget=${target-triple}" ] - ++ stdenv-flags; + ++ [ "-Dtarget=${resolved-target}" ] + ++ optionals (pathExists zigBuildZonLock) [ "--system" "${deps}" ]; - nativeBuildInputs = [ zig.hook removeReferencesTo ] - ++ optionals (!zigDisableWrap) ([ makeWrapper ] ++ (runtime.env.wrapperBuildInputs or [])) - ++ (runtime.build-bins or []) + nativeBuildInputs = [ zig.hook removeReferencesTo pkg-config ] + ++ optionals (length wrapper-args > 0) [ makeWrapper ] ++ (attrs.nativeBuildInputs or []); - postPatch = optionalString (pathExists zigBuildZonLock) '' - ln -s ${deps} "$ZIG_GLOBAL_CACHE_DIR"/p - ${attrs.postPatch or ""} - ''; - - postFixup = optionalString (!zigDisableWrap && length wrapper-args > 0) '' + postFixup = optionalString (length wrapper-args > 0) '' for bin in $out/bin/*; do wrapProgram $bin ${concatStringsSep " " wrapper-args} done @@ -93,6 +84,7 @@ in stdenvNoCC.mkDerivation ( ${attrs.postFixup or ""} ''; - disallowedReferences = [ zig ]; + disallowedReferences = [ zig zig.hook removeReferencesTo ] + ++ optionals (pathExists zigBuildZonLock) [ deps ]; } ) diff --git a/src/runtime.nix b/src/runtime.nix deleted file mode 100644 index 6f79384..0000000 --- a/src/runtime.nix +++ /dev/null @@ -1,105 +0,0 @@ -{ - lib - , coreutils - , pkgsForTarget - , mkZigSystemFromString - , autoPatchelfHook - , customAppHook ? "" - , customDevShellHook ? "" - , customRuntimeLibs ? [] - , enableVulkan - , enableOpenGL - , enableWayland - , enableX11 - , enableAlsa - , buildPlatform - , pkgs -}: - -with builtins; -with lib; - -args': - -let - system = if isString args' then mkZigSystemFromString args' else args'; - targetPkgs = pkgsForTarget system; - - env = rec { - linux = { - LIBRARY_PATH = "LD_LIBRARY_PATH"; - wrapperBuildInputs = optionals (buildPlatform.isLinux) [ autoPatchelfHook ]; - }; - - darwin = { - LIBRARY_PATH = "DYLD_LIBRARY_PATH"; - }; - ios = darwin; - watchos = darwin; - tvos = darwin; - }; - - libs = { - linux = with targetPkgs; [] - ++ optionals (enableVulkan) [ vulkan-loader ] - ++ optionals (enableOpenGL) [ libGL ] - # Some common runtime libs used by x11 apps, for example: https://www.glfw.org/docs/3.3/compat.html - # You can always include more if you need with customRuntimeLibs. - ++ optionals (enableX11) [ xorg.libX11 xorg.libXext xorg.libXfixes xorg.libXi xorg.libXrender xorg.libXrandr xorg.libXinerama xorg.libXcursor xorg.xorgproto ] - ++ optionals (enableWayland) [ wayland libxkbcommon libdecor ] - ++ optionals (enableAlsa) [ alsa-lib ]; - }; - - build-bins = { - linux = with pkgs; [] - ++ optionals (enableWayland) [ wayland-scanner ]; - darwin = with pkgs; [ xcbuild ]; - ios = darwin; - watchos = darwin; - tvos = darwin; - }; - - bins = {}; - - hook-for = kernel: let - _libs = (libs.${kernel} or []) ++ customRuntimeLibs; - ld_string = makeLibraryPath _libs; - # xorgproto puts its pc file in share/pkgconfig for whatever reason - pc_string = concatStringsSep ":" [ - (makeSearchPathOutput "dev" "lib/pkgconfig" _libs) - (makeSearchPathOutput "dev" "share/pkgconfig" _libs) - ]; - in '' - export ${env.${kernel}.LIBRARY_PATH}="${ld_string}:''${${env.${kernel}.LIBRARY_PATH}:-}" - export PKG_CONFIG_PATH="${pc_string}:''${PKG_CONFIG_PATH:-}" - ''; - - shell = { - # https://github.com/ziglang/zig/issues/17282 - linux = '' - ver_between() { printf '%s\n' "$@" | ${coreutils}/bin/sort -C -V; } - if ver_between 6.4.12 "$(${coreutils}/bin/uname -r)" 6.5.5; then - printf -- 'Using ZIG_BTRFS_WORKAROUND=1\n' 1>&2 - printf -- 'It is recommended to update your kernel to 6.5.6 or higher\n' 1>&2 - printf -- 'https://github.com/ziglang/zig/issues/17282\n' 1>&2 - export ZIG_BTRFS_WORKAROUND=1 - fi - ${hook-for "linux"} - ''; - - darwin = hook-for "darwin"; - }; -in { - env = env.${system.kernel.name} or {}; - libs = libs.${system.kernel.name} or []; - bins = bins.${system.kernel.name} or []; - build-bins = (build-bins.${system.kernel.name} or []) ++ [ pkgs.pkg-config ]; - app = '' - ${customAppHook} - ${shell.${system.kernel.name} or ""} - ''; - shell = '' - ${customDevShellHook} - ${shell.${system.kernel.name} or ""} - ''; -} diff --git a/src/shell.nix b/src/shell.nix new file mode 100644 index 0000000..491bb75 --- /dev/null +++ b/src/shell.nix @@ -0,0 +1,52 @@ +{ + lib + , coreutils + , system +}: + +with builtins; +with lib; + +let + os = let + parts = splitString "-" system; + in last parts; + + hook = { LIBRARY_PATH, pkgs }: let + ld_string = makeLibraryPath pkgs; + # xorgproto puts its pc file in share/pkgconfig for whatever reason + pc_string = concatStringsSep ":" [ + (makeSearchPathOutput "dev" "lib/pkgconfig" pkgs) + (makeSearchPathOutput "dev" "share/pkgconfig" pkgs) + ]; + in '' + export ${LIBRARY_PATH}="${ld_string}:''${${LIBRARY_PATH}:-}" + export PKG_CONFIG_PATH="${pc_string}:''${PKG_CONFIG_PATH:-}" + ''; + + runtime = { + linux = rec { + LIBRARY_PATH = "LD_LIBRARY_PATH"; + shell = pkgs: '' + ver_between() { printf '%s\n' "$@" | ${coreutils}/bin/sort -C -V; } + if ver_between 6.4.12 "$(${coreutils}/bin/uname -r)" 6.5.5; then + printf -- 'Using ZIG_BTRFS_WORKAROUND=1\n' 1>&2 + printf -- 'It is recommended to update your kernel to 6.5.6 or higher\n' 1>&2 + printf -- 'https://github.com/ziglang/zig/issues/17282\n' 1>&2 + export ZIG_BTRFS_WORKAROUND=1 + fi + ${hook { inherit LIBRARY_PATH pkgs; }} + ''; + }; + + darwin = rec { + LIBRARY_PATH = "DYLD_LIBRARY_PATH"; + shell = pkgs: hook { inherit LIBRARY_PATH pkgs; }; + }; + ios = darwin; + watchos = darwin; + tvos = darwin; + }; + + env = if runtime ? ${os} then runtime.${os} else throw "unknown system"; +in env.shell diff --git a/src/test.nix b/src/test.nix index 9e1b844..8ebfd2b 100644 --- a/src/test.nix +++ b/src/test.nix @@ -2,31 +2,27 @@ lib , test-app , zig-env - , zon2json-lock + , zig2nix , jq , findutils , coreutils , libarchive , file , zig + , target , deriveLockFile - , resolveTargetSystem - , zigTripleFromSystem - , nixTripleFromSystem - , allFlakeTargetTriples + , buildPlatform }: with builtins; with lib; -let - filteredFlakeTargetTriples = filter (x: x != "x86_64-macos-none") allFlakeTargetTriples; -in { +{ # nix run .#test.zon2json-lock - zon2json-lock = test-app [ zon2json-lock ] '' - for f in tools/fixtures/*.zig.zon tools/fixtures/example/build.zig.zon; do - echo "testing (zon2json-lock): $f" - if ! cmp <(zon2json-lock "$f" -) "''${f}2json-lock"; then + zon2lock = test-app [ zig2nix ] '' + for f in ./fixtures/*.zig.zon ./fixtures/example/build.zig.zon; do + echo "testing (zon2lock): $f" + if ! cmp <(zig2nix zon2lock "$f") "''${f}2json-lock"; then error "unexpected output" fi done @@ -34,21 +30,21 @@ in { # nix run .#test.zon2nix zon2nix = let - fixtures = filter (f: hasSuffix ".zig.zon2json-lock" f) (attrNames (readDir ../tools/fixtures)) ++ [ "example/build.zig.zon2json-lock"]; + fixtures = filter (f: hasSuffix ".zig.zon2json-lock" f) (attrNames (readDir ../fixtures)) ++ [ "example/build.zig.zon2json-lock"]; drvs = map (f: { lck = f; - out = deriveLockFile (../tools/fixtures + "/${f}") { inherit zig; }; + out = deriveLockFile (../fixtures + "/${f}") { inherit zig; }; }) fixtures; test = drv: '' echo "testing (zon2nix): ${drv.lck}" - if [[ -s "${../tools/fixtures/${drv.lck}}" ]]; then + if [[ "$(cat "${../fixtures/${drv.lck}}")" != "{}" ]]; then for d in ${drv.out}/*; do test -d "$d" || error 'is not a directory: %s' "$d" if [[ $(wc -l < <(find "$d/" -mindepth 1 -maxdepth 1 -type f)) == 0 ]]; then error "does not contain any regular files: %s" "$d" fi zhash="$(basename "$d")" - if ! ${jq}/bin/jq -er --arg k "$zhash" '."\($k)"' ${../tools/fixtures/${drv.lck}} > /dev/null; then + if ! ${jq}/bin/jq -er --arg k "$zhash" '."\($k)"' ${../fixtures/${drv.lck}} > /dev/null; then error 'missing zhash: %s' "$zhash" fi done @@ -64,18 +60,12 @@ in { for var in default master; do printf -- 'run . (%s)\n' "$var" (cd templates/"$var"; nix run -L --override-input zig2nix ../.. .) - printf -- 'run .#bundle.default (%s)\n' "$var" - (cd templates/"$var"; nix run -L --override-input zig2nix ../.. .#bundle.default) + printf -- 'run .#bundle (%s)\n' "$var" + (cd templates/"$var"; nix run -L --override-input zig2nix ../.. .#bundle) printf -- 'run .#test (%s)\n' "$var" (cd templates/"$var"; nix run -L --override-input zig2nix ../.. .#test) printf -- 'build . (%s)\n' "$var" (cd templates/"$var"; nix build -L --override-input zig2nix ../.. .; ./result/bin/"$var") - if [[ "$var" == master ]]; then - for arch in x86_64-windows-gnu ${escapeShellArgs filteredFlakeTargetTriples}; do - printf -- 'build .#target.%s (%s)\n' "$arch" "$var" - (cd templates/"$var"; nix build -L --override-input zig2nix ../.. .#target."$arch"; file ./result/bin/"$var"*) - done - fi rm -f templates/"$var"/result rm -rf templates/"$var"/zig-out rm -rf templates/"$var"/zig-cache @@ -86,8 +76,8 @@ in { # nix run .#test.package package = let pkg = zig-env.package { - name = "zon2json"; - src = cleanSource ../tools/zon2json; + name = "zig2nix"; + src = cleanSource ../src/zig2nix; }; in test-app [] "echo ${pkg}"; @@ -95,66 +85,68 @@ in { bundle = let zip1 = zig-env.bundle.zip { package = zig-env.package { - name = "zon2json"; - src = cleanSource ../tools/zon2json; - meta.mainProgram = "zon2json"; + name = "zig2nix"; + src = cleanSource ../src/zig2nix; + meta.mainProgram = "zig2nix"; }; }; zip2 = zig-env.bundle.zip { package = zig-env.package { - name = "zon2json"; - src = cleanSource ../tools/zon2json; - meta.mainProgram = "zon2json"; + name = "zig2nix"; + src = cleanSource ../src/zig2nix; + meta.mainProgram = "zig2nix"; }; packageAsRoot = true; }; lambda = zig-env.bundle.aws.lambda { package = zig-env.packageForTarget "aarch64-linux-musl" { - name = "zon2json"; - src = cleanSource ../tools/zon2json; - meta.mainProgram = "zon2json"; + name = "zig2nix"; + src = cleanSource ../src/zig2nix; + meta.mainProgram = "zig2nix"; }; }; in test-app [ libarchive ] '' tmpdir="$(mktemp -d)" trap 'chmod -R 755 "$tmpdir"; rm -rf "$tmpdir"' EXIT - (cd "$tmpdir"; bsdtar -xf ${zip1}; ./run ${../tools/fixtures/1.zig.zon}; echo) - (cd "$tmpdir"; bsdtar -xf ${zip2}; ./run ${../tools/fixtures/1.zig.zon}; echo) + (cd "$tmpdir"; bsdtar -xf ${zip1}; ./run zon2json ${../fixtures/1.zig.zon}; echo) + (cd "$tmpdir"; bsdtar -xf ${zip2}; ./run zon2json ${../fixtures/1.zig.zon}; echo) echo ${lambda} | grep provided.al2023-arm64.zip bsdtar -tf ${lambda} | grep bootstrap ''; # nix run .#test.cross - cross = test-app [] '' - for target in x86_64-windows-gnu ${escapeShellArgs filteredFlakeTargetTriples}; do - printf -- 'build .#env.master.bin.cross.%s.zlib\n' "$target" - nix build -L .#env.master.bin.cross.$target.zlib - done - ''; + cross = let + blacklist = [ "armv6l-linux" "armv7l-linux" "x86_64-freebsd" "riscv64-linux" "powerpc64le-linux" "i686-linux" ] + ++ optionals (!buildPlatform.isDarwin) [ "aarch64-darwin" ]; + filteredFlakeTargets = filter (x: ! elem x blacklist) systems.flakeExposed; + targets = [ "x86_64-windows-gnu" ] ++ filteredFlakeTargets; + in test-app [] (concatStrings (map (nix: let + crossPkgs = zig-env.zigCrossPkgsForTarget nix; + in '' + printf 'zig cross build (zlib): ${nix}\n' + echo "${crossPkgs.zlib}" + '') targets)); - # nix run .#test.all - all = let - resolved = resolveTargetSystem { target = "x86_64-linux-gnu"; musl = true; }; - nix-triple = nixTripleFromSystem resolved; - zig-triple = zigTripleFromSystem resolved; - in test-app [] '' - # shellcheck disable=SC2268 - test '${nix-triple}' = x86_64-unknown-linux-musl || error '${nix-triple} != x86_64-unknown-linux-musl' - # shellcheck disable=SC2268 - test '${zig-triple}' = x86_64-linux-musl || error '${zig-triple} != x86_64-linux-musl' - nix run -L .#test.zon2json-lock - nix run -L .#test.zon2nix - nix run -L .#test.templates - nix run -L .#test.package - # nix run -L .#test.cross - nix run -L .#test.bundle - ''; + # nix run .#test.targets + targets = test-app [] (concatStrings (map (nix: let + system = (target nix).system; + config1 = (systems.elaborate nix).config; + config2 = (target (systems.elaborate nix).config).config; + in '' + # shellcheck disable=SC2268 + test '${nix}' = '${system}' || error '${nix} != ${system}' + # shellcheck disable=SC2268 + test '${config1}' = '${config2}' || error '${config1} != ${config2}' + '') systems.flakeExposed)); - # nix run .#test.repl - repl = test-app [] '' - confnix="$(mktemp)" - trap 'rm $confnix' EXIT - echo "builtins.getFlake (toString $(git rev-parse --show-toplevel))" >"$confnix" - nix repl "$confnix" + # nix run .#test.all + all = test-app [] '' + nix flake check --keep-going + nix run -L .#test-targets + nix run -L .#test-zon2lock + nix run -L .#test-zon2nix + nix run -L .#test-templates + nix run -L .#test-package + nix run -L .#test-bundle ''; } diff --git a/src/zig/bin.nix b/src/zig/bin.nix new file mode 100644 index 0000000..3ee1a4c --- /dev/null +++ b/src/zig/bin.nix @@ -0,0 +1,78 @@ +{ + lib + , installDocs ? false + , zigHook + , release + , stdenvNoCC + , callPackage + , fetchurl + , zig-shell-completions + , coreutils + , bubblewrap + , writeScriptBin +}: + +with builtins; +with lib; + +let + system = stdenvNoCC.targetPlatform.system; + meta-for = release: { + homepage = "https://ziglang.org/"; + description = "General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software"; + license = licenses.mit; + platforms = platforms.unix; + maintainers = []; # needed by the setup hook + mainProgram = "zig"; + } // optionalAttrs (release ? notes) { + changelog = release.notes; + }; +in if release ? ${system} then stdenvNoCC.mkDerivation (finalAttrs: { + pname = "zig"; + inherit (release) version; + + outputs = [ "out" ] ++ optionals installDocs [ "doc" ]; + + src = fetchurl { + url = release.${system}.tarball; + sha256 = release.${system}.shasum; + }; + + phases = [ "unpackPhase" "installPhase" ]; + + installPhase = '' + mkdir -p $out/{bin,lib} + cp -r lib/* $out/lib + install -Dm755 zig $out/bin/zig + install -m644 LICENSE $out/LICENSE + '' + optionalString installDocs '' + mkdir -p $out/doc + if [[ -d docs ]]; then + cp -r docs $out/doc + else + cp -r doc $out/doc + fi + ''; + + passthru = { + inherit (release) date notes stdDocs docs src; + inherit (release.${system}) size; + hook = callPackage zigHook { + zig = if (stdenvNoCC.isLinux) then + # Wrap binary package zig on linux so /usr/bin/env can be found inside a sandbox + writeScriptBin "zig" '' + args=() + for d in /*; do + args+=("--dev-bind" "$d" "$d") + done + ${bubblewrap}/bin/bwrap "''${args[@]}" \ + --bind ${coreutils} /usr \ + -- ${finalAttrs.finalPackage}/bin/zig "$@" + '' + else finalAttrs.finalPackage; + }; + shell-completions = zig-shell-completions; + }; + + meta = meta-for release; +}) else throw "There is no zig-${release.version} binary available for ${system}, use _src variant to compile from source" diff --git a/src/zig/outputs.nix b/src/zig/outputs.nix new file mode 100644 index 0000000..c415a5e --- /dev/null +++ b/src/zig/outputs.nix @@ -0,0 +1,42 @@ +{ + lib + , zigv + , zig-env + , pkgs +}: + +with lib; +with builtins; + +let + multimedia = with pkgs; [] + ++ optionals stdenv.isLinux [ + vulkan-loader libGL + xorg.libX11 xorg.libXext xorg.libXfixes xorg.libXi xorg.libXrender + xorg.libXrandr xorg.libXinerama xorg.libXcursor xorg.xorgproto + wayland-scanner wayland libxkbcommon libdecor + alsa-lib pulseaudio + ]; +in { + apps = mergeAttrsList (attrValues (mapAttrs (k: zig: let + env = zig-env { inherit zig; }; + in { + "${k}" = env.app-no-root [] ''zig "$@"''; + "multimedia-${k}" = env.app-no-root multimedia ''zig "$@"''; + "zig2nix-${k}" = env.app-no-root [] ''zig2nix "$@"''; + + # Backwards compatiblity + "zon2json-${k}" = env.app-no-root [] ''zig2nix zon2json "$@"''; + "zon2json-lock-${k}" = env.app-no-root [] ''zig2nix zon2lock "$@"''; + "zon2nix-${k}" = env.app-no-root [] ''zig2nix zon2nix "$@"''; + }) zigv)); + + devShells = mergeAttrsList (attrValues (mapAttrs (k: zig: let + env = zig-env { inherit zig; }; + in { + "${k}" = env.mkShell {}; + "multimedia-${k}" = env.mkShell { + nativeBuildInputs = multimedia; + }; + }) zigv)); +} diff --git a/src/zig/src.nix b/src/zig/src.nix new file mode 100644 index 0000000..bd4f99a --- /dev/null +++ b/src/zig/src.nix @@ -0,0 +1,90 @@ +{ + lib + , installDocs ? false + , zigHook + , release + , stdenv + , callPackage + , fetchurl + , zig-shell-completions + , cmake + , llvmPackages_19 + , libxml2 + , zlib + , coreutils +}: + +with builtins; +with lib; + +let + meta-for = release: { + homepage = "https://ziglang.org/"; + description = "General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software"; + license = licenses.mit; + platforms = platforms.unix; + maintainers = []; # needed by the setup hook + mainProgram = "zig"; + } // optionalAttrs (release ? notes) { + changelog = release.notes; + }; +in with llvmPackages_19; stdenv.mkDerivation (finalAttrs: { + pname = "zig"; + inherit (release) version; + + outputs = [ "out" ] ++ optionals installDocs [ "doc" ]; + + src = fetchurl { + url = release.src.tarball; + sha256 = release.src.shasum; + }; + + nativeBuildInputs = [ cmake llvm.dev ]; + buildInputs = [ libxml2 zlib libclang lld llvm ]; + + cmakeFlags = [ + # file RPATH_CHANGE could not write new RPATH + "-DCMAKE_SKIP_BUILD_RPATH=ON" + + # always link against static build of LLVM + "-DZIG_STATIC_LLVM=ON" + + # ensure determinism in the compiler build + "-DZIG_TARGET_MCPU=baseline" + ]; + + env.ZIG_GLOBAL_CACHE_DIR = "$TMPDIR/zig-cache"; + + # Zig's build looks at /usr/bin/env to find dynamic linking info. This doesn't + # work in Nix's sandbox. Use env from our coreutils instead. + postPatch = '' + substituteInPlace lib/std/zig/system/NativeTargetInfo.zig --replace "/usr/bin/env" "${coreutils}/bin/env" || true + substituteInPlace lib/std/zig/system.zig --replace "/usr/bin/env" "${coreutils}/bin/env" || true + ''; + + postBuild = optionalString installDocs '' + stage3/bin/zig run --cache-dir "$TMPDIR/zig-test-cache" ../tools/docgen.zig -- ../doc/langref.html.in langref.html --zig $PWD/stage3/bin/zig + ''; + + postInstall = optionalString installDocs '' + install -Dm444 -t $doc/share/doc/zig-${release.version}/html langref.html + ''; + + doInstallCheck = true; + + installCheckPhase = '' + runHook preInstallCheck + $out/bin/zig test --cache-dir "$TMPDIR/zig-test-cache" -I ../test ../test/behavior.zig + runHook postInstallCheck + ''; + + passthru = { + inherit (release) date notes stdDocs docs src; + hook = callPackage zigHook { + zig = finalAttrs.finalPackage; + }; + shell-completions = zig-shell-completions; + }; + + meta = meta-for release; +}) diff --git a/src/zig/versions.nix b/src/zig/versions.nix new file mode 100644 index 0000000..918b744 --- /dev/null +++ b/src/zig/versions.nix @@ -0,0 +1,1072 @@ +{ + callPackage, + zigHook, +}: + +let + bin = release: callPackage ./bin.nix { inherit zigHook release; }; + src = release: callPackage ./src.nix { inherit zigHook release; }; + + meta-master = { + version = "0.15.0-dev.10+214750fcf"; + date = "2025-03-08"; + docs = "https://ziglang.org/documentation/master/"; + stdDocs = "https://ziglang.org/documentation/master/std/"; + + src = { + tarball = "https://ziglang.org/builds/zig-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "ec5f192f4a484eb35e899bc2c0ed86d4fb7dcf4e142c62d4f515dea8db345573"; + size = 17771160; + }; + + bootstrap = { + tarball = "https://ziglang.org/builds/zig-bootstrap-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "a51c4801c495a9df04d5b36f2809c2c8983d9f3c4cb9e351c2ae049d77364828"; + size = 48036852; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/builds/zig-macos-x86_64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "7347a6e444f5bd83243077af310358d654a20ed305c022fd1d36d8284c1a8301"; + size = 51037472; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/builds/zig-macos-aarch64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "3c949309a2fc68cf1f26aea88a6544ed64efcd032547973e4e12bf7ab4dba1b0"; + size = 45916812; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/builds/zig-linux-x86_64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "a5e3ddf774e3f08afe5f68b54ab704a5e0d0da45867a4e4d43cb494dc19ed5d4"; + size = 49088948; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/builds/zig-linux-aarch64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "649e3b12cf7d77b0b444b9c4bb0c4df77cbc4b10b5ad6a0ca8320581538ef318"; + size = 44940300; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/builds/zig-linux-armv7a-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "f4164d9771c2ac37f45618afa85754b27a0041276df0137e67451d78e0ca4cbc"; + size = 46118988; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/builds/zig-linux-riscv64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "abf0b95d9511abf6d0718eca3ff063ae3e9d7dc0c6d59a9670cdef64394a2b9d"; + size = 48085468; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/builds/zig-linux-powerpc64le-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "426a7816e452f6bb132912581b15b4aabb98acbc2d6686d882ea6162048dd953"; + size = 48713776; + }; + + i686-linux = { + tarball = "https://ziglang.org/builds/zig-linux-x86-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "5d4eb87764b96e58583c1476794767f976f6f75fd74f51120f23feb3fc61e4c8"; + size = 51634364; + }; + + loongarch64-linux = { + tarball = "https://ziglang.org/builds/zig-linux-loongarch64-0.15.0-dev.10+214750fcf.tar.xz"; + shasum = "5f79d5919723614dd9c594a925016a4d487846f02a52a2b1d14e423c9518d512"; + size = 45820772; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/builds/zig-windows-x86_64-0.15.0-dev.10+214750fcf.zip"; + shasum = "37c27964350ca4dcb0819632facccb00146b4faea79122fed7a1d1c8b8efce7f"; + size = 82751180; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/builds/zig-windows-aarch64-0.15.0-dev.10+214750fcf.zip"; + shasum = "1635ab8591ff49a0c12042fb86bf24b567d4dc94213f3671617870883243e845"; + size = 78644235; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/builds/zig-windows-x86-0.15.0-dev.10+214750fcf.zip"; + shasum = "821caa914072961fb94ffebe021947dfb86ab868d668b7d2c8bf7739f3c35c06"; + size = 84497563; + }; + }; + + meta-0_14_0 = { + version = "0.14.0"; + date = "2025-03-05"; + docs = "https://ziglang.org/documentation/0.14.0/"; + stdDocs = "https://ziglang.org/documentation/0.14.0/std/"; + notes = "https://ziglang.org/download/0.14.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.14.0/zig-0.14.0.tar.xz"; + shasum = "c76638c03eb204c4432ae092f6fa07c208567e110fbd4d862d131a7332584046"; + size = 17772188; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.14.0/zig-bootstrap-0.14.0.tar.xz"; + shasum = "bf3fcb22be0b83f4791748adb567d3304779d66d7bf9b1bd557ef6c2e0232807"; + size = 48029040; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.14.0/zig-macos-x86_64-0.14.0.tar.xz"; + shasum = "685816166f21f0b8d6fc7aa6a36e91396dcd82ca6556dfbe3e329deffc01fec3"; + size = 51039964; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.14.0/zig-macos-aarch64-0.14.0.tar.xz"; + shasum = "b71e4b7c4b4be9953657877f7f9e6f7ee89114c716da7c070f4a238220e95d7e"; + size = 45902412; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-x86_64-0.14.0.tar.xz"; + shasum = "473ec26806133cf4d1918caf1a410f8403a13d979726a9045b421b685031a982"; + size = 49091960; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-aarch64-0.14.0.tar.xz"; + shasum = "ab64e3ea277f6fc5f3d723dcd95d9ce1ab282c8ed0f431b4de880d30df891e4f"; + size = 44922728; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-armv7a-0.14.0.tar.xz"; + shasum = "a67dbfa9bdf769228ec994f2098698c619f930883ca5ef638f50eee2d7788d10"; + size = 46112980; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-riscv64-0.14.0.tar.xz"; + shasum = "a2b14d3de326d3fd095548ef38bf5a67b15dadd62fbcc90836d63cc4355f8ef7"; + size = 48069188; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-powerpc64le-0.14.0.tar.xz"; + shasum = "3eabd60876ebc2748de8eb57b4b8cfa78861ba9bf7c6dd83f4e3e1d271d7c45e"; + size = 48707620; + }; + + i686-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-x86-0.14.0.tar.xz"; + shasum = "55d1ba21de5109686ffa675b9cc1dd66930093c202995a637ce3e397816e4c08"; + size = 51621460; + }; + + loongarch64-linux = { + tarball = "https://ziglang.org/download/0.14.0/zig-linux-loongarch64-0.14.0.tar.xz"; + shasum = "31a2f07df55f8f528b92d540db9aae6c0b38643c34dc1ac33a0111d855e996ae"; + size = 45821860; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.14.0/zig-windows-x86_64-0.14.0.zip"; + shasum = "f53e5f9011ba20bbc3e0e6d0a9441b31eb227a97bac0e7d24172f1b8b27b4371"; + size = 82219809; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.14.0/zig-windows-aarch64-0.14.0.zip"; + shasum = "03e984383ebb8f85293557cfa9f48ee8698e7c400239570c9ff1aef3bffaf046"; + size = 78113283; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/download/0.14.0/zig-windows-x86-0.14.0.zip"; + shasum = "1a867d808cf4fa9184358395d94441390b6b24ee8d00d356ca11ea7cbfd3a4ec"; + size = 83970029; + }; + }; + + meta-0_13_0 = { + version = "0.13.0"; + date = "2024-06-07"; + docs = "https://ziglang.org/documentation/0.13.0/"; + stdDocs = "https://ziglang.org/documentation/0.13.0/std/"; + notes = "https://ziglang.org/download/0.13.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.13.0/zig-0.13.0.tar.xz"; + shasum = "06c73596beeccb71cc073805bdb9c0e05764128f16478fa53bf17dfabc1d4318"; + size = 17220728; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.13.0/zig-bootstrap-0.13.0.tar.xz"; + shasum = "cd446c084b5da7bc42e8ad9b4e1c910a957f2bf3f82bcc02888102cd0827c139"; + size = 46440356; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.13.0/zig-freebsd-x86_64-0.13.0.tar.xz"; + shasum = "adc1ffc9be56533b2f1c7191f9e435ad55db00414ff2829d951ef63d95aaad8c"; + size = 47177744; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.13.0/zig-macos-x86_64-0.13.0.tar.xz"; + shasum = "8b06ed1091b2269b700b3b07f8e3be3b833000841bae5aa6a09b1a8b4773effd"; + size = 48857012; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.13.0/zig-macos-aarch64-0.13.0.tar.xz"; + shasum = "46fae219656545dfaf4dce12fb4e8685cec5b51d721beee9389ab4194d43394c"; + size = 44892040; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz"; + shasum = "d45312e61ebcc48032b77bc4cf7fd6915c11fa16e4aad116b66c9468211230ea"; + size = 47082308; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-aarch64-0.13.0.tar.xz"; + shasum = "041ac42323837eb5624068acd8b00cd5777dac4cf91179e8dad7a7e90dd0c556"; + size = 43090688; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-armv7a-0.13.0.tar.xz"; + shasum = "4b0550239c2cd884cc03ddeb2b9934708f4b073ad59a96fccbfe09f7e4f54233"; + size = 43998916; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-riscv64-0.13.0.tar.xz"; + shasum = "9f7f3c685894ff80f43eaf3cad1598f4844ac46f4308374237c7f912f7907bb3"; + size = 45540956; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-powerpc64le-0.13.0.tar.xz"; + shasum = "6a467622448e830e8f85d20cabed151498af2b0a62f87b8c083b2fe127e60417"; + size = 46574596; + }; + + i686-linux = { + tarball = "https://ziglang.org/download/0.13.0/zig-linux-x86-0.13.0.tar.xz"; + shasum = "876159cc1e15efb571e61843b39a2327f8925951d48b9a7a03048c36f72180f7"; + size = 52062336; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip"; + shasum = "d859994725ef9402381e557c60bb57497215682e355204d754ee3df75ee3c158"; + size = 79163968; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.13.0/zig-windows-aarch64-0.13.0.zip"; + shasum = "95ff88427af7ba2b4f312f45d2377ce7a033e5e3c620c8caaa396a9aba20efda"; + size = 75119033; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/download/0.13.0/zig-windows-x86-0.13.0.zip"; + shasum = "eb3d533c3cf868bff7e74455dc005d18fd836c42e50b27106b31e9fec6dffc4a"; + size = 83274739; + }; + }; + + meta-0_12_1 = { + version = "0.12.1"; + date = "2024-06-08"; + docs = "https://ziglang.org/documentation/0.12.1/"; + stdDocs = "https://ziglang.org/documentation/0.12.1/std/"; + + src = { + tarball = "https://ziglang.org/download/0.12.1/zig-0.12.1.tar.xz"; + shasum = "cca0bf5686fe1a15405bd535661811fac7663f81664d2204ea4590ce49a6e9ba"; + size = 17110932; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.12.1/zig-bootstrap-0.12.1.tar.xz"; + shasum = "e533e2cb6ef60edda0ae3f2ca5c6504557db6e985e3c3a80159beb32279ed341"; + size = 45542004; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.12.1/zig-freebsd-x86_64-0.12.1.tar.xz"; + shasum = "30eaa28fa7bc21d01f88528d75ae4b392ae4970406675d5ac712a4937a605123"; + size = 45590080; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.12.1/zig-macos-x86_64-0.12.1.tar.xz"; + shasum = "68f309c6e431d56eb42648d7fe86e8028a23464d401a467831e27c26f1a8d9c9"; + size = 47202232; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.12.1/zig-macos-aarch64-0.12.1.tar.xz"; + shasum = "6587860dbbc070e1ee069e1a3d18ced83b7ba7a80bf67b2c57caf7c9ce5208b1"; + size = 43451512; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-x86_64-0.12.1.tar.xz"; + shasum = "8860fc9725c2d9297a63008f853e9b11e3c5a2441217f99c1e3104cc6fa4a443"; + size = 45512024; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-aarch64-0.12.1.tar.xz"; + shasum = "27d4fef393e8d8b5f3b1d19f4dd43bfdb469b4ed17bbc4c2283c1b1fe650ef7f"; + size = 41867324; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-armv7a-0.12.1.tar.xz"; + shasum = "27493c922fd1454137ed6cbe6b6bec00352838fcd32e6e74f4f9187011816157"; + size = 42665508; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-riscv64-0.12.1.tar.xz"; + shasum = "463511a863acc16911cff6801de97623e6de296aab7b15dcda5f6fd078b400b5"; + size = 43932908; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-powerpc64le-0.12.1.tar.xz"; + shasum = "462d6f10350f3c5d6fc4c9d6cfdede93d69d0103af026889a15f65c5de791d39"; + size = 45227716; + }; + + i686-linux = { + tarball = "https://ziglang.org/download/0.12.1/zig-linux-x86-0.12.1.tar.xz"; + shasum = "c36ac019ca0fc3167e50d17e2affd3d072a06c519761737d0639adfdf2dcfddd"; + size = 50555428; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.12.1/zig-windows-x86_64-0.12.1.zip"; + shasum = "52459b147c2de4d7c28f6b1a4b3d571c114e96836bf8e31c953a7d2f5e94251c"; + size = 76470574; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.12.1/zig-windows-aarch64-0.12.1.zip"; + shasum = "e1286114a11be4695a6ad5cf0ba6a0e5f489bb3b029a5237de93598133f0c13a"; + size = 72998386; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/download/0.12.1/zig-windows-x86-0.12.1.zip"; + shasum = "4f0cc9258527e7b8bcf742772b3069122086a5cd857b38a1c08002462ac81f80"; + size = 80979711; + }; + }; + + meta-0_12_0 = { + version = "0.12.0"; + date = "2024-04-20"; + docs = "https://ziglang.org/documentation/0.12.0/"; + stdDocs = "https://ziglang.org/documentation/0.12.0/std/"; + notes = "https://ziglang.org/download/0.12.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.12.0/zig-0.12.0.tar.xz"; + shasum = "a6744ef84b6716f976dad923075b2f54dc4f785f200ae6c8ea07997bd9d9bd9a"; + size = 17099152; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.12.0/zig-bootstrap-0.12.0.tar.xz"; + shasum = "3efc643d56421fa68072af94d5512cb71c61acf1c32512f77c0b4590bff63187"; + size = 45527312; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.12.0/zig-freebsd-x86_64-0.12.0.tar.xz"; + shasum = "bd49957d1157850b337ee1cf3c00af83585cff98e1ebc3c524a267e7422a2d7b"; + size = 45578364; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.12.0/zig-macos-x86_64-0.12.0.tar.xz"; + shasum = "4d411bf413e7667821324da248e8589278180dbc197f4f282b7dbb599a689311"; + size = 47185720; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.12.0/zig-macos-aarch64-0.12.0.tar.xz"; + shasum = "294e224c14fd0822cfb15a35cf39aa14bd9967867999bf8bdfe3db7ddec2a27f"; + size = 43447724; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-x86_64-0.12.0.tar.xz"; + shasum = "c7ae866b8a76a568e2d5cfd31fe89cdb629bdd161fdd5018b29a4a0a17045cad"; + size = 45480516; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-aarch64-0.12.0.tar.xz"; + shasum = "754f1029484079b7e0ca3b913a0a2f2a6afd5a28990cb224fe8845e72f09de63"; + size = 41849060; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-armv7a-0.12.0.tar.xz"; + shasum = "b48221f4c64416d257f0f9f77d8727dccf7de92aeabe59744ee6e70d650a97bc"; + size = 42638808; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-riscv64-0.12.0.tar.xz"; + shasum = "bb2d1a78b01595a9c00ffd2e12ab46e32f8b6798f76aec643ff78e5b4f5c5afd"; + size = 43917444; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-powerpc64le-0.12.0.tar.xz"; + shasum = "9218beecfb9250e9eff863f58f987dca7077e3258dd263c40269086127f9679b"; + size = 45216736; + }; + + i686-linux = { + tarball = "https://ziglang.org/download/0.12.0/zig-linux-x86-0.12.0.tar.xz"; + shasum = "fb752fceb88749a80d625a6efdb23bea8208962b5150d6d14c92d20efda629a5"; + size = 50498940; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.12.0/zig-windows-x86_64-0.12.0.zip"; + shasum = "2199eb4c2000ddb1fba85ba78f1fcf9c1fb8b3e57658f6a627a8e513131893f5"; + size = 76442958; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.12.0/zig-windows-aarch64-0.12.0.zip"; + shasum = "04c6b92689241ca7a8a59b5f12d2ca2820c09d5043c3c4808b7e93e41c7bf97b"; + size = 72976876; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/download/0.12.0/zig-windows-x86-0.12.0.zip"; + shasum = "497dc9fd415cadf948872f137d6cc0870507488f79db9547b8f2adb73cda9981"; + size = 80950440; + }; + }; + + meta-0_11_0 = { + version = "0.11.0"; + date = "2023-08-04"; + docs = "https://ziglang.org/documentation/0.11.0/"; + stdDocs = "https://ziglang.org/documentation/0.11.0/std/"; + notes = "https://ziglang.org/download/0.11.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.11.0/zig-0.11.0.tar.xz"; + shasum = "72014e700e50c0d3528cef3adf80b76b26ab27730133e8202716a187a799e951"; + size = 15275316; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.11.0/zig-bootstrap-0.11.0.tar.xz"; + shasum = "38dd9e17433c7ce5687c48fa0a757462cbfcbe75d9d5087d14ebbe00efd21fdc"; + size = 43227592; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.11.0/zig-freebsd-x86_64-0.11.0.tar.xz"; + shasum = "ea430327f9178377b79264a1d492868dcff056cd76d43a6fb00719203749e958"; + size = 46432140; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.11.0/zig-macos-x86_64-0.11.0.tar.xz"; + shasum = "1c1c6b9a906b42baae73656e24e108fd8444bb50b6e8fd03e9e7a3f8b5f05686"; + size = 47189164; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.11.0/zig-macos-aarch64-0.11.0.tar.xz"; + shasum = "c6ebf927bb13a707d74267474a9f553274e64906fd21bf1c75a20bde8cadf7b2"; + size = 43855096; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz"; + shasum = "2d00e789fec4f71790a6e7bf83ff91d564943c5ee843c5fd966efc474b423047"; + size = 44961892; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-aarch64-0.11.0.tar.xz"; + shasum = "956eb095d8ba44ac6ebd27f7c9956e47d92937c103bf754745d0a39cdaa5d4c6"; + size = 41492432; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-armv7a-0.11.0.tar.xz"; + shasum = "aebe8bbeca39f13f9b7304465f9aee01ab005d243836bd40f4ec808093dccc9b"; + size = 42240664; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-riscv64-0.11.0.tar.xz"; + shasum = "24a478937eddb507e96d60bd4da00de9092b3f0920190eb45c4c99c946b00ed5"; + size = 43532324; + }; + + powerpc64le-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-powerpc64le-0.11.0.tar.xz"; + shasum = "75260e87325e820a278cf9e74f130c7b3d84c0b5197afb2e3c85eff3fcedd48d"; + size = 44656184; + }; + + powerpc-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-powerpc-0.11.0.tar.xz"; + shasum = "70a5f9668a66fb2a91a7c3488b15bcb568e1f9f44b95cd10075c138ad8c42864"; + size = 44539972; + }; + + i686-linux = { + tarball = "https://ziglang.org/download/0.11.0/zig-linux-x86-0.11.0.tar.xz"; + shasum = "7b0dc3e0e070ae0e0d2240b1892af6a1f9faac3516cae24e57f7a0e7b04662a8"; + size = 49824456; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.11.0/zig-windows-x86_64-0.11.0.zip"; + shasum = "142caa3b804d86b4752556c9b6b039b7517a08afa3af842645c7e2dcd125f652"; + size = 77216743; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.11.0/zig-windows-aarch64-0.11.0.zip"; + shasum = "5d4bd13db5ecb0ddc749231e00f125c1d31087d708e9ff9b45c4f4e13e48c661"; + size = 73883137; + }; + + i686-mingw32 = { + tarball = "https://ziglang.org/download/0.11.0/zig-windows-x86-0.11.0.zip"; + shasum = "e72b362897f28c671633e650aa05289f2e62b154efcca977094456c8dac3aefa"; + size = 81576961; + }; + }; + + meta-0_10_1 = { + version = "0.10.1"; + date = "2023-01-19"; + docs = "https://ziglang.org/documentation/0.10.1/"; + stdDocs = "https://ziglang.org/documentation/0.10.1/std/"; + notes = "https://ziglang.org/download/0.10.1/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.10.1/zig-0.10.1.tar.xz"; + shasum = "69459bc804333df077d441ef052ffa143d53012b655a51f04cfef1414c04168c"; + size = 15143112; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.10.1/zig-bootstrap-0.10.1.tar.xz"; + shasum = "9f5781210b9be8f832553d160851635780f9bd71816065351ab29cfd8968f5e9"; + size = 43971816; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.10.1/zig-macos-x86_64-0.10.1.tar.xz"; + shasum = "02483550b89d2a3070c2ed003357fd6e6a3059707b8ee3fbc0c67f83ca898437"; + size = 45119596; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.10.1/zig-macos-aarch64-0.10.1.tar.xz"; + shasum = "b9b00477ec5fa1f1b89f35a7d2a58688e019910ab80a65eac2a7417162737656"; + size = 40517896; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.10.1/zig-linux-x86_64-0.10.1.tar.xz"; + shasum = "6699f0e7293081b42428f32c9d9c983854094bd15fee5489f12c4cf4518cc380"; + size = 44085596; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.10.1/zig-linux-aarch64-0.10.1.tar.xz"; + shasum = "db0761664f5f22aa5bbd7442a1617dd696c076d5717ddefcc9d8b95278f71f5d"; + size = 40321280; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.10.1/zig-linux-riscv64-0.10.1.tar.xz"; + shasum = "9db5b59a5112b8beb995094ba800e88b0060e9cf7cfadf4dc3e666c9010dc77b"; + size = 42196008; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.10.1/zig-linux-i386-0.10.1.tar.xz"; + shasum = "8c710ca5966b127b0ee3efba7310601ee57aab3dd6052a082ebc446c5efb2316"; + size = 48367388; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.10.1/zig-windows-x86_64-0.10.1.zip"; + shasum = "5768004e5e274c7969c3892e891596e51c5df2b422d798865471e05049988125"; + size = 73259729; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.10.1/zig-windows-aarch64-0.10.1.zip"; + shasum = "ece93b0d77b2ab03c40db99ef7ccbc63e0b6bd658af12b97898960f621305428"; + size = 69417459; + }; + }; + + meta-0_10_0 = { + version = "0.10.0"; + date = "2022-10-31"; + docs = "https://ziglang.org/documentation/0.10.0/"; + stdDocs = "https://ziglang.org/documentation/0.10.0/std/"; + notes = "https://ziglang.org/download/0.10.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.10.0/zig-0.10.0.tar.xz"; + shasum = "d8409f7aafc624770dcd050c8fa7e62578be8e6a10956bca3c86e8531c64c136"; + size = 14530912; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.10.0/zig-bootstrap-0.10.0.tar.xz"; + shasum = "c13dc70c4ff4c09f749adc0d473cbd3942991dd4d1bd2d860fbf257d8c1bbabf"; + size = 45625516; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.10.0/zig-freebsd-x86_64-0.10.0.tar.xz"; + shasum = "dd77afa2a8676afbf39f7d6068eda81b0723afd728642adaac43cb2106253d65"; + size = 44056504; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.10.0/zig-linux-aarch64-0.10.0.tar.xz"; + shasum = "09ef50c8be73380799804169197820ee78760723b0430fa823f56ed42b06ea0f"; + size = 40387688; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.10.0/zig-linux-armv7a-0.10.0.tar.xz"; + shasum = "7201b2e89cd7cc2dde95d39485fd7d5641ba67dc6a9a58c036cb4c308d2e82de"; + size = 50805936; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.10.0/zig-linux-i386-0.10.0.tar.xz"; + shasum = "dac8134f1328c50269f3e50b334298ec7916cb3b0ef76927703ddd1c96fd0115"; + size = 48451732; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.10.0/zig-linux-riscv64-0.10.0.tar.xz"; + shasum = "2a126f3401a7a7efc4b454f0a85c133db1af5a9dfee117f172213b7cbd47bfba"; + size = 42272968; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.10.0/zig-linux-x86_64-0.10.0.tar.xz"; + shasum = "631ec7bcb649cd6795abe40df044d2473b59b44e10be689c15632a0458ddea55"; + size = 44142400; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.10.0/zig-macos-aarch64-0.10.0.tar.xz"; + shasum = "02f7a7839b6a1e127eeae22ea72c87603fb7298c58bc35822a951479d53c7557"; + size = 40602664; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.10.0/zig-macos-x86_64-0.10.0.tar.xz"; + shasum = "3a22cb6c4749884156a94ea9b60f3a28cf4e098a69f08c18fbca81c733ebfeda"; + size = 45175104; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.10.0/zig-windows-x86_64-0.10.0.zip"; + shasum = "a66e2ff555c6e48781de1bcb0662ef28ee4b88af3af2a577f7b1950e430897ee"; + size = 73181558; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.10.0/zig-windows-aarch64-0.10.0.zip"; + shasum = "1bbda8d123d44f3ae4fa90d0da04b1e9093c3f9ddae3429a4abece1e1c0bf19a"; + size = 69332389; + }; + }; + + meta-0_9_1 = { + version = "0.9.1"; + date = "2022-02-14"; + docs = "https://ziglang.org/documentation/0.9.1/"; + stdDocs = "https://ziglang.org/documentation/0.9.1/std/"; + notes = "https://ziglang.org/download/0.9.1/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.9.1/zig-0.9.1.tar.xz"; + shasum = "38cf4e84481f5facc766ba72783e7462e08d6d29a5d47e3b75c8ee3142485210"; + size = 13940828; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.9.1/zig-bootstrap-0.9.1.tar.xz"; + shasum = "0a8e221c71860d8975c15662b3ed3bd863e81c4fe383455a596e5e0e490d6109"; + size = 42488812; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.9.1/zig-freebsd-x86_64-0.9.1.tar.xz"; + shasum = "4e06009bd3ede34b72757eec1b5b291b30aa0d5046dadd16ecb6b34a02411254"; + size = 39028848; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.9.1/zig-linux-aarch64-0.9.1.tar.xz"; + shasum = "5d99a39cded1870a3fa95d4de4ce68ac2610cca440336cfd252ffdddc2b90e66"; + size = 37034860; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.9.1/zig-linux-armv7a-0.9.1.tar.xz"; + shasum = "6de64456cb4757a555816611ea697f86fba7681d8da3e1863fa726a417de49be"; + size = 37974652; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.9.1/zig-linux-i386-0.9.1.tar.xz"; + shasum = "e776844fecd2e62fc40d94718891057a1dbca1816ff6013369e9a38c874374ca"; + size = 44969172; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.9.1/zig-linux-riscv64-0.9.1.tar.xz"; + shasum = "208dea53662c2c52777bd9e3076115d2126a4f71aed7f2ff3b8fe224dc3881aa"; + size = 39390868; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz"; + shasum = "be8da632c1d3273f766b69244d80669fe4f5e27798654681d77c992f17c237d7"; + size = 41011464; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.9.1/zig-macos-aarch64-0.9.1.tar.xz"; + shasum = "8c473082b4f0f819f1da05de2dbd0c1e891dff7d85d2c12b6ee876887d438287"; + size = 38995640; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.9.1/zig-macos-x86_64-0.9.1.tar.xz"; + shasum = "2d94984972d67292b55c1eb1c00de46580e9916575d083003546e9a01166754c"; + size = 43713044; + }; + + i386-windows = { + tarball = "https://ziglang.org/download/0.9.1/zig-windows-i386-0.9.1.zip"; + shasum = "74a640ed459914b96bcc572183a8db687bed0af08c30d2ea2f8eba03ae930f69"; + size = 67929868; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.9.1/zig-windows-x86_64-0.9.1.zip"; + shasum = "443da53387d6ae8ba6bac4b3b90e9fef4ecbe545e1c5fa3a89485c36f5c0e3a2"; + size = 65047697; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.9.1/zig-windows-aarch64-0.9.1.zip"; + shasum = "621bf95f54dc3ff71466c5faae67479419951d7489e40e87fd26d195825fb842"; + size = 61478151; + }; + }; + + meta-0_9_0 = { + version = "0.9.0"; + date = "2021-12-20"; + docs = "https://ziglang.org/documentation/0.9.0/"; + stdDocs = "https://ziglang.org/documentation/0.9.0/std/"; + notes = "https://ziglang.org/download/0.9.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.9.0/zig-0.9.0.tar.xz"; + shasum = "cd1be83b12f8269cc5965e59877b49fdd8fa638efb6995ac61eb4cea36a2e381"; + size = 13928772; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.9.0/zig-bootstrap-0.9.0.tar.xz"; + shasum = "16b0bdf0bc0a5ed1e0950e08481413d806192e06443a512347526647b2baeabc"; + size = 42557736; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.9.0/zig-freebsd-x86_64-0.9.0.tar.xz"; + shasum = "c95afe679b7cc4110dc2ecd3606c83a699718b7a958d6627f74c20886333e194"; + size = 41293236; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.9.0/zig-linux-aarch64-0.9.0.tar.xz"; + shasum = "1524fedfdbade2dbc9bae1ed98ad38fa7f2114c9a3e94da0d652573c75efbc5a"; + size = 40008396; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.9.0/zig-linux-armv7a-0.9.0.tar.xz"; + shasum = "50225dee6e6448a63ee96383a34d9fe3bba34ae8da1a0c8619bde2cdfc1df87d"; + size = 41196876; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.9.0/zig-linux-i386-0.9.0.tar.xz"; + shasum = "b0dcf688349268c883292acdd55eaa3c13d73b9146e4b990fad95b84a2ac528b"; + size = 47408656; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.9.0/zig-linux-riscv64-0.9.0.tar.xz"; + shasum = "85466de07504767ed37f59782672ad41bbdf43d6480fafd07f45543278b07620"; + size = 44171420; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.9.0/zig-linux-x86_64-0.9.0.tar.xz"; + shasum = "5c55344a877d557fb1b28939785474eb7f4f2f327aab55293998f501f7869fa6"; + size = 43420796; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.9.0/zig-macos-aarch64-0.9.0.tar.xz"; + shasum = "3991c70594d61d09fb4b316157a7c1d87b1d4ec159e7a5ecd11169ff74cad832"; + size = 39013392; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.9.0/zig-macos-x86_64-0.9.0.tar.xz"; + shasum = "c5280eeec4d6e5ea5ce5b448dc9a7c4bdd85ecfed4c1b96aa0835e48b36eccf0"; + size = 43764596; + }; + + i386-windows = { + tarball = "https://ziglang.org/download/0.9.0/zig-windows-i386-0.9.0.zip"; + shasum = "bb839434afc75092015cf4c33319d31463c18512bc01dd719aedf5dcbc368466"; + size = 67946715; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.9.0/zig-windows-x86_64-0.9.0.zip"; + shasum = "084ea2646850aaf068234b0f1a92b914ed629be47075e835f8a67d55c21d880e"; + size = 65045849; + }; + + aarch64-mingw32 = { + tarball = "https://ziglang.org/download/0.9.0/zig-windows-aarch64-0.9.0.zip"; + shasum = "f9018725e3fb2e8992b17c67034726971156eb190685018a9ac8c3a9f7a22340"; + size = 61461921; + }; + }; + + meta-0_8_1 = { + version = "0.8.1"; + date = "2021-09-06"; + docs = "https://ziglang.org/documentation/0.8.1/"; + stdDocs = "https://ziglang.org/documentation/0.8.1/std/"; + notes = "https://ziglang.org/download/0.8.1/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.8.1/zig-0.8.1.tar.xz"; + shasum = "8c428e14a0a89cb7a15a6768424a37442292858cdb695e2eb503fa3c7bf47f1a"; + size = 12650228; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.8.1/zig-bootstrap-0.8.1.tar.xz"; + shasum = "fa1239247f830ecd51c42537043f5220e4d1dfefdc54356fa419616a0efb3902"; + size = 43613464; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.8.1/zig-freebsd-x86_64-0.8.1.tar.xz"; + shasum = "fc4f6478bcf3a9fce1b8ef677a91694f476dd35be6d6c9c4f44a8b76eedbe176"; + size = 39150924; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.8.1/zig-linux-aarch64-0.8.1.tar.xz"; + shasum = "2166dc9f2d8df387e8b4122883bb979d739281e1ff3f3d5483fec3a23b957510"; + size = 37605932; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.8.1/zig-linux-armv7a-0.8.1.tar.xz"; + shasum = "5ba58141805e2519f38cf8e715933cbf059f4f3dade92c71838cce341045de05"; + size = 39185876; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.8.1/zig-linux-i386-0.8.1.tar.xz"; + shasum = "2f3e84f30492b5f1c5f97cecc0166f07a8a8d50c5f85dbb3a6ef2a4ee6f915e6"; + size = 44782932; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.8.1/zig-linux-riscv64-0.8.1.tar.xz"; + shasum = "4adfaf147b025917c03367462fe5018aaa9edbc6439ef9cd0da2b074ae960554"; + size = 41234480; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.8.1/zig-linux-x86_64-0.8.1.tar.xz"; + shasum = "6c032fc61b5d77a3f3cf781730fa549f8f059ffdb3b3f6ad1c2994d2b2d87983"; + size = 41250060; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.8.1/zig-macos-aarch64-0.8.1.tar.xz"; + shasum = "5351297e3b8408213514b29c0a938002c5cf9f97eee28c2f32920e1227fd8423"; + size = 35340712; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.8.1/zig-macos-x86_64-0.8.1.tar.xz"; + shasum = "16b0e1defe4c1807f2e128f72863124bffdd906cefb21043c34b673bf85cd57f"; + size = 39946200; + }; + + i386-windows = { + tarball = "https://ziglang.org/download/0.8.1/zig-windows-i386-0.8.1.zip"; + shasum = "099605051eb0452a947c8eab8fbbc7e43833c8376d267e94e41131c289a1c535"; + size = 64152358; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.8.1/zig-windows-x86_64-0.8.1.zip"; + shasum = "43573db14cd238f7111d6bdf37492d363f11ecd1eba802567a172f277d003926"; + size = 61897838; + }; + }; + + meta-0_8_0 = { + version = "0.8.0"; + date = "2021-06-04"; + docs = "https://ziglang.org/documentation/0.8.0/"; + stdDocs = "https://ziglang.org/documentation/0.8.0/std/"; + notes = "https://ziglang.org/download/0.8.0/release-notes.html"; + + src = { + tarball = "https://ziglang.org/download/0.8.0/zig-0.8.0.tar.xz"; + shasum = "03a828d00c06b2e3bb8b7ff706997fd76bf32503b08d759756155b6e8c981e77"; + size = 12614896; + }; + + bootstrap = { + tarball = "https://ziglang.org/download/0.8.0/zig-bootstrap-0.8.0.tar.xz"; + shasum = "10600bc9c01f92e343f40d6ecc0ad05d67d27c3e382bce75524c0639cd8ca178"; + size = 43574248; + }; + + x86_64-freebsd = { + tarball = "https://ziglang.org/download/0.8.0/zig-freebsd-x86_64-0.8.0.tar.xz"; + shasum = "0d3ccc436c8c0f50fd55462f72f8492d98723c7218ffc2a8a1831967d81b4bdc"; + size = 39125332; + }; + + aarch64-linux = { + tarball = "https://ziglang.org/download/0.8.0/zig-linux-aarch64-0.8.0.tar.xz"; + shasum = "ee204ca2c2037952cf3f8b10c609373a08a291efa4af7b3c73be0f2b27720470"; + size = 37575428; + }; + + armv7l-linux = { + tarball = "https://ziglang.org/download/0.8.0/zig-linux-armv7a-0.8.0.tar.xz"; + shasum = "d00b8bd97b79f45d6f5da956983bafeaa082e6c2ae8c6e1c6d4faa22fa29b320"; + size = 38884212; + }; + + i386-linux = { + tarball = "https://ziglang.org/download/0.8.0/zig-linux-i386-0.8.0.tar.xz"; + shasum = "96e43ee6ed81c3c63401f456bd1c58ee6d42373a43cb324f5cf4974ca0998865"; + size = 42136032; + }; + + riscv64-linux = { + tarball = "https://ziglang.org/download/0.8.0/zig-linux-riscv64-0.8.0.tar.xz"; + shasum = "75997527a78cdab64c40c43d9df39c01c4cdb557bb3992a869838371a204cfea"; + size = 40016268; + }; + + x86_64-linux = { + tarball = "https://ziglang.org/download/0.8.0/zig-linux-x86_64-0.8.0.tar.xz"; + shasum = "502625d3da3ae595c5f44a809a87714320b7a40e6dff4a895b5fa7df3391d01e"; + size = 41211184; + }; + + aarch64-darwin = { + tarball = "https://ziglang.org/download/0.8.0/zig-macos-aarch64-0.8.0.tar.xz"; + shasum = "b32d13f66d0e1ff740b3326d66a469ee6baddbd7211fa111c066d3bd57683111"; + size = 35292180; + }; + + x86_64-darwin = { + tarball = "https://ziglang.org/download/0.8.0/zig-macos-x86_64-0.8.0.tar.xz"; + shasum = "279f9360b5cb23103f0395dc4d3d0d30626e699b1b4be55e98fd985b62bc6fbe"; + size = 39969312; + }; + + i386-windows = { + tarball = "https://ziglang.org/download/0.8.0/zig-windows-i386-0.8.0.zip"; + shasum = "b6ec9aa6cd6f3872fcb30d43ff411802d82008a0c4142ee49e208a09b2c1c5fe"; + size = 61507213; + }; + + x86_64-mingw32 = { + tarball = "https://ziglang.org/download/0.8.0/zig-windows-x86_64-0.8.0.zip"; + shasum = "8580fbbf3afb72e9b495c7f8aeac752a03475ae0bbcf5d787f3775c7e1f4f807"; + size = 61766193; + }; + }; +in +{ + latest = bin meta-0_14_0; + master = bin meta-master; + src-master = src meta-master; + "0_14_0" = bin meta-0_14_0; + src-0_14_0 = src meta-0_14_0; + "0_13_0" = bin meta-0_13_0; + src-0_13_0 = src meta-0_13_0; + "0_12_1" = bin meta-0_12_1; + src-0_12_1 = src meta-0_12_1; + "0_12_0" = bin meta-0_12_0; + src-0_12_0 = src meta-0_12_0; + "0_11_0" = bin meta-0_11_0; + src-0_11_0 = src meta-0_11_0; + "0_10_1" = bin meta-0_10_1; + src-0_10_1 = src meta-0_10_1; + "0_10_0" = bin meta-0_10_0; + src-0_10_0 = src meta-0_10_0; + "0_9_1" = bin meta-0_9_1; + src-0_9_1 = src meta-0_9_1; + "0_9_0" = bin meta-0_9_0; + src-0_9_0 = src meta-0_9_0; + "0_8_1" = bin meta-0_8_1; + src-0_8_1 = src meta-0_8_1; + "0_8_0" = bin meta-0_8_0; + src-0_8_0 = src meta-0_8_0; +} diff --git a/tools/zon2json/LICENSE b/src/zig2nix/LICENSE similarity index 100% rename from tools/zon2json/LICENSE rename to src/zig2nix/LICENSE diff --git a/tools/zon2json/build.zig b/src/zig2nix/build.zig similarity index 75% rename from tools/zon2json/build.zig rename to src/zig2nix/build.zig index 2d61353..446b6cd 100644 --- a/tools/zon2json/build.zig +++ b/src/zig2nix/build.zig @@ -4,20 +4,13 @@ pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const mod = b.addModule("zon2json", .{ - .root_source_file = b.path("src/zon2json.zig"), - .target = target, - .optimize = optimize, - }); - const exe = b.addExecutable(.{ - .name = "zon2json", + .name = "zig2nix", .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .single_threaded = true, }); - exe.root_module.addImport("zon2json", mod); b.installArtifact(exe); const run_cmd = b.addRunArtifact(exe); @@ -27,7 +20,7 @@ pub fn build(b: *std.Build) void { run_step.dependOn(&run_cmd.step); const unit_tests = b.addTest(.{ - .root_source_file = b.path("src/zon2json.zig"), + .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, .single_threaded = true, diff --git a/src/zig2nix/default.nix b/src/zig2nix/default.nix new file mode 100644 index 0000000..2cabcb7 --- /dev/null +++ b/src/zig2nix/default.nix @@ -0,0 +1,30 @@ +{ + lib + , stdenvNoCC + , zig + , git + , nixfmt-rfc-style + , nix-prefetch-git + , nix + , makeWrapper + , zigBuildFlags ? [] +}: + +with builtins; +with lib; + +stdenvNoCC.mkDerivation { + inherit zigBuildFlags; + name = "zig2nix"; + src = cleanSource ./.; + nativeBuildInputs = [ zig.hook makeWrapper ]; + meta.mainProgram = "zig2nix"; + postFixup = '' + wrapProgram $out/bin/zig2nix --prefix PATH : ${lib.makeBinPath [ + git + nix + nixfmt-rfc-style + nix-prefetch-git + ]} + ''; +} diff --git a/src/zig2nix/src/Target.zig b/src/zig2nix/src/Target.zig new file mode 100644 index 0000000..1a65380 --- /dev/null +++ b/src/zig2nix/src/Target.zig @@ -0,0 +1,186 @@ +const std = @import("std"); +const cli = @import("cli.zig"); + +zig: []const u8, +system: []const u8, +config: []const u8, +os: []const u8, +libc: bool, + +pub fn parse(allocator: std.mem.Allocator, arch_os_abi: []const u8) !@This() { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + const Arch = enum { + i686, + armv7a, + armv7l, + armv6l, + armv5tel, + mipsel, + mips, + mipsel64, + mips64, + powerpc, + _passthru, + }; + + const Platform = enum { + apple, + pc, + w64, + unknown, + _passthru, + }; + + const Os = enum { + darwin, + mingw32, + _passthru, + }; + + var cpu_features: std.ArrayListUnmanaged(u8) = .{}; + const fixed_arch_os_abi: []const u8 = D: { + var buf: std.ArrayListUnmanaged(u8) = try .initCapacity(arena, arch_os_abi.len); + var iter = std.mem.splitScalar(u8, arch_os_abi, '-'); + + const arch = iter.next() orelse break :D arch_os_abi; + switch (std.meta.stringToEnum(Arch, arch) orelse ._passthru) { + .i686 => try buf.appendSlice(arena, "x86"), + .armv7a, .armv7l => try buf.appendSlice(arena, "arm"), + .armv6l => { + try buf.appendSlice(arena, "arm"); + try cpu_features.appendSlice(arena, "-v7a+v6"); + }, + .armv5tel => { + try buf.appendSlice(arena, "arm"); + try cpu_features.appendSlice(arena, "-v7a+v5te"); + }, + .mipsel, + .mips, + .mipsel64, + .mips64, + .powerpc, + ._passthru, + => try buf.appendSlice(arena, arch), + } + try buf.appendSlice(arena, "-"); + + const platform = iter.peek() orelse break :D arch_os_abi; + switch (std.meta.stringToEnum(Platform, platform) orelse ._passthru) { + .w64 => { + try buf.appendSlice(arena, "windows-"); + _ = iter.next(); + }, + ._passthru => {}, + else => _ = iter.next(), + } + + const os = iter.next() orelse break :D arch_os_abi; + switch (std.meta.stringToEnum(Os, os) orelse ._passthru) { + .darwin => try buf.appendSlice(arena, "macos"), + .mingw32 => try buf.appendSlice(arena, "gnu"), + ._passthru => try buf.appendSlice(arena, os), + } + + if (iter.peek()) |_| { + try buf.appendSlice(arena, "-"); + try buf.appendSlice(arena, iter.rest()); + } else { + if (std.mem.eql(u8, os, "linux")) { + // default to -gnu + try buf.appendSlice( + arena, + switch (std.meta.stringToEnum(Arch, arch) orelse ._passthru) { + .mipsel64, .mips64 => "-gnuabi64", + .mipsel, .mips, .powerpc, .armv7a, .armv7l, .armv6l => "-gnueabihf", + else => "-gnu", + }, + ); + } + } + + break :D buf.items; + }; + + const target = try std.zig.system.resolveTargetQuery(try .parse(.{ + .arch_os_abi = fixed_arch_os_abi, + .cpu_features = try std.fmt.allocPrint(arena, "baseline{s}", .{cpu_features.items}), + })); + + const arch = switch (target.cpu.arch) { + .x86 => "i686", + .arm => D: { + if (std.Target.arm.featureSetHas(target.cpu.features, .v6)) { + break :D "armv6l"; + } else if (std.Target.arm.featureSetHas(target.cpu.features, .v5te)) { + break :D "armv5tel"; + } else if (std.Target.arm.featureSetHas(target.cpu.features, .v7a)) { + break :D "armv7l"; + } + return error.UnknownArmSubArch; + }, + else => |tag| @tagName(tag), + }; + + const os = switch (target.os.tag) { + .windows => switch (target.abi) { + .gnu => "mingw32", + .msvc => "windows", + else => @tagName(target.os.tag), + }, + .macos => "darwin", + .freestanding => "none", + else => |tag| @tagName(tag), + }; + + const abi = switch (target.os.tag) { + else => switch (target.cpu.arch) { + .powerpc64 => switch (target.abi) { + .gnu => "gnuabielfv2", + else => @tagName(target.abi), + }, + else => @tagName(target.abi), + }, + }; + + const vendor = switch (target.os.tag) { + .macos, .ios, .watchos, .visionos => "apple", + .windows => switch (target.abi) { + .gnu => "w64", + else => "pc", + }, + else => "unknown", + }; + + const config_format: enum { + quad, + triple, + } = switch (target.os.tag) { + .linux => .quad, + else => .triple, + }; + + const config = switch (config_format) { + .quad => try std.fmt.allocPrint(allocator, "{s}-{s}-{s}-{s}", .{ + arch, + vendor, + os, + abi, + }), + .triple => try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{ + arch, + vendor, + os, + }), + }; + + return .{ + .zig = try target.linuxTriple(allocator), + .system = try std.fmt.allocPrint(allocator, "{s}-{s}", .{ arch, os }), + .config = config, + .os = @tagName(target.os.tag), + .libc = std.zig.target.canBuildLibC(target), + }; +} diff --git a/src/zig2nix/src/cli.zig b/src/zig2nix/src/cli.zig new file mode 100644 index 0000000..b8721ed --- /dev/null +++ b/src/zig2nix/src/cli.zig @@ -0,0 +1,160 @@ +const std = @import("std"); + +pub const ExitStatus = enum(u8) { + /// succesful termination + ok = 0, + /// command line usage error + usage = 64, + /// data format error + dataerr = 65, + /// cannot open input + noinput = 66, + /// addressee unknown + nouser = 67, + /// host name unknown + nohost = 68, + /// service unavailable + unavailable = 69, + /// internal software error + software = 70, + /// system error (e.g., can't fork) + oserr = 71, + /// critical os file missing + osfile = 72, + /// can't create (user) output file + cantcreat = 73, + /// input/output error + ioerr = 74, + /// temp failure; user is invited to retry + tempfail = 75, + /// remote error in proctol + protocol = 76, + /// permission denied + noperm = 77, + /// configuration error + config = 78, + /// rest is custom + _, +}; + +pub fn exit(status: ExitStatus) noreturn { + std.posix.exit(@intFromEnum(status)); +} + +pub fn download(allocator: std.mem.Allocator, url: []const u8, writer: anytype, max_read_size: usize) !void { + var client: std.http.Client = .{ .allocator = allocator }; + defer client.deinit(); + + var body: std.ArrayList(u8) = .init(allocator); + defer body.deinit(); + + _ = try client.fetch(.{ + .method = .GET, + .location = .{ .url = url }, + .response_storage = .{ .dynamic = &body }, + .max_append_size = max_read_size, + }); + + try writer.writeAll(body.items); +} + +pub const Pipe = struct { + child: std.process.Child, + finished: bool = false, + + pub fn writer(self: *@This()) std.fs.File.Writer { + return self.child.stdin.?.writer(); + } + + pub fn reader(self: *@This()) std.fs.File.Reader { + return self.child.stdout.?.reader(); + } + + pub fn close(self: *@This()) void { + self.child.stdin.?.close(); + self.child.stdin = null; + } + + pub fn finish(self: *@This()) !std.process.Child.Term { + defer self.finished = true; + return self.child.wait(); + } + + pub fn deinit(self: *@This()) void { + if (!self.finished) _ = self.child.kill() catch {}; + self.* = undefined; + } +}; + +pub fn pipe(allocator: std.mem.Allocator, cwd: ?std.fs.Dir, argv: []const []const u8) !Pipe { + var child: std.process.Child = .init(argv, allocator); + child.cwd_dir = cwd; + child.stdout_behavior = .Pipe; + child.stdin_behavior = .Pipe; + child.stderr_behavior = .Inherit; + try child.spawn(); + _ = child.stdin orelse return error.NoStdinAvailable; + _ = child.stdout orelse return error.NoStdoutAvailable; + return .{ .child = child }; +} + +pub fn run(allocator: std.mem.Allocator, cwd: ?std.fs.Dir, argv: []const []const u8, max_size: usize) ![]const u8 { + var proc = try pipe(allocator, cwd, argv); + defer proc.deinit(); + proc.close(); + const body = try proc.reader().readAllAlloc(allocator, max_size); + switch (try proc.finish()) { + .Exited => |status| switch (status) { + 0 => {}, + else => return error.ProcessRunFailed, + }, + else => return error.ProcessRunFailed, + } + return std.mem.trim(u8, body, &std.ascii.whitespace); +} + +pub const TmpDir = struct { + path: std.BoundedArray(u8, 32), + dir: std.fs.Dir, + + pub fn close(self: *@This()) void { + defer self.* = undefined; + var tmp = std.fs.openDirAbsolute("/tmp", .{}) catch return; + defer tmp.close(); + tmp.deleteTree(self.path.constSlice()) catch unreachable; + } +}; + +pub fn mktemp(comptime prefix: []const u8) !TmpDir { + var tmp = try std.fs.openDirAbsolute("/tmp", .{ .access_sub_paths = false }); + defer tmp.close(); + const random_bytes = 8; + var buf: [prefix.len + random_bytes * 2]u8 = (prefix ++ ("00" ** random_bytes)).*; + var random_part = buf[prefix.len..][0..]; + std.crypto.random.bytes(random_part[0..random_bytes]); + const hex = std.fmt.bytesToHex(random_part[0..random_bytes], .lower); + random_part.* = hex; + const dir = try tmp.makeOpenPath(&buf, .{ .no_follow = true, .access_sub_paths = false }); + var cpy: std.BoundedArray(u8, 32) = .{}; + try cpy.appendSlice(&buf); + return .{ .path = cpy, .dir = dir }; +} + +const ZigEnv = struct { + zig_exe: []const u8, + lib_dir: []const u8, + std_dir: []const u8, + global_cache_dir: []const u8, + version: []const u8, +}; + +pub fn fetchZigEnv(allocator: std.mem.Allocator) !std.json.Parsed(ZigEnv) { + var proc = try pipe(allocator, null, &.{ "zig", "env" }); + defer proc.deinit(); + proc.close(); + var reader = std.json.reader(allocator, proc.reader()); + defer reader.deinit(); + const env = try std.json.parseFromTokenSource(ZigEnv, allocator, &reader, .{ .ignore_unknown_fields = true }); + _ = try proc.finish(); + return env; +} diff --git a/src/zig2nix/src/main.zig b/src/zig2nix/src/main.zig new file mode 100644 index 0000000..3b4db51 --- /dev/null +++ b/src/zig2nix/src/main.zig @@ -0,0 +1,173 @@ +const std = @import("std"); +const cli = @import("cli.zig"); +const zon2json = @import("zon2json.zig"); +const zon2lock = @import("zon2lock.zig"); +const zon2nix = @import("zon2nix.zig"); +const versions = @import("versions.zig"); +const Target = @import("Target.zig"); + +test { + comptime { + _ = cli; + _ = zon2json; + _ = zon2lock; + _ = versions; + _ = Target; + } +} + +const mib_in_bytes = 1048576; + +pub const MainCommand = enum { + zon2json, + zon2lock, + zon2nix, + target, + versions, + help, + zen, +}; + +pub const GeneralOptions = enum { + help, +}; + +fn usage(writer: anytype) !void { + try writer.writeAll( + \\Usage: zig2nix [command] [options] + \\ + \\Commands: + \\ + ); + for (std.enums.values(MainCommand)) |cmd| { + var counter = std.io.countingWriter(writer); + try counter.writer().print(" {s}", .{@tagName(cmd)}); + try writer.writeByteNTimes(' ', 20 - counter.bytes_written); + try switch (cmd) { + .zon2json => writer.writeAll("Convert zon to json\n"), + .zon2lock => writer.writeAll("Convert build.zig.zon to build.zig.zon2json-lock\n"), + .zon2nix => writer.writeAll("Convert build.zig.zon2json-lock to a nix derivation\n"), + .target => writer.writeAll("Print information about the target\n"), + .versions => writer.writeAll("Generate versions.nix from a zig binary index\n"), + .help => writer.writeAll("Print this help and exit\n"), + .zen => writer.writeAll("Print zen of zig2nix and exit\n"), + }; + } + try writer.writeAll( + \\ + \\General Options: + \\ + ); + for (std.enums.values(GeneralOptions)) |opt| { + var counter = std.io.countingWriter(writer); + try counter.writer().print(" -{c}, --{s}", .{ @tagName(opt)[0], @tagName(opt) }); + try writer.writeByteNTimes(' ', 20 - counter.bytes_written); + try switch (opt) { + .help => writer.writeAll("Print command-specific usage\n"), + }; + } +} + +fn @"cmd::help"(_: std.mem.Allocator, _: *std.process.ArgIterator, stdout: anytype, _: anytype) !void { + try usage(stdout); +} + +fn @"cmd::zen"(_: std.mem.Allocator, _: *std.process.ArgIterator, stdout: anytype, _: anytype) !void { + try stdout.writeAll( + \\ + \\ * Death to NativePaths.zig + \\ + \\ + ); +} + +fn @"cmd::target"(arena: std.mem.Allocator, args: *std.process.ArgIterator, stdout: anytype, _: anytype) !void { + const result = try Target.parse(arena, args.next() orelse "native"); + try stdout.print("{s}", .{std.json.fmt(result, .{ .whitespace = .indent_2 })}); +} + +fn @"cmd::zon2json"(arena: std.mem.Allocator, args: *std.process.ArgIterator, stdout: anytype, stderr: anytype) !void { + const path = args.next() orelse "build.zig.zon"; + var file = try std.fs.cwd().openFile(path, .{ .mode = .read_only }); + defer file.close(); + try zon2json.parse(arena, file.reader(), stdout, stderr, .{ .file_name = path }); +} + +fn @"cmd::zon2lock"(arena: std.mem.Allocator, args: *std.process.ArgIterator, stdout: anytype, stderr: anytype) !void { + const path = args.next() orelse "build.zig.zon"; + try zon2lock.write(arena, std.fs.cwd(), path, stdout, stderr); +} + +fn @"cmd::zon2nix"(arena: std.mem.Allocator, args: *std.process.ArgIterator, stdout: anytype, stderr: anytype) !void { + const path = args.next() orelse "build.zig.zon"; + if (std.mem.endsWith(u8, path, "zig.zon")) { + const lock_path = try std.fmt.allocPrint(arena, "{s}2json-lock", .{path}); + if (std.fs.cwd().access(lock_path, .{})) { + try zon2nix.write(arena, std.fs.cwd(), lock_path, stdout); + } else |_| { + var json: std.ArrayListUnmanaged(u8) = .{}; + defer json.deinit(arena); + try zon2lock.write(arena, std.fs.cwd(), path, json.writer(arena), stderr); + try zon2nix.writeFromSlice(arena, json.items, stdout); + } + } else { + try zon2nix.write(arena, std.fs.cwd(), path, stdout); + } +} + +fn @"cmd::versions"(arena: std.mem.Allocator, args: *std.process.ArgIterator, stdout: anytype, _: anytype) !void { + var json: std.ArrayListUnmanaged(u8) = .{}; + defer json.deinit(arena); + const url = args.next() orelse "https://ziglang.org/download/index.json"; + try cli.download(arena, url, json.writer(arena), mib_in_bytes * 40); + try versions.write(arena, json.items, stdout); +} + +fn realMain(stdout: anytype, stderr: anytype) !void { + var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator); + const arena = arena_state.allocator(); + + var args = try std.process.argsWithAllocator(arena); + defer args.deinit(); + + _ = args.skip(); + const cmd_str = args.next() orelse return error.MainCommandRequired; + const cmd = std.meta.stringToEnum(MainCommand, cmd_str) orelse return error.UnknownMainCommand; + + switch (cmd) { + inline else => |tag| { + const fn_name = "cmd::" ++ @tagName(tag); + try @call(.auto, @field(@This(), fn_name), .{ arena, &args, stdout, stderr }); + }, + } +} + +pub fn main() !noreturn { + var status: cli.ExitStatus = .ok; + { + var stdout = std.io.bufferedWriter(std.io.getStdOut().writer()); + defer stdout.flush() catch {}; + var stderr = std.io.bufferedWriter(std.io.getStdErr().writer()); + defer stderr.flush() catch {}; + realMain(stdout.writer(), stderr.writer()) catch |err| { + switch (err) { + error.MainCommandRequired, + error.UnknownMainCommand, + => { + try usage(stderr.writer()); + status = .usage; + }, + else => |suberr| { + try stderr.writer().print("{}", .{suberr}); + if (@errorReturnTrace()) |trace| { + std.debug.dumpStackTrace(trace.*); + } + status = switch (suberr) { + else => .software, + }; + }, + } + }; + } + cli.exit(status); +} diff --git a/src/zig2nix/src/versions.zig b/src/zig2nix/src/versions.zig new file mode 100644 index 0000000..bbb4e81 --- /dev/null +++ b/src/zig2nix/src/versions.zig @@ -0,0 +1,133 @@ +const std = @import("std"); +const cli = @import("cli.zig"); +const Target = @import("Target.zig"); + +const Meta = enum { + version, + date, + docs, + stdDocs, + notes, +}; + +const Source = struct { + tarball: []const u8, + shasum: []const u8, + size: u64, + + pub fn write(self: @This(), writer: anytype) !void { + inline for (std.meta.fields(@This())) |field| { + switch (field.type) { + []const u8 => try writer.print("{s} = \"{s}\";\n", .{ field.name, @field(self, field.name) }), + else => try writer.print("{s} = {};\n", .{ field.name, @field(self, field.name) }), + } + } + } +}; + +fn assumeNext(scanner: *std.json.Scanner, comptime expected: std.json.TokenType) !std.meta.TagPayload(std.json.Token, @enumFromInt(@intFromEnum(expected))) { + const tok = try scanner.next(); + switch (tok) { + inline else => |_, tag| if (!std.mem.eql(u8, @tagName(tag), @tagName(expected))) return error.UnexpectedJson, + } + return @field(tok, @tagName(expected)); +} + +pub fn write(allocator: std.mem.Allocator, json: []const u8, out: anytype) !void { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + var scanner = std.json.Scanner.initCompleteInput(arena, json); + defer scanner.deinit(); + + var pipe = try cli.pipe(arena, null, &.{ "nixfmt", "-v" }); + defer pipe.deinit(); + const writer = pipe.writer(); + + try writer.writeAll( + \\{ + \\ callPackage + \\ , zigHook + \\}: + \\ + \\let + \\ bin = release: callPackage ./bin.nix { inherit zigHook release; }; + \\ src = release: callPackage ./src.nix { inherit zigHook release; }; + \\ + ); + + var releases: std.ArrayListUnmanaged([]const u8) = .{}; + defer releases.deinit(arena); + + try assumeNext(&scanner, .object_begin); + const opts: std.json.ParseOptions = .{ .max_value_len = 4096, .allocate = .alloc_if_needed }; + while (true) { + if (try scanner.peekNextTokenType() == .object_end) break; + const release = try assumeNext(&scanner, .string); + const release_name = try arena.dupe(u8, release); + std.mem.replaceScalar(u8, release_name, '.', '_'); + try releases.append(arena, release_name); + try assumeNext(&scanner, .object_begin); + try writer.print("\nmeta-{s} = {{\n", .{release_name}); + if (!std.mem.eql(u8, release, "master")) { + try writer.print("version = \"{s}\";\n", .{release}); + } + while (true) { + if (try scanner.peekNextTokenType() == .object_end) break; + const str_key = try assumeNext(&scanner, .string); + if (std.meta.stringToEnum(Meta, str_key)) |_| { + const value = try assumeNext(&scanner, .string); + try writer.print("{s} = \"{s}\";\n", .{ str_key, value }); + } else { + const src = try std.json.innerParse(Source, arena, &scanner, opts); + if (Target.parse(arena, str_key)) |target| { + try writer.print("\n{s} = {{\n", .{target.system}); + } else |_| { + try writer.print("\n{s} = {{\n", .{str_key}); + } + try src.write(writer); + try writer.writeAll("};\n"); + } + } + try writer.writeAll("};\n"); + try assumeNext(&scanner, .object_end); + if (std.mem.eql(u8, release, "0.8.0")) break; + } + + try writer.writeAll("in {\n"); + + const latest: []const u8 = D: { + for (releases.items) |rel| { + if (std.mem.eql(u8, rel, "master")) continue; + break :D rel; + } + return error.NoVersions; + }; + + try writer.print("latest = bin meta-{s};\n", .{latest}); + for (releases.items) |release| { + if (std.mem.eql(u8, release, "master")) { + try writer.print("{s} = bin meta-{s};\n", .{ release, release }); + } else { + try writer.print("\"{s}\" = bin meta-{s};\n", .{ release, release }); + } + try writer.print("src-{s} = src meta-{s};\n", .{ release, release }); + } + + try writer.writeAll("}"); + + pipe.close(); + pipe.reader().streamUntilDelimiter(out, 0, null) catch |err| switch (err) { + error.EndOfStream => {}, + else => |e| return e, + }; + + return switch (try pipe.finish()) { + .Exited => |status| switch (status) { + 0 => {}, + else => error.NixFmtFailed, + }, + else => error.NixFmtFailed, + }; +} diff --git a/tools/zon2json/src/zon2json.zig b/src/zig2nix/src/zon2json.zig similarity index 57% rename from tools/zon2json/src/zon2json.zig rename to src/zig2nix/src/zon2json.zig index f705bbe..a32ff29 100644 --- a/tools/zon2json/src/zon2json.zig +++ b/src/zig2nix/src/zon2json.zig @@ -26,6 +26,9 @@ fn stringifyValue(allocator: std.mem.Allocator, ast: std.zig.Ast, idx: std.zig.A defer allocator.free(v); return try std.json.stringifyAlloc(allocator, v, .{}); } + if (std.mem.startsWith(u8, slice, "0x")) { + return try std.fmt.allocPrint(allocator, "\"{s}\"", .{slice}); + } switch (std.zig.number_literal.parseNumberLiteral(slice)) { .int => |v| return try std.json.stringifyAlloc(allocator, v, .{}), .float => |v| return try std.json.stringifyAlloc(allocator, v, .{}), @@ -56,7 +59,7 @@ fn stringify(allocator: std.mem.Allocator, writer: anytype, ast: std.zig.Ast, id } else if (ast.fullArrayInit(&buf, idx)) |v| { try writer.writeAll("["); for (v.ast.elements, 0..) |i, n| { - try stringify(allocator, writer, ast, i, false) ; + try stringify(allocator, writer, ast, i, false); if (n + 1 != v.ast.elements.len) try writer.writeAll(","); } try writer.writeAll("]"); @@ -73,24 +76,25 @@ pub const Options = struct { file_name: []const u8 = "build.zig.zon", // for errors }; -pub fn parse(allocator: std.mem.Allocator, reader: std.io.AnyReader, writer: anytype, error_writer: anytype, opts: Options) !void { +pub fn parse(allocator: std.mem.Allocator, reader: anytype, writer: anytype, error_writer: anytype, opts: Options) !void { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + const zon = blk: { - var tmp = try reader.readAllAlloc(allocator, opts.limit); - errdefer allocator.free(tmp); - tmp = try allocator.realloc(tmp, tmp.len + 1); + var tmp = try reader.readAllAlloc(arena, opts.limit); + tmp = try arena.realloc(tmp, tmp.len + 1); tmp[tmp.len - 1] = 0; - break :blk tmp[0..tmp.len - 1 :0]; + break :blk tmp[0 .. tmp.len - 1 :0]; }; - defer allocator.free(zon); - var ast = try std.zig.Ast.parse(allocator, zon, .zon); - defer ast.deinit(allocator); + var ast = try std.zig.Ast.parse(arena, zon, .zon); if (ast.errors.len > 0) { if (@TypeOf(error_writer) != void) { for (ast.errors) |e| { const loc = ast.tokenLocation(ast.errorOffset(e), e.token); - try error_writer.print("error: {s}:{}:{}: ", .{opts.file_name, loc.line, loc.column}); + try error_writer.print("error: {s}:{}:{}: ", .{ opts.file_name, loc.line, loc.column }); try ast.renderError(e, error_writer); try error_writer.writeAll("\n"); } @@ -98,17 +102,46 @@ pub fn parse(allocator: std.mem.Allocator, reader: std.io.AnyReader, writer: any return error.ParseFailed; } - try stringify(allocator, writer, ast, ast.nodes.items(.data)[0].lhs, false); + try stringify(arena, writer, ast, ast.nodes.items(.data)[0].lhs, false); +} + +pub fn parsePath(allocator: std.mem.Allocator, cwd: std.fs.Dir, path: []const u8, writer: anytype, error_writer: anytype) !void { + var file = try cwd.openFile(path, .{ .mode = .read_only }); + defer file.close(); + try parse(allocator, file.reader(), writer, error_writer, .{ .file_name = path }); +} + +pub fn parseFromSlice(allocator: std.mem.Allocator, slice: []const u8, writer: anytype, error_writer: anytype, opts: Options) !void { + var stream = std.io.fixedBufferStream(slice); + return parse(allocator, stream.reader(), writer, error_writer, opts); } test { const allocator = std.testing.allocator; - var json = std.ArrayList(u8).init(allocator); - defer json.deinit(); - var file = try std.fs.cwd().openFile("build.zig.zon", .{.mode = .read_only}); - defer file.close(); - try parse(allocator, file.reader().any(), json.writer(), {}, .{}); + var json: std.ArrayListUnmanaged(u8) = .{}; + defer json.deinit(allocator); + const zon = + \\.{ + \\ .name = .fixture1, + \\ .version = "0.0.1", + \\ .paths = .{ + \\ "src", + \\ "build.zig", + \\ "build.zig.zon", + \\ }, + \\ .dependencies = .{ + \\ .router = .{ + \\ .path = ".", + \\ }, + \\ .getty = .{ + \\ .url = "https://github.com/getty-zig/getty/archive/cb007b8ed148510de71ccc52143343b2e11413ff.tar.gz", + \\ .hash = "getty-0.4.0-AAAAAI4bCAAwD1LXWSkUZg7jyORh3HwQvUVwjrMt6w40", + \\ }, + \\ }, + \\} + ; + try parseFromSlice(allocator, zon, json.writer(allocator), {}, .{}); try std.testing.expectEqualStrings( - \\{"name":"zon2json","version":"0.0.0","dependencies":{},"paths":["src","build.zig","build.zig.zon","LICENSE"]} - , json.items); + \\{"name":"fixture1","version":"0.0.1","paths":["src","build.zig","build.zig.zon"],"dependencies":{"router":{"path":"."},"getty":{"url":"https://github.com/getty-zig/getty/archive/cb007b8ed148510de71ccc52143343b2e11413ff.tar.gz","hash":"getty-0.4.0-AAAAAI4bCAAwD1LXWSkUZg7jyORh3HwQvUVwjrMt6w40"}}} + , json.items); } diff --git a/src/zig2nix/src/zon2lock.zig b/src/zig2nix/src/zon2lock.zig new file mode 100644 index 0000000..9d9ed7e --- /dev/null +++ b/src/zig2nix/src/zon2lock.zig @@ -0,0 +1,325 @@ +const std = @import("std"); +const cli = @import("cli.zig"); +const zon2json = @import("zon2json.zig"); + +fn assumeNext(scanner: anytype, comptime expected: std.json.TokenType) !std.meta.TagPayload(std.json.Token, @enumFromInt(@intFromEnum(expected))) { + const tok = try scanner.next(); + switch (tok) { + inline else => |_, tag| if (!std.mem.eql(u8, @tagName(tag), @tagName(expected))) return error.UnexpectedJson, + } + return @field(tok, @tagName(expected)); +} + +pub const LockDependency = struct { + name: []const u8, + url: []const u8, + hash: []const u8, + rev: ?[]const u8 = null, + + pub fn dupeFields(self: *@This(), allocator: std.mem.Allocator) !void { + inline for (std.meta.fields(@This())) |field| { + if (field.type == ?[]const u8) { + if (@field(self, field.name)) |slice| { + @field(self, field.name) = try allocator.dupe(u8, slice); + } + } else { + @field(self, field.name) = try allocator.dupe(u8, @field(self, field.name)); + } + } + } +}; + +pub const Lock = struct { + arena: ?std.heap.ArenaAllocator = null, + map: std.StringArrayHashMapUnmanaged(LockDependency) = .{}, + + pub fn cacheHit(self: @This(), zdep: ZonDependency) bool { + const ldep = self.map.get(zdep.hash.?) orelse return false; + return std.mem.eql(u8, ldep.url, zdep.url.?); + } + + pub fn deinit(self: *@This()) void { + if (self.arena) |a| a.deinit(); + self.* = undefined; + } +}; + +pub fn parse(allocator: std.mem.Allocator, reader: anytype) !?Lock { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + errdefer arena_state.deinit(); + const arena = arena_state.allocator(); + + var map: std.StringArrayHashMapUnmanaged(LockDependency) = .{}; + assumeNext(reader, .object_begin) catch |err| switch (err) { + error.UnexpectedEndOfInput => return null, + else => |e| return e, + }; + + const opts: std.json.ParseOptions = .{ .max_value_len = 4096, .allocate = .alloc_if_needed }; + while (true) { + if (try reader.peekNextTokenType() == .object_end) break; + const zhash = try assumeNext(reader, .string); + var dep = try std.json.innerParse(LockDependency, arena, reader, opts); + try dep.dupeFields(arena); + try map.putNoClobber(arena, try arena.dupe(u8, zhash), dep); + } + try assumeNext(reader, .object_end); + + return .{ .arena = arena_state, .map = map }; +} + +pub fn parseSlice(allocator: std.mem.Allocator, json: []const u8) !?Lock { + var stream = std.io.fixedBufferStream(json); + var reader = std.json.reader(allocator, stream.reader()); + defer reader.deinit(); + return parse(allocator, &reader); +} + +pub fn parsePath(allocator: std.mem.Allocator, cwd: std.fs.Dir, path: []const u8) !?Lock { + var file = try cwd.openFile(path, .{}); + defer file.close(); + var reader = std.json.reader(allocator, file.reader()); + defer reader.deinit(); + return parse(allocator, &reader); +} + +const ZonDependency = struct { + url: ?[]const u8 = null, + hash: ?[]const u8 = null, + path: ?[]const u8 = null, +}; + +const LockBuilderContext = struct { + tmp: std.fs.Dir, + zig_cache: std.fs.Dir, + cwd: std.fs.Dir, + path: []const u8, + set: *std.StringHashMapUnmanaged(void), + lock: ?Lock, + + pub fn with(self: @This(), cwd: std.fs.Dir, path: []const u8) @This() { + var cpy = self; + cpy.cwd = cwd; + cpy.path = path; + return cpy; + } +}; + +const NixFetchResult = struct { + hash: []const u8, + rev: ?[]const u8 = null, +}; + +fn nixFetchHttp(allocator: std.mem.Allocator, ctx: LockBuilderContext, zhash: []const u8, url: []const u8) !NixFetchResult { + { + var artifact: std.ArrayListUnmanaged(u8) = .{}; + defer artifact.deinit(allocator); + try cli.download(allocator, url, artifact.writer(allocator), std.math.maxInt(usize)); + try ctx.tmp.writeFile(.{ + .data = artifact.items, + .sub_path = zhash, + }); + } + defer ctx.tmp.deleteFile(zhash) catch {}; + return .{ .hash = try cli.run(allocator, ctx.tmp, &.{ "nix", "hash", "path", "--mode", "flat", zhash }, 128) }; +} + +fn gitPrefetch(allocator: std.mem.Allocator, cwd: std.fs.Dir, zhash: []const u8, url: []const u8, rev: []const u8) !NixFetchResult { + const json = try cli.run( + allocator, + cwd, + &.{ "nix-prefetch-git", "--out", zhash, "--url", url, "--rev", rev, "--no-deepClone", "--fetch-submodules", "--quiet" }, + 4096, + ); + defer cwd.deleteTree(zhash) catch {}; + const Result = struct { hash: []const u8, rev: []const u8 }; + const res = try std.json.parseFromSliceLeaky(Result, allocator, json, .{ .ignore_unknown_fields = true, .max_value_len = 128 }); + return .{ .hash = res.hash, .rev = res.rev }; +} + +fn gitResolveRev(allocator: std.mem.Allocator, url: []const u8, sha_tag_branch: []const u8) ![]const u8 { + const is_sha: bool = D: { + if (sha_tag_branch.len == 40) { + for (sha_tag_branch) |chr| { + if (!std.ascii.isAlphanumeric(chr)) { + break :D false; + } + } + break :D true; + } + break :D false; + }; + if (is_sha) return sha_tag_branch; + const out = try cli.run(allocator, null, &.{ "git", "ls-remote", "--refs", "-tb", url, sha_tag_branch }, 4096); + var iter = std.mem.tokenizeAny(u8, out, &std.ascii.whitespace); + return iter.next() orelse return error.GitResolveShaFailed; +} + +fn nixFetchGit(allocator: std.mem.Allocator, ctx: LockBuilderContext, zhash: []const u8, url: []const u8) !NixFetchResult { + const base: []const u8 = D: { + var iter = std.mem.tokenizeAny(u8, url, "?#"); + break :D iter.next() orelse return error.InvalidGitUrl; + }; + + const rev: []const u8 = D: { + var iter = std.mem.tokenizeScalar(u8, url, '#'); + _ = iter.next() orelse return error.InvalidGitUrl; + break :D try gitResolveRev(allocator, base, iter.rest()); + }; + + return gitPrefetch(allocator, ctx.tmp, zhash, base, rev); +} + +fn nixFetch(allocator: std.mem.Allocator, ctx: LockBuilderContext, zhash: []const u8, url: []const u8, stderr: anytype) !NixFetchResult { + const Prefix = enum { + @"git+http://", + @"git+https://", + @"http://", + @"https://", + }; + + try stderr.print("fetching (nix hash): {s}\n", .{url}); + inline for (std.meta.fields(Prefix)) |field| { + if (std.mem.startsWith(u8, url, field.name)) { + return switch (@as(Prefix, @enumFromInt(field.value))) { + .@"git+http://", .@"git+https://" => nixFetchGit(allocator, ctx, zhash, url[4..]), + .@"http://", .@"https://" => nixFetchHttp(allocator, ctx, zhash, url), + }; + } + } + + return error.UnsupportedUrl; +} + +fn zigFetch(allocator: std.mem.Allocator, zhash: []const u8, url: []const u8, stderr: anytype) !void { + const zfhash = try cli.run(allocator, null, &.{ "zig", "fetch", url }, 128); + defer allocator.free(zfhash); + if (!std.mem.eql(u8, zhash, zfhash)) { + try stderr.print("fetching (zig fetch): {s}\n", .{url}); + try stderr.print("unexpected zig hash for dependency\ngot: {s}\nexpected: {s}\n", .{ + zfhash, + zhash, + }); + return error.BrokenZigZonDependency; + } +} + +fn writeInner(arena: std.mem.Allocator, ctx: LockBuilderContext, writer: anytype, stderr: anytype) !void { + var json: std.ArrayListUnmanaged(u8) = .{}; + defer json.deinit(arena); + zon2json.parsePath(arena, ctx.cwd, ctx.path, json.writer(arena), stderr) catch |err| switch (err) { + error.FileNotFound => return, + else => |e| return e, + }; + + var scanner = std.json.Scanner.initCompleteInput(arena, json.items); + defer scanner.deinit(); + + try assumeNext(&scanner, .object_begin); + while (true) { + switch (try scanner.next()) { + .string => |tok| if (std.mem.eql(u8, tok, "dependencies")) break, + .end_of_document => return error.InvalidBuildZigZon, + else => {}, + } + } + + const opts: std.json.ParseOptions = .{ .max_value_len = 4096, .allocate = .alloc_if_needed }; + try assumeNext(&scanner, .object_begin); + while (true) { + if (try scanner.peekNextTokenType() == .object_end) break; + const name = try assumeNext(&scanner, .string); + const dep = try std.json.innerParse(ZonDependency, arena, &scanner, opts); + if (dep.hash) |hash| { + const res = try ctx.set.getOrPut(arena, hash); + if (res.found_existing) continue; + if (ctx.zig_cache.access(hash, .{})) continue else |_| {} + res.value_ptr.* = {}; + res.key_ptr.* = try arena.dupe(u8, res.key_ptr.*); + } + + if (dep.url) |url| { + const zhash = dep.hash orelse return error.ZigZonDepMissingAHash; + + var pdir = ctx.zig_cache.openDir("p", .{}) catch D: { + try zigFetch(arena, zhash, url, stderr); + break :D try ctx.zig_cache.openDir("p", .{}); + }; + defer pdir.close(); + + var dir = pdir.openDir(zhash, .{}) catch D: { + try zigFetch(arena, zhash, url, stderr); + break :D try pdir.openDir(zhash, .{}); + }; + defer dir.close(); + + const nix: NixFetchResult = D: { + if (ctx.lock == null or !ctx.lock.?.cacheHit(dep)) { + break :D try nixFetch(arena, ctx, zhash, url, stderr); + } else { + const cached = ctx.lock.?.map.get(zhash).?; + break :D .{ .hash = cached.hash, .rev = cached.rev }; + } + }; + + try writer.objectField(zhash); + try writer.beginObject(); + try writer.objectField("name"); + try writer.write(name); + try writer.objectField("url"); + try writer.write(url); + try writer.objectField("hash"); + try writer.write(nix.hash); + if (nix.rev) |rev| { + try writer.objectField("rev"); + try writer.write(rev); + } + try writer.endObject(); + + try writeInner(arena, ctx.with(dir, "build.zig.zon"), writer, stderr); + } + + if (dep.path) |path| { + var dir = try ctx.cwd.openDir(path, .{}); + defer dir.close(); + try writeInner(arena, ctx.with(dir, "build.zig.zon"), writer, stderr); + } + } + + try assumeNext(&scanner, .object_end); +} + +fn openFileDir(cwd: std.fs.Dir, path: []const u8) !std.fs.Dir { + const dname = std.fs.path.dirname(path) orelse return cwd; + return cwd.openDir(dname, .{}); +} + +pub fn write(allocator: std.mem.Allocator, cwd: std.fs.Dir, path: []const u8, stdout: anytype, stderr: anytype) !void { + var dir = try openFileDir(cwd, path); + defer if (cwd.fd != dir.fd) dir.close(); + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + var env = try cli.fetchZigEnv(allocator); + defer env.deinit(); + var tmp = try cli.mktemp("zig2nix_"); + defer tmp.close(); + var set: std.StringHashMapUnmanaged(void) = .{}; + var writer = std.json.writeStream(stdout, .{ .whitespace = .indent_2 }); + defer writer.deinit(); + try writer.beginObject(); + const lock_path = try std.fmt.allocPrint(arena_state.allocator(), "{s}2json-lock", .{path}); + var lock = parsePath(arena_state.allocator(), cwd, lock_path) catch |err| switch (err) { + error.FileNotFound => null, + else => |e| return e, + }; + defer if (lock) |*lck| lck.deinit(); + try writeInner(arena_state.allocator(), .{ + .tmp = tmp.dir, + .zig_cache = try cwd.makeOpenPath(env.value.global_cache_dir, .{ .no_follow = true }), + .cwd = dir, + .path = std.fs.path.basename(path), + .set = &set, + .lock = lock, + }, &writer, stderr); + try writer.endObject(); +} diff --git a/src/zig2nix/src/zon2nix.zig b/src/zig2nix/src/zon2nix.zig new file mode 100644 index 0000000..0a71a7d --- /dev/null +++ b/src/zig2nix/src/zon2nix.zig @@ -0,0 +1,121 @@ +const std = @import("std"); +const cli = @import("cli.zig"); +const zon2lock = @import("zon2lock.zig"); + +fn writeInternal(arena: std.mem.Allocator, lock: zon2lock.Lock, out: anytype) !void { + var pipe = try cli.pipe(arena, null, &.{ "nixfmt", "-v" }); + defer pipe.deinit(); + const writer = pipe.writer(); + + try writer.writeAll( + \\# generated by zon2nix (https://github.com/Cloudef/zig2nix) + \\ + \\{ + \\ lib, + \\ linkFarm, + \\ fetchurl, + \\ fetchgit, + \\ runCommandLocal, + \\ zig, + \\ name ? "zig-packages", + \\}: + \\ + \\with builtins; + \\with lib; + \\ + \\let + \\ unpackZigArtifact = { name, artifact }: + \\ runCommandLocal name { nativeBuildInputs = [ zig ]; } + \\ '' + \\ hash="$(zig fetch --global-cache-dir "$TMPDIR" ${artifact})" + \\ mv "$TMPDIR/p/$hash" "$out" + \\ chmod 755 "$out" + \\ ''; + \\ + \\ fetchZig = { name, url, hash }: let + \\ artifact = fetchurl { inherit url hash; }; + \\ in unpackZigArtifact { inherit name artifact; }; + \\ + \\ fetchGitZig = { name, url, hash, rev ? throw "rev is required, remove and regenerate the zon2json-lock file" }: let + \\ parts = splitString "#" url; + \\ url_base = elemAt parts 0; + \\ url_without_query = elemAt (splitString "?" url_base) 0; + \\ in fetchgit { + \\ inherit name rev hash; + \\ url = url_without_query; + \\ deepClone = false; + \\ }; + \\ + \\ fetchZigArtifact = { name, url, hash, ... } @ args: let + \\ parts = splitString "://" url; + \\ proto = elemAt parts 0; + \\ path = elemAt parts 1; + \\ fetcher = { + \\ "git+http" = fetchGitZig (args // { + \\ url = "http://${path}"; + \\ }); + \\ "git+https" = fetchGitZig (args // { + \\ url = "https://${path}"; + \\ }); + \\ http = fetchZig { + \\ inherit name hash; + \\ url = "http://${path}"; + \\ }; + \\ https = fetchZig { + \\ inherit name hash; + \\ url = "https://${path}"; + \\ }; + \\ }; + \\ in fetcher.${proto}; + \\in linkFarm name [ + \\ + ); + + var iter = lock.map.iterator(); + while (iter.next()) |kv| { + const zhash = kv.key_ptr.*; + const dep = kv.value_ptr; + try writer.writeAll("{\n"); + try writer.print("name = \"{s}\";\n", .{zhash}); + try writer.writeAll("path = fetchZigArtifact {\n"); + try writer.print("name = \"{s}\";\n", .{dep.name}); + try writer.print("url = \"{s}\";\n", .{dep.url}); + try writer.print("hash = \"{s}\";\n", .{dep.hash}); + if (dep.rev) |rev| try writer.print("rev = \"{s}\";\n", .{rev}); + try writer.writeAll("};\n"); + try writer.writeAll("}\n"); + } + + try writer.writeAll("]"); + pipe.close(); + pipe.reader().streamUntilDelimiter(out, 0, null) catch |err| switch (err) { + error.EndOfStream => {}, + else => |e| return e, + }; + + return switch (try pipe.finish()) { + .Exited => |status| switch (status) { + 0 => {}, + else => error.NixFmtFailed, + }, + else => error.NixFmtFailed, + }; +} + +pub fn writeFromSlice(allocator: std.mem.Allocator, slice: []const u8, writer: anytype) !void { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + var lock = (try zon2lock.parseSlice(arena, slice)) orelse return; + defer lock.deinit(); + try writeInternal(arena, lock, writer); +} + +pub fn write(allocator: std.mem.Allocator, cwd: std.fs.Dir, path: []const u8, writer: anytype) !void { + var arena_state: std.heap.ArenaAllocator = .init(allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + var lock = (try zon2lock.parsePath(arena, cwd, path)) orelse return; + defer lock.deinit(); + try writeInternal(arena, lock, writer); +} diff --git a/templates/default/build.zig.zon b/templates/default/build.zig.zon index 03d8a4f..2444f5a 100644 --- a/templates/default/build.zig.zon +++ b/templates/default/build.zig.zon @@ -24,7 +24,7 @@ // original project's identity. Thus it is recommended to leave the comment // on the following line intact, so that it shows up in code reviews that // modify the field. - .fingerprint = 0xe35e00dfbebc0371, // Changing this has security and trust implications. + .fingerprint = 0xe35e00dff578ec7f, // Changing this has security and trust implications. // Tracks the earliest Zig version that the package considers to be a // supported use case. diff --git a/templates/default/flake.nix b/templates/default/flake.nix index c4d1c81..ce85609 100644 --- a/templates/default/flake.nix +++ b/templates/default/flake.nix @@ -12,15 +12,17 @@ # Check the flake.nix in zig2nix project for more options: # env = zig2nix.outputs.zig-env.${system} {}; - system-triple = env.lib.zigTripleFromString system; - in with builtins; with env.lib; with env.pkgs.lib; rec { - # nix build .#target.{zig-target} - # e.g. nix build .#target.x86_64-linux-gnu - packages.target = genAttrs allTargetTriples (target: env.packageForTarget target ({ + in with builtins; with env.pkgs.lib; rec { + # Produces clean binaries meant to be ship'd outside of nix + # nix build .#foreign + packages.foreign = env.package ({ src = cleanSource ./.; + # Packages required for compiling nativeBuildInputs = with env.pkgs; []; - buildInputs = with env.pkgsForTarget target; []; + + # Packages required for linking + buildInputs = with env.pkgs; []; # Smaller binaries and avoids shipping glibc. zigPreferMusl = true; @@ -31,26 +33,28 @@ } // optionalAttrs (!pathExists ./build.zig.zon) { pname = "my-zig-project"; version = "0.0.0"; - })); + }); # nix build . - packages.default = packages.target.${system-triple}.override { + packages.default = packages.foreign.overrideAttrs (attrs: { # Prefer nix friendly settings. zigPreferMusl = false; - zigDisableWrap = false; - }; + + # Executables requires for runtime + # These packages will be added to the PATH + zigWrapperBins = with env.pkgs; []; + + # Libraries requires for runtime + # These packages will be added to the LD_LIBRARY_PATH + zigWrapperLibs = with env.pkgs; []; + }); # For bundling with nix bundle for running outside of nix # example: https://github.com/ralismark/nix-appimage - apps.bundle.target = genAttrs allTargetTriples (target: let - pkg = packages.target.${target}; - in { + apps.bundle = { type = "app"; - program = "${pkg}/bin/default"; - }); - - # default bundle - apps.bundle.default = apps.bundle.target.${system-triple}; + program = "${packages.foreign}/bin/default"; + }; # nix run . apps.default = env.app [] "zig build run -- \"$@\""; @@ -64,16 +68,14 @@ # nix run .#docs apps.docs = env.app [] "zig build docs -- \"$@\""; - # nix run .#zon2json - apps.zon2json = env.app [env.zon2json] "zon2json \"$@\""; - - # nix run .#zon2json-lock - apps.zon2json-lock = env.app [env.zon2json-lock] "zon2json-lock \"$@\""; - - # nix run .#zon2nix - apps.zon2nix = env.app [env.zon2nix] "zon2nix \"$@\""; + # nix run .#zig2nix + apps.zig2nix = env.app [] "zig2nix \"$@\""; # nix develop - devShells.default = env.mkShell {}; + devShells.default = env.mkShell { + # Packages required for compiling, linking and running + # Libraries added here will be automatically added to the LD_LIBRARY_PATH and PKG_CONFIG_PATH + nativeBuildInputs = with env.pkgs; []; + }; })); } diff --git a/templates/flake.nix b/templates/flake.nix index 9c9326f..67f9814 100644 --- a/templates/flake.nix +++ b/templates/flake.nix @@ -12,15 +12,17 @@ # Check the flake.nix in zig2nix project for more options: # env = zig2nix.outputs.zig-env.${system} {/*SED_ZIG_VER*/}; - system-triple = env.lib.zigTripleFromString system; - in with builtins; with env.lib; with env.pkgs.lib; rec { - # nix build .#target.{zig-target} - # e.g. nix build .#target.x86_64-linux-gnu - packages.target = genAttrs allTargetTriples (target: env.packageForTarget target ({ + in with builtins; with env.pkgs.lib; rec { + # Produces clean binaries meant to be ship'd outside of nix + # nix build .#foreign + packages.foreign = env.package ({ src = cleanSource ./.; + # Packages required for compiling nativeBuildInputs = with env.pkgs; []; - buildInputs = with env.pkgsForTarget target; []; + + # Packages required for linking + buildInputs = with env.pkgs; []; # Smaller binaries and avoids shipping glibc. zigPreferMusl = true; @@ -31,26 +33,28 @@ } // optionalAttrs (!pathExists ./build.zig.zon) { pname = "my-zig-project"; version = "0.0.0"; - })); + }); # nix build . - packages.default = packages.target.${system-triple}.override { + packages.default = packages.foreign.overrideAttrs (attrs: { # Prefer nix friendly settings. zigPreferMusl = false; - zigDisableWrap = false; - }; + + # Executables requires for runtime + # These packages will be added to the PATH + zigWrapperBins = with env.pkgs; []; + + # Libraries requires for runtime + # These packages will be added to the LD_LIBRARY_PATH + zigWrapperLibs = with env.pkgs; []; + }); # For bundling with nix bundle for running outside of nix # example: https://github.com/ralismark/nix-appimage - apps.bundle.target = genAttrs allTargetTriples (target: let - pkg = packages.target.${target}; - in { + apps.bundle = { type = "app"; - program = "${pkg}/bin/@SED_ZIG_BIN@"; - }); - - # default bundle - apps.bundle.default = apps.bundle.target.${system-triple}; + program = "${packages.foreign}/bin/@SED_ZIG_BIN@"; + }; # nix run . apps.default = env.app [] "zig build run -- \"$@\""; @@ -64,16 +68,14 @@ # nix run .#docs apps.docs = env.app [] "zig build docs -- \"$@\""; - # nix run .#zon2json - apps.zon2json = env.app [env.zon2json] "zon2json \"$@\""; - - # nix run .#zon2json-lock - apps.zon2json-lock = env.app [env.zon2json-lock] "zon2json-lock \"$@\""; - - # nix run .#zon2nix - apps.zon2nix = env.app [env.zon2nix] "zon2nix \"$@\""; + # nix run .#zig2nix + apps.zig2nix = env.app [] "zig2nix \"$@\""; # nix develop - devShells.default = env.mkShell {}; + devShells.default = env.mkShell { + # Packages required for compiling, linking and running + # Libraries added here will be automatically added to the LD_LIBRARY_PATH and PKG_CONFIG_PATH + nativeBuildInputs = with env.pkgs; []; + }; })); } diff --git a/templates/master/build.zig.zon b/templates/master/build.zig.zon index 2ffdc44..f22f3f8 100644 --- a/templates/master/build.zig.zon +++ b/templates/master/build.zig.zon @@ -24,11 +24,11 @@ // original project's identity. Thus it is recommended to leave the comment // on the following line intact, so that it shows up in code reviews that // modify the field. - .fingerprint = 0x2d09a3d6b9655a0f, // Changing this has security and trust implications. + .fingerprint = 0x2d09a3d6aa3a9d22, // Changing this has security and trust implications. // Tracks the earliest Zig version that the package considers to be a // supported use case. - .minimum_zig_version = "0.14.0", + .minimum_zig_version = "0.15.0-dev.10+214750fcf", // This field is optional. // Each dependency must either provide a `url` and `hash`, or a `path`. diff --git a/templates/master/flake.nix b/templates/master/flake.nix index a104e14..261da2a 100644 --- a/templates/master/flake.nix +++ b/templates/master/flake.nix @@ -11,16 +11,18 @@ # Zig flake helper # Check the flake.nix in zig2nix project for more options: # - env = zig2nix.outputs.zig-env.${system} { zig = zig2nix.outputs.packages.${system}.zig.master.bin; }; - system-triple = env.lib.zigTripleFromString system; - in with builtins; with env.lib; with env.pkgs.lib; rec { - # nix build .#target.{zig-target} - # e.g. nix build .#target.x86_64-linux-gnu - packages.target = genAttrs allTargetTriples (target: env.packageForTarget target ({ + env = zig2nix.outputs.zig-env.${system} { zig = zig2nix.outputs.packages.${system}.zig-master; }; + in with builtins; with env.pkgs.lib; rec { + # Produces clean binaries meant to be ship'd outside of nix + # nix build .#foreign + packages.foreign = env.package ({ src = cleanSource ./.; + # Packages required for compiling nativeBuildInputs = with env.pkgs; []; - buildInputs = with env.pkgsForTarget target; []; + + # Packages required for linking + buildInputs = with env.pkgs; []; # Smaller binaries and avoids shipping glibc. zigPreferMusl = true; @@ -31,26 +33,28 @@ } // optionalAttrs (!pathExists ./build.zig.zon) { pname = "my-zig-project"; version = "0.0.0"; - })); + }); # nix build . - packages.default = packages.target.${system-triple}.override { + packages.default = packages.foreign.overrideAttrs (attrs: { # Prefer nix friendly settings. zigPreferMusl = false; - zigDisableWrap = false; - }; + + # Executables requires for runtime + # These packages will be added to the PATH + zigWrapperBins = with env.pkgs; []; + + # Libraries requires for runtime + # These packages will be added to the LD_LIBRARY_PATH + zigWrapperLibs = with env.pkgs; []; + }); # For bundling with nix bundle for running outside of nix # example: https://github.com/ralismark/nix-appimage - apps.bundle.target = genAttrs allTargetTriples (target: let - pkg = packages.target.${target}; - in { + apps.bundle = { type = "app"; - program = "${pkg}/bin/master"; - }); - - # default bundle - apps.bundle.default = apps.bundle.target.${system-triple}; + program = "${packages.foreign}/bin/master"; + }; # nix run . apps.default = env.app [] "zig build run -- \"$@\""; @@ -64,16 +68,14 @@ # nix run .#docs apps.docs = env.app [] "zig build docs -- \"$@\""; - # nix run .#zon2json - apps.zon2json = env.app [env.zon2json] "zon2json \"$@\""; - - # nix run .#zon2json-lock - apps.zon2json-lock = env.app [env.zon2json-lock] "zon2json-lock \"$@\""; - - # nix run .#zon2nix - apps.zon2nix = env.app [env.zon2nix] "zon2nix \"$@\""; + # nix run .#zig2nix + apps.zig2nix = env.app [] "zig2nix \"$@\""; # nix develop - devShells.default = env.mkShell {}; + devShells.default = env.mkShell { + # Packages required for compiling, linking and running + # Libraries added here will be automatically added to the LD_LIBRARY_PATH and PKG_CONFIG_PATH + nativeBuildInputs = with env.pkgs; []; + }; })); } diff --git a/tools/fixtures/2.zig.zon2json-lock b/tools/fixtures/2.zig.zon2json-lock deleted file mode 100644 index e69de29..0000000 diff --git a/tools/zon2json-lock.nix b/tools/zon2json-lock.nix deleted file mode 100644 index 7a46bdf..0000000 --- a/tools/zon2json-lock.nix +++ /dev/null @@ -1,138 +0,0 @@ -{ - zon2json - , writeShellApplication - , jq - , zig - , curl - , coreutils - , findutils - , nix-prefetch-git -}: - -writeShellApplication { - name = "zon2json-lock"; - runtimeInputs = [ zon2json jq zig curl findutils coreutils nix-prefetch-git ]; - text = '' - # shellcheck disable=SC2059 - error() { printf -- "error: $1\n" "''${@:2}" 1>&2; exit 1; } - - path="''${1:-build.zig.zon}" - if [[ ! -f "$path" ]]; then - error 'file does not exist: %s' "$path" - fi - - tmpdir="$(mktemp -d)" - trap 'rm -rf "$tmpdir"' EXIT - read -r zig_cache < <(zig env | jq -er '.global_cache_dir') - - split_git_url() { - url_part="''${1##git+}" - case "$1" in - *#*) - url_w_query="''${url_part%\#*}" - url="''${url_w_query%\?*}" - rev="''${url_part##*\#}" - printf -- "%s\n%s" "$url" "$rev" - ;; - *) - printf -- "%s\n%s" "$url_part" "HEAD" - ;; - esac - } - - git-prefetch() { - IFS=$'\n' read -rd "" git_url git_rev < <(split_git_url "$1") || true - if [[ "$git_rev" =~ ^[a-fA-F0-9]{40}$ ]]; then - nix-prefetch-git --out "$tmpdir/$zhash.git" \ - --url "$git_url" --rev "$git_rev" \ - --no-deepClone --fetch-submodules --quiet - else - read -r rev _ < <(git ls-remote --refs -tb "$git_url" "$git_rev") - nix-prefetch-git --out "$tmpdir/$zhash.git" \ - --url "$git_url" --rev "$rev" \ - --no-deepClone --fetch-submodules --quiet - fi - rm -rf "$tmpdir/$zhash.git" - } - - zon2json-recursive() { - while { - read -r name; - read -r url; - read -r zhash; - } do - # Prevent dependency loop - if [[ ! -f "$tmpdir/$zhash.read" ]]; then - # do not zig fetch if we have the dep already - if [[ ! -d "$zig_cache/p/$zhash" ]]; then - printf -- 'fetching (zig fetch): %s\n' "$url" 1>&2 - case "$url" in - file://*) - error 'unsupported url: %s' "$url" - ;; - *) - zhash2="$(zig fetch "$url" || true)" - ;; - esac - if [[ ! "$zhash2" ]] || [[ "$zhash" != "$zhash2" ]]; then - error 'unexpected zig hash, got: %s, expected: %s' "''${zhash2:-nothing}" "$zhash" - fi - fi - - # do not redownload artifact if we know its hash already - # we can't just rely on the zhash because it may not change even though the artifact change - old_url="$(jq -er --arg k "$zhash" '."\($k)".url' "''${path}2json-lock" 2>/dev/null || true)" - if [[ ! "$old_url" ]] || [[ "$old_url" != "$url" ]]; then - printf -- 'fetching (nix hash): %s\n' "$url" 1>&2 - case "$url" in - git+http://*|git+https://*) - read -r ahash rev < <(git-prefetch "$url" | jq -er '"\(.hash) \(.rev)"') - ;; - http://*|https://*) - curl -sSL "$url" -o "$tmpdir/$zhash.artifact" - ahash="$(cd "$tmpdir"; nix hash path --mode flat "$zhash.artifact")" - rm -f "$tmpdir/$zhash.artifact" - ;; - *) - error 'unsupported url: %s' "$url" - ;; - esac - else - read -r ahash rev < <(jq -er --arg k "$zhash" '."\($k)" | "\(.hash) \(.rev)"' "''${path}2json-lock") - fi - - if [[ "$rev" != "null" ]]; then - printf '{"%s":{"name":"%s","url":"%s","hash":"%s","rev":"%s"}}\n' "$zhash" "$name" "$url" "$ahash" "$rev" - else - printf '{"%s":{"name":"%s","url":"%s","hash":"%s"}}\n' "$zhash" "$name" "$url" "$ahash" - fi - touch "$tmpdir/$zhash.read" - - if [[ -f "$zig_cache/p/$zhash/build.zig.zon" ]]; then - zon2json-recursive "$zig_cache/p/$zhash/build.zig.zon" - fi - fi - done < <(zon2json "$1" | jq -r '.dependencies | to_entries | .[] | select(.value.url != null) | .key, .value.url, .value.hash' 2>/dev/null) - - # Go through path deps as well in case they have network deps - while read -r path_dep; do - rpath="$(realpath "$(dirname "$1")/$path_dep")" - if [[ -f "$rpath/build.zig.zon" ]]; then - zon2json-recursive "$rpath/build.zig.zon" - fi - done < <(zon2json "$1" | jq -r '.dependencies | to_entries | .[] | select(.value.path != null) | .value.path' 2>/dev/null) - } - - if ! jq -e '.dependencies[] | select(.url != null or .path != null) | length > 0' <(zon2json "$path") >/dev/null; then - printf -- '%s has no dependencies\n' "$path" 1>&2 - exit 0 - fi - - zon2json-recursive "$path" | jq -se add > "$tmpdir/build.zig.zon2json-lock" - if [[ "''${2:-}" == "-" ]]; then - jq . "$tmpdir/build.zig.zon2json-lock" - else - cp -f "$tmpdir/build.zig.zon2json-lock" "''${2:-''${path}2json-lock}" - fi - ''; -} diff --git a/tools/zon2json/default.nix b/tools/zon2json/default.nix deleted file mode 100644 index eb5a1e8..0000000 --- a/tools/zon2json/default.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ - lib - , stdenvNoCC - , zig -}: - -{ ... }@attrs: - -with builtins; -with lib; - -stdenvNoCC.mkDerivation (attrs // { - name = "zon2json"; - src = cleanSource ./.; - nativeBuildInputs = [ zig.hook ]; - meta.mainProgram = "zon2json"; -}) diff --git a/tools/zon2json/src/main.zig b/tools/zon2json/src/main.zig deleted file mode 100644 index 1d1f883..0000000 --- a/tools/zon2json/src/main.zig +++ /dev/null @@ -1,35 +0,0 @@ -const std = @import("std"); -const zon2json = @import("zon2json.zig"); - -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); - - const path: ?[]const u8 = blk: { - const args = try std.process.argsAlloc(allocator); - defer std.process.argsFree(allocator, args); - if (args.len > 1) break :blk try allocator.dupe(u8, args[1]); - break :blk null; - }; - defer if (path) |p| allocator.free(p); - - var json = std.ArrayList(u8).init(allocator); - defer json.deinit(); - - const fname = path orelse "build.zig.zon"; - var file = try std.fs.cwd().openFile(fname, .{.mode = .read_only}); - defer file.close(); - - try zon2json.parse( - allocator, - file.reader().any(), - json.writer(), - std.io.getStdErr().writer(), - .{ - .file_name = fname - } - ); - - try std.io.getStdOut().writer().writeAll(json.items); -} diff --git a/tools/zon2nix.nix b/tools/zon2nix.nix deleted file mode 100644 index 8dcffba..0000000 --- a/tools/zon2nix.nix +++ /dev/null @@ -1,143 +0,0 @@ -{ - zon2json-lock - , writeShellApplication - , jq -}: - -writeShellApplication { - name = "zon2nix"; - runtimeInputs = [ zon2json-lock jq ]; - text = '' - path="''${1:-build.zig.zon}" - - # Call zon2json-lock automatically if needed - # Requires network access - if [[ "$path" == *.zig.zon ]]; then - if [[ ! -f "''${path}2json-lock" ]]; then - zon2json-lock "$path" - fi - path="''${path}2json-lock" - fi - - if [[ ! -f "$path" ]]; then - printf -- "error: file does not exist: %s\n" "$path" 1>&2 - exit 1 - fi - - cat <<'EOF' - # generated by zon2nix (https://github.com/Cloudef/zig2nix) - - { - lib, - linkFarm, - fetchurl, - fetchgit, - runCommandLocal, - zig, - name ? "zig-packages", - }: - - with builtins; - with lib; - - let - unpackZigArtifact = - { name, artifact }: - runCommandLocal name - { - nativeBuildInputs = [ zig ]; - } - ${"''"} - hash="$(zig fetch --global-cache-dir "$TMPDIR" ''${artifact})" - mv "$TMPDIR/p/$hash" "$out" - chmod 755 "$out" - ${"''"}; - - fetchZig = - { - name, - url, - hash, - }: - let - artifact = fetchurl { inherit url hash; }; - in - unpackZigArtifact { inherit name artifact; }; - - fetchGitZig = - { - name, - url, - hash, - rev ? throw "rev is required, remove and regenerate the zon2json-lock file", - }: - let - parts = splitString "#" url; - url_base = elemAt parts 0; - url_without_query = elemAt (splitString "?" url_base) 0; - in - fetchgit { - inherit name hash rev; - url = url_without_query; - deepClone = false; - }; - - fetchZigArtifact = - { - name, - url, - hash, - ... - } @ args: - let - parts = splitString "://" url; - proto = elemAt parts 0; - path = elemAt parts 1; - fetcher = { - "git+http" = fetchGitZig (args // { - url = "http://''${path}"; - }); - "git+https" = fetchGitZig (args // { - url = "https://''${path}"; - }); - http = fetchZig { - inherit name hash; - url = "http://''${path}"; - }; - https = fetchZig { - inherit name hash; - url = "https://''${path}"; - }; - }; - in - fetcher.''${proto}; - in - linkFarm name [ - EOF - - while { - read -r zhash; - read -r name; - read -r url; - read -r ahash; - read -r rev; - } do - cat <