nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix

Merge pull request #293420 from DavHau/writers-wrap

writers: add support for wrapping

authored by

lassulus and committed by
GitHub
7154ccbb 59dd321a

+432 -148
+350 -142
pkgs/build-support/writers/scripts.nix
··· 1 - { pkgs, buildPackages, lib, stdenv, libiconv, mkNugetDeps, mkNugetSource, gixy }: 1 + { 2 + buildPackages, 3 + gixy, 4 + lib, 5 + libiconv, 6 + makeBinaryWrapper, 7 + mkNugetDeps, 8 + mkNugetSource, 9 + pkgs, 10 + stdenv, 11 + }: 2 12 let 3 13 inherit (lib) 4 14 concatMapStringsSep ··· 16 6 escapeShellArg 17 7 last 18 8 optionalString 19 - stringLength 20 9 strings 21 10 types 22 11 ; ··· 27 18 # Examples: 28 19 # writeBash = makeScriptWriter { interpreter = "${pkgs.bash}/bin/bash"; } 29 20 # makeScriptWriter { interpreter = "${pkgs.dash}/bin/dash"; } "hello" "echo hello world" 30 - makeScriptWriter = { interpreter, check ? "" }: nameOrPath: content: 21 + makeScriptWriter = { interpreter, check ? "", makeWrapperArgs ? [], }: nameOrPath: content: 31 22 assert lib.or (types.path.check nameOrPath) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null); 32 23 assert lib.or (types.path.check content) (types.str.check content); 33 24 let 25 + nameIsPath = types.path.check nameOrPath; 34 26 name = last (builtins.split "/" nameOrPath); 35 - in 27 + path = if nameIsPath then nameOrPath else "/bin/${name}"; 28 + # The inner derivation which creates the executable under $out/bin (never at $out directly) 29 + # This is required in order to support wrapping, as wrapped programs consist of at least two files: the executable and the wrapper. 30 + inner = 31 + pkgs.runCommandLocal name ( 32 + { 33 + inherit makeWrapperArgs; 34 + nativeBuildInputs = [ 35 + makeBinaryWrapper 36 + ]; 37 + meta.mainProgram = name; 38 + } 39 + // ( 40 + if (types.str.check content) then { 41 + inherit content interpreter; 42 + passAsFile = [ "content" ]; 43 + } else { 44 + inherit interpreter; 45 + contentPath = content; 46 + } 47 + ) 48 + ) 49 + '' 50 + # On darwin a script cannot be used as an interpreter in a shebang but 51 + # there doesn't seem to be a limit to the size of shebang and multiple 52 + # arguments to the interpreter are allowed. 53 + if [[ -n "${toString pkgs.stdenvNoCC.isDarwin}" ]] && isScript $interpreter 54 + then 55 + wrapperInterpreterLine=$(head -1 "$interpreter" | tail -c+3) 56 + # Get first word from the line (note: xargs echo remove leading spaces) 57 + wrapperInterpreter=$(echo "$wrapperInterpreterLine" | xargs echo | cut -d " " -f1) 36 58 37 - pkgs.runCommandLocal name ( 38 - lib.optionalAttrs (nameOrPath == "/bin/${name}") { 39 - meta.mainProgram = name; 40 - } 41 - // ( 42 - if (types.str.check content) then { 43 - inherit content interpreter; 44 - passAsFile = [ "content" ]; 45 - } else { 46 - inherit interpreter; 47 - contentPath = content; 48 - } 49 - ) 50 - ) 51 - '' 52 - # On darwin a script cannot be used as an interpreter in a shebang but 53 - # there doesn't seem to be a limit to the size of shebang and multiple 54 - # arguments to the interpreter are allowed. 55 - if [[ -n "${toString pkgs.stdenvNoCC.isDarwin}" ]] && isScript $interpreter 56 - then 57 - wrapperInterpreterLine=$(head -1 "$interpreter" | tail -c+3) 58 - # Get first word from the line (note: xargs echo remove leading spaces) 59 - wrapperInterpreter=$(echo "$wrapperInterpreterLine" | xargs echo | cut -d " " -f1) 59 + if isScript $wrapperInterpreter 60 + then 61 + echo "error: passed interpreter ($interpreter) is a script which has another script ($wrapperInterpreter) as an interpreter, which is not supported." 62 + exit 1 63 + fi 60 64 61 - if isScript $wrapperInterpreter 62 - then 63 - echo "error: passed interpreter ($interpreter) is a script which has another script ($wrapperInterpreter) as an interpreter, which is not supported." 64 - exit 1 65 - fi 65 + # This should work as long as wrapperInterpreter is a shell, which is 66 + # the case for programs wrapped with makeWrapper, like 67 + # python3.withPackages etc. 68 + interpreterLine="$wrapperInterpreterLine $interpreter" 69 + else 70 + interpreterLine=$interpreter 71 + fi 66 72 67 - # This should work as long as wrapperInterpreter is a shell, which is 68 - # the case for programs wrapped with makeWrapper, like 69 - # python3.withPackages etc. 70 - interpreterLine="$wrapperInterpreterLine $interpreter" 71 - else 72 - interpreterLine=$interpreter 73 - fi 73 + echo "#! $interpreterLine" > $out 74 + cat "$contentPath" >> $out 75 + ${optionalString (check != "") '' 76 + ${check} $out 77 + ''} 78 + chmod +x $out 74 79 75 - echo "#! $interpreterLine" > $out 76 - cat "$contentPath" >> $out 77 - ${optionalString (check != "") '' 78 - ${check} $out 79 - ''} 80 - chmod +x $out 81 - ${optionalString (types.path.check nameOrPath) '' 82 - mv $out tmp 83 - mkdir -p $out/$(dirname "${nameOrPath}") 84 - mv tmp $out/${nameOrPath} 85 - ''} 86 - ''; 80 + # Relocate executable 81 + # Wrap it if makeWrapperArgs are specified 82 + mv $out tmp 83 + mkdir -p $out/$(dirname "${path}") 84 + mv tmp $out/${path} 85 + if [ -n "''${makeWrapperArgs+''${makeWrapperArgs[@]}}" ]; then 86 + wrapProgram $out/${path} ''${makeWrapperArgs[@]} 87 + fi 88 + ''; 89 + in 90 + if nameIsPath 91 + then inner 92 + # In case nameOrPath is a name, the user intends the executable to be located at $out. 93 + # This is achieved by creating a separate derivation containing a symlink at $out linking to ${inner}/bin/${name}. 94 + # This breaks the override pattern. 95 + # In case this turns out to be a problem, we can still add more magic 96 + else pkgs.runCommandLocal name {} '' 97 + ln -s ${inner}/bin/${name} $out 98 + ''; 99 + 87 100 88 101 # Base implementation for compiled executables. 89 102 # Takes a compile script, which in turn takes the name as an argument. 90 103 # 91 104 # Examples: 92 105 # writeSimpleC = makeBinWriter { compileScript = name: "gcc -o $out $contentPath"; } 93 - makeBinWriter = { compileScript, strip ? true }: nameOrPath: content: 106 + makeBinWriter = { compileScript, strip ? true, makeWrapperArgs ? [] }: nameOrPath: content: 94 107 assert lib.or (types.path.check nameOrPath) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null); 95 108 assert lib.or (types.path.check content) (types.str.check content); 96 109 let 110 + nameIsPath = types.path.check nameOrPath; 97 111 name = last (builtins.split "/" nameOrPath); 112 + path = if nameIsPath then nameOrPath else "/bin/${name}"; 113 + # The inner derivation which creates the executable under $out/bin (never at $out directly) 114 + # This is required in order to support wrapping, as wrapped programs consist of at least two files: the executable and the wrapper. 115 + inner = 116 + pkgs.runCommandLocal name ( 117 + { 118 + inherit makeWrapperArgs; 119 + nativeBuildInputs = [ 120 + makeBinaryWrapper 121 + ]; 122 + meta.mainProgram = name; 123 + } 124 + // ( 125 + if (types.str.check content) then { 126 + inherit content; 127 + passAsFile = [ "content" ]; 128 + } else { 129 + contentPath = content; 130 + } 131 + ) 132 + ) 133 + '' 134 + ${compileScript} 135 + ${lib.optionalString strip 136 + "${lib.getBin buildPackages.bintools-unwrapped}/bin/${buildPackages.bintools-unwrapped.targetPrefix}strip -S $out"} 137 + # Sometimes binaries produced for darwin (e. g. by GHC) won't be valid 138 + # mach-o executables from the get-go, but need to be corrected somehow 139 + # which is done by fixupPhase. 140 + ${lib.optionalString pkgs.stdenvNoCC.hostPlatform.isDarwin "fixupPhase"} 141 + mv $out tmp 142 + mkdir -p $out/$(dirname "${path}") 143 + mv tmp $out/${path} 144 + if [ -n "''${makeWrapperArgs+''${makeWrapperArgs[@]}}" ]; then 145 + wrapProgram $out/${path} ''${makeWrapperArgs[@]} 146 + fi 147 + ''; 98 148 in 99 - pkgs.runCommand name ((if (types.str.check content) then { 100 - inherit content; 101 - passAsFile = [ "content" ]; 102 - } else { 103 - contentPath = content; 104 - }) // lib.optionalAttrs (nameOrPath == "/bin/${name}") { 105 - meta.mainProgram = name; 106 - }) '' 107 - ${compileScript} 108 - ${lib.optionalString strip 109 - "${lib.getBin buildPackages.bintools-unwrapped}/bin/${buildPackages.bintools-unwrapped.targetPrefix}strip -S $out"} 110 - # Sometimes binaries produced for darwin (e. g. by GHC) won't be valid 111 - # mach-o executables from the get-go, but need to be corrected somehow 112 - # which is done by fixupPhase. 113 - ${lib.optionalString pkgs.stdenvNoCC.hostPlatform.isDarwin "fixupPhase"} 114 - ${optionalString (types.path.check nameOrPath) '' 115 - mv $out tmp 116 - mkdir -p $out/$(dirname "${nameOrPath}") 117 - mv tmp $out/${nameOrPath} 118 - ''} 119 - ''; 149 + if nameIsPath 150 + then inner 151 + # In case nameOrPath is a name, the user intends the executable to be located at $out. 152 + # This is achieved by creating a separate derivation containing a symlink at $out linking to ${inner}/bin/${name}. 153 + # This breaks the override pattern. 154 + # In case this turns out to be a problem, we can still add more magic 155 + else pkgs.runCommandLocal name {} '' 156 + ln -s ${inner}/bin/${name} $out 157 + ''; 120 158 121 159 # Like writeScript but the first line is a shebang to bash 122 160 # 123 - # Example: 161 + # Can be called with or without extra arguments. 162 + # 163 + # Example without arguments: 124 164 # writeBash "example" '' 125 165 # echo hello world 126 166 # '' 127 - writeBash = makeScriptWriter { 128 - interpreter = "${lib.getExe pkgs.bash}"; 129 - }; 167 + # 168 + # Example with arguments: 169 + # writeBash "example" 170 + # { 171 + # makeWrapperArgs = [ 172 + # "--prefix" "PATH" ":" "${pkgs.hello}/bin" 173 + # ]; 174 + # } 175 + # '' 176 + # hello 177 + # '' 178 + writeBash = name: argsOrScript: 179 + if lib.isAttrs argsOrScript && ! lib.isDerivation argsOrScript 180 + then makeScriptWriter (argsOrScript // { interpreter = "${lib.getExe pkgs.bash}"; }) name 181 + else makeScriptWriter { interpreter = "${lib.getExe pkgs.bash}"; } name argsOrScript; 130 182 131 183 # Like writeScriptBin but the first line is a shebang to bash 184 + # 185 + # Can be called with or without extra arguments. 186 + # 187 + # Example without arguments: 188 + # writeBashBin "example" '' 189 + # echo hello world 190 + # '' 191 + # 192 + # Example with arguments: 193 + # writeBashBin "example" 194 + # { 195 + # makeWrapperArgs = [ 196 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 197 + # ]; 198 + # } 199 + # '' 200 + # hello 201 + # '' 132 202 writeBashBin = name: 133 203 writeBash "/bin/${name}"; 134 204 135 205 # Like writeScript but the first line is a shebang to dash 136 206 # 137 - # Example: 207 + # Can be called with or without extra arguments. 208 + # 209 + # Example without arguments: 138 210 # writeDash "example" '' 139 211 # echo hello world 140 212 # '' 141 - writeDash = makeScriptWriter { 142 - interpreter = "${lib.getExe pkgs.dash}"; 143 - }; 213 + # 214 + # Example with arguments: 215 + # writeDash "example" 216 + # { 217 + # makeWrapperArgs = [ 218 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 219 + # ]; 220 + # } 221 + # '' 222 + # hello 223 + # '' 224 + writeDash = name: argsOrScript: 225 + if lib.isAttrs argsOrScript && ! lib.isDerivation argsOrScript 226 + then makeScriptWriter (argsOrScript // { interpreter = "${lib.getExe pkgs.dash}"; }) name 227 + else makeScriptWriter { interpreter = "${lib.getExe pkgs.dash}"; } name argsOrScript; 144 228 145 229 # Like writeScriptBin but the first line is a shebang to dash 230 + # 231 + # Can be called with or without extra arguments. 232 + # 233 + # Example without arguments: 234 + # writeDashBin "example" '' 235 + # echo hello world 236 + # '' 237 + # 238 + # Example with arguments: 239 + # writeDashBin "example" 240 + # { 241 + # makeWrapperArgs = [ 242 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 243 + # ]; 244 + # } 245 + # '' 246 + # hello 247 + # '' 146 248 writeDashBin = name: 147 249 writeDash "/bin/${name}"; 148 250 149 251 # Like writeScript but the first line is a shebang to fish 150 252 # 151 - # Example: 253 + # Can be called with or without extra arguments. 254 + # 255 + # Example without arguments: 152 256 # writeFish "example" '' 153 257 # echo hello world 154 258 # '' 155 - writeFish = makeScriptWriter { 156 - interpreter = "${lib.getExe pkgs.fish} --no-config"; 157 - check = "${lib.getExe pkgs.fish} --no-config --no-execute"; # syntax check only 158 - }; 259 + # 260 + # Example with arguments: 261 + # writeFish "example" 262 + # { 263 + # makeWrapperArgs = [ 264 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 265 + # ]; 266 + # } 267 + # '' 268 + # hello 269 + # '' 270 + writeFish = name: argsOrScript: 271 + if lib.isAttrs argsOrScript && ! lib.isDerivation argsOrScript 272 + then makeScriptWriter (argsOrScript // { 273 + interpreter = "${lib.getExe pkgs.fish} --no-config"; 274 + check = "${lib.getExe pkgs.fish} --no-config --no-execute"; # syntax check only 275 + }) name 276 + else makeScriptWriter { 277 + interpreter = "${lib.getExe pkgs.fish} --no-config"; 278 + check = "${lib.getExe pkgs.fish} --no-config --no-execute"; # syntax check only 279 + } name argsOrScript; 159 280 160 281 # Like writeScriptBin but the first line is a shebang to fish 282 + # 283 + # Can be called with or without extra arguments. 284 + # 285 + # Example without arguments: 286 + # writeFishBin "example" '' 287 + # echo hello world 288 + # '' 289 + # 290 + # Example with arguments: 291 + # writeFishBin "example" 292 + # { 293 + # makeWrapperArgs = [ 294 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 295 + # ]; 296 + # } 297 + # '' 298 + # hello 299 + # '' 161 300 writeFishBin = name: 162 301 writeFish "/bin/${name}"; 163 302 ··· 319 162 # main = launchMissiles 320 163 # ''; 321 164 writeHaskell = name: { 322 - libraries ? [], 323 165 ghc ? pkgs.ghc, 324 166 ghcArgs ? [], 167 + libraries ? [], 168 + makeWrapperArgs ? [], 169 + strip ? true, 325 170 threadedRuntime ? true, 326 - strip ? true 327 171 }: 328 172 let 329 173 appendIfNotSet = el: list: if elem el list then list else list ++ [ el ]; ··· 336 178 ${(ghc.withPackages (_: libraries ))}/bin/ghc ${lib.escapeShellArgs ghcArgs'} tmp.hs 337 179 mv tmp $out 338 180 ''; 339 - inherit strip; 181 + inherit makeWrapperArgs strip; 340 182 } name; 341 183 342 184 # writeHaskellBin takes the same arguments as writeHaskell but outputs a directory (like writeScriptBin) ··· 345 187 346 188 # Like writeScript but the first line is a shebang to nu 347 189 # 348 - # Example: 190 + # Can be called with or without extra arguments. 191 + # 192 + # Example without arguments: 349 193 # writeNu "example" '' 350 194 # echo hello world 351 195 # '' 352 - writeNu = makeScriptWriter { 353 - interpreter = "${lib.getExe pkgs.nushell} --no-config-file"; 354 - }; 196 + # 197 + # Example with arguments: 198 + # writeNu "example" 199 + # { 200 + # makeWrapperArgs = [ 201 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 202 + # ]; 203 + # } 204 + # '' 205 + # hello 206 + # '' 207 + writeNu = name: argsOrScript: 208 + if lib.isAttrs argsOrScript && ! lib.isDerivation argsOrScript 209 + then makeScriptWriter (argsOrScript // { interpreter = "${lib.getExe pkgs.nushell} --no-config-file"; }) name 210 + else makeScriptWriter { interpreter = "${lib.getExe pkgs.nushell} --no-config-file"; } name argsOrScript; 211 + 355 212 356 213 # Like writeScriptBin but the first line is a shebang to nu 214 + # 215 + # Can be called with or without extra arguments. 216 + # 217 + # Example without arguments: 218 + # writeNuBin "example" '' 219 + # echo hello world 220 + # '' 221 + # 222 + # Example with arguments: 223 + # writeNuBin "example" 224 + # { 225 + # makeWrapperArgs = [ 226 + # "--prefix", "PATH", ":", "${pkgs.hello}/bin", 227 + # ]; 228 + # } 229 + # '' 230 + # hello 231 + # '' 357 232 writeNuBin = name: 358 233 writeNu "/bin/${name}"; 359 234 360 235 # makeRubyWriter takes ruby and compatible rubyPackages and produces ruby script writer, 361 236 # If any libraries are specified, ruby.withPackages is used as interpreter, otherwise the "bare" ruby is used. 362 - makeRubyWriter = ruby: rubyPackages: buildRubyPackages: name: { libraries ? [], }: 363 - makeScriptWriter { 364 - interpreter = 365 - if libraries == [] 366 - then "${ruby}/bin/ruby" 367 - else "${(ruby.withPackages (ps: libraries))}/bin/ruby"; 368 - # Rubocop doesnt seem to like running in this fashion. 369 - #check = (writeDash "rubocop.sh" '' 370 - # exec ${lib.getExe buildRubyPackages.rubocop} "$1" 371 - #''); 372 - } name; 237 + makeRubyWriter = ruby: rubyPackages: buildRubyPackages: name: { libraries ? [], ... } @ args: 238 + makeScriptWriter ( 239 + (builtins.removeAttrs args ["libraries"]) 240 + // { 241 + interpreter = 242 + if libraries == [] 243 + then "${ruby}/bin/ruby" 244 + else "${(ruby.withPackages (ps: libraries))}/bin/ruby"; 245 + # Rubocop doesn't seem to like running in this fashion. 246 + #check = (writeDash "rubocop.sh" '' 247 + # exec ${lib.getExe buildRubyPackages.rubocop} "$1" 248 + #''); 249 + } 250 + ) name; 373 251 374 252 # Like writeScript but the first line is a shebang to ruby 375 253 # 376 254 # Example: 377 - # writeRuby "example" '' 255 + # writeRuby "example" { libraries = [ pkgs.rubyPackages.git ]; } '' 378 256 # puts "hello world" 379 257 # '' 380 258 writeRuby = makeRubyWriter pkgs.ruby pkgs.rubyPackages buildPackages.rubyPackages; ··· 421 227 # makeLuaWriter takes lua and compatible luaPackages and produces lua script writer, 422 228 # which validates the script with luacheck at build time. If any libraries are specified, 423 229 # lua.withPackages is used as interpreter, otherwise the "bare" lua is used. 424 - makeLuaWriter = lua: luaPackages: buildLuaPackages: name: { libraries ? [], }: 425 - makeScriptWriter { 426 - interpreter = lua.interpreter; 427 - # if libraries == [] 428 - # then lua.interpreter 429 - # else (lua.withPackages (ps: libraries)).interpreter 430 - # This should support packages! I just cant figure out why some dependency collision happens whenever I try to run this. 431 - check = (writeDash "luacheck.sh" '' 432 - exec ${buildLuaPackages.luacheck}/bin/luacheck "$1" 433 - ''); 434 - } name; 230 + makeLuaWriter = lua: luaPackages: buildLuaPackages: name: { libraries ? [], ... } @ args: 231 + makeScriptWriter ( 232 + (builtins.removeAttrs args ["libraries"]) 233 + // { 234 + interpreter = lua.interpreter; 235 + # if libraries == [] 236 + # then lua.interpreter 237 + # else (lua.withPackages (ps: libraries)).interpreter 238 + # This should support packages! I just cant figure out why some dependency collision happens whenever I try to run this. 239 + check = (writeDash "luacheck.sh" '' 240 + exec ${buildLuaPackages.luacheck}/bin/luacheck "$1" 241 + ''); 242 + } 243 + ) name; 435 244 436 245 # writeLua takes a name an attributeset with libraries and some lua source code and 437 246 # returns an executable (should also work with luajit) ··· 462 265 writeLua "/bin/${name}"; 463 266 464 267 writeRust = name: { 465 - rustc ? pkgs.rustc, 466 - rustcArgs ? [], 467 - strip ? true 268 + makeWrapperArgs ? [], 269 + rustc ? pkgs.rustc, 270 + rustcArgs ? [], 271 + strip ? true, 468 272 }: 469 273 let 470 274 darwinArgs = lib.optionals stdenv.isDarwin [ "-L${lib.getLib libiconv}/lib" ]; ··· 475 277 cp "$contentPath" tmp.rs 476 278 PATH=${lib.makeBinPath [pkgs.gcc]} ${rustc}/bin/rustc ${lib.escapeShellArgs rustcArgs} ${lib.escapeShellArgs darwinArgs} -o "$out" tmp.rs 477 279 ''; 478 - inherit strip; 280 + inherit makeWrapperArgs strip; 479 281 } name; 480 282 481 283 writeRustBin = name: ··· 535 337 # use boolean; 536 338 # print "Howdy!\n" if true; 537 339 # '' 538 - writePerl = name: { libraries ? [] }: 539 - makeScriptWriter { 540 - interpreter = "${lib.getExe (pkgs.perl.withPackages (p: libraries))}"; 541 - } name; 340 + writePerl = name: { libraries ? [], ... } @ args: 341 + makeScriptWriter ( 342 + (builtins.removeAttrs args ["libraries"]) 343 + // { 344 + interpreter = "${lib.getExe (pkgs.perl.withPackages (p: libraries))}"; 345 + } 346 + ) name; 542 347 543 348 # writePerlBin takes the same arguments as writePerl but outputs a directory (like writeScriptBin) 544 349 writePerlBin = name: ··· 550 349 # makePythonWriter takes python and compatible pythonPackages and produces python script writer, 551 350 # which validates the script with flake8 at build time. If any libraries are specified, 552 351 # python.withPackages is used as interpreter, otherwise the "bare" python is used. 553 - makePythonWriter = python: pythonPackages: buildPythonPackages: name: { libraries ? [], flakeIgnore ? [] }: 352 + makePythonWriter = python: pythonPackages: buildPythonPackages: name: { libraries ? [], flakeIgnore ? [], ... } @ args: 554 353 let 555 354 ignoreAttribute = optionalString (flakeIgnore != []) "--ignore ${concatMapStringsSep "," escapeShellArg flakeIgnore}"; 556 355 in 557 - makeScriptWriter { 558 - interpreter = 559 - if pythonPackages != pkgs.pypy2Packages || pythonPackages != pkgs.pypy3Packages then 560 - if libraries == [] 561 - then python.interpreter 562 - else (python.withPackages (ps: libraries)).interpreter 563 - else python.interpreter 564 - ; 565 - check = optionalString python.isPy3k (writeDash "pythoncheck.sh" '' 566 - exec ${buildPythonPackages.flake8}/bin/flake8 --show-source ${ignoreAttribute} "$1" 567 - ''); 568 - } name; 356 + makeScriptWriter 357 + ( 358 + (builtins.removeAttrs args ["libraries" "flakeIgnore"]) 359 + // { 360 + interpreter = 361 + if pythonPackages != pkgs.pypy2Packages || pythonPackages != pkgs.pypy3Packages then 362 + if libraries == [] 363 + then python.interpreter 364 + else (python.withPackages (ps: libraries)).interpreter 365 + else python.interpreter 366 + ; 367 + check = optionalString python.isPy3k (writeDash "pythoncheck.sh" '' 368 + exec ${buildPythonPackages.flake8}/bin/flake8 --show-source ${ignoreAttribute} "$1" 369 + ''); 370 + } 371 + ) 372 + name; 569 373 570 374 # writePyPy2 takes a name an attributeset with libraries and some pypy2 sourcecode and 571 375 # returns an executable ··· 627 421 writePyPy3 "/bin/${name}"; 628 422 629 423 630 - makeFSharpWriter = { dotnet-sdk ? pkgs.dotnet-sdk, fsi-flags ? "", libraries ? _: [] }: nameOrPath: 424 + makeFSharpWriter = { dotnet-sdk ? pkgs.dotnet-sdk, fsi-flags ? "", libraries ? _: [], ... } @ args: nameOrPath: 631 425 let 632 426 fname = last (builtins.split "/" nameOrPath); 633 427 path = if strings.hasSuffix ".fsx" nameOrPath then nameOrPath else "${nameOrPath}.fsx"; ··· 648 442 ${lib.getExe dotnet-sdk} fsi --quiet --nologo --readline- ${fsi-flags} "$@" < "$script" 649 443 ''; 650 444 651 - in content: makeScriptWriter { 652 - interpreter = fsi; 653 - } path 445 + in content: makeScriptWriter ( 446 + (builtins.removeAttrs args ["dotnet-sdk" "fsi-flags" "libraries"]) 447 + // { 448 + interpreter = fsi; 449 + } 450 + ) path 654 451 '' 655 452 #i "nuget: ${nuget-source}/lib" 656 453 ${ content } ··· 665 456 666 457 writeFSharpBin = name: 667 458 writeFSharp "/bin/${name}"; 668 - 669 459 }
+82 -6
pkgs/build-support/writers/test.nix
··· 1 - { glib 2 - , haskellPackages 1 + { haskellPackages 3 2 , lib 4 3 , nodePackages 5 4 , perlPackages 6 - , pypy2Packages 7 5 , python3Packages 8 - , pypy3Packages 9 - , luaPackages 10 - , rubyPackages 11 6 , runCommand 12 7 , testers 13 8 , writers ··· 304 309 file = writeYAML "data.yaml" { hello = "world"; }; 305 310 expected = "hello: world\n"; 306 311 }; 312 + }; 313 + 314 + wrapping = lib.recurseIntoAttrs { 315 + bash-bin = expectSuccessBin ( 316 + writeBashBin "test-writers-wrapping-bash-bin" 317 + { 318 + makeWrapperArgs = [ 319 + "--set" 320 + "ThaigerSprint" 321 + "Thailand" 322 + ]; 323 + } 324 + '' 325 + if [[ "$ThaigerSprint" == "Thailand" ]]; then 326 + echo "success" 327 + fi 328 + '' 329 + ); 330 + 331 + bash = expectSuccess ( 332 + writeBash "test-writers-wrapping-bash" 333 + { 334 + makeWrapperArgs = [ 335 + "--set" 336 + "ThaigerSprint" 337 + "Thailand" 338 + ]; 339 + } 340 + '' 341 + if [[ "$ThaigerSprint" == "Thailand" ]]; then 342 + echo "success" 343 + fi 344 + '' 345 + ); 346 + 347 + python = expectSuccess ( 348 + writePython3 "test-writers-wrapping-python" 349 + { 350 + makeWrapperArgs = [ 351 + "--set" 352 + "ThaigerSprint" 353 + "Thailand" 354 + ]; 355 + } 356 + '' 357 + import os 358 + 359 + if os.environ.get("ThaigerSprint") == "Thailand": 360 + print("success") 361 + '' 362 + ); 363 + 364 + rust = expectSuccess ( 365 + writeRust "test-writers-wrapping-rust" 366 + { 367 + makeWrapperArgs = [ 368 + "--set" 369 + "ThaigerSprint" 370 + "Thailand" 371 + ]; 372 + } 373 + '' 374 + fn main(){ 375 + if std::env::var("ThaigerSprint").unwrap() == "Thailand" { 376 + println!("success") 377 + } 378 + } 379 + '' 380 + ); 381 + 382 + no-empty-wrapper = let 383 + bin = writeBashBin "bin" { makeWrapperArgs = []; } ''true''; 384 + in runCommand "run-test-writers-wrapping-no-empty-wrapper" {} '' 385 + ls -A ${bin}/bin 386 + if [ $(ls -A ${bin}/bin | wc -l) -eq 1 ]; then 387 + touch $out 388 + else 389 + echo "Error: Empty wrapper was created" >&2 390 + exit 1 391 + fi 392 + ''; 307 393 }; 308 394 }