1# Define the list of system with their properties.
2#
3# See https://clang.llvm.org/docs/CrossCompilation.html and
4# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially
5# Triple::normalize. Parsing should essentially act as a more conservative
6# version of that last function.
7
8with import ../lists.nix;
9with import ../types.nix;
10with import ../attrsets.nix;
11with (import ./inspect.nix).predicates;
12
13let
14 lib = import ../default.nix;
15 setTypesAssert = type: pred:
16 mapAttrs (name: value:
17 assert pred value;
18 setType type ({ inherit name; } // value));
19 setTypes = type: setTypesAssert type (_: true);
20
21in
22
23rec {
24
25 isSignificantByte = isType "significant-byte";
26 significantBytes = setTypes "significant-byte" {
27 bigEndian = {};
28 littleEndian = {};
29 };
30
31 isCpuType = isType "cpu-type";
32 cpuTypes = with significantBytes; setTypesAssert "cpu-type"
33 (x: elem x.bits [8 16 32 64 128]
34 && (if 8 < x.bits
35 then isSignificantByte x.significantByte
36 else !(x ? significantByte)))
37 {
38 arm = { bits = 32; significantByte = littleEndian; family = "arm"; };
39 armv5tel = { bits = 32; significantByte = littleEndian; family = "arm"; };
40 armv6l = { bits = 32; significantByte = littleEndian; family = "arm"; };
41 armv7a = { bits = 32; significantByte = littleEndian; family = "arm"; };
42 armv7l = { bits = 32; significantByte = littleEndian; family = "arm"; };
43 aarch64 = { bits = 64; significantByte = littleEndian; family = "aarch64"; };
44 i686 = { bits = 32; significantByte = littleEndian; family = "x86"; };
45 x86_64 = { bits = 64; significantByte = littleEndian; family = "x86"; };
46 mips64el = { bits = 32; significantByte = littleEndian; family = "mips"; };
47 powerpc = { bits = 32; significantByte = bigEndian; family = "power"; };
48 };
49
50 isVendor = isType "vendor";
51 vendors = setTypes "vendor" {
52 apple = {};
53 pc = {};
54
55 unknown = {};
56 };
57
58 isExecFormat = isType "exec-format";
59 execFormats = setTypes "exec-format" {
60 aout = {}; # a.out
61 elf = {};
62 macho = {};
63 pe = {};
64
65 unknown = {};
66 };
67
68 isKernelFamily = isType "kernel-family";
69 kernelFamilies = setTypes "kernel-family" {
70 bsd = {};
71 };
72
73 isKernel = x: isType "kernel" x;
74 kernels = with execFormats; with kernelFamilies; setTypesAssert "kernel"
75 (x: isExecFormat x.execFormat && all isKernelFamily (attrValues x.families))
76 {
77 darwin = { execFormat = macho; families = { }; };
78 freebsd = { execFormat = elf; families = { inherit bsd; }; };
79 hurd = { execFormat = elf; families = { }; };
80 linux = { execFormat = elf; families = { }; };
81 netbsd = { execFormat = elf; families = { inherit bsd; }; };
82 none = { execFormat = unknown; families = { }; };
83 openbsd = { execFormat = elf; families = { inherit bsd; }; };
84 solaris = { execFormat = elf; families = { }; };
85 windows = { execFormat = pe; families = { }; };
86 } // { # aliases
87 # TODO(@Ericson2314): Handle these Darwin version suffixes more generally.
88 darwin10 = kernels.darwin;
89 darwin14 = kernels.darwin;
90 win32 = kernels.windows;
91 };
92
93 isAbi = isType "abi";
94 abis = setTypes "abi" {
95 cygnus = {};
96 gnu = {};
97 msvc = {};
98 eabi = {};
99 androideabi = {};
100 gnueabi = {};
101 gnueabihf = {};
102
103 unknown = {};
104 };
105
106 isSystem = isType "system";
107 mkSystem = { cpu, vendor, kernel, abi }:
108 assert isCpuType cpu && isVendor vendor && isKernel kernel && isAbi abi;
109 setType "system" {
110 inherit cpu vendor kernel abi;
111 };
112
113 mkSkeletonFromList = l: {
114 "2" = # We only do 2-part hacks for things Nix already supports
115 if elemAt l 1 == "cygwin"
116 then { cpu = elemAt l 0; kernel = "windows"; abi = "cygnus"; }
117 else if elemAt l 1 == "gnu"
118 then { cpu = elemAt l 0; kernel = "hurd"; abi = "gnu"; }
119 else { cpu = elemAt l 0; kernel = elemAt l 1; };
120 "3" = # Awkwards hacks, beware!
121 if elemAt l 1 == "apple"
122 then { cpu = elemAt l 0; vendor = "apple"; kernel = elemAt l 2; }
123 else if (elemAt l 1 == "linux") || (elemAt l 2 == "gnu")
124 then { cpu = elemAt l 0; kernel = elemAt l 1; abi = elemAt l 2; }
125 else if (elemAt l 2 == "mingw32") # autotools breaks on -gnu for window
126 then { cpu = elemAt l 0; vendor = elemAt l 1; kernel = "windows"; abi = "gnu"; }
127 else throw "Target specification with 3 components is ambiguous";
128 "4" = { cpu = elemAt l 0; vendor = elemAt l 1; kernel = elemAt l 2; abi = elemAt l 3; };
129 }.${toString (length l)}
130 or (throw "system string has invalid number of hyphen-separated components");
131
132 # This should revert the job done by config.guess from the gcc compiler.
133 mkSystemFromSkeleton = { cpu
134 , # Optional, but fallback too complex for here.
135 # Inferred below instead.
136 vendor ? assert false; null
137 , kernel
138 , # Also inferred below
139 abi ? assert false; null
140 } @ args: let
141 getCpu = name: cpuTypes.${name} or (throw "Unknown CPU type: ${name}");
142 getVendor = name: vendors.${name} or (throw "Unknown vendor: ${name}");
143 getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}");
144 getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}");
145
146 parsed = rec {
147 cpu = getCpu args.cpu;
148 vendor =
149 /**/ if args ? vendor then getVendor args.vendor
150 else if isDarwin parsed then vendors.apple
151 else if isWindows parsed then vendors.pc
152 else vendors.unknown;
153 kernel = getKernel args.kernel;
154 abi =
155 /**/ if args ? abi then getAbi args.abi
156 else if isLinux parsed then abis.gnu
157 else if isWindows parsed then abis.gnu
158 else abis.unknown;
159 };
160
161 in mkSystem parsed;
162
163 mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
164
165 doubleFromSystem = { cpu, vendor, kernel, abi, ... }:
166 if abi == abis.cygnus
167 then "${cpu.name}-cygwin"
168 else "${cpu.name}-${kernel.name}";
169
170 tripleFromSystem = { cpu, vendor, kernel, abi, ... } @ sys: assert isSystem sys; let
171 optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
172 in "${cpu.name}-${vendor.name}-${kernel.name}${optAbi}";
173
174}