about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/compilers/gcc/common/pre-configure.nix
blob: e386693b22c7ae89217a491a0d8baddb4120468a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
{ lib
, stdenv
, version, buildPlatform, hostPlatform, targetPlatform
, gnat-bootstrap ? null
, langAda ? false
, langJava ? false
, langJit ? false
, langGo
, withoutTargetLibc
, enableShared
, enableMultilib
}:

assert langJava -> lib.versionOlder version "7";
assert langAda -> gnat-bootstrap != null; let
  needsLib
    =  (lib.versionOlder version "7" && (langJava || langGo))
    || (lib.versions.major version == "4" && lib.versions.minor version == "9" && targetPlatform.isDarwin);
in lib.optionalString (hostPlatform.isSunOS && hostPlatform.is64bit) ''
  export NIX_LDFLAGS=`echo $NIX_LDFLAGS | sed -e s~$prefix/lib~$prefix/lib/amd64~g`
  export LDFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $LDFLAGS_FOR_TARGET"
  export CXXFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $CXXFLAGS_FOR_TARGET"
  export CFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $CFLAGS_FOR_TARGET"
'' + lib.optionalString needsLib ''
  export lib=$out;
'' + lib.optionalString langAda ''
  export PATH=${gnat-bootstrap}/bin:$PATH
''

# On x86_64-darwin, the gnat-bootstrap bootstrap compiler that we need to build a
# native GCC with Ada support emits assembly that is accepted by the Clang
# integrated assembler, but not by the GNU assembler in cctools-port that Nix
# usually in the x86_64-darwin stdenv.  In particular, x86_64-darwin gnat-bootstrap
# emits MOVQ as the mnemonic for quadword interunit moves, such as between XMM
# and general registers (e.g "movq %xmm0, %rbp"); the cctools-port assembler,
# however, only recognises MOVD for such moves.
#
# Therefore, for native x86_64-darwin builds that support Ada, we have to use
# the Clang integrated assembler to build (at least stage 1 of) GCC, but have to
# target GCC at the cctools-port GNU assembler.  In the wrapped x86_64-darwin
# gnat-bootstrap, the former is provided as `as`, while the latter is provided as
# `gas`.
#
+ lib.optionalString (
    langAda
    && buildPlatform == hostPlatform
    && hostPlatform == targetPlatform
    && targetPlatform.isx86_64
    && targetPlatform.isDarwin
  ) ''
  export AS_FOR_BUILD=${gnat-bootstrap}/bin/as
  export AS_FOR_TARGET=${gnat-bootstrap}/bin/gas
''

# NOTE 2020/3/18: This environment variable prevents configure scripts from
# detecting the presence of aligned_alloc on Darwin.  There are many facts that
# collectively make this fix necessary:
#  - Nix uses a fixed set of standard library headers on all MacOS systems,
#    regardless of their actual version.  (Nix uses version 10.12 headers.)
#  - Nix uses the native standard library binaries for the build system.  That
#    means the standard library binaries may not exactly match the standard
#    library headers.
#  - The aligned_alloc procedure is present in MacOS 10.15 (Catalina), but not
#    in earlier versions.  Therefore on Catalina systems, aligned_alloc is
#    linkable (i.e. present in the binary libraries) but not present in the
#    headers.
#  - Configure scripts detect a procedure's existence by checking whether it is
#    linkable.  They do not check whether it is present in the headers.
#  - GCC throws an error during compilation because aligned_alloc is not
#    defined in the headers---even though the linker can see it.
#
# This fix would not be necessary if ANY of the above were false:
#  - If Nix used native headers for each different MacOS version, aligned_alloc
#    would be in the headers on Catalina.
#  - If Nix used the same library binaries for each MacOS version, aligned_alloc
#    would not be in the library binaries.
#  - If Catalina did not include aligned_alloc, this wouldn't be a problem.
#  - If the configure scripts looked for header presence as well as
#    linkability, they would see that aligned_alloc is missing.
#  - If GCC allowed implicit declaration of symbols, it would not fail during
#    compilation even if the configure scripts did not check header presence.
#
+ lib.optionalString (buildPlatform.isDarwin) ''
    export build_configargs=ac_cv_func_aligned_alloc=no
'' + lib.optionalString (hostPlatform.isDarwin) ''
    export host_configargs=ac_cv_func_aligned_alloc=no
'' + lib.optionalString (targetPlatform.isDarwin) ''
    export target_configargs=ac_cv_func_aligned_alloc=no
''

# In order to properly install libgccjit on macOS Catalina, strip(1)
# upon installation must not remove external symbols, otherwise the
# install step errors with "symbols referenced by indirect symbol
# table entries that can't be stripped".
+ lib.optionalString (hostPlatform.isDarwin && langJit) ''
  export STRIP='strip -x'
''

# HACK: if host and target config are the same, but the platforms are
# actually different we need to convince the configure script that it
# is in fact building a cross compiler although it doesn't believe it.
+ lib.optionalString (targetPlatform.config == hostPlatform.config && targetPlatform != hostPlatform) ''
  substituteInPlace configure --replace is_cross_compiler=no is_cross_compiler=yes
''

# Normally (for host != target case) --without-headers automatically
# enables 'inhibit_libc=true' in gcc's gcc/configure.ac. But case of
# gcc->clang "cross"-compilation manages to evade it: there
# hostPlatform != targetPlatform, hostPlatform.config == targetPlatform.config.
# We explicitly inhibit libc headers use in this case as well.
+ lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc) ''
  export inhibit_libc=true
''

# Trick to build a gcc that is capable of emitting shared libraries *without* having the
# targetPlatform libc available beforehand.  Taken from:
#   https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/
#   https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff
+ lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc && enableShared)
  (let

    # crt{i,n}.o are the first and last (respectively) object file
    # linked when producing an executable.  Traditionally these
    # files are delivered as part of the C library, but on GNU
    # systems they are in fact built by GCC.  Since libgcc needs to
    # build before glibc, we can't wait for them to be copied by
    # glibc.  At this early pre-glibc stage these files sometimes
    # have different names.
    crtstuff-ofiles =
      if targetPlatform.isPower
      then "ecrti.o ecrtn.o ncrti.o ncrtn.o"
      else "crti.o crtn.o";

    # Normally, `SHLIB_LC` is set to `-lc`, which means that
    # `libgcc_s.so` cannot be built until `libc.so` is available.
    # The assignment below clobbers this variable, removing the
    # `-lc`.
    #
    # On PowerPC we add `-mnewlib`, which means "libc has not been
    # built yet".  This causes libgcc's Makefile to use the
    # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the
    # versions which have been repackaged in libc as `crt{n,i}.o`
    #
    SHLIB_LC = lib.optionalString targetPlatform.isPower "-mnewlib";

  in ''
    echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in
    echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in
  '')

+ lib.optionalString (!enableMultilib && hostPlatform.is64bit && !hostPlatform.isMips64n32) ''
  export linkLib64toLib=1
''

# On mips platforms, gcc follows the IRIX naming convention:
#
#  $PREFIX/lib   = mips32
#  $PREFIX/lib32 = mips64n32
#  $PREFIX/lib64 = mips64
#
+ lib.optionalString (!enableMultilib && targetPlatform.isMips64n32) ''
  export linkLib32toLib=1
''