diff options
author | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:36 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2019-01-07 02:18:47 +0000 |
commit | 36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2 (patch) | |
tree | b3faaf573407b32aa645237a4d16b82778a39a92 /nixpkgs/pkgs/build-support/writers | |
parent | 4e31070265257dc67d120c27e0f75c2344fdfa9a (diff) | |
parent | abf060725d7614bd3b9f96764262dfbc2f9c2199 (diff) | |
download | nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.gz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.bz2 nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.lz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.xz nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.tar.zst nixlib-36f56d99fa0a0765c9f1de4a5f17a9b05830c3f2.zip |
Add 'nixpkgs/' from commit 'abf060725d7614bd3b9f96764262dfbc2f9c2199'
git-subtree-dir: nixpkgs git-subtree-mainline: 4e31070265257dc67d120c27e0f75c2344fdfa9a git-subtree-split: abf060725d7614bd3b9f96764262dfbc2f9c2199
Diffstat (limited to 'nixpkgs/pkgs/build-support/writers')
-rw-r--r-- | nixpkgs/pkgs/build-support/writers/default.nix | 262 | ||||
-rw-r--r-- | nixpkgs/pkgs/build-support/writers/test.nix | 168 |
2 files changed, 430 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/build-support/writers/default.nix b/nixpkgs/pkgs/build-support/writers/default.nix new file mode 100644 index 000000000000..ef520f68320a --- /dev/null +++ b/nixpkgs/pkgs/build-support/writers/default.nix @@ -0,0 +1,262 @@ +{ pkgs, lib }: + +with lib; +rec { + # Base implementation for non-compiled executables. + # Takes an interpreter, for example `${pkgs.bash}/bin/bash` + # + # Examples: + # writeBash = makeScriptWriter { interpreter = "${pkgs.bash}/bin/bash"; } + # makeScriptWriter { interpreter = "${pkgs.dash}/bin/dash"; } "hello" "echo hello world" + makeScriptWriter = { interpreter, check ? "" }: nameOrPath: content: + assert lib.or (types.path.check nameOrPath) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null); + assert lib.or (types.path.check content) (types.string.check content); + let + name = last (builtins.split "/" nameOrPath); + in + + pkgs.runCommand name (if (types.string.check content) then { + inherit content interpreter; + passAsFile = [ "content" ]; + } else { + inherit interpreter; + contentPath = content; + }) '' + echo "#! $interpreter" > $out + cat "$contentPath" >> $out + chmod +x $out + ${optionalString (types.path.check nameOrPath) '' + mv $out tmp + mkdir -p $out/$(dirname "${nameOrPath}") + mv tmp $out/${nameOrPath} + ''} + ''; + + # Base implementation for compiled executables. + # Takes a compile script, which in turn takes the name as an argument. + # + # Examples: + # writeSimpleC = makeBinWriter { compileScript = name: "gcc -o $out $contentPath"; } + makeBinWriter = { compileScript }: nameOrPath: content: + assert lib.or (types.path.check nameOrPath) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" nameOrPath != null); + assert lib.or (types.path.check content) (types.string.check content); + let + name = last (builtins.split "/" nameOrPath); + in + pkgs.runCommand name (if (types.string.check content) then { + inherit content; + passAsFile = [ "content" ]; + } else { + contentPath = content; + }) '' + ${compileScript} + ${optionalString (types.path.check nameOrPath) '' + mv $out tmp + mkdir -p $out/$(dirname "${nameOrPath}") + mv tmp $out/${nameOrPath} + ''} + ''; + + # Like writeScript but the first line is a shebang to bash + # + # Example: + # writeBash "example" '' + # echo hello world + # '' + writeBash = makeScriptWriter { + interpreter = "${pkgs.bash}/bin/bash"; + }; + + # Like writeScriptBIn but the first line is a shebang to bash + writeBashBin = name: + writeBash "/bin/${name}"; + + # writeC writes an executable c package called `name` to `destination` using `libraries`. + # + # Examples: + # writeC "hello-world-ncurses" { libraries = [ pkgs.ncurses ]; } '' + # #include <ncurses.h> + # int main() { + # initscr(); + # printw("Hello World !!!"); + # refresh(); endwin(); + # return 0; + # } + # '' + writeC = name: { libraries ? [] }: + makeBinWriter { + compileScript = '' + PATH=${makeBinPath [ + pkgs.binutils-unwrapped + pkgs.coreutils + pkgs.gcc + pkgs.pkgconfig + ]} + gcc \ + ${optionalString (libraries != []) + "$(pkgs.pkgconfig}/bin/pkg-config --cflags --libs ${ + concatMapStringsSep " " (lib: escapeShellArg (builtins.parseDrvName lib.name).name) (libraries) + })" + } \ + -O \ + -o "$out" \ + -Wall \ + -x c \ + "$contentPath" + strip --strip-unneeded "$out" + ''; + } name; + + # writeCBin takes the same arguments as writeC but outputs a directory (like writeScriptBin) + writeCBin = name: + writeC "/bin/${name}"; + + # Like writeScript but the first line is a shebang to dash + # + # Example: + # writeDash "example" '' + # echo hello world + # '' + writeDash = makeScriptWriter { + interpreter = "${pkgs.dash}/bin/dash"; + }; + + # Like writeScriptBin but the first line is a shebang to dash + writeDashBin = name: + writeDash "/bin/${name}"; + + # writeHaskell takes a name, an attrset with libraries and haskell version (both optional) + # and some haskell source code and returns an executable. + # + # Example: + # writeHaskell "missiles" { libraries = [ pkgs.haskellPackages.acme-missiles ]; } '' + # import Acme.Missiles + # + # main = launchMissiles + # ''; + writeHaskell = name: { + libraries ? [], + ghc ? pkgs.ghc + }: + makeBinWriter { + compileScript = '' + cp $contentPath tmp.hs + ${ghc.withPackages (_: libraries )}/bin/ghc tmp.hs + mv tmp $out + ''; + } name; + + # writeHaskellBin takes the same arguments as writeHaskell but outputs a directory (like writeScriptBin) + writeHaskellBin = name: + writeHaskell "/bin/${name}"; + + # writeJS takes a name an attributeset with libraries and some JavaScript sourcecode and + # returns an executable + # + # Example: + # writeJS "example" { libraries = [ pkgs.nodePackages.uglify-js ]; } '' + # var UglifyJS = require("uglify-js"); + # var code = "function add(first, second) { return first + second; }"; + # var result = UglifyJS.minify(code); + # console.log(result.code); + # '' + writeJS = name: { libraries ? [] }: content: + let + node-env = pkgs.buildEnv { + name = "node"; + paths = libraries; + pathsToLink = [ + "/lib/node_modules" + ]; + }; + in writeDash name '' + export NODE_PATH=${node-env}/lib/node_modules + exec ${pkgs.nodejs}/bin/node ${pkgs.writeText "js" content} + ''; + + # writeJSBin takes the same arguments as writeJS but outputs a directory (like writeScriptBin) + writeJSBin = name: + writeJS "/bin/${name}"; + + # writePerl takes a name an attributeset with libraries and some perl sourcecode and + # returns an executable + # + # Example: + # writePerl "example" { libraries = [ pkgs.perlPackages.boolean ]; } '' + # use boolean; + # print "Howdy!\n" if true; + # '' + writePerl = name: { libraries ? [] }: + let + perl-env = pkgs.buildEnv { + name = "perl-environment"; + paths = libraries; + pathsToLink = [ + "/lib/perl5/site_perl" + ]; + }; + in + makeScriptWriter { + interpreter = "${pkgs.perl}/bin/perl -I ${perl-env}/lib/perl5/site_perl"; + } name; + + # writePerlBin takes the same arguments as writePerl but outputs a directory (like writeScriptBin) + writePerlBin = name: + writePerl "/bin/${name}"; + + # writePython2 takes a name an attributeset with libraries and some python2 sourcecode and + # returns an executable + # + # Example: + # writePython2 "test_python2" { libraries = [ pkgs.python2Packages.enum ]; } '' + # from enum import Enum + # + # class Test(Enum): + # a = "success" + # + # print Test.a + # '' + writePython2 = name: { libraries ? [], flakeIgnore ? [] }: + let + py = pkgs.python2.withPackages (ps: libraries); + ignoreAttribute = optionalString (flakeIgnore != []) "--ignore ${concatMapStringsSep "," escapeShellArg flakeIgnore}"; + in + makeScriptWriter { + interpreter = "${py}/bin/python"; + check = writeDash "python2check.sh" '' + exec ${pkgs.python2Packages.flake8}/bin/flake8 --show-source ${ignoreAttribute} "$1" + ''; + } name; + + # writePython2Bin takes the same arguments as writePython2 but outputs a directory (like writeScriptBin) + writePython2Bin = name: + writePython2 "/bin/${name}"; + + # writePython3 takes a name an attributeset with libraries and some python3 sourcecode and + # returns an executable + # + # Example: + # writePython3 "test_python3" { libraries = [ pkgs.python3Packages.pyyaml ]; } '' + # import yaml + # + # y = yaml.load(""" + # - test: success + # """) + # print(y[0]['test']) + # '' + writePython3 = name: { libraries ? [], flakeIgnore ? [] }: + let + py = pkgs.python3.withPackages (ps: libraries); + ignoreAttribute = optionalString (flakeIgnore != []) "--ignore ${concatMapStringsSep "," escapeShellArg flakeIgnore}"; + in + makeScriptWriter { + interpreter = "${py}/bin/python"; + check = writeDash "python3check.sh" '' + exec ${pkgs.python3Packages.flake8}/bin/flake8 --show-source ${ignoreAttribute} "$1" + ''; + } name; + + # writePython3Bin takes the same arguments as writePython3 but outputs a directory (like writeScriptBin) + writePython3Bin = name: + writePython3 "/bin/${name}"; +} diff --git a/nixpkgs/pkgs/build-support/writers/test.nix b/nixpkgs/pkgs/build-support/writers/test.nix new file mode 100644 index 000000000000..80e9543f9c85 --- /dev/null +++ b/nixpkgs/pkgs/build-support/writers/test.nix @@ -0,0 +1,168 @@ +{ stdenv, lib, runCommand, haskellPackages, nodePackages, perlPackages, python2Packages, python3Packages, writers, writeText }: +with writers; +let + + bin = { + bash = writeBashBin "test_writers" '' + if [[ "test" == "test" ]]; then echo "success"; fi + ''; + + c = writeCBin "test_writers" { libraries = [ ]; } '' + #include <stdio.h> + int main() { + printf("success\n"); + return 0; + } + ''; + + dash = writeDashBin "test_writers" '' + test '~' = '~' && echo 'success' + ''; + + haskell = writeHaskellBin "test_writers" { libraries = [ haskellPackages.acme-default ]; } '' + import Data.Default + + int :: Int + int = def + + main :: IO () + main = case int of + 18871 -> putStrLn $ id "success" + _ -> print "fail" + ''; + + js = writeJSBin "test_writers" { libraries = [ nodePackages.semver ]; } '' + var semver = require('semver'); + + if (semver.valid('1.2.3')) { + console.log('success') + } else { + console.log('fail') + } + ''; + + perl = writePerlBin "test_writers" { libraries = [ perlPackages.boolean ]; } '' + use boolean; + print "success\n" if true; + ''; + + python2 = writePython2Bin "test_writers" { libraries = [ python2Packages.enum ]; } '' + from enum import Enum + + class Test(Enum): + a = "success" + + print Test.a + ''; + + python3 = writePython3Bin "test_writers" { libraries = [ python3Packages.pyyaml ]; } '' + import yaml + + y = yaml.load(""" + - test: success + """) + print(y[0]['test']) + ''; + }; + + simple = { + bash = writeBash "test_bash" '' + if [[ "test" == "test" ]]; then echo "success"; fi + ''; + + c = writeC "test_c" { libraries = [ ]; } '' + #include <stdio.h> + int main() { + printf("success\n"); + return 0; + } + ''; + + dash = writeDash "test_dash" '' + test '~' = '~' && echo 'success' + ''; + + haskell = writeHaskell "test_haskell" { libraries = [ haskellPackages.acme-default ]; } '' + import Data.Default + + int :: Int + int = def + + main :: IO () + main = case int of + 18871 -> putStrLn $ id "success" + _ -> print "fail" + ''; + + js = writeJS "test_js" { libraries = [ nodePackages.semver ]; } '' + var semver = require('semver'); + + if (semver.valid('1.2.3')) { + console.log('success') + } else { + console.log('fail') + } + ''; + + perl = writePerl "test_perl" { libraries = [ perlPackages.boolean ]; } '' + use boolean; + print "success\n" if true; + ''; + + python2 = writePython2 "test_python2" { libraries = [ python2Packages.enum ]; } '' + from enum import Enum + + class Test(Enum): + a = "success" + + print Test.a + ''; + + python3 = writePython3 "test_python3" { libraries = [ python3Packages.pyyaml ]; } '' + import yaml + + y = yaml.load(""" + - test: success + """) + print(y[0]['test']) + ''; + }; + + + path = { + bash = writeBash "test_bash" (writeText "test" '' + if [[ "test" == "test" ]]; then echo "success"; fi + ''); + haskell = writeHaskell "test_haskell" { libraries = [ haskellPackages.acme-default ]; } (writeText "test" '' + import Data.Default + + int :: Int + int = def + + main :: IO () + main = case int of + 18871 -> putStrLn $ id "success" + _ -> print "fail" + ''); + }; + + writeTest = expectedValue: test: + writeDash "test-writers" '' + if test "$(${test})" != "${expectedValue}"; then + echo 'test ${test} failed' + exit 1 + fi + ''; + +in runCommand "test-writers" { + passthru = { inherit writeTest bin simple; }; + meta.platforms = stdenv.lib.platforms.all; +} '' + ${lib.concatMapStringsSep "\n" (test: writeTest "success" "${test}/bin/test_writers") (lib.attrValues bin)} + ${lib.concatMapStringsSep "\n" (test: writeTest "success" "${test}") (lib.attrValues simple)} + ${lib.concatMapStringsSep "\n" (test: writeTest "success" "${test}") (lib.attrValues path)} + + echo 'nix-writers successfully tested' >&2 + touch $out +'' + |