treewide: stdenv.is -> stdenv.hostPlatform.is (#356363)
[NixPkgs.git] / pkgs / development / libraries / boost / generic.nix
blob94ee8c236423fc067b88530e317b14d7cb716ee8
1 { lib, stdenv, icu, expat, zlib, bzip2, zstd, xz, python ? null, fixDarwinDylibNames, libiconv, libxcrypt
2 , makePkgconfigItem
3 , copyPkgconfigItems
4 , boost-build
5 , fetchpatch
6 , which
7 , toolset ? /**/ if stdenv.cc.isClang  then "clang"
8             else if stdenv.cc.isGNU    then "gcc"
9             else null
10 , enableRelease ? true
11 , enableDebug ? false
12 , enableSingleThreaded ? false
13 , enableMultiThreaded ? true
14 , enableShared ? !(with stdenv.hostPlatform; isStatic || isMinGW) # problems for now
15 , enableStatic ? !enableShared
16 , enablePython ? false
17 , enableNumpy ? false
18 , enableIcu ? stdenv.hostPlatform == stdenv.buildPlatform
19 , taggedLayout ? ((enableRelease && enableDebug) || (enableSingleThreaded && enableMultiThreaded) || (enableShared && enableStatic))
20 , patches ? []
21 , boostBuildPatches ? []
22 , useMpi ? false
23 , mpi
24 , extraB2Args ? []
26 # Attributes inherit from specific versions
27 , version, src
28 , ...
31 # We must build at least one type of libraries
32 assert enableShared || enableStatic;
34 assert enableNumpy -> enablePython;
36 let
38   variant = lib.concatStringsSep ","
39     (lib.optional enableRelease "release" ++
40      lib.optional enableDebug "debug");
42   threading = lib.concatStringsSep ","
43     (lib.optional enableSingleThreaded "single" ++
44      lib.optional enableMultiThreaded "multi");
46   link = lib.concatStringsSep ","
47     (lib.optional enableShared "shared" ++
48      lib.optional enableStatic "static");
50   runtime-link = if enableShared then "shared" else "static";
52   # To avoid library name collisions
53   layout = if taggedLayout then "tagged" else "system";
55   needUserConfig = stdenv.hostPlatform != stdenv.buildPlatform || useMpi || (stdenv.hostPlatform.isDarwin && enableShared);
57   b2Args = lib.concatStringsSep " " ([
58     "--includedir=$dev/include"
59     "--libdir=$out/lib"
60     "-j$NIX_BUILD_CORES"
61     "--layout=${layout}"
62     "variant=${variant}"
63     "threading=${threading}"
64     "link=${link}"
65     "-sEXPAT_INCLUDE=${expat.dev}/include"
66     "-sEXPAT_LIBPATH=${expat.out}/lib"
68     # TODO: make this unconditional
69   ] ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform ||
70                   # required on mips; see 61d9f201baeef4c4bb91ad8a8f5f89b747e0dfe4
71                   (stdenv.hostPlatform.isMips && lib.versionAtLeast version "1.79")) [
72     "address-model=${toString stdenv.hostPlatform.parsed.cpu.bits}"
73     "architecture=${if stdenv.hostPlatform.isMips64
74                     then if lib.versionOlder version "1.78" then "mips1" else "mips"
75                     else if stdenv.hostPlatform.isS390 then "s390x"
76                     else toString stdenv.hostPlatform.parsed.cpu.family}"
77     # env in host triplet for Mach-O is "macho", but boost binary format for Mach-O is "mach-o"
78     "binary-format=${if stdenv.hostPlatform.isMacho then "mach-o"
79                      else toString stdenv.hostPlatform.parsed.kernel.execFormat.name}"
80     "target-os=${toString stdenv.hostPlatform.parsed.kernel.name}"
82     # adapted from table in boost manual
83     # https://www.boost.org/doc/libs/1_66_0/libs/context/doc/html/context/architectures.html
84     "abi=${if stdenv.hostPlatform.parsed.cpu.family == "arm" then "aapcs"
85            else if stdenv.hostPlatform.isWindows then "ms"
86            else if stdenv.hostPlatform.isMips32 then "o32"
87            else if stdenv.hostPlatform.isMips64n64 then "n64"
88            else "sysv"}"
89   ] ++ lib.optional (link != "static") "runtime-link=${runtime-link}"
90     ++ lib.optional (variant == "release") "debug-symbols=off"
91     ++ lib.optional (toolset != null) "toolset=${toolset}"
92     ++ lib.optional (!enablePython) "--without-python"
93     ++ lib.optional needUserConfig "--user-config=user-config.jam"
94     ++ lib.optional (stdenv.buildPlatform.isDarwin && stdenv.hostPlatform.isLinux) "pch=off"
95     ++ lib.optionals stdenv.hostPlatform.isMinGW [
96     "threadapi=win32"
97   ] ++ extraB2Args
98   );
102 stdenv.mkDerivation {
103   pname = "boost";
105   inherit src version;
107   patchFlags = [];
109   patches = patches
110   ++ lib.optional stdenv.hostPlatform.isDarwin ./darwin-no-system-python.patch
111   ++ [ ./cmake-paths-173.patch ]
112   ++ lib.optional (version == "1.77.0") (fetchpatch {
113     url = "https://github.com/boostorg/math/commit/7d482f6ebc356e6ec455ccb5f51a23971bf6ce5b.patch";
114     relative = "include";
115     sha256 = "sha256-KlmIbixcds6GyKYt1fx5BxDIrU7msrgDdYo9Va/KJR4=";
116   })
117   # Fixes ABI detection
118   ++ lib.optional (version == "1.83.0") (fetchpatch {
119     url = "https://github.com/boostorg/context/commit/6fa6d5c50d120e69b2d8a1c0d2256ee933e94b3b.patch";
120     stripLen = 1;
121     extraPrefix = "libs/context/";
122     sha256 = "sha256-bCfLL7bD1Rn4Ie/P3X+nIcgTkbXdCX6FW7B9lHsmVW8=";
123   })
124   # This fixes another issue regarding ill-formed constant expressions, which is a default error
125   # in clang 16 and will be a hard error in clang 17.
126   ++ lib.optional (lib.versionOlder version "1.80") (fetchpatch {
127     url = "https://github.com/boostorg/log/commit/77f1e20bd69c2e7a9e25e6a9818ae6105f7d070c.patch";
128     relative = "include";
129     hash = "sha256-6qOiGJASm33XzwoxVZfKJd7sTlQ5yd+MMFQzegXm5RI=";
130   })
131   ++ lib.optionals (lib.versionOlder version "1.81") [
132     # libc++ 15 dropped support for `std::unary_function` and `std::binary_function` in C++17+.
133     # C++17 is the default for clang 16, but clang 15 is also affected in that language mode.
134     # This patch is for Boost 1.80, but it also applies to earlier versions.
135     (fetchpatch {
136       url = "https://www.boost.org/patches/1_80_0/0005-config-libcpp15.patch";
137       hash = "sha256-ULFMzKphv70unvPZ3o4vSP/01/xbSM9a2TlIV67eXDQ=";
138     })
139     # This fixes another ill-formed contant expressions issue flagged by clang 16.
140     (fetchpatch {
141       url = "https://github.com/boostorg/numeric_conversion/commit/50a1eae942effb0a9b90724323ef8f2a67e7984a.patch";
142       relative = "include";
143       hash = "sha256-dq4SVgxkPJSC7Fvr59VGnXkM4Lb09kYDaBksCHo9C0s=";
144     })
145     # This fixes an issue in Python 3.11 about Py_TPFLAGS_HAVE_GC
146     (fetchpatch {
147       name = "python311-compatibility.patch";
148       url = "https://github.com/boostorg/python/commit/a218babc8daee904a83f550fb66e5cb3f1cb3013.patch";
149       hash = "sha256-IHxLtJBx0xSy7QEr8FbCPofsjcPuSYzgtPwDlx1JM+4=";
150       stripLen = 1;
151       extraPrefix = "libs/python/";
152     })
153   ]
154   ++ lib.optional (lib.versionAtLeast version "1.81" && stdenv.cc.isClang) ./fix-clang-target.patch;
156   meta = with lib; {
157     homepage = "http://boost.org/";
158     description = "Collection of C++ libraries";
159     license = licenses.boost;
160     platforms = platforms.unix ++ platforms.windows;
161     # boost-context lacks support for the N32 ABI on mips64.  The build
162     # will succeed, but packages depending on boost-context will fail with
163     # a very cryptic error message.
164     badPlatforms = [ lib.systems.inspect.patterns.isMips64n32 ];
165     maintainers = with maintainers; [ hjones2199 ];
166   };
168   passthru = {
169     inherit boostBuildPatches;
170   };
172   preConfigure = lib.optionalString useMpi ''
173     cat << EOF >> user-config.jam
174     using mpi : ${lib.getDev mpi}/bin/mpiCC ;
175     EOF
176   ''
177   # On darwin we need to add the `$out/lib` to the libraries' rpath explicitly,
178   # otherwise the dynamic linker is unable to resolve the reference to @rpath
179   # when the boost libraries want to load each other at runtime.
180   + lib.optionalString (stdenv.hostPlatform.isDarwin && enableShared) ''
181     cat << EOF >> user-config.jam
182     using clang-darwin : : ${stdenv.cc.targetPrefix}c++
183       : <linkflags>"-rpath $out/lib/"
184         <archiver>$AR
185         <ranlib>$RANLIB
186       ;
187     EOF
188   ''
189   # b2 has trouble finding the correct compiler and tools for cross compilation
190   # since it apparently ignores $CC, $AR etc. Thus we need to set everything
191   # in user-config.jam. To keep things simple we just set everything in an
192   # uniform way for clang and gcc (which works thanks to our cc-wrapper).
193   # We pass toolset later which will make b2 invoke everything in the right
194   # way -- the other toolset in user-config.jam will be ignored.
195   + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
196     cat << EOF >> user-config.jam
197     using gcc : cross : ${stdenv.cc.targetPrefix}c++
198       : <archiver>$AR
199         <ranlib>$RANLIB
200       ;
202     using clang : cross : ${stdenv.cc.targetPrefix}c++
203       : <archiver>$AR
204         <ranlib>$RANLIB
205       ;
206     EOF
207   ''
208   # b2 needs to be explicitly told how to find Python when cross-compiling
209   + lib.optionalString enablePython ''
210     cat << EOF >> user-config.jam
211     using python : : ${python.interpreter}
212       : ${python}/include/python${python.pythonVersion}
213       : ${python}/lib
214       ;
215     EOF
216   '';
218   env = {
219     NIX_CFLAGS_LINK = lib.optionalString stdenv.hostPlatform.isDarwin "-headerpad_max_install_names";
220     # copyPkgconfigItems will substitute these in the pkg-config file
221     includedir = "${placeholder "dev"}/include";
222     libdir = "${placeholder "out"}/lib";
223   };
225   pkgconfigItems = [
226     (makePkgconfigItem {
227       name = "boost";
228       inherit version;
229       # Exclude other variables not needed by meson
230       variables = {
231         includedir = "@includedir@";
232         libdir = "@libdir@";
233       };
234     })
235   ];
237   enableParallelBuilding = true;
239   nativeBuildInputs = [ which boost-build copyPkgconfigItems ]
240     ++ lib.optional stdenv.hostPlatform.isDarwin fixDarwinDylibNames;
241   buildInputs = [ expat zlib bzip2 libiconv ]
242     ++ lib.optional (lib.versionAtLeast version "1.69") zstd
243     ++ [ xz ]
244     ++ lib.optional enableIcu icu
245     ++ lib.optionals enablePython [ libxcrypt python ]
246     ++ lib.optional enableNumpy python.pkgs.numpy;
248   configureScript = "./bootstrap.sh";
249   configurePlatforms = [];
250   dontDisableStatic = true;
251   dontAddStaticConfigureFlags = true;
252   configureFlags = [
253     "--includedir=$(dev)/include"
254     "--libdir=$(out)/lib"
255     "--with-bjam=b2" # prevent bootstrapping b2 in configurePhase
256   ] ++ lib.optional (toolset != null) "--with-toolset=${toolset}"
257     ++ [ (if enableIcu then "--with-icu=${icu.dev}" else "--without-icu") ];
259   buildPhase = ''
260     runHook preBuild
261     b2 ${b2Args}
262     runHook postBuild
263   '';
265   installPhase = ''
266     runHook preInstall
268     # boostbook is needed by some applications
269     mkdir -p $dev/share/boostbook
270     cp -a tools/boostbook/{xsl,dtd} $dev/share/boostbook/
272     # Let boost install everything else
273     b2 ${b2Args} install
275     runHook postInstall
276   '';
278   postFixup = ''
279     # Make boost header paths relative so that they are not runtime dependencies
280     cd "$dev" && find include \( -name '*.hpp' -or -name '*.h' -or -name '*.ipp' \) \
281       -exec sed '1s/^\xef\xbb\xbf//;1i#line 1 "{}"' -i '{}' \;
282   '' + lib.optionalString stdenv.hostPlatform.isMinGW ''
283     $RANLIB "$out/lib/"*.a
284   '';
286   outputs = [ "out" "dev" ];
287   setOutputFlags = false;