1{
2 lib,
3 stdenv,
4 targetPackages,
5
6 withoutTargetLibc,
7 libcCross,
8 threadsCross,
9 version,
10
11 apple-sdk,
12 binutils,
13 gmp,
14 mpfr,
15 libmpc,
16 isl,
17
18 enableLTO,
19 enableMultilib,
20 enablePlugin,
21 disableGdbPlugin ? !enablePlugin,
22 enableShared,
23 targetPrefix,
24
25 langC,
26 langCC,
27 langFortran,
28 langAda ? false,
29 langGo,
30 langObjC,
31 langObjCpp,
32 langJit,
33 langRust ? false,
34 disableBootstrap ? (!lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform),
35}:
36
37assert !enablePlugin -> disableGdbPlugin;
38
39# Note [Windows Exception Handling]
40# sjlj (short jump long jump) exception handling makes no sense on x86_64,
41# it's forcibly slowing programs down as it produces a constant overhead.
42# On x86_64 we have SEH (Structured Exception Handling) and we should use
43# that. On i686, we do not have SEH, and have to use sjlj with dwarf2.
44# Hence it's now conditional on x86_32 (i686 is 32bit).
45#
46# ref: https://stackoverflow.com/questions/15670169/what-is-difference-between-sjlj-vs-dwarf-vs-seh
47
48let
49 inherit (stdenv)
50 buildPlatform
51 hostPlatform
52 targetPlatform
53 ;
54
55 # See https://github.com/NixOS/nixpkgs/pull/209870#issuecomment-1500550903
56 disableBootstrap' = disableBootstrap && !langFortran && !langGo;
57
58 crossMingw = (!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.isMinGW;
59 crossDarwin =
60 (!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.libc == "libSystem";
61
62 crossConfigureFlags =
63 # Ensure that -print-prog-name is able to find the correct programs.
64 [
65 "--with-as=${
66 if targetPackages.stdenv.cc.bintools.isLLVM then binutils else targetPackages.stdenv.cc.bintools
67 }/bin/${targetPlatform.config}-as"
68 ]
69 ++ (
70 if withoutTargetLibc then
71 [
72 "--disable-libssp"
73 "--disable-nls"
74 "--without-headers"
75 "--disable-threads"
76 "--disable-libgomp"
77 "--disable-libquadmath"
78 (lib.enableFeature enableShared "shared")
79 "--disable-libatomic" # requires libc
80 "--disable-decimal-float" # requires libc
81 "--disable-libmpx" # requires libc
82 "--disable-hosted-libstdcxx" # requires libc
83 "--disable-libstdcxx-backtrace"
84 "--disable-linux-futex"
85 "--disable-libvtv"
86 "--disable-libitm"
87 ]
88 ++ lib.optionals crossMingw [
89 "--with-headers=${lib.getDev libcCross}/include"
90 "--with-gcc"
91 "--with-gnu-as"
92 "--with-gnu-ld"
93 "--disable-debug"
94 "--disable-win32-registry"
95 "--enable-hash-synchronization"
96 "--enable-libssp"
97 "--disable-nls"
98 # To keep ABI compatibility with upstream mingw-w64
99 "--enable-fully-dynamic-string"
100 ]
101 ++ lib.optionals (crossMingw && targetPlatform.isx86_32) [
102 # See Note [Windows Exception Handling]
103 "--enable-sjlj-exceptions"
104 "--with-dwarf2"
105 ]
106 else
107 [
108 (
109 if crossDarwin then
110 "--with-sysroot=${lib.getLib libcCross}/share/sysroot"
111 else
112 "--with-headers=${lib.getDev libcCross}${libcCross.incdir or "/include"}"
113 )
114 "--enable-__cxa_atexit"
115 "--enable-long-long"
116 "--enable-threads=${
117 if targetPlatform.isUnix then
118 "posix"
119 else if targetPlatform.isWindows then
120 (threadsCross.model or "win32")
121 else
122 "single"
123 }"
124 "--enable-nls"
125 ]
126 ++ lib.optionals (targetPlatform.libc == "uclibc" || targetPlatform.libc == "musl") [
127 # libsanitizer requires netrom/netrom.h which is not
128 # available in uclibc.
129 "--disable-libsanitizer"
130 ]
131 ++ lib.optional (
132 targetPlatform.libc == "newlib" || targetPlatform.libc == "newlib-nano"
133 ) "--with-newlib"
134 ++ lib.optional (targetPlatform.libc == "avrlibc") "--with-avrlibc"
135 );
136
137 configureFlags =
138 # Basic dependencies
139 [
140 "--with-gmp-include=${gmp.dev}/include"
141 "--with-gmp-lib=${gmp.out}/lib"
142 "--with-mpfr-include=${mpfr.dev}/include"
143 "--with-mpfr-lib=${mpfr.out}/lib"
144 "--with-mpc=${libmpc}"
145 ]
146 ++ lib.optionals (!withoutTargetLibc) [
147 (
148 if libcCross == null then
149 (
150 # GCC will search for the headers relative to SDKROOT on Darwin, so it will find them in the store.
151 if targetPlatform.isDarwin then
152 "--with-native-system-header-dir=/usr/include"
153 else
154 "--with-native-system-header-dir=${lib.getDev stdenv.cc.libc}/include"
155 )
156 else
157 "--with-native-system-header-dir=${lib.getDev libcCross}${libcCross.incdir or "/include"}"
158 )
159 # gcc builds for cross-compilers (build != host) or cross-built
160 # gcc (host != target) always apply the offset prefix to disentangle
161 # target headers from build or host headers:
162 # ${with_build_sysroot}${native_system_header_dir}
163 # or ${test_exec_prefix}/${target_noncanonical}/sys-include
164 # or ${with_sysroot}${native_system_header_dir}
165 # While native build (build == host == target) uses passed headers
166 # path as is:
167 # ${with_build_sysroot}${native_system_header_dir}
168 #
169 # Nixpkgs uses flat directory structure for both native and cross
170 # cases. As a result libc headers don't get found for cross case
171 # and many modern features get disabled (libssp is used instead of
172 # target-specific implementations and similar). More details at:
173 # https://github.com/NixOS/nixpkgs/pull/181802#issuecomment-1186822355
174 #
175 # We pick "/" path to effectively avoid sysroot offset and make it work
176 # as a native case.
177 # Darwin requires using the SDK as the sysroot for `SDKROOT` to work correctly.
178 "--with-build-sysroot=${if targetPlatform.isDarwin then apple-sdk.sdkroot else "/"}"
179 # Same with the stdlibc++ headers embedded in the gcc output
180 "--with-gxx-include-dir=${placeholder "out"}/include/c++/${version}/"
181 ]
182
183 # Basic configuration
184 ++ [
185 # Force target prefix. The behavior if `--target` and `--host`
186 # are specified is inconsistent: Sometimes specifying `--target`
187 # always causes a prefix to be generated, sometimes it's only
188 # added if the `--host` and `--target` differ. This means that
189 # sometimes there may be a prefix even though nixpkgs doesn't
190 # expect one and sometimes there may be none even though nixpkgs
191 # expects one (since not all information is serialized into the
192 # config attribute). The easiest way out of these problems is to
193 # always set the program prefix, so gcc will conform to our
194 # expectations.
195 "--program-prefix=${targetPrefix}"
196
197 (lib.enableFeature enableLTO "lto")
198 "--disable-libstdcxx-pch"
199 "--without-included-gettext"
200 "--with-system-zlib"
201 "--enable-static"
202 "--enable-languages=${
203 lib.concatStringsSep "," (
204 lib.optional langC "c"
205 ++ lib.optional langCC "c++"
206 ++ lib.optional langFortran "fortran"
207 ++ lib.optional langAda "ada"
208 ++ lib.optional langGo "go"
209 ++ lib.optional langObjC "objc"
210 ++ lib.optional langObjCpp "obj-c++"
211 ++ lib.optionals crossDarwin [
212 "objc"
213 "obj-c++"
214 ]
215 ++ lib.optional langJit "jit"
216 ++ lib.optional langRust "rust"
217 )
218 }"
219 ]
220
221 ++ (
222 if (enableMultilib || targetPlatform.isAvr) then
223 [
224 "--enable-multilib"
225 "--disable-libquadmath"
226 ]
227 else
228 [ "--disable-multilib" ]
229 )
230 ++ lib.optional (!enableShared) "--disable-shared"
231 ++ lib.singleton (lib.enableFeature enablePlugin "plugin")
232 # Libcc1 is the GCC cc1 plugin for the GDB debugger which is only used by gdb
233 ++ lib.optional disableGdbPlugin "--disable-libcc1"
234
235 # Support -m32 on powerpc64le/be
236 ++ lib.optional (targetPlatform.system == "powerpc64le-linux") "--enable-targets=powerpcle-linux"
237 ++ lib.optional (targetPlatform.system == "powerpc64-linux") "--enable-targets=powerpc-linux"
238
239 # Fix "unknown long double size, cannot define BFP_FMT"
240 ++ lib.optional (targetPlatform.isPower && targetPlatform.isMusl) "--disable-decimal-float"
241
242 # Optional features
243 ++ lib.optional (isl != null) "--with-isl=${isl}"
244
245 # Ada options, gcc can't build the runtime library for a cross compiler
246 ++ lib.optional langAda (
247 if lib.systems.equals hostPlatform targetPlatform then "--enable-libada" else "--disable-libada"
248 )
249
250 ++ import ../common/platform-flags.nix {
251 inherit (stdenv) targetPlatform;
252 inherit lib;
253 }
254 ++ lib.optionals (!lib.systems.equals targetPlatform hostPlatform) crossConfigureFlags
255 ++ lib.optional disableBootstrap' "--disable-bootstrap"
256
257 # Platform-specific flags
258 ++ lib.optional (
259 lib.systems.equals targetPlatform hostPlatform && targetPlatform.isx86_32
260 ) "--with-arch=${stdenv.hostPlatform.parsed.cpu.name}"
261 ++ lib.optional (targetPlatform.isNetBSD || targetPlatform.isCygwin) "--disable-libssp" # Provided by libc.
262 ++ lib.optionals hostPlatform.isSunOS [
263 "--enable-long-long"
264 "--enable-libssp"
265 "--enable-threads=posix"
266 "--disable-nls"
267 "--enable-__cxa_atexit"
268 # On Illumos/Solaris GNU as is preferred
269 "--with-gnu-as"
270 "--without-gnu-ld"
271 ]
272 ++
273 lib.optional (targetPlatform.libc == "musl")
274 # musl at least, disable: https://git.buildroot.net/buildroot/commit/?id=873d4019f7fb00f6a80592224236b3ba7d657865
275 "--disable-libmpx"
276 ++ lib.optionals (lib.systems.equals targetPlatform hostPlatform && targetPlatform.libc == "musl") [
277 "--disable-libsanitizer"
278 "--disable-symvers"
279 "libat_cv_have_ifunc=no"
280 "--disable-gnu-indirect-function"
281 ]
282 ++ lib.optionals langJit [
283 "--enable-host-shared"
284 ]
285 ++ lib.optionals targetPlatform.isAlpha [
286 # Workaround build failures like:
287 # cc1: error: fp software completion requires '-mtrap-precision=i' [-Werror]
288 "--disable-werror"
289 ];
290
291in
292configureFlags