This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / lib / make-wrapper.nix
5.9 kB 203 lines
1{ lib, pkgs, ... }: 2{ 3 /** 4 Create a wrapped application that preserves all original outputs (man pages, completions, etc.) 5 6 # Arguments 7 8 - `package`: The package to wrap 9 - `runtimeInputs`: List of packages to add to PATH (optional) 10 - `env`: Attribute set of environment variables to export (optional) 11 - `flags`: Attribute set of command-line flags to add (optional) 12 - `flagSeparator`: Separator between flag names and values (optional, defaults to " ") 13 - `preHook`: Shell script to run before executing the command (optional) 14 - `passthru`: Attribute set to pass through to the wrapped derivation (optional) 15 - `wrapper`: Custom wrapper function (optional, defaults to exec'ing the original binary with flags) 16 - Called with { env, flags, envString, flagsString, exePath, preHook } 17 18 # Example 19 20 ```nix 21 makeWrapper pkgs.curl { 22 runtimeInputs = [ pkgs.jq ]; 23 env = { 24 CURL_CA_BUNDLE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; 25 }; 26 flags = { 27 "--silent" = { }; # becomes --silent 28 "--connect-timeout" = "30"; # becomes --connect-timeout 30 29 }; 30 preHook = '' 31 echo "Making request..." >&2 32 ''; 33 } 34 35 # Or with custom wrapper: 36 makeWrapper pkgs.someProgram { 37 wrapper = { exePath, flagsString, envString, preHook, ... }: '' 38 ${envString} 39 ${preHook} 40 echo "Custom logic here" 41 exec ${exePath} ${flagsString} "$@" 42 ''; 43 } 44 ``` 45 */ 46 makeWrapper = 47 package: 48 { 49 runtimeInputs ? [ ], 50 env ? { }, 51 flags ? { }, 52 flagSeparator ? " ", # " " for "--flag value" or "=" for "--flag=value" 53 preHook ? "", 54 passthru ? { }, 55 wrapper ? ( 56 { 57 exePath, 58 flagsString, 59 envString, 60 preHook, 61 ... 62 }: 63 '' 64 ${envString} 65 ${preHook} 66 exec ${exePath}${flagsString} "$@" 67 '' 68 ), 69 }: 70 let 71 # Extract binary name from the exe path 72 exePath = lib.getExe package; 73 binName = baseNameOf exePath; 74 75 # Generate environment variable exports 76 envString = 77 if env == { } then 78 "" 79 else 80 lib.concatStringsSep "\n" ( 81 lib.mapAttrsToList (name: value: ''export ${name}="${toString value}"'') env 82 ) 83 + "\n"; 84 85 # Generate flag arguments with proper line breaks and indentation 86 flagsString = 87 if flags == { } then 88 "" 89 else 90 " \\\n " 91 + lib.concatStringsSep " \\\n " ( 92 lib.mapAttrsToList ( 93 name: value: 94 if value == { } then "${name}" else "${name}${flagSeparator}${lib.escapeShellArg (toString value)}" 95 ) flags 96 ); 97 98 finalWrapper = wrapper { 99 inherit 100 env 101 flags 102 envString 103 flagsString 104 exePath 105 preHook 106 ; 107 }; 108 109 # Multi-output aware symlink join function 110 multiOutputSymlinkJoin = 111 { 112 name, 113 paths, 114 outputs ? [ "out" ], 115 originalOutputs ? { }, 116 passthru ? { }, 117 meta ? { }, 118 ... 119 }@args: 120 pkgs.stdenv.mkDerivation ( 121 { 122 inherit name outputs; 123 124 buildCommand = '' 125 # Symlink all paths to the main output 126 mkdir -p $out 127 for path in ${lib.concatStringsSep " " (map toString paths)}; do 128 ${pkgs.lndir}/bin/lndir -silent "$path" $out 129 done 130 131 # Handle additional outputs by symlinking from the original package's outputs 132 ${lib.concatMapStringsSep "\n" ( 133 output: 134 if output != "out" && originalOutputs ? ${output} && originalOutputs.${output} != null then 135 '' 136 if [[ -n "''${${output}:-}" ]]; then 137 mkdir -p ${"$" + output} 138 # Only symlink from the original package's corresponding output 139 ${pkgs.lndir}/bin/lndir -silent "${originalOutputs.${output}}" ${"$" + output} 140 fi 141 '' 142 else 143 "" 144 ) outputs} 145 ''; 146 147 inherit passthru meta; 148 } 149 // (removeAttrs args [ 150 "name" 151 "paths" 152 "outputs" 153 "originalOutputs" 154 "passthru" 155 "meta" 156 ]) 157 ); 158 159 # Get original package outputs for symlinking 160 originalOutputs = 161 if package ? outputs then 162 lib.listToAttrs ( 163 map (output: { 164 name = output; 165 value = if package ? ${output} then package.${output} else null; 166 }) package.outputs 167 ) 168 else 169 { }; 170 171 # Create the wrapper derivation using our multi-output aware symlink join 172 wrappedPackage = multiOutputSymlinkJoin ( 173 { 174 name = package.pname or package.name; 175 paths = [ 176 (pkgs.writeShellApplication { 177 name = binName; 178 runtimeInputs = runtimeInputs; 179 text = finalWrapper; 180 }) 181 package 182 ]; 183 outputs = if package ? outputs then package.outputs else [ "out" ]; 184 inherit originalOutputs; 185 passthru = 186 (package.passthru or { }) 187 // passthru 188 // { 189 inherit env flags preHook; 190 }; 191 # Pass through original attributes 192 meta = package.meta or { }; 193 } 194 // lib.optionalAttrs (package ? version) { 195 inherit (package) version; 196 } 197 // lib.optionalAttrs (package ? pname) { 198 inherit (package) pname; 199 } 200 ); 201 in 202 wrappedPackage; 203}