2017-07-29 01:05:35 +01:00
|
|
|
{ lib }:
|
|
|
|
let inherit (lib.attrsets) mapAttrs; in
|
2017-05-21 18:39:23 +01:00
|
|
|
|
2017-02-09 02:27:22 +00:00
|
|
|
rec {
|
2017-07-29 01:05:35 +01:00
|
|
|
doubles = import ./doubles.nix { inherit lib; };
|
|
|
|
parse = import ./parse.nix { inherit lib; };
|
|
|
|
inspect = import ./inspect.nix { inherit lib; };
|
|
|
|
platforms = import ./platforms.nix { inherit lib; };
|
|
|
|
examples = import ./examples.nix { inherit lib; };
|
2020-08-05 03:32:41 +01:00
|
|
|
architectures = import ./architectures.nix { inherit lib; };
|
2017-03-24 00:49:28 +00: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.
|
2019-06-04 16:10:03 +01:00
|
|
|
elaborate = args': let
|
|
|
|
args = if lib.isString args' then { system = args'; }
|
|
|
|
else args';
|
2017-03-24 00:49:28 +00:00
|
|
|
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;
|
2019-02-22 03:17:51 +00:00
|
|
|
# Determine whether we are compatible with the provided CPU
|
|
|
|
isCompatible = platform: parse.isCompatible final.parsed.cpu platform.parsed.cpu;
|
2017-02-17 05:36:10 +00:00
|
|
|
# Derived meta-data
|
2017-05-21 19:02:19 +01:00
|
|
|
libc =
|
2017-02-17 05:36:10 +00:00
|
|
|
/**/ if final.isDarwin then "libSystem"
|
|
|
|
else if final.isMinGW then "msvcrt"
|
2019-01-30 02:01:24 +00:00
|
|
|
else if final.isWasi then "wasilibc"
|
2020-07-21 21:11:36 +01:00
|
|
|
else if final.isRedox then "relibc"
|
2017-02-17 05:36:10 +00:00
|
|
|
else if final.isMusl then "musl"
|
2018-05-10 04:33:31 +01:00
|
|
|
else if final.isUClibc then "uclibc"
|
2017-02-17 05:36:10 +00:00
|
|
|
else if final.isAndroid then "bionic"
|
|
|
|
else if final.isLinux /* default */ then "glibc"
|
2018-10-15 02:41:33 +01:00
|
|
|
else if final.isAvr then "avrlibc"
|
2020-02-22 17:37:46 +00:00
|
|
|
else if final.isNone then "newlib"
|
2018-07-28 17:29:02 +01:00
|
|
|
else if final.isNetBSD then "nblibc"
|
2017-05-21 19:02:19 +01:00
|
|
|
# TODO(@Ericson2314) think more about other operating systems
|
2017-02-17 05:36:10 +00:00
|
|
|
else "native/impure";
|
2021-05-01 04:03:19 +01:00
|
|
|
# Choose what linker we wish to use by default. Someday we might also
|
|
|
|
# choose the C compiler, runtime library, C++ standard library, etc. in
|
|
|
|
# this way, nice and orthogonally, and deprecate `useLLVM`. But due to
|
|
|
|
# the monolithic GCC build we cannot actually make those choices
|
|
|
|
# independently, so we are just doing `linker` and keeping `useLLVM` for
|
|
|
|
# now.
|
|
|
|
linker =
|
|
|
|
/**/ if final.useLLVM or false then "lld"
|
|
|
|
else if final.isDarwin then "cctools"
|
|
|
|
# "bfd" and "gold" both come from GNU binutils. The existance of Gold
|
|
|
|
# is why we use the more obscure "bfd" and not "binutils" for this
|
|
|
|
# choice.
|
|
|
|
else "bfd";
|
2017-09-12 20:24:03 +01: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 05:36:10 +00:00
|
|
|
# Misc boolean options
|
|
|
|
useAndroidPrebuilt = false;
|
2018-04-16 00:21:45 +01:00
|
|
|
useiOSPrebuilt = false;
|
2018-10-17 03:48:43 +01:00
|
|
|
|
|
|
|
# Output from uname
|
|
|
|
uname = {
|
|
|
|
# uname -s
|
2018-10-17 20:43:49 +01:00
|
|
|
system = {
|
2019-08-13 22:52:01 +01:00
|
|
|
linux = "Linux";
|
|
|
|
windows = "Windows";
|
|
|
|
darwin = "Darwin";
|
|
|
|
netbsd = "NetBSD";
|
|
|
|
freebsd = "FreeBSD";
|
|
|
|
openbsd = "OpenBSD";
|
|
|
|
wasi = "Wasi";
|
2020-07-21 21:11:36 +01:00
|
|
|
redox = "Redox";
|
2020-03-24 08:02:18 +00:00
|
|
|
genode = "Genode";
|
2018-10-17 20:43:49 +01:00
|
|
|
}.${final.parsed.kernel.name} or null;
|
2018-10-17 03:48:43 +01:00
|
|
|
|
|
|
|
# uname -p
|
|
|
|
processor = final.parsed.cpu.name;
|
|
|
|
|
|
|
|
# uname -r
|
|
|
|
release = null;
|
|
|
|
};
|
2020-08-25 02:46:48 +01:00
|
|
|
isStatic = final.isWasm || final.isRedox;
|
2018-11-13 22:54:08 +00:00
|
|
|
|
2021-01-23 01:33:55 +00:00
|
|
|
# Just a guess, based on `system`
|
|
|
|
inherit
|
|
|
|
({
|
|
|
|
linux-kernel = args.linux-kernel or {};
|
|
|
|
gcc = args.gcc or {};
|
|
|
|
rustc = args.rust or {};
|
|
|
|
} // platforms.select final)
|
|
|
|
linux-kernel gcc rustc;
|
|
|
|
|
|
|
|
linuxArch =
|
2019-04-19 19:51:25 +01:00
|
|
|
if final.isAarch32 then "arm"
|
|
|
|
else if final.isAarch64 then "arm64"
|
2021-01-23 01:33:55 +00:00
|
|
|
else if final.isx86_32 then "i386"
|
|
|
|
else if final.isx86_64 then "x86_64"
|
2019-11-03 05:17:33 +00:00
|
|
|
else if final.isMips then "mips"
|
2021-01-26 01:55:04 +00:00
|
|
|
else if final.isPower then "powerpc"
|
|
|
|
else if final.isRiscV then "riscv"
|
2021-09-07 10:10:38 +01:00
|
|
|
else if final.isS390 then "s390"
|
2019-04-19 19:51:25 +01:00
|
|
|
else final.parsed.cpu.name;
|
|
|
|
|
2018-11-13 22:54:08 +00:00
|
|
|
qemuArch =
|
2020-02-05 18:54:54 +00:00
|
|
|
if final.isAarch32 then "arm"
|
2018-11-13 22:54:08 +00:00
|
|
|
else if final.isx86_64 then "x86_64"
|
|
|
|
else if final.isx86 then "i386"
|
|
|
|
else {
|
2019-08-13 22:52:01 +01:00
|
|
|
powerpc = "ppc";
|
|
|
|
powerpcle = "ppc";
|
|
|
|
powerpc64 = "ppc64";
|
|
|
|
powerpc64le = "ppc64le";
|
2018-11-13 22:54:08 +00:00
|
|
|
}.${final.parsed.cpu.name} or final.parsed.cpu.name;
|
|
|
|
|
2020-12-11 11:15:34 +00:00
|
|
|
darwinArch = {
|
|
|
|
armv7a = "armv7";
|
|
|
|
aarch64 = "arm64";
|
|
|
|
}.${final.parsed.cpu.name} or final.parsed.cpu.name;
|
|
|
|
|
2021-02-05 07:24:43 +00:00
|
|
|
darwinPlatform =
|
|
|
|
if final.isMacOS then "macos"
|
|
|
|
else if final.isiOS then "ios"
|
|
|
|
else null;
|
|
|
|
# The canonical name for this attribute is darwinSdkVersion, but some
|
|
|
|
# platforms define the old name "sdkVer".
|
2021-02-15 06:45:37 +00:00
|
|
|
darwinSdkVersion = final.sdkVer or (if final.isAarch64 then "11.0" else "10.12");
|
2021-02-05 07:24:43 +00:00
|
|
|
darwinMinVersion = final.darwinSdkVersion;
|
2021-04-10 10:06:25 +01:00
|
|
|
darwinMinVersionVariable =
|
|
|
|
if final.isMacOS then "MACOSX_DEPLOYMENT_TARGET"
|
|
|
|
else if final.isiOS then "IPHONEOS_DEPLOYMENT_TARGET"
|
|
|
|
else null;
|
2021-02-05 07:24:43 +00:00
|
|
|
|
2018-11-13 22:54:08 +00:00
|
|
|
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 03:17:51 +00:00
|
|
|
pkgs.stdenv.hostPlatform.isCompatible final
|
2019-04-17 21:41:33 +01:00
|
|
|
then "${pkgs.runtimeShell} -c '\"$@\"' --"
|
2018-11-13 22:54:08 +00: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 03:22:16 +01:00
|
|
|
else if final.isWasi
|
|
|
|
then "${pkgs.wasmtime}/bin/wasmtime"
|
2020-12-31 06:21:35 +00:00
|
|
|
else if final.isMmix
|
|
|
|
then "${pkgs.mmixware}/bin/mmix"
|
2018-11-13 22:54:08 +00:00
|
|
|
else throw "Don't know how to run ${final.config} executables.";
|
|
|
|
|
2017-05-21 18:39:23 +01:00
|
|
|
} // mapAttrs (n: v: v final.parsed) inspect.predicates
|
2021-01-23 01:33:55 +00:00
|
|
|
// mapAttrs (n: v: v final.gcc.arch or "default") architectures.predicates
|
2017-05-21 18:39:23 +01:00
|
|
|
// args;
|
2017-02-17 05:36:10 +00:00
|
|
|
in assert final.useAndroidPrebuilt -> final.isAndroid;
|
2018-05-09 23:50:51 +01:00
|
|
|
assert lib.foldl
|
|
|
|
(pass: { assertion, message }:
|
|
|
|
if assertion final
|
|
|
|
then pass
|
|
|
|
else throw message)
|
|
|
|
true
|
|
|
|
(final.parsed.abi.assertions or []);
|
2017-02-17 05:36:10 +00:00
|
|
|
final;
|
2017-02-09 02:27:22 +00:00
|
|
|
}
|