2017-07-29 02:05:35 +02:00
|
|
|
{ lib }:
|
|
|
|
let inherit (lib.attrsets) mapAttrs; in
|
2017-05-21 19:39:23 +02:00
|
|
|
|
2017-02-09 03:27:22 +01:00
|
|
|
rec {
|
2017-07-29 02:05:35 +02:00
|
|
|
doubles = import ./doubles.nix { inherit lib; };
|
lib, stdenv: Check `meta.platforms` against host platform and be open world
First, we need check against the host platform, not the build platform.
That's simple enough.
Second, we move away from exahustive finite case analysis (i.e.
exhaustively listing all platforms the package builds on). That only
work in a closed-world setting, where we know all platforms we might
build one. But with cross compilation, we may be building for arbitrary
platforms, So we need fancier filters. This is the closed world to open
world change.
The solution is instead of having a list of systems (strings in the form
"foo-bar"), we have a list of of systems or "patterns", i.e. attributes
that partially match the output of the parsers in `lib.systems.parse`.
The "check meta" logic treats the systems strings as an exact whitelist
just as before, but treats the patterns as a fuzzy whitelist,
intersecting the actual `hostPlatform` with the pattern and then
checking for equality. (This is done using `matchAttrs`).
The default convenience lists for `meta.platforms` are now changed to be
lists of patterns (usually a single pattern) in
`lib/systems/for-meta.nix` for maximum flexibility under this new
system.
Fixes #30902
2018-01-31 06:11:03 +01:00
|
|
|
forMeta = import ./for-meta.nix { inherit lib; };
|
2017-07-29 02:05:35 +02:00
|
|
|
parse = import ./parse.nix { inherit lib; };
|
|
|
|
inspect = import ./inspect.nix { inherit lib; };
|
|
|
|
platforms = import ./platforms.nix { inherit lib; };
|
|
|
|
examples = import ./examples.nix { inherit lib; };
|
2017-03-24 01:49:28 +01:00
|
|
|
|
|
|
|
# Elaborate a `localSystem` or `crossSystem` so that it contains everything
|
|
|
|
# necessary.
|
|
|
|
#
|
|
|
|
# `parsed` is inferred from args, both because there are two options with one
|
|
|
|
# clearly prefered, and to prevent cycles. A simpler fixed point where the RHS
|
|
|
|
# always just used `final.*` would fail on both counts.
|
|
|
|
elaborate = args: let
|
|
|
|
final = {
|
|
|
|
# Prefer to parse `config` as it is strictly more informative.
|
|
|
|
parsed = parse.mkSystemFromString (if args ? config then args.config else args.system);
|
|
|
|
# Either of these can be losslessly-extracted from `parsed` iff parsing succeeds.
|
|
|
|
system = parse.doubleFromSystem final.parsed;
|
|
|
|
config = parse.tripleFromSystem final.parsed;
|
|
|
|
# Just a guess, based on `system`
|
|
|
|
platform = platforms.selectBySystem final.system;
|
2019-02-22 04:17:51 +01:00
|
|
|
# Determine whether we are compatible with the provided CPU
|
|
|
|
isCompatible = platform: parse.isCompatible final.parsed.cpu platform.parsed.cpu;
|
2017-02-17 06:36:10 +01:00
|
|
|
# Derived meta-data
|
2017-05-21 20:02:19 +02:00
|
|
|
libc =
|
2017-02-17 06:36:10 +01:00
|
|
|
/**/ if final.isDarwin then "libSystem"
|
|
|
|
else if final.isMinGW then "msvcrt"
|
2019-01-30 03:01:24 +01:00
|
|
|
else if final.isWasi then "wasilibc"
|
2017-02-17 06:36:10 +01:00
|
|
|
else if final.isMusl then "musl"
|
2018-05-10 05:33:31 +02:00
|
|
|
else if final.isUClibc then "uclibc"
|
2017-02-17 06:36:10 +01:00
|
|
|
else if final.isAndroid then "bionic"
|
|
|
|
else if final.isLinux /* default */ then "glibc"
|
2019-03-26 04:33:39 +01:00
|
|
|
else if final.isMsp430 then "newlib"
|
2018-10-15 03:41:33 +02:00
|
|
|
else if final.isAvr then "avrlibc"
|
2018-07-28 18:29:02 +02:00
|
|
|
else if final.isNetBSD then "nblibc"
|
2017-05-21 20:02:19 +02:00
|
|
|
# TODO(@Ericson2314) think more about other operating systems
|
2017-02-17 06:36:10 +01:00
|
|
|
else "native/impure";
|
2017-09-12 21:24:03 +02:00
|
|
|
extensions = {
|
|
|
|
sharedLibrary =
|
|
|
|
/**/ if final.isDarwin then ".dylib"
|
|
|
|
else if final.isWindows then ".dll"
|
|
|
|
else ".so";
|
|
|
|
executable =
|
|
|
|
/**/ if final.isWindows then ".exe"
|
|
|
|
else "";
|
|
|
|
};
|
2017-02-17 06:36:10 +01:00
|
|
|
# Misc boolean options
|
|
|
|
useAndroidPrebuilt = false;
|
2018-04-16 01:21:45 +02:00
|
|
|
useiOSPrebuilt = false;
|
2018-10-17 04:48:43 +02:00
|
|
|
|
|
|
|
# Output from uname
|
|
|
|
uname = {
|
|
|
|
# uname -s
|
2018-10-17 21:43:49 +02:00
|
|
|
system = {
|
|
|
|
"linux" = "Linux";
|
|
|
|
"windows" = "Windows";
|
|
|
|
"darwin" = "Darwin";
|
|
|
|
"netbsd" = "NetBSD";
|
|
|
|
"freebsd" = "FreeBSD";
|
|
|
|
"openbsd" = "OpenBSD";
|
2019-01-30 03:01:24 +01:00
|
|
|
"wasi" = "Wasi";
|
2018-10-17 21:43:49 +02:00
|
|
|
}.${final.parsed.kernel.name} or null;
|
2018-10-17 04:48:43 +02:00
|
|
|
|
|
|
|
# uname -p
|
|
|
|
processor = final.parsed.cpu.name;
|
|
|
|
|
|
|
|
# uname -r
|
|
|
|
release = null;
|
|
|
|
};
|
2018-11-13 23:54:08 +01:00
|
|
|
|
2019-04-19 20:51:25 +02:00
|
|
|
kernelArch =
|
|
|
|
if final.isAarch32 then "arm"
|
|
|
|
else if final.isAarch64 then "arm64"
|
|
|
|
else if final.isx86_32 then "x86"
|
|
|
|
else if final.isx86_64 then "ia64"
|
|
|
|
else final.parsed.cpu.name;
|
|
|
|
|
2018-11-13 23:54:08 +01:00
|
|
|
qemuArch =
|
|
|
|
if final.isArm then "arm"
|
|
|
|
else if final.isx86_64 then "x86_64"
|
|
|
|
else if final.isx86 then "i386"
|
|
|
|
else {
|
|
|
|
"powerpc" = "ppc";
|
2019-04-17 19:09:34 +02:00
|
|
|
"powerpcle" = "ppc";
|
2018-11-13 23:54:08 +01:00
|
|
|
"powerpc64" = "ppc64";
|
2019-04-17 19:09:34 +02:00
|
|
|
"powerpc64le" = "ppc64le";
|
2018-11-13 23:54:08 +01:00
|
|
|
}.${final.parsed.cpu.name} or final.parsed.cpu.name;
|
|
|
|
|
|
|
|
emulator = pkgs: let
|
|
|
|
qemu-user = pkgs.qemu.override {
|
|
|
|
smartcardSupport = false;
|
|
|
|
spiceSupport = false;
|
|
|
|
openGLSupport = false;
|
|
|
|
virglSupport = false;
|
|
|
|
vncSupport = false;
|
|
|
|
gtkSupport = false;
|
|
|
|
sdlSupport = false;
|
|
|
|
pulseSupport = false;
|
|
|
|
smbdSupport = false;
|
|
|
|
seccompSupport = false;
|
|
|
|
hostCpuTargets = ["${final.qemuArch}-linux-user"];
|
|
|
|
};
|
|
|
|
wine-name = "wine${toString final.parsed.cpu.bits}";
|
|
|
|
wine = (pkgs.winePackagesFor wine-name).minimal;
|
|
|
|
in
|
|
|
|
if final.parsed.kernel.name == pkgs.stdenv.hostPlatform.parsed.kernel.name &&
|
2019-02-22 04:17:51 +01:00
|
|
|
pkgs.stdenv.hostPlatform.isCompatible final
|
2019-04-17 22:41:33 +02:00
|
|
|
then "${pkgs.runtimeShell} -c '\"$@\"' --"
|
2018-11-13 23:54:08 +01:00
|
|
|
else if final.isWindows
|
|
|
|
then "${wine}/bin/${wine-name}"
|
|
|
|
else if final.isLinux && pkgs.stdenv.hostPlatform.isLinux
|
|
|
|
then "${qemu-user}/bin/qemu-${final.qemuArch}"
|
2019-04-16 04:22:16 +02:00
|
|
|
else if final.isWasi
|
|
|
|
then "${pkgs.wasmtime}/bin/wasmtime"
|
2018-11-13 23:54:08 +01:00
|
|
|
else throw "Don't know how to run ${final.config} executables.";
|
|
|
|
|
2017-05-21 19:39:23 +02:00
|
|
|
} // mapAttrs (n: v: v final.parsed) inspect.predicates
|
|
|
|
// args;
|
2017-02-17 06:36:10 +01:00
|
|
|
in assert final.useAndroidPrebuilt -> final.isAndroid;
|
2018-05-10 00:50:51 +02:00
|
|
|
assert lib.foldl
|
|
|
|
(pass: { assertion, message }:
|
|
|
|
if assertion final
|
|
|
|
then pass
|
|
|
|
else throw message)
|
|
|
|
true
|
|
|
|
(final.parsed.abi.assertions or []);
|
2017-02-17 06:36:10 +01:00
|
|
|
final;
|
2017-02-09 03:27:22 +01:00
|
|
|
}
|