Add Nix port tooling
This commit is contained in:
parent
990692a9c1
commit
b37b36731f
|
@ -1,3 +1,4 @@
|
|||
/build-*
|
||||
##### TUP GITIGNORE #####
|
||||
##### Lines below automatically generated by Tup.
|
||||
##### Do not edit.
|
||||
|
|
|
@ -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>
|
|
@ -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
|
||||
'';
|
||||
}
|
|
@ -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)
|
||||
)
|
||||
)
|
|
@ -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>
|
|
@ -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
|
||||
'';
|
||||
}
|
|
@ -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)
|
||||
)));
|
||||
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
source $preparePort/setup
|
||||
genericBuild
|
|
@ -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) ];
|
||||
})
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue