Merge pull request #49290 from krebs/nix-writers
get nix-writers into nixpkgs
This commit is contained in:
commit
f12bd000b9
239
pkgs/build-support/writers/default.nix
Normal file
239
pkgs/build-support/writers/default.nix
Normal file
|
@ -0,0 +1,239 @@
|
|||
{ 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 ? "" }: name: text:
|
||||
assert lib.or (types.path.check name) (builtins.match "([0-9A-Za-z._])[0-9A-Za-z._-]*" name != null);
|
||||
|
||||
pkgs.writeTextFile {
|
||||
name = last (builtins.split "/" name);
|
||||
executable = true;
|
||||
destination = if types.path.check name then name else "";
|
||||
text = ''
|
||||
#! ${interpreter}
|
||||
${text}
|
||||
'';
|
||||
checkPhase = check;
|
||||
};
|
||||
|
||||
# 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 ? [],
|
||||
}: text: pkgs.runCommand name {
|
||||
inherit text;
|
||||
buildInputs = [ pkgs.pkgconfig ] ++ libraries;
|
||||
passAsFile = [ "text" ];
|
||||
} ''
|
||||
PATH=${makeBinPath [
|
||||
pkgs.binutils-unwrapped
|
||||
pkgs.coreutils
|
||||
pkgs.gcc
|
||||
pkgs.pkgconfig
|
||||
]}
|
||||
mkdir -p "$(dirname "$out")"
|
||||
gcc \
|
||||
${optionalString (libraries != [])
|
||||
"$(pkg-config --cflags --libs ${
|
||||
concatMapStringsSep " " (lib: escapeShellArg (builtins.parseDrvName lib.name).name) (libraries)
|
||||
})"
|
||||
} \
|
||||
-O \
|
||||
-o "$out" \
|
||||
-Wall \
|
||||
-x c \
|
||||
"$textPath"
|
||||
strip --strip-unneeded "$out"
|
||||
'';
|
||||
|
||||
# writeCBin takes the same arguments as writeC but outputs a directory (like writeScriptBin)
|
||||
writeCBin = name: spec: text:
|
||||
pkgs.runCommand name {
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
ln -s ${writeC name spec text} $out/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
|
||||
}: text: pkgs.runCommand name {
|
||||
inherit text;
|
||||
passAsFile = [ "text" ];
|
||||
} ''
|
||||
cp $textPath ${name}.hs
|
||||
${ghc.withPackages (_: libraries )}/bin/ghc ${name}.hs
|
||||
cp ${name} $out
|
||||
'';
|
||||
|
||||
# writeHaskellBin takes the same arguments as writeHaskell but outputs a directory (like writeScriptBin)
|
||||
writeHaskellBin = name: spec: text:
|
||||
pkgs.runCommand name {
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
ln -s ${writeHaskell name spec text} $out/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 ? [] }: text:
|
||||
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" text}
|
||||
'';
|
||||
|
||||
# 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}";
|
||||
}
|
149
pkgs/build-support/writers/test.nix
Normal file
149
pkgs/build-support/writers/test.nix
Normal file
|
@ -0,0 +1,149 @@
|
|||
{ stdenv, lib, runCommand, haskellPackages, nodePackages, perlPackages, python2Packages, python3Packages, writers}:
|
||||
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'])
|
||||
'';
|
||||
};
|
||||
|
||||
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)}
|
||||
|
||||
echo 'nix-writers successfully tested' >&2
|
||||
touch $out
|
||||
''
|
||||
|
|
@ -33,4 +33,6 @@ with pkgs;
|
|||
nixos-functions = callPackage ./nixos-functions {};
|
||||
|
||||
patch-shebangs = callPackage ./patch-shebangs {};
|
||||
|
||||
writers = callPackage ../build-support/writers/test.nix {};
|
||||
}
|
||||
|
|
|
@ -420,6 +420,8 @@ with pkgs;
|
|||
|
||||
iconConvTools = callPackage ../build-support/icon-conv-tools {};
|
||||
|
||||
#package writers
|
||||
writers = callPackage ../build-support/writers {};
|
||||
|
||||
### TOOLS
|
||||
|
||||
|
|
Loading…
Reference in a new issue