From bb2771a3f0c0b51422bcb3a7d929c2cf29308e24 Mon Sep 17 00:00:00 2001 From: winston Date: Tue, 19 Dec 2023 00:13:11 +0100 Subject: [PATCH] feat: try to stabilize/rework before docs --- ci.nix | 95 ++++++++++++---------------- nix/default.nix | 3 +- nix/hooks/default.nix | 16 +++++ nix/hooks/deno-build-hook.sh | 33 ++++++++++ nix/hooks/deno-cache-restore-hook.sh | 6 +- nix/hooks/deno-install-hook.sh | 28 ++++++++ nix/lib/default.nix | 4 -- nix/mkDenoBinary.nix | 26 +++++--- nix/mkDenoDerivation.nix | 32 +++++----- nix/mkDenoPackage.nix | 4 +- 10 files changed, 155 insertions(+), 92 deletions(-) create mode 100644 nix/hooks/deno-build-hook.sh create mode 100644 nix/hooks/deno-install-hook.sh diff --git a/ci.nix b/ci.nix index e13fc7a..c246559 100644 --- a/ci.nix +++ b/ci.nix @@ -1,94 +1,54 @@ {pkgs ? import {overlays = [(import ./nix)];}}: let - buildPhase = '' - mkdir -p $out - deno run -A ./main.ts > $out/output.txt - ''; nvfetcher = pkgs.callPackage ./_sources/generated.nix {}; - esbuild = nvfetcher."esbuild-${pkgs.hostPlatform.system}"; + esbuild = nvfetcher."esbuild-${pkgs.stdenv.hostPlatform.system}"; in { - # simple imports, following the `deps.ts` convention - remote-simple = pkgs.denoPlatform.mkDenoDerivation { + # simple deno.land imports + remote-simple = pkgs.denoPlatform.mkDenoPackage { name = "remote-simple"; - src = ./examples/remote; + }; - inherit buildPhase; + # with esm.sh dependencies + esm-simple = pkgs.denoPlatform.mkDenoPackage { + name = "esm-simple"; + src = ./examples/esm-simple; }; # with npm dependencies - npm-simple = pkgs.denoPlatform.mkDenoDerivation { + npm-simple = pkgs.denoPlatform.mkDenoPackage { name = "npm-simple"; - src = ./examples/npm-simple; - - inherit buildPhase; }; # with npm dependencies + custom registry - npm-simple-custom-npm-registry = pkgs.denoPlatform.mkDenoDerivation { + npm-simple-custom-npm-registry = pkgs.denoPlatform.mkDenoPackage { name = "npm-simple-custom-npm-registry"; - src = ./examples/npm-simple; npmRegistryUrl = "http://localhost:4873"; - - inherit buildPhase; - }; - - # with esm.sh dependencies - esm-simple = pkgs.denoPlatform.mkDenoDerivation { - name = "esm-simple"; - - src = ./examples/esm-simple; - - inherit buildPhase; }; # Fresh project heavily utilizing esm.sh dependencies - fresh = pkgs.denoPlatform.mkDenoDerivation { + fresh = pkgs.denoPlatform.mkDenoPackage { name = "fresh"; - src = ./examples/fresh; - buildPhase = '' - deno task build - ''; - env.ESBUILD_BINARY_PATH = "${esbuild.src}/bin/esbuild"; - - installPhase = '' - cp -r _fresh $out - ''; }; - # Lume project with mixed dependencies + # Lume project with mixed dependencies, building a simple static site lume = pkgs.denoPlatform.mkDenoDerivation { name = "lume"; - stdenv = pkgs.stdenvNoCC; - src = ./examples/lume; - buildPhase = '' - deno task build - ''; - - installPhase = '' - mkdir -p $out - cp -r _site/* $out - ''; + stdenv = pkgs.stdenvNoCC; + installPhase = "cp -r _site $out"; }; - cliffy-runtime = pkgs.denoPlatform.mkDenoPackage { + cliffy = pkgs.denoPlatform.mkDenoPackage { name = "cliffy-runtime"; src = ./examples/cliffy; - permissions.allow.all = true; - }; - - cliffy-binary = pkgs.denoPlatform.mkDenoBinary { - name = "cliffy"; - src = ./examples/cliffy; - permissions.allow.net = "localhost:8080"; }; @@ -106,6 +66,29 @@ in { unstable = true; include = ["worker.tsx"]; - entryPoint = "main.ts"; + nativeBuildInputs = [pkgs.makeWrapper]; + postInstall = let + hash = + { + "aarch64-darwin" = { + url = "https://github.com/webview/webview_deno/releases/download/0.7.4/libwebview.aarch64.dylib"; + sha256 = "06zr23pfzz71q01dvzks23n6maj6g82irj7scp3arydfi0lk0ys6"; + }; + "x86_64-darwin" = { + url = "https://github.com/webview/webview_deno/releases/download/0.7.4/libwebview.x86_64.dylib"; + sha256 = "1r321sd3h12qx1ql5bgbn8bnpvsmfd0dzvv6g23w95zalqz5jifk"; + }; + "x86_64-linux" = { + url = "https://github.com/webview/webview_deno/releases/download/0.7.4/libwebview.so"; + sha256 = "0gmcb4ky2bhk3inh45wdgxab0l95xgd3h4zgqcw4iccxq638mca3"; + }; + } + .${pkgs.stdenv.hostPlatform.system}; + ffiLib = pkgs.fetchurl {inherit (hash) url sha256;}; + in '' + mkdir -p $out/lib + cp ${ffiLib} $out/lib/${baseNameOf ffiLib.url} + wrapProgram $out/bin/webview --set PLUGIN_URL "$out/lib/" + ''; }; } diff --git a/nix/default.nix b/nix/default.nix index d18e308..ef57a2a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -4,8 +4,9 @@ final: prev: { mkDenoDerivation = final.callPackage ./mkDenoDerivation.nix {}; mkDenoDir = final.callPackage ./mkDenoDir.nix {}; mkDenoPackage = final.callPackage ./mkDenoPackage.nix {}; - resolveImportMap = final.callPackage ./resolveImportMap.nix {}; + hooks = final.callPackage ./hooks {}; lib = final.callPackage ./lib {}; + resolveImportMap = final.callPackage ./resolveImportMap.nix {}; }; } diff --git a/nix/hooks/default.nix b/nix/hooks/default.nix index 486150c..045636a 100644 --- a/nix/hooks/default.nix +++ b/nix/hooks/default.nix @@ -2,12 +2,28 @@ stdenv, callPackage, makeSetupHook, + deno, jq, }: { denoCacheRestoreHook = callPackage ({}: makeSetupHook { name = "deno-cache-restore-hook.sh"; propagatedBuildInputs = [jq]; + substitutions = { + }; } ./deno-cache-restore-hook.sh) {}; + + denoBuildHook = callPackage ({}: + makeSetupHook { + name = "deno-build-hook.sh"; + propagatedBuildInputs = [jq deno]; + } + ./deno-build-hook.sh) {}; + + denoInstallHook = callPackage ({}: + makeSetupHook { + name = "deno-install-hook.sh"; + } + ./deno-install-hook.sh) {}; } diff --git a/nix/hooks/deno-build-hook.sh b/nix/hooks/deno-build-hook.sh new file mode 100644 index 0000000..dcbe9ed --- /dev/null +++ b/nix/hooks/deno-build-hook.sh @@ -0,0 +1,33 @@ +# shellcheck shell=bash disable=SC2016 + +denoBuildHook() { + echo "Executing denoBuildHook" + + runHook preBuild + + local -r depsOut="$out/lib/deno_dir" + + if [ -z "${denoBuildTask-}" ]; then + echo + echo "ERROR: no build task was specified" + echo 'Hint: set `denoBuildTask`, override `buildPhase`, or set `dontDenoBuild = true`.' + echo + exit 1 + fi + + if ! deno task "$denoBuildTask"; then + echo + echo "ERROR: build task failed" + echo + echo 'Make sure that the `deno.json` file exists and that the specified task is valid.' + exit 1 + fi + + runHook postBuild + + echo "Finished denoBuildHook" +} + +if [ -z "${dontDenoBuild-}" ] && [ -z "${buildPhase-}" ]; then + buildPhase=denoBuildHook +fi diff --git a/nix/hooks/deno-cache-restore-hook.sh b/nix/hooks/deno-cache-restore-hook.sh index 1e03e57..138a7c8 100644 --- a/nix/hooks/deno-cache-restore-hook.sh +++ b/nix/hooks/deno-cache-restore-hook.sh @@ -5,13 +5,13 @@ denoRestoreCacheHook() { export DENO_DIR="$TMPDIR/deno_cache" # the cache direcory needs to be mutable, so we can't symlink to /nix/store - # shellcheck disable=SC2154 # $DENO_PREFETCH_DIR is external - cp -Lr --reflink=auto -- "$DENO_PREFETCH_DIR" "$DENO_DIR" + echo "Making cache writable" + cp -Lr --reflink=auto -- "$denoDeps" "$DENO_DIR" chmod -R +644 -- "$DENO_DIR" echo "Finished denoRestoreCacheHook" } if [ -z "${dontRestoreDenoCache-}" ]; then - postUnpackHooks+=(denoRestoreCacheHook) + postPatchHooks+=(denoRestoreCacheHook) fi diff --git a/nix/hooks/deno-install-hook.sh b/nix/hooks/deno-install-hook.sh new file mode 100644 index 0000000..cc77ea6 --- /dev/null +++ b/nix/hooks/deno-install-hook.sh @@ -0,0 +1,28 @@ +# shellcheck shell=bash + +denoInstallHook() { + echo "Executing denoInstallHook" + + local -r depsOut="$out/lib/deno_dir" + + if [ -z "${dontCopyDenoDir-}" ]; then + mkdir -p "$depsOut" + cp -Lr --reflink=auto -- "$DENO_PREFETCH_DIR" "$DENO_DIR" + fi + + mkdir -p "$out/bin" + makeWrapper \ + @hostDeno@ \ + "$out/bin/@binaryName@" \ + --set DENO_DIR "$depsOut" \ + --set DENO_NO_UPDATE_CHECK 1 \ + --set DENO_REPL_HISTORY "" \ + --set NPM_CONFIG_REGISTRY "$npmRegistryUrl" \ + --add-flags "@denoFlags@" + + echo "Finished denoInstallHook" +} + +if [ -z "${dontDenoInstall-}" ] && [ -z "${installPhase-}" ]; then + installPhase=denoInstallHook +fi diff --git a/nix/lib/default.nix b/nix/lib/default.nix index d0fcb61..be3c412 100644 --- a/nix/lib/default.nix +++ b/nix/lib/default.nix @@ -33,12 +33,10 @@ allow ++ deny; generateFlags = { - entryPoint, permissions ? {}, unstable ? false, include ? [], additionalDenoArgs ? [], - scriptArgs ? [], }: builtins.concatStringsSep " " (lib.flatten [ ( @@ -49,7 +47,5 @@ (builtins.map (import: "--include=" + import) include) (fromPermissionsAttrs permissions) additionalDenoArgs - entryPoint - scriptArgs ]); } diff --git a/nix/mkDenoBinary.nix b/nix/mkDenoBinary.nix index 6612ea1..6749a30 100644 --- a/nix/mkDenoBinary.nix +++ b/nix/mkDenoBinary.nix @@ -1,5 +1,6 @@ { lib, + makeWrapper, deno, denoPlatform, }: { @@ -14,18 +15,25 @@ ... } @ args: let compileArgs = denoPlatform.lib.generateFlags { - inherit permissions unstable include entryPoint scriptArgs; - additionalDenoArgs = ["--output" binaryName] ++ additionalDenoArgs; + inherit permissions unstable include; + additionalDenoArgs = additionalDenoArgs ++ ["--output" binaryName entryPoint] ++ scriptArgs; }; in denoPlatform.mkDenoDerivation ({ - # fixup corrupts the binary, leaving it in a Deno REPL-only state - dontFixup = true; + nativeBuildInputs = [makeWrapper]; + buildPhase = '' + runHook preBuild + deno compile ${compileArgs} + runHook postBuild + ''; - buildPhase = "deno compile ${compileArgs}"; - installPhase = "install -Dm755 ${binaryName} $out/bin/${binaryName}"; + installPhase = '' + runHook preInstall + install -Dm755 ${binaryName} $out/bin/${binaryName} + runHook postInstall + ''; - # default to Deno's platforms - meta.platforms = deno.meta.platforms; + # fixup corrupts the binary, leaving it in a Deno REPL-only state + dontFixup = true; } - // (builtins.removeAttrs args ["permissions"])) + // (builtins.removeAttrs args ["permissions" "unstable" "include"])) diff --git a/nix/mkDenoDerivation.nix b/nix/mkDenoDerivation.nix index a329cff..5e02801 100644 --- a/nix/mkDenoDerivation.nix +++ b/nix/mkDenoDerivation.nix @@ -11,23 +11,21 @@ nativeBuildInputs ? [], npmRegistryUrl ? "https://registry.npmjs.org", stdenv ? inputs.stdenv, + denoDeps ? denoPlatform.mkDenoDir {inherit lockFile npmRegistryUrl;}, ... -} @ args: -stdenv.mkDerivation ({ - buildInputs = [deno] ++ buildInputs; +} @ args: let + inherit (denoPlatform.hooks) denoCacheRestoreHook; +in + stdenv.mkDerivation (args + // { + # setting the prefetch direcory for the cache restore hook + inherit denoDeps npmRegistryUrl; + env.NPM_CONFIG_REGISTRY = npmRegistryUrl; - # setting the prefetch direcory for the cache restore hook - env = - { - DENO_PREFETCH_DIR = denoPlatform.mkDenoDir {inherit lockFile npmRegistryUrl;}; - NPM_CONFIG_REGISTRY = npmRegistryUrl; - } - // args.env or {}; + nativeBuildInputs = nativeBuildInputs ++ [deno denoCacheRestoreHook]; + buildInputs = buildInputs ++ [deno]; - nativeBuildInputs = [denoPlatform.hooks.denoCacheRestoreHook] ++ nativeBuildInputs; - } - // (builtins.removeAttrs args [ - "buildInputs" - "nativeBuildInputs" - "env" - ])) + strictDeps = true; + + meta = (args.meta or {}) // {platforms = args.meta.platforms or deno.meta.platforms;}; + }) diff --git a/nix/mkDenoPackage.nix b/nix/mkDenoPackage.nix index 0076791..9e35091 100644 --- a/nix/mkDenoPackage.nix +++ b/nix/mkDenoPackage.nix @@ -9,14 +9,14 @@ entryPoint ? "main.ts", binaryName ? name, additionalDenoArgs ? [], + denoBundle ? false, ... } @ args: let runtimeArgs = denoPlatform.lib.generateFlags { inherit permissions unstable additionalDenoArgs; - # since we're running a bundled script, the args are passed to the shebang rather than loading an entrypoint from the filesystem. - entryPoint = ""; }; in + # TODO: rework this to use nativebuildinputs / denoPlatform hooks denoPlatform.mkDenoDerivation ({ # TODO: investigate other bundlers like `deno_emit`, since `deno bundle` is deprecated buildPhase = ''