···11+{ lib
22+, stdenv
33+, cmake
44+, coreutils
55+, gnugrep
66+, perl
77+, ninja
88+, pkg-config
99+, clang
1010+, bintools
1111+, python3
1212+, git
1313+, fetchFromGitHub
1414+, fetchpatch
1515+, makeWrapper
1616+, gnumake
1717+, file
1818+, runCommand
1919+, writeShellScriptBin
2020+# For lldb
2121+, libedit
2222+, ncurses
2323+, swig
2424+, libxml2
2525+# Linux-specific
2626+, glibc
2727+, libuuid
2828+# Darwin-specific
2929+, substituteAll
3030+, fixDarwinDylibNames
3131+, runCommandLocal
3232+, xcbuild
3333+, cctools # libtool
3434+, sigtool
3535+, DarwinTools
3636+, CoreServices
3737+, Foundation
3838+, Combine
3939+, CLTools_Executables
4040+}:
4141+4242+let
4343+4444+ inherit (stdenv) hostPlatform targetPlatform;
4545+4646+ # The Swift toolchain script builds projects with separate repos. By convention, some of them share
4747+ # the same version with the main Swift compiler project per release.
4848+ version = "5.7";
4949+5050+ fetchSwiftRelease = { repo, hash }:
5151+ fetchFromGitHub {
5252+ owner = "apple";
5353+ inherit repo hash;
5454+ rev = "swift-${version}-RELEASE";
5555+ name = "${repo}-${version}-src";
5656+ };
5757+5858+ # Names in this set match the directory the source is unpacked to.
5959+ sources = {
6060+ cmark = fetchSwiftRelease {
6161+ repo = "swift-cmark";
6262+ hash = "sha256-f0BoTs4HYdx/aJ9HIGCWMalhl8PvClWD6R4QK3qSgAw=";
6363+ };
6464+ llvm-project = fetchSwiftRelease {
6565+ repo = "llvm-project";
6666+ hash = "sha256-uW6dEAFaDOlHXnq8lFYxrKNLRPEukauZJxX4UCpWpIY=";
6767+ };
6868+ swift = fetchSwiftRelease {
6969+ repo = "swift";
7070+ hash = "sha256-n8WVQYinAyIj4wmQnDhvPsH+t8ydANkGbjFJ6blfHOY=";
7171+ };
7272+ swift-experimental-string-processing = fetchSwiftRelease {
7373+ repo = "swift-experimental-string-processing";
7474+ hash = "sha256-Ar9fQWi8bYSvGErrS0SWrxIxwEwCjsYIZcWweZ8bV28=";
7575+ };
7676+ }
7777+ // lib.optionalAttrs (!stdenv.isDarwin) {
7878+ swift-corelibs-libdispatch = fetchSwiftRelease {
7979+ repo = "swift-corelibs-libdispatch";
8080+ hash = "sha256-1qbXiC1k9+T+L6liqXKg6EZXqem6KEEx8OctuL4Kb2o=";
8181+ };
8282+ };
8383+8484+ # Tools invoked by swift at run-time.
8585+ runtimeDeps = lib.optionals stdenv.isDarwin [
8686+ # libtool is used for static linking. This is part of cctools, but adding
8787+ # that as a build input puts an unwrapped linker in PATH, and breaks
8888+ # builds. This small derivation exposes just libtool.
8989+ # NOTE: The same applies to swift-driver, but that is currently always
9090+ # invoked via the old `swift` / `swiftc`. May change in the future.
9191+ (runCommandLocal "libtool" { } ''
9292+ mkdir -p $out/bin
9393+ ln -s ${cctools}/bin/libtool $out/bin/libtool
9494+ '')
9595+ ];
9696+9797+ # There are apparently multiple naming conventions on Darwin. Swift uses the
9898+ # xcrun naming convention. See `configure_sdk_darwin` calls in CMake files.
9999+ swiftOs = if targetPlatform.isDarwin
100100+ then {
101101+ "macos" = "macosx";
102102+ "ios" = "iphoneos";
103103+ #iphonesimulator
104104+ #appletvos
105105+ #appletvsimulator
106106+ #watchos
107107+ #watchsimulator
108108+ }.${targetPlatform.darwinPlatform}
109109+ or (throw "Cannot build Swift for target Darwin platform '${targetPlatform.darwinPlatform}'")
110110+ else targetPlatform.parsed.kernel.name;
111111+112112+ # Apple Silicon uses a different CPU name in the target triple.
113113+ swiftArch = if stdenv.isDarwin && stdenv.isAarch64 then "arm64"
114114+ else targetPlatform.parsed.cpu.name;
115115+116116+ # On Darwin, a `.swiftmodule` is a subdirectory in `lib/swift/<OS>`,
117117+ # containing binaries for supported archs. On other platforms, binaries are
118118+ # installed to `lib/swift/<OS>/<ARCH>`. Note that our setup-hook also adds
119119+ # `lib/swift` for convenience.
120120+ swiftLibSubdir = "lib/swift/${swiftOs}";
121121+ swiftModuleSubdir = if hostPlatform.isDarwin
122122+ then "lib/swift/${swiftOs}"
123123+ else "lib/swift/${swiftOs}/${swiftArch}";
124124+125125+ # And then there's also a separate subtree for statically linked modules.
126126+ toStaticSubdir = lib.replaceStrings [ "/swift/" ] [ "/swift_static/" ];
127127+ swiftStaticLibSubdir = toStaticSubdir swiftLibSubdir;
128128+ swiftStaticModuleSubdir = toStaticSubdir swiftModuleSubdir;
129129+130130+ # This matches _SWIFT_DEFAULT_COMPONENTS, with specific components disabled.
131131+ swiftInstallComponents = [
132132+ "autolink-driver"
133133+ "compiler"
134134+ # "clang-builtin-headers"
135135+ "stdlib"
136136+ "sdk-overlay"
137137+ "parser-lib"
138138+ "static-mirror-lib"
139139+ "editor-integration"
140140+ # "tools"
141141+ # "testsuite-tools"
142142+ "toolchain-tools"
143143+ "toolchain-dev-tools"
144144+ "license"
145145+ (if stdenv.isDarwin then "sourcekit-xpc-service" else "sourcekit-inproc")
146146+ "swift-remote-mirror"
147147+ "swift-remote-mirror-headers"
148148+ ];
149149+150150+ # Build a tool used during the build to create a custom clang wrapper, with
151151+ # which we wrap the clang produced by the swift build.
152152+ #
153153+ # This is used in a `POST_BUILD` for the CMake target, so we rename the
154154+ # actual clang to clang-unwrapped, then put the wrapper in place.
155155+ #
156156+ # We replace the `exec ...` command with `exec -a "$0"` in order to
157157+ # preserve $0 for clang. This is because, unlike Nix, we don't have
158158+ # separate wrappers for clang/clang++, and clang uses $0 to detect C++.
159159+ #
160160+ # Similarly, the C++ detection in the wrapper itself also won't work for us,
161161+ # so we base it on $0 as well.
162162+ makeClangWrapper = writeShellScriptBin "nix-swift-make-clang-wrapper" ''
163163+ set -euo pipefail
164164+165165+ targetFile="$1"
166166+ unwrappedClang="$targetFile-unwrapped"
167167+168168+ mv "$targetFile" "$unwrappedClang"
169169+ sed < '${clang}/bin/clang' > "$targetFile" \
170170+ -e 's|^\s*exec|exec -a "$0"|g' \
171171+ -e 's|^\[\[ "${clang.cc}/bin/clang" = \*++ ]]|[[ "$0" = *++ ]]|' \
172172+ -e "s|${clang.cc}/bin/clang|$unwrappedClang|g"
173173+ chmod a+x "$targetFile"
174174+ '';
175175+176176+ # Create a tool used during the build to create a custom swift wrapper for
177177+ # each of the swift executables produced by the build.
178178+ #
179179+ # The build produces several `swift-frontend` executables during
180180+ # bootstrapping. Each of these has numerous aliases via symlinks, and the
181181+ # executable uses $0 to detect what tool is called.
182182+ wrapperParams = {
183183+ inherit bintools;
184184+ default_cc_wrapper = clang; # Instead of `@out@` in the original.
185185+ coreutils_bin = lib.getBin coreutils;
186186+ gnugrep_bin = gnugrep;
187187+ suffixSalt = lib.replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
188188+ use_response_file_by_default = 1;
189189+ # NOTE: @prog@ needs to be filled elsewhere.
190190+ };
191191+ swiftWrapper = runCommand "swift-wrapper.sh" wrapperParams ''
192192+ substituteAll '${../wrapper/wrapper.sh}' "$out"
193193+ '';
194194+ makeSwiftcWrapper = writeShellScriptBin "nix-swift-make-swift-wrapper" ''
195195+ set -euo pipefail
196196+197197+ targetFile="$1"
198198+ unwrappedSwift="$targetFile-unwrapped"
199199+200200+ mv "$targetFile" "$unwrappedSwift"
201201+ sed < '${swiftWrapper}' > "$targetFile" \
202202+ -e "s|@prog@|'$unwrappedSwift'|g" \
203203+ -e 's|exec "$prog"|exec -a "$0" "$prog"|g'
204204+ chmod a+x "$targetFile"
205205+ '';
206206+207207+in stdenv.mkDerivation {
208208+ pname = "swift";
209209+ inherit version;
210210+211211+ outputs = [ "out" "lib" "dev" "doc" "man" ];
212212+213213+ nativeBuildInputs = [
214214+ cmake
215215+ git
216216+ ninja
217217+ perl # pod2man
218218+ pkg-config
219219+ python3
220220+ makeWrapper
221221+ makeClangWrapper
222222+ makeSwiftcWrapper
223223+ ]
224224+ ++ lib.optionals stdenv.isDarwin [
225225+ xcbuild
226226+ sigtool # codesign
227227+ DarwinTools # sw_vers
228228+ fixDarwinDylibNames
229229+ ];
230230+231231+ buildInputs = [
232232+ # For lldb
233233+ python3
234234+ swig
235235+ libxml2
236236+ ]
237237+ ++ lib.optionals stdenv.isLinux [
238238+ libuuid
239239+ ]
240240+ ++ lib.optionals stdenv.isDarwin [
241241+ CoreServices
242242+ Foundation
243243+ Combine
244244+ ];
245245+246246+ # This is a partial reimplementation of our setup hook. Because we reuse
247247+ # the Swift wrapper for the Swift build itself, we need to do some of the
248248+ # same preparation.
249249+ postHook = ''
250250+ for pkg in "''${pkgsHostTarget[@]}" '${clang.libc}'; do
251251+ for subdir in ${swiftModuleSubdir} ${swiftStaticModuleSubdir} lib/swift; do
252252+ if [[ -d "$pkg/$subdir" ]]; then
253253+ export NIX_SWIFTFLAGS_COMPILE+=" -I $pkg/$subdir"
254254+ fi
255255+ done
256256+ for subdir in ${swiftLibSubdir} ${swiftStaticLibSubdir} lib/swift; do
257257+ if [[ -d "$pkg/$subdir" ]]; then
258258+ export NIX_LDFLAGS+=" -L $pkg/$subdir"
259259+ fi
260260+ done
261261+ done
262262+ '';
263263+264264+ # We invoke cmakeConfigurePhase multiple times, but only need this once.
265265+ dontFixCmake = true;
266266+ # We setup custom build directories.
267267+ dontUseCmakeBuildDir = true;
268268+269269+ unpackPhase = ''
270270+ mkdir src
271271+ cd src
272272+273273+ ${lib.concatStrings (lib.mapAttrsToList (dir: src: ''
274274+ cp -r ${src} ${dir}
275275+ '') sources)}
276276+277277+ chmod -R u+w .
278278+ '';
279279+280280+ patchPhase = ''
281281+ # Just patch all the things for now, we can focus this later.
282282+ # TODO: eliminate use of env.
283283+ find -type f -print0 | xargs -0 sed -i \
284284+ ${lib.optionalString stdenv.isDarwin
285285+ "-e 's|/usr/libexec/PlistBuddy|${xcbuild}/bin/PlistBuddy|g'"} \
286286+ -e 's|/usr/bin/env|${coreutils}/bin/env|g' \
287287+ -e 's|/usr/bin/make|${gnumake}/bin/make|g' \
288288+ -e 's|/bin/mkdir|${coreutils}/bin/mkdir|g' \
289289+ -e 's|/bin/cp|${coreutils}/bin/cp|g' \
290290+ -e 's|/usr/bin/file|${file}/bin/file|g'
291291+292292+ patch -p1 -d swift -i ${./patches/swift-wrap.patch}
293293+ patch -p1 -d swift -i ${./patches/swift-nix-resource-root.patch}
294294+ patch -p1 -d swift -i ${./patches/swift-linux-fix-linking.patch}
295295+ patch -p1 -d swift -i ${./patches/swift-darwin-fix-bootstrap.patch}
296296+ patch -p1 -d swift -i ${substituteAll {
297297+ src = ./patches/swift-darwin-plistbuddy-workaround.patch;
298298+ inherit swiftArch;
299299+ }}
300300+ patch -p1 -d swift -i ${substituteAll {
301301+ src = ./patches/swift-prevent-sdk-dirs-warning.patch;
302302+ inherit (builtins) storeDir;
303303+ }}
304304+ substituteInPlace swift/cmake/modules/SwiftConfigureSDK.cmake \
305305+ --replace '/usr/include' "${stdenv.cc.libc_dev}/include"
306306+307307+ # This patch needs to know the lib output location, so must be substituted
308308+ # in the same derivation as the compiler.
309309+ storeDir="${builtins.storeDir}" \
310310+ substituteAll ${./patches/swift-separate-lib.patch} $TMPDIR/swift-separate-lib.patch
311311+ patch -p1 -d swift -i $TMPDIR/swift-separate-lib.patch
312312+313313+ patch -p1 -d llvm-project/llvm -i ${./patches/llvm-module-cache.patch}
314314+315315+ patch -p1 -d llvm-project/clang -i ${./patches/clang-toolchain-dir.patch}
316316+ patch -p1 -d llvm-project/clang -i ${./patches/clang-wrap.patch}
317317+ patch -p1 -d llvm-project/clang -i ${../../llvm/14/clang/purity.patch}
318318+ patch -p2 -d llvm-project/clang -i ${fetchpatch {
319319+ name = "clang-cmake-fix-interpreter.patch";
320320+ url = "https://github.com/llvm/llvm-project/commit/b5eaf500f2441eff2277ea2973878fb1f171fd0a.patch";
321321+ sha256 = "1rma1al0rbm3s3ql6bnvbcighp74lri1lcrwbyacgdqp80fgw1b6";
322322+ }}
323323+324324+ ${lib.optionalString stdenv.isLinux ''
325325+ substituteInPlace llvm-project/clang/lib/Driver/ToolChains/Linux.cpp \
326326+ --replace 'SysRoot + "/lib' '"${glibc}/lib" "' \
327327+ --replace 'SysRoot + "/usr/lib' '"${glibc}/lib" "' \
328328+ --replace 'LibDir = "lib";' 'LibDir = "${glibc}/lib";' \
329329+ --replace 'LibDir = "lib64";' 'LibDir = "${glibc}/lib";' \
330330+ --replace 'LibDir = X32 ? "libx32" : "lib64";' 'LibDir = "${glibc}/lib";'
331331+332332+ # uuid.h is not part of glibc, but of libuuid.
333333+ sed -i 's|''${GLIBC_INCLUDE_PATH}/uuid/uuid.h|${libuuid.dev}/include/uuid/uuid.h|' \
334334+ swift/stdlib/public/Platform/glibc.modulemap.gyb
335335+ ''}
336336+337337+ # Remove tests for cross compilation, which we don't currently support.
338338+ rm swift/test/Interop/Cxx/class/constructors-copy-irgen.swift
339339+ rm swift/test/Interop/Cxx/class/constructors-irgen.swift
340340+341341+ # TODO: consider fixing and re-adding. This test fails due to a non-standard "install_prefix".
342342+ rm swift/validation-test/Python/build_swift.swift
343343+344344+ # We cannot handle the SDK location being in "Weird Location" due to Nix isolation.
345345+ rm swift/test/DebugInfo/compiler-flags.swift
346346+347347+ # TODO: Fix issue with ld.gold invoked from script finding crtbeginS.o and crtendS.o.
348348+ rm swift/test/IRGen/ELF-remove-autolink-section.swift
349349+350350+ # The following two tests fail because we use don't use the bundled libicu:
351351+ # [SOURCE_DIR/utils/build-script] ERROR: can't find source directory for libicu (tried /build/src/icu)
352352+ rm swift/validation-test/BuildSystem/default_build_still_performs_epilogue_opts_after_split.test
353353+ rm swift/validation-test/BuildSystem/test_early_swift_driver_and_infer.swift
354354+355355+ # TODO: This test fails for some unknown reason
356356+ rm swift/test/Serialization/restrict-swiftmodule-to-revision.swift
357357+358358+ # This test was flaky in ofborg, see #186476
359359+ rm swift/test/AutoDiff/compiler_crashers_fixed/sr14290-missing-debug-scopes-in-pullback-trampoline.swift
360360+361361+ patchShebangs .
362362+363363+ ${lib.optionalString (!stdenv.isDarwin) ''
364364+ # NOTE: This interferes with ABI stability on Darwin, which uses the system
365365+ # libraries in the hardcoded path /usr/lib/swift.
366366+ fixCmakeFiles .
367367+ ''}
368368+ '';
369369+370370+ configurePhase = ''
371371+ export SWIFT_SOURCE_ROOT="$PWD"
372372+ mkdir -p ../build
373373+ cd ../build
374374+ export SWIFT_BUILD_ROOT="$PWD"
375375+376376+ # Most builds set a target, but LLDB doesn't. Harmless on non-Darwin.
377377+ export MACOSX_DEPLOYMENT_TARGET=10.15
378378+ '';
379379+380380+ # These steps are derived from doing a normal build with.
381381+ #
382382+ # ./swift/utils/build-toolchain test --dry-run
383383+ #
384384+ # But dealing with the custom Python build system is far more trouble than
385385+ # simply invoking CMake directly. Few variables it passes to CMake are
386386+ # actually required or non-default.
387387+ #
388388+ # Using CMake directly also allows us to split up the already large build,
389389+ # and package Swift components separately.
390390+ #
391391+ # Besides `--dry-run`, another good way to compare build changes between
392392+ # Swift releases is to diff the scripts:
393393+ #
394394+ # git diff swift-5.6.3-RELEASE..swift-5.7-RELEASE -- utils/build*
395395+ #
396396+ buildPhase = ''
397397+ # Helper to build a subdirectory.
398398+ #
399399+ # Always reset cmakeFlags before calling this. The cmakeConfigurePhase
400400+ # amends flags and would otherwise keep expanding it.
401401+ function buildProject() {
402402+ mkdir -p $SWIFT_BUILD_ROOT/$1
403403+ cd $SWIFT_BUILD_ROOT/$1
404404+405405+ cmakeDir=$SWIFT_SOURCE_ROOT/''${2-$1}
406406+ cmakeConfigurePhase
407407+408408+ ninjaBuildPhase
409409+ }
410410+411411+ cmakeFlags="-GNinja"
412412+ buildProject cmark
413413+414414+ # Some notes:
415415+ # - The Swift build just needs Clang.
416416+ # - We can further reduce targets to just our targetPlatform.
417417+ cmakeFlags="
418418+ -GNinja
419419+ -DLLVM_ENABLE_PROJECTS=clang
420420+ -DLLVM_TARGETS_TO_BUILD=${{
421421+ "x86_64" = "X86";
422422+ "aarch64" = "AArch64";
423423+ }.${targetPlatform.parsed.cpu.name}}
424424+ "
425425+ buildProject llvm llvm-project/llvm
426426+427427+ # Some notes:
428428+ # - Building with libswift defaults to OFF in CMake, but is enabled in
429429+ # standard builds, so we enable it as well.
430430+ # - Experimental features are OFF by default in CMake, but some are
431431+ # required to build the stdlib.
432432+ # - SWIFT_STDLIB_ENABLE_OBJC_INTEROP is set explicitely because its check
433433+ # is buggy. (Uses SWIFT_HOST_VARIANT_SDK before initialized.)
434434+ # Fixed in: https://github.com/apple/swift/commit/84083afef1de5931904d5c815d53856cdb3fb232
435435+ cmakeFlags="
436436+ -GNinja
437437+ -DBOOTSTRAPPING_MODE=BOOTSTRAPPING
438438+ -DSWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY=ON
439439+ -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm
440440+ -DClang_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/clang
441441+ -DSWIFT_PATH_TO_CMARK_SOURCE=$SWIFT_SOURCE_ROOT/cmark
442442+ -DSWIFT_PATH_TO_CMARK_BUILD=$SWIFT_BUILD_ROOT/cmark
443443+ -DSWIFT_PATH_TO_LIBDISPATCH_SOURCE=$SWIFT_SOURCE_ROOT/swift-corelibs-libdispatch
444444+ -DEXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR=$SWIFT_SOURCE_ROOT/swift-experimental-string-processing
445445+ -DSWIFT_INSTALL_COMPONENTS=${lib.concatStringsSep ";" swiftInstallComponents}
446446+ -DSWIFT_STDLIB_ENABLE_OBJC_INTEROP=${if stdenv.isDarwin then "ON" else "OFF"}
447447+ "
448448+ buildProject swift
449449+450450+ # These are based on flags in `utils/build-script-impl`.
451451+ #
452452+ # LLDB_USE_SYSTEM_DEBUGSERVER=ON disables the debugserver build on Darwin,
453453+ # which requires a special signature.
454454+ #
455455+ # CMAKE_BUILD_WITH_INSTALL_NAME_DIR ensures we don't use rpath on Darwin.
456456+ #
457457+ # NOTE: On Darwin, we only want ncurses in the linker search path, because
458458+ # headers are part of libsystem. Adding its headers to the search path
459459+ # causes strange mixing and errors. Note that libedit propagates ncurses,
460460+ # so we add both manually here, instead of relying on setup hooks.
461461+ # TODO: Find a better way to prevent this conflict.
462462+ cmakeFlags="
463463+ -GNinja
464464+ -DLLDB_SWIFTC=$SWIFT_BUILD_ROOT/swift/bin/swiftc
465465+ -DLLDB_SWIFT_LIBS=$SWIFT_BUILD_ROOT/swift/lib/swift
466466+ -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm
467467+ -DClang_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/clang
468468+ -DSwift_DIR=$SWIFT_BUILD_ROOT/swift/lib/cmake/swift
469469+ -DLLDB_ENABLE_CURSES=ON
470470+ -DLLDB_ENABLE_LIBEDIT=ON
471471+ -DLLDB_ENABLE_PYTHON=ON
472472+ -DLLDB_ENABLE_LZMA=OFF
473473+ -DLLDB_ENABLE_LUA=OFF
474474+ -DLLDB_INCLUDE_TESTS=OFF
475475+ -DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON
476476+ ${lib.optionalString stdenv.isDarwin ''
477477+ -DLLDB_USE_SYSTEM_DEBUGSERVER=ON
478478+ ''}
479479+ -DLibEdit_INCLUDE_DIRS=${libedit.dev}/include
480480+ -DLibEdit_LIBRARIES=${libedit}/lib/libedit${stdenv.hostPlatform.extensions.sharedLibrary}
481481+ -DCURSES_INCLUDE_DIRS=${if stdenv.isDarwin then "/var/empty" else ncurses.dev}/include
482482+ -DCURSES_LIBRARIES=${ncurses}/lib/libncurses${stdenv.hostPlatform.extensions.sharedLibrary}
483483+ -DPANEL_LIBRARIES=${ncurses}/lib/libpanel${stdenv.hostPlatform.extensions.sharedLibrary}
484484+ ";
485485+ buildProject lldb llvm-project/lldb
486486+487487+ ${lib.optionalString stdenv.isDarwin ''
488488+ # Need to do a standalone build of concurrency for Darwin back deployment.
489489+ # Based on: utils/swift_build_support/swift_build_support/products/backdeployconcurrency.py
490490+ cmakeFlags="
491491+ -GNinja
492492+ -DCMAKE_Swift_COMPILER=$SWIFT_BUILD_ROOT/swift/bin/swiftc
493493+494494+ -DTOOLCHAIN_DIR=/var/empty
495495+ -DSWIFT_NATIVE_LLVM_TOOLS_PATH=${stdenv.cc}/bin
496496+ -DSWIFT_NATIVE_CLANG_TOOLS_PATH=${stdenv.cc}/bin
497497+ -DSWIFT_NATIVE_SWIFT_TOOLS_PATH=$SWIFT_BUILD_ROOT/swift/bin
498498+499499+ -DCMAKE_CROSSCOMPILING=ON
500500+501501+ -DBUILD_SWIFT_CONCURRENCY_BACK_DEPLOYMENT_LIBRARIES=ON
502502+ -DSWIFT_INCLUDE_TOOLS=OFF
503503+ -DSWIFT_BUILD_STDLIB_EXTRA_TOOLCHAIN_CONTENT=OFF
504504+ -DSWIFT_BUILD_TEST_SUPPORT_MODULES=OFF
505505+ -DSWIFT_BUILD_STDLIB=OFF
506506+ -DSWIFT_BUILD_DYNAMIC_STDLIB=OFF
507507+ -DSWIFT_BUILD_STATIC_STDLIB=OFF
508508+ -DSWIFT_BUILD_REMOTE_MIRROR=OFF
509509+ -DSWIFT_BUILD_SDK_OVERLAY=OFF
510510+ -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=OFF
511511+ -DSWIFT_BUILD_STATIC_SDK_OVERLAY=OFF
512512+ -DSWIFT_INCLUDE_TESTS=OFF
513513+ -DSWIFT_BUILD_PERF_TESTSUITE=OFF
514514+515515+ -DSWIFT_HOST_VARIANT_ARCH=${swiftArch}
516516+ -DBUILD_STANDALONE=ON
517517+518518+ -DSWIFT_INSTALL_COMPONENTS=back-deployment
519519+520520+ -DSWIFT_SDKS=${{
521521+ "macos" = "OSX";
522522+ "ios" = "IOS";
523523+ #IOS_SIMULATOR
524524+ #TVOS
525525+ #TVOS_SIMULATOR
526526+ #WATCHOS
527527+ #WATCHOS_SIMULATOR
528528+ }.${targetPlatform.darwinPlatform}}
529529+530530+ -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm
531531+532532+ -DSWIFT_DEST_ROOT=$out
533533+ -DSWIFT_HOST_VARIANT_SDK=OSX
534534+535535+ -DSWIFT_DARWIN_DEPLOYMENT_VERSION_OSX=10.15
536536+ -DSWIFT_DARWIN_DEPLOYMENT_VERSION_IOS=13.0
537537+ -DSWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST=13.0
538538+ -DSWIFT_DARWIN_DEPLOYMENT_VERSION_TVOS=13.0
539539+ -DSWIFT_DARWIN_DEPLOYMENT_VERSION_WATCHOS=6.0
540540+ "
541541+542542+ # This depends on the special Clang build specific to the Swift branch.
543543+ # We also need to call a specific Ninja target.
544544+ export CC=$SWIFT_BUILD_ROOT/llvm/bin/clang
545545+ export CXX=$SWIFT_BUILD_ROOT/llvm/bin/clang++
546546+ ninjaFlags="back-deployment"
547547+548548+ buildProject swift-concurrency-backdeploy swift
549549+550550+ export CC=$NIX_CC/bin/clang
551551+ export CXX=$NIX_CC/bin/clang++
552552+ unset ninjaFlags
553553+ ''}
554554+ '';
555555+556556+ # TODO: ~50 failing tests on x86_64-linux. Other platforms not checked.
557557+ doCheck = false;
558558+ checkInputs = [ file ];
559559+ # TODO: consider using stress-tester and integration-test.
560560+ checkPhase = ''
561561+ cd $SWIFT_BUILD_ROOT/swift
562562+ checkTarget=check-swift-all
563563+ ninjaCheckPhase
564564+ unset checkTarget
565565+ '';
566566+567567+ installPhase = ''
568568+ # Undo the clang and swift wrapping we did for the build.
569569+ # (This happened via patches to cmake files.)
570570+ cd $SWIFT_BUILD_ROOT
571571+ mv llvm/bin/clang-14{-unwrapped,}
572572+ mv swift/bin/swift-frontend{-unwrapped,}
573573+574574+ mkdir $out $lib
575575+576576+ # Install clang binaries only. We hide these with the wrapper, so they are
577577+ # for private use by Swift only.
578578+ cd $SWIFT_BUILD_ROOT/llvm
579579+ installTargets=install-clang
580580+ ninjaInstallPhase
581581+ unset installTargets
582582+583583+ # LLDB is also a private install.
584584+ cd $SWIFT_BUILD_ROOT/lldb
585585+ ninjaInstallPhase
586586+587587+ cd $SWIFT_BUILD_ROOT/swift
588588+ ninjaInstallPhase
589589+590590+ ${lib.optionalString stdenv.isDarwin ''
591591+ cd $SWIFT_BUILD_ROOT/swift-concurrency-backdeploy
592592+ installTargets=install-back-deployment
593593+ ninjaInstallPhase
594594+ unset installTargets
595595+ ''}
596596+597597+ # Separate $lib output here, because specific logic follows.
598598+ # Only move the dynamic run-time parts, to keep $lib small. Every Swift
599599+ # build will depend on it.
600600+ moveToOutput "lib/swift" "$lib"
601601+ moveToOutput "lib/libswiftDemangle.*" "$lib"
602602+603603+ # This link is here because various tools (swiftpm) check for stdlib
604604+ # relative to the swift compiler. It's fine if this is for build-time
605605+ # stuff, but we should patch all cases were it would end up in an output.
606606+ ln -s $lib/lib/swift $out/lib/swift
607607+608608+ # Swift has a separate resource root from Clang, but locates the Clang
609609+ # resource root via subdir or symlink. Provide a default here, but we also
610610+ # patch Swift to prefer NIX_CC if set.
611611+ ln -s ${clang}/resource-root $lib/lib/swift/clang
612612+613613+ ${lib.optionalString stdenv.isDarwin ''
614614+ # Install required library for ObjC interop.
615615+ # TODO: Is there no source code for this available?
616616+ cp -r ${CLTools_Executables}/usr/lib/arc $out/lib/arc
617617+ ''}
618618+ '';
619619+620620+ preFixup = lib.optionalString stdenv.isLinux ''
621621+ # This is cheesy, but helps the patchelf hook remove /build from RPATH.
622622+ cd $NIX_BUILD_TOP
623623+ mv build buildx
624624+ '';
625625+626626+ postFixup = lib.optionalString stdenv.isDarwin ''
627627+ # These libraries need to use the system install name. The official SDK
628628+ # does the same (as opposed to using rpath). Presumably, they are part of
629629+ # the stable ABI. Not using the system libraries at run-time is known to
630630+ # cause ObjC class conflicts and segfaults.
631631+ declare -A systemLibs=(
632632+ [libswiftCore.dylib]=1
633633+ [libswiftDarwin.dylib]=1
634634+ [libswiftSwiftOnoneSupport.dylib]=1
635635+ [libswift_Concurrency.dylib]=1
636636+ )
637637+638638+ for systemLib in "''${!systemLibs[@]}"; do
639639+ install_name_tool -id /usr/lib/swift/$systemLib $lib/${swiftLibSubdir}/$systemLib
640640+ done
641641+642642+ for file in $out/bin/swift-frontend $lib/${swiftLibSubdir}/*.dylib; do
643643+ changeArgs=""
644644+ for dylib in $(otool -L $file | awk '{ print $1 }'); do
645645+ if [[ ''${systemLibs["$(basename $dylib)"]} ]]; then
646646+ changeArgs+=" -change $dylib /usr/lib/swift/$(basename $dylib)"
647647+ elif [[ "$dylib" = */bootstrapping1/* ]]; then
648648+ changeArgs+=" -change $dylib $lib/lib/swift/$(basename $dylib)"
649649+ fi
650650+ done
651651+ if [[ -n "$changeArgs" ]]; then
652652+ install_name_tool $changeArgs $file
653653+ fi
654654+ done
655655+656656+ wrapProgram $out/bin/swift-frontend \
657657+ --prefix PATH : ${lib.makeBinPath runtimeDeps}
658658+ '';
659659+660660+ passthru = {
661661+ inherit
662662+ swiftOs swiftArch
663663+ swiftModuleSubdir swiftLibSubdir
664664+ swiftStaticModuleSubdir swiftStaticLibSubdir;
665665+666666+ # Internal attr for the wrapper.
667667+ _wrapperParams = wrapperParams;
668668+ };
669669+670670+ meta = {
671671+ description = "The Swift Programming Language";
672672+ homepage = "https://github.com/apple/swift";
673673+ maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ];
674674+ license = lib.licenses.asl20;
675675+ platforms = with lib.platforms; linux ++ darwin;
676676+ # Swift doesn't support 32-bit Linux, unknown on other platforms.
677677+ badPlatforms = lib.platforms.i686;
678678+ timeout = 86400; # 24 hours.
679679+ };
680680+}
···11+This patch fixes dylib references during bootstrapping. It's possible
22+`LIBSWIFT_BUILD_MODE=BOOTSTRAPPING` is not really well tested on Darwin,
33+because official builds don't use it.
44+55+In the near future, Swift will require an existing Swift toolchain to
66+bootstrap, and we will likely have to replace this any way.
77+88+--- a/stdlib/cmake/modules/AddSwiftStdlib.cmake
99++++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake
1010+@@ -1035,6 +1035,10 @@ function(add_swift_target_library_single target name)
1111+ set(install_name_dir "${SWIFTLIB_SINGLE_DARWIN_INSTALL_NAME_DIR}")
1212+ endif()
1313+1414++ if(DEFINED SWIFTLIB_SINGLE_BOOTSTRAPPING)
1515++ set(install_name_dir "${lib_dir}/${output_sub_dir}")
1616++ endif()
1717++
1818+ set_target_properties("${target}"
1919+ PROPERTIES
2020+ INSTALL_NAME_DIR "${install_name_dir}")
···11+CMake tries to read a list field from SDKSettings.plist, but the output of
22+facebook/xcbuild PlistBuddy is incompatible with Apple's.
33+44+Simply set the supported architectures to the one target architecture we're
55+building for.
66+77+--- a/cmake/modules/SwiftConfigureSDK.cmake
88++++ b/cmake/modules/SwiftConfigureSDK.cmake
99+@@ -189,7 +189,7 @@ macro(configure_sdk_darwin
1010+ endif()
1111+1212+ # Remove any architectures not supported by the SDK.
1313+- remove_sdk_unsupported_archs(${name} ${xcrun_name} ${SWIFT_SDK_${prefix}_PATH} SWIFT_SDK_${prefix}_ARCHITECTURES)
1414++ set(SWIFT_SDK_${prefix}_ARCHITECTURES "@swiftArch@")
1515+1616+ list_intersect(
1717+ "${SWIFT_DARWIN_MODULE_ARCHS}" # lhs
···11+--- a/lib/Driver/ToolChains.cpp
22++++ b/lib/Driver/ToolChains.cpp
33+@@ -1475,7 +1475,17 @@ const char *ToolChain::getClangLinkerDriver(
44+55+ // If there is a linker driver in the toolchain folder, use that instead.
66+ if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath}))
77+- LinkerDriver = Args.MakeArgString(tool.get());
88++ return Args.MakeArgString(tool.get());
99++ }
1010++
1111++ // For Nix, prefer linking using the wrapped system clang, instead of using
1212++ // the unwrapped clang packaged with swift. The latter is unable to link, but
1313++ // we still want to use it for other purposes (clang importer).
1414++ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) {
1515++ llvm::SmallString<128> binDir(nixCC.getValue());
1616++ llvm::sys::path::append(binDir, "bin");
1717++ if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {binDir.str()}))
1818++ return Args.MakeArgString(tool.get());
1919+ }
2020+2121+ return LinkerDriver;
···11+Swift normally looks for the Clang resource dir in a subdir/symlink of its own
22+resource dir. We provide a symlink to the Swift build-time Clang as a default
33+there, but we also here patch two checks to try locate it via NIX_CC.
44+55+The first (ClangImporter.cpp) happens when Swift code imports C modules. The
66+second (ToolChains.cpp) happens when Swift is used to link the final product.
77+88+--- a/lib/ClangImporter/ClangImporter.cpp
99++++ b/lib/ClangImporter/ClangImporter.cpp
1010+@@ -68,6 +68,7 @@
1111+ #include "llvm/Support/FileSystem.h"
1212+ #include "llvm/Support/Memory.h"
1313+ #include "llvm/Support/Path.h"
1414++#include "llvm/Support/Process.h"
1515+ #include "llvm/Support/YAMLParser.h"
1616+ #include "llvm/Support/YAMLTraits.h"
1717+ #include <algorithm>
1818+@@ -809,6 +810,17 @@ importer::addCommonInvocationArguments(
1919+2020+ const std::string &overrideResourceDir = importerOpts.OverrideResourceDir;
2121+ if (overrideResourceDir.empty()) {
2222++ // Prefer the Clang resource directory from NIX_CC, to allow swapping in a
2323++ // different stdenv.
2424++ // TODO: Figure out how to provide a user override for this. Probably a
2525++ // niche use case, though, and for now a user can unset NIX_CC to work
2626++ // around it if necessary.
2727++ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) {
2828++ llvm::SmallString<128> resourceDir(nixCC.getValue());
2929++ llvm::sys::path::append(resourceDir, "resource-root");
3030++ invocationArgStrs.push_back("-resource-dir");
3131++ invocationArgStrs.push_back(std::string(resourceDir.str()));
3232++ } else {
3333+ llvm::SmallString<128> resourceDir(searchPathOpts.RuntimeResourcePath);
3434+3535+ // Adjust the path to refer to our copy of the Clang resource directory
3636+@@ -824,6 +836,7 @@ importer::addCommonInvocationArguments(
3737+ // Set the Clang resource directory to the path we computed.
3838+ invocationArgStrs.push_back("-resource-dir");
3939+ invocationArgStrs.push_back(std::string(resourceDir.str()));
4040++ } // nixCC
4141+ } else {
4242+ invocationArgStrs.push_back("-resource-dir");
4343+ invocationArgStrs.push_back(overrideResourceDir);
4444+--- a/lib/Driver/ToolChains.cpp
4545++++ b/lib/Driver/ToolChains.cpp
4646+@@ -1372,10 +1372,20 @@ void ToolChain::getClangLibraryPath(const ArgList &Args,
4747+ SmallString<128> &LibPath) const {
4848+ const llvm::Triple &T = getTriple();
4949+5050++ // Nix: We provide a `clang` symlink in the default Swift resource root, but
5151++ // prefer detecting the Clang resource root via NIX_CC, to allow swapping in
5252++ // a different stdenv. However, always honor a user-provided `-resource-dir`.
5353++ auto nixCC = llvm::sys::Process::GetEnv("NIX_CC");
5454++ if (nixCC && !Args.hasArgNoClaim(options::OPT_resource_dir)) {
5555++ LibPath.assign(nixCC.getValue());
5656++ llvm::sys::path::append(LibPath, "resource-root");
5757++ } else {
5858+ getResourceDirPath(LibPath, Args, /*Shared=*/true);
5959+ // Remove platform name.
6060+ llvm::sys::path::remove_filename(LibPath);
6161+- llvm::sys::path::append(LibPath, "clang", "lib",
6262++ llvm::sys::path::append(LibPath, "clang");
6363++ } // nixCC
6464++ llvm::sys::path::append(LibPath, "lib",
6565+ T.isOSDarwin() ? "darwin"
6666+ : getPlatformNameForTriple(T));
6767+ }
···11+Patch paths to use the separate 'lib' output. One of the things this patch
22+fixes is the output of `swift -frontend -print-target-info`, which swiftpm uses
33+to set rpath on Linux.
44+55+The check if the executable path starts with 'out' is necessary for
66+bootstrapping, or the compiler will fail when run from the build directory.
77+88+--- a/lib/Frontend/CompilerInvocation.cpp
99++++ b/lib/Frontend/CompilerInvocation.cpp
1010+@@ -49,11 +49,16 @@ swift::CompilerInvocation::CompilerInvocation() {
1111+ void CompilerInvocation::computeRuntimeResourcePathFromExecutablePath(
1212+ StringRef mainExecutablePath, bool shared,
1313+ llvm::SmallVectorImpl<char> &runtimeResourcePath) {
1414++ if (mainExecutablePath.startswith("@storeDir@")) {
1515++ auto libPath = StringRef("@lib@");
1616++ runtimeResourcePath.append(libPath.begin(), libPath.end());
1717++ } else {
1818+ runtimeResourcePath.append(mainExecutablePath.begin(),
1919+ mainExecutablePath.end());
2020+2121+ llvm::sys::path::remove_filename(runtimeResourcePath); // Remove /swift
2222+ llvm::sys::path::remove_filename(runtimeResourcePath); // Remove /bin
2323++ }
2424+ appendSwiftLibDir(runtimeResourcePath, shared);
2525+ }
2626+
···11+{ stdenv
22+, swift
33+, wrapperParams ? swift._wrapperParams
44+}:
55+66+stdenv.mkDerivation (wrapperParams // {
77+ pname = "swift-wrapper";
88+ inherit (swift) version meta;
99+1010+ outputs = [ "out" "man" ];
1111+1212+ # Setup hook variables.
1313+ inherit swift;
1414+ inherit (swift)
1515+ swiftOs swiftArch
1616+ swiftModuleSubdir swiftLibSubdir
1717+ swiftStaticModuleSubdir swiftStaticLibSubdir;
1818+1919+ passAsFile = [ "buildCommand" ];
2020+ buildCommand = ''
2121+ mkdir -p $out/bin $out/nix-support
2222+2323+ # Symlink all Swift binaries first.
2424+ # NOTE: This specifically omits clang binaries. We want to hide these for
2525+ # private use by Swift only.
2626+ ln -s -t $out/bin/ $swift/bin/swift*
2727+2828+ # Replace specific binaries with wrappers.
2929+ for executable in swift swiftc swift-frontend; do
3030+ export prog=$swift/bin/$executable
3131+ rm $out/bin/$executable
3232+ substituteAll '${./wrapper.sh}' $out/bin/$executable
3333+ chmod a+x $out/bin/$executable
3434+ done
3535+3636+ ln -s ${swift.man} $man
3737+3838+ # This link is here because various tools (swiftpm) check for stdlib
3939+ # relative to the swift compiler. It's fine if this is for build-time
4040+ # stuff, but we should patch all cases were it would end up in an output.
4141+ ln -s ${swift.lib}/lib $out/lib
4242+4343+ substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook
4444+ '';
4545+4646+ passthru = {
4747+ inherit swift;
4848+ inherit (swift) swiftOs swiftArch swiftModuleSubdir swiftLibSubdir;
4949+ };
5050+})
···11+# Add import paths for build inputs.
22+swiftWrapper_addImports () {
33+ # Include subdirectories following both the Swift platform convention, and
44+ # a simple `lib/swift` for Nix convenience.
55+ for subdir in @swiftModuleSubdir@ @swiftStaticModuleSubdir@ lib/swift; do
66+ if [[ -d "$1/$subdir" ]]; then
77+ export NIX_SWIFTFLAGS_COMPILE+=" -I $1/$subdir"
88+ fi
99+ done
1010+ for subdir in @swiftLibSubdir@ @swiftStaticLibSubdir@ lib/swift; do
1111+ if [[ -d "$1/$subdir" ]]; then
1212+ export NIX_LDFLAGS+=" -L $1/$subdir"
1313+ fi
1414+ done
1515+}
1616+1717+addEnvHooks "$targetOffset" swiftWrapper_addImports
1818+1919+# Use a postHook here because we rely on NIX_CC, which is set by the cc-wrapper
2020+# setup hook, so delay until we're sure it was run.
2121+swiftWrapper_postHook () {
2222+ # On Darwin, libc also contains Swift modules.
2323+ if [[ -e "$NIX_CC/nix-support/orig-libc" ]]; then
2424+ swiftWrapper_addImports "$(<$NIX_CC/nix-support/orig-libc)"
2525+ fi
2626+}
2727+2828+postHooks+=(swiftWrapper_postHook)
···11+#! @shell@
22+# NOTE: This wrapper is derived from cc-wrapper.sh, and is hopefully somewhat
33+# diffable with the original, so changes can be merged if necessary.
44+set -eu -o pipefail +o posix
55+shopt -s nullglob
66+77+if (( "${NIX_DEBUG:-0}" >= 7 )); then
88+ set -x
99+fi
1010+1111+cc_wrapper="${NIX_CC:-@default_cc_wrapper@}"
1212+1313+source $cc_wrapper/nix-support/utils.bash
1414+1515+expandResponseParams "$@"
1616+1717+# Check if we should wrap this Swift invocation at all, and how. Specifically,
1818+# there are some internal tools we don't wrap, plus swift-frontend doesn't link
1919+# and doesn't understand linker flags. This follows logic in
2020+# `lib/DriverTool/driver.cpp`.
2121+prog=@prog@
2222+progName="$(basename "$prog")"
2323+firstArg="${params[0]:-}"
2424+isFrontend=0
2525+isRepl=0
2626+2727+# These checks follow `shouldRunAsSubcommand`.
2828+if [[ "$progName" == swift ]]; then
2929+ case "$firstArg" in
3030+ "" | -* | *.* | */* | repl)
3131+ ;;
3232+ *)
3333+ exec "swift-$firstArg" "${params[@]:1}"
3434+ ;;
3535+ esac
3636+fi
3737+3838+# These checks follow the first part of `run_driver`.
3939+#
4040+# NOTE: The original function short-circuits, but we can't here, because both
4141+# paths must be wrapped. So we use an 'isFrontend' flag instead.
4242+case "$firstArg" in
4343+ -frontend)
4444+ isFrontend=1
4545+ # Ensure this stays the first argument.
4646+ params=( "${params[@]:1}" )
4747+ extraBefore+=( "-frontend" )
4848+ ;;
4949+ -modulewrap)
5050+ # Don't wrap this integrated tool.
5151+ exec "$prog" "${params[@]}"
5252+ ;;
5353+ repl)
5454+ isRepl=1
5555+ params=( "${params[@]:1}" )
5656+ ;;
5757+ --driver-mode=*)
5858+ ;;
5959+ *)
6060+ if [[ "$progName" == swift-frontend ]]; then
6161+ isFrontend=1
6262+ fi
6363+ ;;
6464+esac
6565+6666+path_backup="$PATH"
6767+6868+# That @-vars are substituted separately from bash evaluation makes
6969+# shellcheck think this, and others like it, are useless conditionals.
7070+# shellcheck disable=SC2157
7171+if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
7272+ PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
7373+fi
7474+7575+# Parse command line options and set several variables.
7676+# For instance, figure out if linker flags should be passed.
7777+# GCC prints annoying warnings when they are not needed.
7878+isCxx=0
7979+dontLink=$isFrontend
8080+8181+for p in "${params[@]}"; do
8282+ case "$p" in
8383+ -enable-cxx-interop)
8484+ isCxx=1 ;;
8585+ esac
8686+done
8787+8888+# NOTE: We don't modify these for Swift, but sourced scripts may use them.
8989+cxxInclude=1
9090+cxxLibrary=1
9191+cInclude=1
9292+9393+linkType=$(checkLinkType "${params[@]}")
9494+9595+# Optionally filter out paths not refering to the store.
9696+if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then
9797+ kept=()
9898+ nParams=${#params[@]}
9999+ declare -i n=0
100100+ while (( "$n" < "$nParams" )); do
101101+ p=${params[n]}
102102+ p2=${params[n+1]:-} # handle `p` being last one
103103+ n+=1
104104+105105+ skipNext=false
106106+ path=""
107107+ case "$p" in
108108+ -[IL]/*) path=${p:2} ;;
109109+ -[IL]) path=$p2 skipNext=true ;;
110110+ esac
111111+112112+ if [[ -n $path ]] && badPath "$path"; then
113113+ skip "$path"
114114+ $skipNext && n+=1
115115+ continue
116116+ fi
117117+118118+ kept+=("$p")
119119+ done
120120+ # Old bash empty array hack
121121+ params=(${kept+"${kept[@]}"})
122122+fi
123123+124124+# Flirting with a layer violation here.
125125+if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
126126+ source @bintools@/nix-support/add-flags.sh
127127+fi
128128+129129+# Put this one second so libc ldflags take priority.
130130+if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
131131+ source $cc_wrapper/nix-support/add-flags.sh
132132+fi
133133+134134+if [[ "$isCxx" = 1 ]]; then
135135+ if [[ "$cxxInclude" = 1 ]]; then
136136+ NIX_CFLAGS_COMPILE_@suffixSalt@+=" $NIX_CXXSTDLIB_COMPILE_@suffixSalt@"
137137+ fi
138138+ if [[ "$cxxLibrary" = 1 ]]; then
139139+ NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@"
140140+ fi
141141+fi
142142+143143+source $cc_wrapper/nix-support/add-hardening.sh
144144+145145+# Add the flags for the C compiler proper.
146146+addCFlagsToList() {
147147+ declare -n list="$1"
148148+ shift
149149+150150+ for ((i = 1; i <= $#; i++)); do
151151+ local val="${!i}"
152152+ case "$val" in
153153+ # Pass through using -Xcc, but also convert to Swift -I.
154154+ # These have slightly different meaning for Clang, but Swift
155155+ # doesn't have exact equivalents.
156156+ -isystem | -idirafter)
157157+ i=$((i + 1))
158158+ list+=("-Xcc" "$val" "-Xcc" "${!i}" "-I" "${!i}")
159159+ ;;
160160+ # Simple rename.
161161+ -iframework)
162162+ i=$((i + 1))
163163+ list+=("-Fsystem" "${!i}")
164164+ ;;
165165+ # Pass through verbatim.
166166+ -I | -Fsystem)
167167+ i=$((i + 1))
168168+ list+=("${val}" "${!i}")
169169+ ;;
170170+ -I* | -L* | -F*)
171171+ list+=("${val}")
172172+ ;;
173173+ # Pass through using -Xcc.
174174+ *)
175175+ list+=("-Xcc" "$val")
176176+ ;;
177177+ esac
178178+ done
179179+}
180180+for i in ${NIX_SWIFTFLAGS_COMPILE:-}; do
181181+ extraAfter+=("$i")
182182+done
183183+for i in ${NIX_SWIFTFLAGS_COMPILE_BEFORE:-}; do
184184+ extraBefore+=("$i")
185185+done
186186+addCFlagsToList extraAfter $NIX_CFLAGS_COMPILE_@suffixSalt@
187187+addCFlagsToList extraBefore ${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@
188188+189189+if [ "$dontLink" != 1 ]; then
190190+191191+ # Add the flags that should only be passed to the compiler when
192192+ # linking.
193193+ addCFlagsToList extraAfter $(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@)
194194+195195+ # Add the flags that should be passed to the linker (and prevent
196196+ # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
197197+ for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
198198+ extraBefore+=("-Xlinker" "$i")
199199+ done
200200+ if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
201201+ extraBefore+=("-Xlinker" "-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
202202+ fi
203203+ for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
204204+ if [ "${i:0:3}" = -L/ ]; then
205205+ extraAfter+=("$i")
206206+ else
207207+ extraAfter+=("-Xlinker" "$i")
208208+ fi
209209+ done
210210+ export NIX_LINK_TYPE_@suffixSalt@=$linkType
211211+fi
212212+213213+# TODO: If we ever need to expand functionality of this hook, it may no longer
214214+# be compatible with Swift. Right now, it is only used on Darwin to force
215215+# -target, which also happens to work with Swift.
216216+if [[ -e $cc_wrapper/nix-support/add-local-cc-cflags-before.sh ]]; then
217217+ source $cc_wrapper/nix-support/add-local-cc-cflags-before.sh
218218+fi
219219+220220+# May need to transform the triple injected by the above.
221221+for ((i = 1; i < ${#extraBefore[@]}; i++)); do
222222+ if [[ "${extraBefore[i]}" = -target ]]; then
223223+ i=$((i + 1))
224224+ # On Darwin only, need to change 'aarch64' to 'arm64'.
225225+ extraBefore[i]="${extraBefore[i]/aarch64-apple-/arm64-apple-}"
226226+ # On Darwin, Swift requires the triple to be annotated with a version.
227227+ # TODO: Assumes macOS.
228228+ extraBefore[i]="${extraBefore[i]/-apple-darwin/-apple-macosx${MACOSX_DEPLOYMENT_TARGET:-11.0}}"
229229+ break
230230+ fi
231231+done
232232+233233+# As a very special hack, if the arguments are just `-v', then don't
234234+# add anything. This is to prevent `gcc -v' (which normally prints
235235+# out the version number and returns exit code 0) from printing out
236236+# `No input files specified' and returning exit code 1.
237237+if [ "$*" = -v ]; then
238238+ extraAfter=()
239239+ extraBefore=()
240240+fi
241241+242242+# Optionally print debug info.
243243+if (( "${NIX_DEBUG:-0}" >= 1 )); then
244244+ # Old bash workaround, see ld-wrapper for explanation.
245245+ echo "extra flags before to $prog:" >&2
246246+ printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2
247247+ echo "original flags to $prog:" >&2
248248+ printf " %q\n" ${params+"${params[@]}"} >&2
249249+ echo "extra flags after to $prog:" >&2
250250+ printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2
251251+fi
252252+253253+PATH="$path_backup"
254254+# Old bash workaround, see above.
255255+256256+if (( "${NIX_CC_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then
257257+ exec "$prog" @<(printf "%q\n" \
258258+ ${extraBefore+"${extraBefore[@]}"} \
259259+ ${params+"${params[@]}"} \
260260+ ${extraAfter+"${extraAfter[@]}"})
261261+else
262262+ exec "$prog" \
263263+ ${extraBefore+"${extraBefore[@]}"} \
264264+ ${params+"${params[@]}"} \
265265+ ${extraAfter+"${extraAfter[@]}"}
266266+fi