Add Nix port tooling

This commit is contained in:
Ehmry - 2019-07-01 13:56:43 +02:00
parent 990692a9c1
commit b37b36731f
11 changed files with 1826 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/build-*
##### TUP GITIGNORE #####
##### Lines below automatically generated by Tup.
##### Do not edit.

7
ports/chuck/Tupfile Normal file
View File

@ -0,0 +1,7 @@
include_rules
: |> $(NIX_BUILD) .. --out-link port \
--attr source --attr include |> port-source port-include {port}
: port-source |> cp %f/%d.pc %o \
|> $(PKG_CONFIG_DIR)/%d.pc $(GENODE_DIR)/<pkg-config>

14
ports/chuck/default.nix Normal file
View File

@ -0,0 +1,14 @@
{ preparePort, chuck }:
preparePort rec {
inherit (chuck) name version src;
outputs = [ "source" ];
sourceRoot = "${name}/src";
installPhase =
''
mkdir -p $source
cp -r core host scripts $source
'';
}

23
ports/default.nix Normal file
View File

@ -0,0 +1,23 @@
{ tool ? import ../tool { } }:
let
importPort = path:
let f = (import path);
in f (builtins.intersectAttrs (builtins.functionArgs f) (tool.nixpkgs // tool) );
hasSuffixNix = tool.hasSuffix ".nix";
dir = builtins.readDir ../ports;
in
builtins.listToAttrs (
builtins.filter
(x: x != null)
(map
(name:
if (builtins.getAttr name dir) != "directory" then null else
{ inherit name;
value = importPort (../ports + "/${name}");
}
)
(builtins.attrNames dir)
)
)

7
ports/rtaudio/Tupfile Normal file
View File

@ -0,0 +1,7 @@
include_rules
: |> $(NIX_BUILD) .. --out-link port \
--attr source --attr include |> port-source port-include {port}
: port-source |> cp %f/%d.pc %o \
|> $(PKG_CONFIG_DIR)/%d.pc $(GENODE_DIR)/<pkg-config>

25
ports/rtaudio/default.nix Normal file
View File

@ -0,0 +1,25 @@
{ preparePort, rtaudio }:
preparePort rec {
inherit (rtaudio) name version src;
outputs = [ "source" "include" ];
buildPhase =
''
mkdir $source $include
sed \
-e "s|^includedir.*|include=$include|" \
-e 's/@PACKAGE_VERSION@/${version}/' \
-e 's/@req@/stdcxx/' \
-e 's/^Libs:.*/Libs: -l:rtaudio.lib.so/' \
-e '/pthread/d' \
-e 's/@api@/-D__GENODE_AUDIO__/' \
-e '/@/d' \
-e '/prefix/d' \
< rtaudio.pc.in > $source/rtaudio.pc
'';
installPhase =
''
cp -rv RtAudio.cpp rtaudio_c.cpp include $source
cp RtAudio.h rtaudio_c.h $include
'';
}

477
tool/default.nix Normal file
View File

@ -0,0 +1,477 @@
/*
* \brief Tools and utility functions
* \author Emery Hemingway
* \date 2014-09-30
*/
{ nixpkgs ? import <nixpkgs> { } }:
with builtins;
rec {
inherit nixpkgs;
inherit (nixpkgs) fetchurl;
##
# Add a prefix to a list of strings.
addPrefix = prefix: map (s: prefix+s);
##
# Determine if any of the following libs are shared.
anyShared = libs:
let h = head libs; in
if libs == [] then false else
if h.shared or false then true else anyShared (tail libs);
##
# Drop a suffix from the end of a string.
dropSuffix = suf: str:
let
strL = stringLength str;
sufL = stringLength suf;
in
if lessThan strL sufL || substring (sub strL sufL) strL str != suf
then abort "${str} does not have suffix ${suf}"
else substring 0 (sub strL sufL) str;
##
# Generate a list of file paths from a directory and
# filenames.
fromDir = dir: map (s: dir+("/"+s));
##
# Utility functions for gathering sources.
fromGlob =
dir: glob:
let
dirName = dir.name or baseNameOf (toString dir);
in
import (shellDerivation {
name = "${dirName}-glob.nix";
script = ./from-glob.sh;
#PATH="${nixpkgs.coreutils}/bin";
inherit dir glob;
});
fromPath = path: [ [ path (baseNameOf (toString path)) ] ];
fromPaths = paths: map (p: [ p (baseNameOf (toString p)) ]) paths;
##
# Filter out libs that are not derivations
filterFakeLibs = libs: filter (lib: hasAttr "shared" lib) libs;
##
# Test if a string ends in '.h'.
hasDotH = s: substring (sub (stringLength s) 2) 2 s == ".h";
hasDotHH = s: substring (sub (stringLength s) 3) 3 s == ".hh";
hasDotHPP = s: substring (sub (stringLength s) 4) 4 s == ".hpp";
##
# Filter out everything but *.h on a path.
# Prevents files that exist alongside headers from changing header path hash.
filterHeaders = dir: filterSource
(path: type: hasDotH path || hasDotHH path || hasDotHPP path || type == "directory")
dir;
##
# Find a filename in a search path.
findFile = fn: searchPath:
if searchPath == [] then []
else
let
sp = head searchPath;
fn' = sp + "/${fn}";
in
if builtins.typeOf fn' != "path" then [] else
if pathExists fn' then
[ { key = fn'; relative = fn; } ]
else findFile fn (tail searchPath);
findIncludes = main: path:
map (x: [ x.key x.relative ]) (genericClosure {
startSet = [ { key = main; relative = baseNameOf (toString main); } ];
operator =
{ key, ... }:
let
includes = import (includesOf key);
includesFound =
nixpkgs.lib.concatMap
(fn: findFile fn ([ (dirOf main) ] ++ path))
includes;
in includesFound;
});
##
# Recursively find libraries.
findLibraries = libs:
let
list = map (lib: { key = lib.name; inherit lib; });
in
map (x: x.lib) (genericClosure {
startSet = list libs;
operator = { key, lib }: list lib.libs or [];
});
##
# Recursively find libraries to link.
findLinkLibraries = libs:
let
list = libs: map
(lib: { key = lib.name; inherit lib; })
(filter (lib: hasAttr "drvPath" lib) libs);
in
map (x: x.lib) (genericClosure {
startSet = list libs;
operator =
{ key, lib }:
if lib.shared then []
else list lib.libs or [];
});
findLocalIncludes = main: path:
let path' = [ (dirOf main) ] ++ path; in
map (x: [ x.key x.relative ]) (genericClosure {
startSet = [ { key = main; relative = baseNameOf (toString main); } ];
operator =
{ key, ... }:
let
includes = import (localIncludesOf key);
includesFound =
nixpkgs.lib.concatMap
(fn: findFile fn path')
includes;
in includesFound;
});
##
# Recursively find shared libraries.
findRuntimeLibraries = libs:
let
filter = libs: builtins.filter (lib: lib.shared) libs;
list = libs:
map (lib: { key = lib.name; inherit lib; }) libs;
in
filter (map (x: x.lib) (genericClosure {
startSet = list libs;
operator =
{ key, lib }:
list ([lib ] ++ lib.libs);
}));
##
# Determine if a string has the given suffix.
hasSuffix = suf: str:
let
strL = stringLength str;
sufL = stringLength suf;
in
if lessThan strL sufL then false else
substring (sub strL sufL) strL str == suf;
includesOf = file:
import (derivation {
name =
if typeOf file == "path"
then "${baseNameOf (toString file)}-includes"
else "includes";
system = currentSystem;
preferLocalBuild = true;
builder = "${nixpkgs.perl}/bin/perl";
args = [ ./find-includes.pl ];
inherit file;
});
##
# Create a bootable ISO.
iso =
{ name, contents, kernel, kernelArgs }:
shellDerivation {
name = "${name}.iso";
script = ./iso.sh;
PATH="${nixpkgs.coreutils}/bin:${nixpkgs.cdrkit}/bin:${nixpkgs.binutils}/bin";
inherit kernel kernelArgs;
inherit (nixpkgs) syslinux cdrkit;
sources = map (x: x.source) contents;
targets = map (x: x.target) contents;
};
##
# Generate a contents list of runtime libraries for a package.
# This will go away as tool.runtime matures.
libContents = contents: builtins.concatLists (map (
content:
map (source: { target = "/"; inherit source; }) content.source.runtime.libs or []
) contents);
localIncludesOf = main: derivation {
name =
if typeOf main == "path"
then "${baseNameOf (toString main)}-local-includes"
else "local-includes";
system = currentSystem;
preferLocalBuild = true;
builder = "${nixpkgs.perl}/bin/perl";
args = [ ./find-local-includes.pl ];
inherit main;
};
##
# Merge an attr between two sets.
mergeAttr =
name: s1: s2:
let
a1 = getAttr name s1;
a2 = getAttr name s2;
type1 = typeOf a1;
type2 = typeOf a2;
in
if type1 == "null" then a2 else if type2 == "null" then a1 else
if type1 != type2 then abort "cannot merge ${name}s of type ${type1} and ${type2}" else
if type1 == "set" then mergeSet a1 a2 else
if type1 == "list" then a1 ++ a2 else
if type1 == "string" then "${a1} ${a2}" else
#if type1 == "int" then add a1 a2 else
abort "cannot merge ${type1} ${name} ${toString a1} ${toString a2}";
##
# Merge two sets together.
mergeSet = s1: s2:
s1 // s2 // (listToAttrs (map
(name: { inherit name; value = mergeAttr name s1 s2; })
(attrNames (intersectAttrs s1 s2))
));
##
# Merge a list of sets.
mergeSets =
sets:
if sets == [] then {} else
mergeSet (head sets) (mergeSets (tail sets));
newDir =
name: contents:
derivation {
inherit name contents;
system = builtins.currentSystem;
preferLocalBuild = true;
builder = shell;
PATH="${nixpkgs.coreutils}/bin";
args = [ "-e" "-c" ''
mkdir -p $out ; \
for i in $contents; do cp -Hr $i $out; done
'' ];
};
##
# Generate a list of paths from a path and a shell glob.
pathsFromGlob = dir: glob:
let path = toString dir; in
import (derivation {
name = "${baseNameOf path}-glob.nix";
args = [ "-e" "-O" "nullglob" ./path-from-glob.sh ];
inherit dir glob path;
preferLocalBuild = true;
});
preparePort = import ./prepare-port { inherit nixpkgs; };
# Concatenate the named attr found in pkgs.
propagate = attrName: pkgs:
let
pkg = head pkgs;
in
if pkgs == [] then [] else
( if hasAttr attrName pkg
then getAttr attrName pkg
else []
) ++
(propagate attrName (tail pkgs));
##
# Replace substring a with substring b in string s.
replaceInString =
a: b: s:
let
al = stringLength a;
bl = stringLength b;
sl = stringLength s;
in
if al == 0 then s else
if sl == 0 then "" else
if ((substring 0 al s) == a) then
b+(replaceInString a b (substring al sl s))
else
(substring 0 1 s) + (replaceInString a b (substring 1 sl s));
shell = nixpkgs.bash + "/bin/sh";
# Save some typing when creating derivation that use our shell.
shellDerivation = { script, ... } @ args:
derivation ( (removeAttrs args [ "script" ]) //
{ system = builtins.currentSystem;
builder = shell;
args = [ "-e" script ];
}
);
singleton = x: [x];
# Bootability is not assured, so its really system image.
systemImage = import ./system-image { inherit nixpkgs; };
bootImage = systemImage; # get rid of this
wildcard =
path: glob:
let
relativePaths = import (shellDerivation {
name = "files.nix";
PATH="${nixpkgs.coreutils}/bin";
script = ./wildcard.sh;
inherit path glob;
});
in
map (rp: (path+"/${rp}")) relativePaths;
# Appends string context from another string
addContextFrom = a: b: substring 0 0 a + b;
# Compares strings not requiring context equality
# Obviously, a workaround but works on all Nix versions
eqStrings = a: b: addContextFrom b a == addContextFrom a b;
##
# Cut a string with a separator and produces a list of strings which were
# separated by this separator. e.g.,
# `splitString "." "foo.bar.baz"' returns ["foo" "bar" "baz"].
# From nixpkgs.
splitString = _sep: _s:
let
sep = addContextFrom _s _sep;
s = addContextFrom _sep _s;
sepLen = stringLength sep;
sLen = stringLength s;
lastSearch = sLen - sepLen;
startWithSep = startAt:
substring startAt sepLen s == sep;
recurse = index: startAt:
let cutUntil = i: [(substring startAt (i - startAt) s)]; in
if index < lastSearch then
if startWithSep index then
let restartAt = index + sepLen; in
cutUntil index ++ recurse restartAt restartAt
else
recurse (index + 1) startAt
else
cutUntil sLen;
in
recurse 0 0;
##
# What I thought builtins.match would do.
matchPattern = pat: str:
concatLists (
map
( l:
let m = match pat l; in
if m == null then [] else m
)
(splitString "\n" str)
);
##
# Generate a set of local ("") and system (<>)
# preprocessor include directives from a file.
relativeIncludes = file:
let
matches = pattern: lines:
concatLists (filter (x: x != null) (map (match pattern) lines));
lines = splitString "\n" (readFile file);
in
{ local = matches ''.*#include\s*"([^>]*)".*'' lines;
system = matches ''.*#include\s*<([^>]*)>.*'' lines;
};
##
# Find a file in a set of directories.
findFile' = key: dirs:
if substring 0 1 key == "!" then builtins.trace "found a !key" key else
if dirs == [] then null else
let abs = (builtins.head dirs) +"/${key}"; in
if builtins.pathExists abs then abs
else findFile' key (builtins.tail dirs);
##
# Generate a set of relative to absolute include mappings from a file.
# This set includes a mapping from the orginal file basename to its
# absolute path.
#
# The genericClosure primative applies an operation to a list of sets that
# contain the attribute 'key'. This operation returns a similar list of sets,
# and genericClosure appends elements of that list that contain a key
# that does not already exist in the previous set. All sets returned by this
# operation contain a function to resolve the relative path at 'key' into an
# absolute one at 'abs', and a function to parse the absolute path at 'abs'
# into a list of relative includes at 'inc'. GenericClosure discards any set
# with a relative path at 'key' that it has already been seen, and thus due
# to lazy evaulation, no relative path is resolved or parsed twice.
#
# A ! is prepended to the files of the initial set, to differentiate them from
# files with unsolved locations and to satisfy the requirement that strings
# not directly reference store paths in findFile'
includesOfFiles = files: searchPath:
let
concat = sets:
if sets == [] then {} else
let x = head sets; in
(if x.abs == null || substring 0 1 x.key == "!" then {} else { "${x.key}" = x.abs; }) // concat (tail sets);
in
concat (genericClosure {
# Can the startSet really be filled with elements sharing a key?
startSet = map (abs: { key = "!${abs}"; inherit abs; inc = includesOf abs; }) files;
operator =
{ key, abs, inc }: if abs == null then [] else let abs' = abs; in
(map
(key: rec { inherit key; abs = (findFile' key searchPath); inc = includesOf abs; })
inc.system)
++
(map
(key: rec { inherit key; abs = (findFile' key (if typeOf abs' == "path" then searchPath ++ [ (dirOf abs') ] else searchPath)); inc = relativeIncludes abs; })
inc.local);
});
##
# Load expressions from a directory path and apply func.
loadExpressions = func: path:
let
dirSet = builtins.readDir path;
default =
if builtins.hasAttr "default.nix" dirSet
then func (import (path + "/default.nix"))
else {};
in
default // (builtins.listToAttrs (builtins.filter (x: x != {}) (map
(name:
let
type = builtins.getAttr name dirSet;
more = loadExpressions func (path + "/${name}");
in
if type == "directory"
then { inherit name; value = more; }
else
if
(type == "regular" || type == "symlink") &&
(hasSuffix ".nix" name)
then
{ name = dropSuffix ".nix" name;
value = func (import (path+"/${name}"));
}
else { }
)
(builtins.attrNames dirSet)
)));
}

View File

@ -0,0 +1,10 @@
export PATH=
for i in $initialPath; do
if [ "$i" = / ]; then i=; fi
PATH=$PATH${PATH:+:}$i/bin
done
mkdir $out
sed -e "s^@initialPath@^$initialPath^g" \
< $setup > $out/setup

View File

@ -0,0 +1,2 @@
source $preparePort/setup
genericBuild

View File

@ -0,0 +1,39 @@
{ nixpkgs }:
let
shell = nixpkgs.bash + "/bin/sh";
initialPath =
[ nixpkgs.coreutils
nixpkgs.findutils
nixpkgs.diffutils
nixpkgs.gawk
nixpkgs.gnugrep
nixpkgs.gnused
nixpkgs.gnutar
nixpkgs.patch
nixpkgs.gzip
nixpkgs.bzip2
nixpkgs.xz
];
in
{ name
, outputs ? [ "out" ]
, preferLocalBuild ? true
, ... } @ attrs:
derivation (attrs // {
inherit name outputs initialPath;
preparePort = derivation {
name = "prepare-port";
system = builtins.currentSystem;
builder = shell;
args = [ "-e" ./builder.sh ];
setup = ./setup.sh;
inherit initialPath;
};
system = builtins.currentSystem;
builder = attrs.realBuilder or shell;
args = attrs.args or [ "-e" (attrs.builder or ./default-builder.sh) ];
})

1221
tool/prepare-port/setup.sh Normal file

File diff suppressed because it is too large Load Diff