diff --git a/pkgs/development/compilers/swift/compiler/default.nix b/pkgs/development/compilers/swift/compiler/default.nix new file mode 100644 index 0000000000000..0612deb471d17 --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/default.nix @@ -0,0 +1,651 @@ +{ lib +, stdenv +, callPackage +, cmake +, coreutils +, gnugrep +, perl +, ninja +, pkg-config +, clang +, bintools +, python3 +, git +, fetchpatch +, makeWrapper +, gnumake +, file +, runCommand +, writeShellScriptBin +# For lldb +, libedit +, ncurses +, swig +, libxml2 +# Linux-specific +, glibc +, libuuid +# Darwin-specific +, substituteAll +, fixDarwinDylibNames +, runCommandLocal +, xcbuild +, cctools # libtool +, sigtool +, DarwinTools +, CoreServices +, Foundation +, Combine +, CLTools_Executables +}: + +let + + inherit (stdenv) hostPlatform targetPlatform; + + sources = callPackage ../sources.nix { }; + + # Tools invoked by swift at run-time. + runtimeDeps = lib.optionals stdenv.isDarwin [ + # libtool is used for static linking. This is part of cctools, but adding + # that as a build input puts an unwrapped linker in PATH, and breaks + # builds. This small derivation exposes just libtool. + # NOTE: The same applies to swift-driver, but that is currently always + # invoked via the old `swift` / `swiftc`. May change in the future. + (runCommandLocal "libtool" { } '' + mkdir -p $out/bin + ln -s ${cctools}/bin/libtool $out/bin/libtool + '') + ]; + + # There are apparently multiple naming conventions on Darwin. Swift uses the + # xcrun naming convention. See `configure_sdk_darwin` calls in CMake files. + swiftOs = if targetPlatform.isDarwin + then { + "macos" = "macosx"; + "ios" = "iphoneos"; + #iphonesimulator + #appletvos + #appletvsimulator + #watchos + #watchsimulator + }.${targetPlatform.darwinPlatform} + or (throw "Cannot build Swift for target Darwin platform '${targetPlatform.darwinPlatform}'") + else targetPlatform.parsed.kernel.name; + + # Apple Silicon uses a different CPU name in the target triple. + swiftArch = if stdenv.isDarwin && stdenv.isAarch64 then "arm64" + else targetPlatform.parsed.cpu.name; + + # On Darwin, a `.swiftmodule` is a subdirectory in `lib/swift/`, + # containing binaries for supported archs. On other platforms, binaries are + # installed to `lib/swift//`. Note that our setup-hook also adds + # `lib/swift` for convenience. + swiftLibSubdir = "lib/swift/${swiftOs}"; + swiftModuleSubdir = if hostPlatform.isDarwin + then "lib/swift/${swiftOs}" + else "lib/swift/${swiftOs}/${swiftArch}"; + + # And then there's also a separate subtree for statically linked modules. + toStaticSubdir = lib.replaceStrings [ "/swift/" ] [ "/swift_static/" ]; + swiftStaticLibSubdir = toStaticSubdir swiftLibSubdir; + swiftStaticModuleSubdir = toStaticSubdir swiftModuleSubdir; + + # This matches _SWIFT_DEFAULT_COMPONENTS, with specific components disabled. + swiftInstallComponents = [ + "autolink-driver" + "compiler" + # "clang-builtin-headers" + "stdlib" + "sdk-overlay" + "parser-lib" + "static-mirror-lib" + "editor-integration" + # "tools" + # "testsuite-tools" + "toolchain-tools" + "toolchain-dev-tools" + "license" + (if stdenv.isDarwin then "sourcekit-xpc-service" else "sourcekit-inproc") + "swift-remote-mirror" + "swift-remote-mirror-headers" + ]; + + # Build a tool used during the build to create a custom clang wrapper, with + # which we wrap the clang produced by the swift build. + # + # This is used in a `POST_BUILD` for the CMake target, so we rename the + # actual clang to clang-unwrapped, then put the wrapper in place. + # + # We replace the `exec ...` command with `exec -a "$0"` in order to + # preserve $0 for clang. This is because, unlike Nix, we don't have + # separate wrappers for clang/clang++, and clang uses $0 to detect C++. + # + # Similarly, the C++ detection in the wrapper itself also won't work for us, + # so we base it on $0 as well. + makeClangWrapper = writeShellScriptBin "nix-swift-make-clang-wrapper" '' + set -euo pipefail + + targetFile="$1" + unwrappedClang="$targetFile-unwrapped" + + mv "$targetFile" "$unwrappedClang" + sed < '${clang}/bin/clang' > "$targetFile" \ + -e 's|^\s*exec|exec -a "$0"|g' \ + -e 's|^\[\[ "${clang.cc}/bin/clang" = \*++ ]]|[[ "$0" = *++ ]]|' \ + -e "s|${clang.cc}/bin/clang|$unwrappedClang|g" + chmod a+x "$targetFile" + ''; + + # Create a tool used during the build to create a custom swift wrapper for + # each of the swift executables produced by the build. + # + # The build produces several `swift-frontend` executables during + # bootstrapping. Each of these has numerous aliases via symlinks, and the + # executable uses $0 to detect what tool is called. + wrapperParams = { + inherit bintools; + default_cc_wrapper = clang; # Instead of `@out@` in the original. + coreutils_bin = lib.getBin coreutils; + gnugrep_bin = gnugrep; + suffixSalt = lib.replaceStrings ["-" "."] ["_" "_"] targetPlatform.config; + use_response_file_by_default = 1; + swiftDriver = ""; + # NOTE: @prog@ needs to be filled elsewhere. + }; + swiftWrapper = runCommand "swift-wrapper.sh" wrapperParams '' + substituteAll '${../wrapper/wrapper.sh}' "$out" + ''; + makeSwiftcWrapper = writeShellScriptBin "nix-swift-make-swift-wrapper" '' + set -euo pipefail + + targetFile="$1" + unwrappedSwift="$targetFile-unwrapped" + + mv "$targetFile" "$unwrappedSwift" + sed < '${swiftWrapper}' > "$targetFile" \ + -e "s|@prog@|'$unwrappedSwift'|g" \ + -e 's|exec "$prog"|exec -a "$0" "$prog"|g' + chmod a+x "$targetFile" + ''; + +in stdenv.mkDerivation { + pname = "swift"; + inherit (sources) version; + + outputs = [ "out" "lib" "dev" "doc" "man" ]; + + nativeBuildInputs = [ + cmake + git + ninja + perl # pod2man + pkg-config + python3 + makeWrapper + makeClangWrapper + makeSwiftcWrapper + ] + ++ lib.optionals stdenv.isDarwin [ + xcbuild + sigtool # codesign + DarwinTools # sw_vers + fixDarwinDylibNames + ]; + + buildInputs = [ + # For lldb + python3 + swig + libxml2 + ] + ++ lib.optionals stdenv.isLinux [ + libuuid + ] + ++ lib.optionals stdenv.isDarwin [ + CoreServices + Foundation + Combine + ]; + + # This is a partial reimplementation of our setup hook. Because we reuse + # the Swift wrapper for the Swift build itself, we need to do some of the + # same preparation. + postHook = '' + for pkg in "''${pkgsHostTarget[@]}" '${clang.libc}'; do + for subdir in ${swiftModuleSubdir} ${swiftStaticModuleSubdir} lib/swift; do + if [[ -d "$pkg/$subdir" ]]; then + export NIX_SWIFTFLAGS_COMPILE+=" -I $pkg/$subdir" + fi + done + for subdir in ${swiftLibSubdir} ${swiftStaticLibSubdir} lib/swift; do + if [[ -d "$pkg/$subdir" ]]; then + export NIX_LDFLAGS+=" -L $pkg/$subdir" + fi + done + done + ''; + + # We invoke cmakeConfigurePhase multiple times, but only need this once. + dontFixCmake = true; + # We setup custom build directories. + dontUseCmakeBuildDir = true; + + unpackPhase = let + copySource = repo: "cp -r ${sources.${repo}} ${repo}"; + in '' + mkdir src + cd src + + ${copySource "swift-cmark"} + ${copySource "llvm-project"} + ${copySource "swift"} + ${copySource "swift-experimental-string-processing"} + ${lib.optionalString + (!stdenv.isDarwin) + (copySource "swift-corelibs-libdispatch")} + + chmod -R u+w . + ''; + + patchPhase = '' + # Just patch all the things for now, we can focus this later. + # TODO: eliminate use of env. + find -type f -print0 | xargs -0 sed -i \ + ${lib.optionalString stdenv.isDarwin + "-e 's|/usr/libexec/PlistBuddy|${xcbuild}/bin/PlistBuddy|g'"} \ + -e 's|/usr/bin/env|${coreutils}/bin/env|g' \ + -e 's|/usr/bin/make|${gnumake}/bin/make|g' \ + -e 's|/bin/mkdir|${coreutils}/bin/mkdir|g' \ + -e 's|/bin/cp|${coreutils}/bin/cp|g' \ + -e 's|/usr/bin/file|${file}/bin/file|g' + + patch -p1 -d swift -i ${./patches/swift-wrap.patch} + patch -p1 -d swift -i ${./patches/swift-nix-resource-root.patch} + patch -p1 -d swift -i ${./patches/swift-linux-fix-linking.patch} + patch -p1 -d swift -i ${./patches/swift-darwin-fix-bootstrap.patch} + patch -p1 -d swift -i ${substituteAll { + src = ./patches/swift-darwin-plistbuddy-workaround.patch; + inherit swiftArch; + }} + patch -p1 -d swift -i ${substituteAll { + src = ./patches/swift-prevent-sdk-dirs-warning.patch; + inherit (builtins) storeDir; + }} + substituteInPlace swift/cmake/modules/SwiftConfigureSDK.cmake \ + --replace '/usr/include' "${stdenv.cc.libc_dev}/include" + + # This patch needs to know the lib output location, so must be substituted + # in the same derivation as the compiler. + storeDir="${builtins.storeDir}" \ + substituteAll ${./patches/swift-separate-lib.patch} $TMPDIR/swift-separate-lib.patch + patch -p1 -d swift -i $TMPDIR/swift-separate-lib.patch + + patch -p1 -d llvm-project/llvm -i ${./patches/llvm-module-cache.patch} + + patch -p1 -d llvm-project/clang -i ${./patches/clang-toolchain-dir.patch} + patch -p1 -d llvm-project/clang -i ${./patches/clang-wrap.patch} + patch -p1 -d llvm-project/clang -i ${../../llvm/14/clang/purity.patch} + patch -p2 -d llvm-project/clang -i ${fetchpatch { + name = "clang-cmake-fix-interpreter.patch"; + url = "https://github.com/llvm/llvm-project/commit/b5eaf500f2441eff2277ea2973878fb1f171fd0a.patch"; + sha256 = "1rma1al0rbm3s3ql6bnvbcighp74lri1lcrwbyacgdqp80fgw1b6"; + }} + + ${lib.optionalString stdenv.isLinux '' + substituteInPlace llvm-project/clang/lib/Driver/ToolChains/Linux.cpp \ + --replace 'SysRoot + "/lib' '"${glibc}/lib" "' \ + --replace 'SysRoot + "/usr/lib' '"${glibc}/lib" "' \ + --replace 'LibDir = "lib";' 'LibDir = "${glibc}/lib";' \ + --replace 'LibDir = "lib64";' 'LibDir = "${glibc}/lib";' \ + --replace 'LibDir = X32 ? "libx32" : "lib64";' 'LibDir = "${glibc}/lib";' + + # uuid.h is not part of glibc, but of libuuid. + sed -i 's|''${GLIBC_INCLUDE_PATH}/uuid/uuid.h|${libuuid.dev}/include/uuid/uuid.h|' \ + swift/stdlib/public/Platform/glibc.modulemap.gyb + ''} + + # Remove tests for cross compilation, which we don't currently support. + rm swift/test/Interop/Cxx/class/constructors-copy-irgen.swift + rm swift/test/Interop/Cxx/class/constructors-irgen.swift + + # TODO: consider fixing and re-adding. This test fails due to a non-standard "install_prefix". + rm swift/validation-test/Python/build_swift.swift + + # We cannot handle the SDK location being in "Weird Location" due to Nix isolation. + rm swift/test/DebugInfo/compiler-flags.swift + + # TODO: Fix issue with ld.gold invoked from script finding crtbeginS.o and crtendS.o. + rm swift/test/IRGen/ELF-remove-autolink-section.swift + + # The following two tests fail because we use don't use the bundled libicu: + # [SOURCE_DIR/utils/build-script] ERROR: can't find source directory for libicu (tried /build/src/icu) + rm swift/validation-test/BuildSystem/default_build_still_performs_epilogue_opts_after_split.test + rm swift/validation-test/BuildSystem/test_early_swift_driver_and_infer.swift + + # TODO: This test fails for some unknown reason + rm swift/test/Serialization/restrict-swiftmodule-to-revision.swift + + # This test was flaky in ofborg, see #186476 + rm swift/test/AutoDiff/compiler_crashers_fixed/sr14290-missing-debug-scopes-in-pullback-trampoline.swift + + patchShebangs . + + ${lib.optionalString (!stdenv.isDarwin) '' + # NOTE: This interferes with ABI stability on Darwin, which uses the system + # libraries in the hardcoded path /usr/lib/swift. + fixCmakeFiles . + ''} + ''; + + configurePhase = '' + export SWIFT_SOURCE_ROOT="$PWD" + mkdir -p ../build + cd ../build + export SWIFT_BUILD_ROOT="$PWD" + + # Most builds set a target, but LLDB doesn't. Harmless on non-Darwin. + export MACOSX_DEPLOYMENT_TARGET=10.15 + ''; + + # These steps are derived from doing a normal build with. + # + # ./swift/utils/build-toolchain test --dry-run + # + # But dealing with the custom Python build system is far more trouble than + # simply invoking CMake directly. Few variables it passes to CMake are + # actually required or non-default. + # + # Using CMake directly also allows us to split up the already large build, + # and package Swift components separately. + # + # Besides `--dry-run`, another good way to compare build changes between + # Swift releases is to diff the scripts: + # + # git diff swift-5.6.3-RELEASE..swift-5.7-RELEASE -- utils/build* + # + buildPhase = '' + # Helper to build a subdirectory. + # + # Always reset cmakeFlags before calling this. The cmakeConfigurePhase + # amends flags and would otherwise keep expanding it. + function buildProject() { + mkdir -p $SWIFT_BUILD_ROOT/$1 + cd $SWIFT_BUILD_ROOT/$1 + + cmakeDir=$SWIFT_SOURCE_ROOT/''${2-$1} + cmakeConfigurePhase + + ninjaBuildPhase + } + + cmakeFlags="-GNinja" + buildProject swift-cmark + + # Some notes: + # - The Swift build just needs Clang. + # - We can further reduce targets to just our targetPlatform. + cmakeFlags=" + -GNinja + -DLLVM_ENABLE_PROJECTS=clang + -DLLVM_TARGETS_TO_BUILD=${{ + "x86_64" = "X86"; + "aarch64" = "AArch64"; + }.${targetPlatform.parsed.cpu.name}} + " + buildProject llvm llvm-project/llvm + + # Some notes: + # - Building with libswift defaults to OFF in CMake, but is enabled in + # standard builds, so we enable it as well. + # - Experimental features are OFF by default in CMake, but some are + # required to build the stdlib. + # - SWIFT_STDLIB_ENABLE_OBJC_INTEROP is set explicitely because its check + # is buggy. (Uses SWIFT_HOST_VARIANT_SDK before initialized.) + # Fixed in: https://github.com/apple/swift/commit/84083afef1de5931904d5c815d53856cdb3fb232 + cmakeFlags=" + -GNinja + -DBOOTSTRAPPING_MODE=BOOTSTRAPPING + -DSWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY=ON + -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm + -DClang_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/clang + -DSWIFT_PATH_TO_CMARK_SOURCE=$SWIFT_SOURCE_ROOT/swift-cmark + -DSWIFT_PATH_TO_CMARK_BUILD=$SWIFT_BUILD_ROOT/swift-cmark + -DSWIFT_PATH_TO_LIBDISPATCH_SOURCE=$SWIFT_SOURCE_ROOT/swift-corelibs-libdispatch + -DEXPERIMENTAL_STRING_PROCESSING_SOURCE_DIR=$SWIFT_SOURCE_ROOT/swift-experimental-string-processing + -DSWIFT_INSTALL_COMPONENTS=${lib.concatStringsSep ";" swiftInstallComponents} + -DSWIFT_STDLIB_ENABLE_OBJC_INTEROP=${if stdenv.isDarwin then "ON" else "OFF"} + " + buildProject swift + + # These are based on flags in `utils/build-script-impl`. + # + # LLDB_USE_SYSTEM_DEBUGSERVER=ON disables the debugserver build on Darwin, + # which requires a special signature. + # + # CMAKE_BUILD_WITH_INSTALL_NAME_DIR ensures we don't use rpath on Darwin. + # + # NOTE: On Darwin, we only want ncurses in the linker search path, because + # headers are part of libsystem. Adding its headers to the search path + # causes strange mixing and errors. Note that libedit propagates ncurses, + # so we add both manually here, instead of relying on setup hooks. + # TODO: Find a better way to prevent this conflict. + cmakeFlags=" + -GNinja + -DLLDB_SWIFTC=$SWIFT_BUILD_ROOT/swift/bin/swiftc + -DLLDB_SWIFT_LIBS=$SWIFT_BUILD_ROOT/swift/lib/swift + -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm + -DClang_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/clang + -DSwift_DIR=$SWIFT_BUILD_ROOT/swift/lib/cmake/swift + -DLLDB_ENABLE_CURSES=ON + -DLLDB_ENABLE_LIBEDIT=ON + -DLLDB_ENABLE_PYTHON=ON + -DLLDB_ENABLE_LZMA=OFF + -DLLDB_ENABLE_LUA=OFF + -DLLDB_INCLUDE_TESTS=OFF + -DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON + ${lib.optionalString stdenv.isDarwin '' + -DLLDB_USE_SYSTEM_DEBUGSERVER=ON + ''} + -DLibEdit_INCLUDE_DIRS=${libedit.dev}/include + -DLibEdit_LIBRARIES=${libedit}/lib/libedit${stdenv.hostPlatform.extensions.sharedLibrary} + -DCURSES_INCLUDE_DIRS=${if stdenv.isDarwin then "/var/empty" else ncurses.dev}/include + -DCURSES_LIBRARIES=${ncurses}/lib/libncurses${stdenv.hostPlatform.extensions.sharedLibrary} + -DPANEL_LIBRARIES=${ncurses}/lib/libpanel${stdenv.hostPlatform.extensions.sharedLibrary} + "; + buildProject lldb llvm-project/lldb + + ${lib.optionalString stdenv.isDarwin '' + # Need to do a standalone build of concurrency for Darwin back deployment. + # Based on: utils/swift_build_support/swift_build_support/products/backdeployconcurrency.py + cmakeFlags=" + -GNinja + -DCMAKE_Swift_COMPILER=$SWIFT_BUILD_ROOT/swift/bin/swiftc + + -DTOOLCHAIN_DIR=/var/empty + -DSWIFT_NATIVE_LLVM_TOOLS_PATH=${stdenv.cc}/bin + -DSWIFT_NATIVE_CLANG_TOOLS_PATH=${stdenv.cc}/bin + -DSWIFT_NATIVE_SWIFT_TOOLS_PATH=$SWIFT_BUILD_ROOT/swift/bin + + -DCMAKE_CROSSCOMPILING=ON + + -DBUILD_SWIFT_CONCURRENCY_BACK_DEPLOYMENT_LIBRARIES=ON + -DSWIFT_INCLUDE_TOOLS=OFF + -DSWIFT_BUILD_STDLIB_EXTRA_TOOLCHAIN_CONTENT=OFF + -DSWIFT_BUILD_TEST_SUPPORT_MODULES=OFF + -DSWIFT_BUILD_STDLIB=OFF + -DSWIFT_BUILD_DYNAMIC_STDLIB=OFF + -DSWIFT_BUILD_STATIC_STDLIB=OFF + -DSWIFT_BUILD_REMOTE_MIRROR=OFF + -DSWIFT_BUILD_SDK_OVERLAY=OFF + -DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=OFF + -DSWIFT_BUILD_STATIC_SDK_OVERLAY=OFF + -DSWIFT_INCLUDE_TESTS=OFF + -DSWIFT_BUILD_PERF_TESTSUITE=OFF + + -DSWIFT_HOST_VARIANT_ARCH=${swiftArch} + -DBUILD_STANDALONE=ON + + -DSWIFT_INSTALL_COMPONENTS=back-deployment + + -DSWIFT_SDKS=${{ + "macos" = "OSX"; + "ios" = "IOS"; + #IOS_SIMULATOR + #TVOS + #TVOS_SIMULATOR + #WATCHOS + #WATCHOS_SIMULATOR + }.${targetPlatform.darwinPlatform}} + + -DLLVM_DIR=$SWIFT_BUILD_ROOT/llvm/lib/cmake/llvm + + -DSWIFT_DEST_ROOT=$out + -DSWIFT_HOST_VARIANT_SDK=OSX + + -DSWIFT_DARWIN_DEPLOYMENT_VERSION_OSX=10.15 + -DSWIFT_DARWIN_DEPLOYMENT_VERSION_IOS=13.0 + -DSWIFT_DARWIN_DEPLOYMENT_VERSION_MACCATALYST=13.0 + -DSWIFT_DARWIN_DEPLOYMENT_VERSION_TVOS=13.0 + -DSWIFT_DARWIN_DEPLOYMENT_VERSION_WATCHOS=6.0 + " + + # This depends on the special Clang build specific to the Swift branch. + # We also need to call a specific Ninja target. + export CC=$SWIFT_BUILD_ROOT/llvm/bin/clang + export CXX=$SWIFT_BUILD_ROOT/llvm/bin/clang++ + ninjaFlags="back-deployment" + + buildProject swift-concurrency-backdeploy swift + + export CC=$NIX_CC/bin/clang + export CXX=$NIX_CC/bin/clang++ + unset ninjaFlags + ''} + ''; + + # TODO: ~50 failing tests on x86_64-linux. Other platforms not checked. + doCheck = false; + checkInputs = [ file ]; + # TODO: consider using stress-tester and integration-test. + checkPhase = '' + cd $SWIFT_BUILD_ROOT/swift + checkTarget=check-swift-all + ninjaCheckPhase + unset checkTarget + ''; + + installPhase = '' + # Undo the clang and swift wrapping we did for the build. + # (This happened via patches to cmake files.) + cd $SWIFT_BUILD_ROOT + mv llvm/bin/clang-14{-unwrapped,} + mv swift/bin/swift-frontend{-unwrapped,} + + mkdir $out $lib + + # Install clang binaries only. We hide these with the wrapper, so they are + # for private use by Swift only. + cd $SWIFT_BUILD_ROOT/llvm + installTargets=install-clang + ninjaInstallPhase + unset installTargets + + # LLDB is also a private install. + cd $SWIFT_BUILD_ROOT/lldb + ninjaInstallPhase + + cd $SWIFT_BUILD_ROOT/swift + ninjaInstallPhase + + ${lib.optionalString stdenv.isDarwin '' + cd $SWIFT_BUILD_ROOT/swift-concurrency-backdeploy + installTargets=install-back-deployment + ninjaInstallPhase + unset installTargets + ''} + + # Separate $lib output here, because specific logic follows. + # Only move the dynamic run-time parts, to keep $lib small. Every Swift + # build will depend on it. + moveToOutput "lib/swift" "$lib" + moveToOutput "lib/libswiftDemangle.*" "$lib" + + # This link is here because various tools (swiftpm) check for stdlib + # relative to the swift compiler. It's fine if this is for build-time + # stuff, but we should patch all cases were it would end up in an output. + ln -s $lib/lib/swift $out/lib/swift + + # Swift has a separate resource root from Clang, but locates the Clang + # resource root via subdir or symlink. Provide a default here, but we also + # patch Swift to prefer NIX_CC if set. + ln -s ${clang}/resource-root $lib/lib/swift/clang + + ${lib.optionalString stdenv.isDarwin '' + # Install required library for ObjC interop. + # TODO: Is there no source code for this available? + cp -r ${CLTools_Executables}/usr/lib/arc $out/lib/arc + ''} + ''; + + preFixup = lib.optionalString stdenv.isLinux '' + # This is cheesy, but helps the patchelf hook remove /build from RPATH. + cd $SWIFT_BUILD_ROOT/.. + mv build buildx + ''; + + postFixup = lib.optionalString stdenv.isDarwin '' + # These libraries need to use the system install name. The official SDK + # does the same (as opposed to using rpath). Presumably, they are part of + # the stable ABI. Not using the system libraries at run-time is known to + # cause ObjC class conflicts and segfaults. + declare -A systemLibs=( + [libswiftCore.dylib]=1 + [libswiftDarwin.dylib]=1 + [libswiftSwiftOnoneSupport.dylib]=1 + [libswift_Concurrency.dylib]=1 + ) + + for systemLib in "''${!systemLibs[@]}"; do + install_name_tool -id /usr/lib/swift/$systemLib $lib/${swiftLibSubdir}/$systemLib + done + + for file in $out/bin/swift-frontend $lib/${swiftLibSubdir}/*.dylib; do + changeArgs="" + for dylib in $(otool -L $file | awk '{ print $1 }'); do + if [[ ''${systemLibs["$(basename $dylib)"]} ]]; then + changeArgs+=" -change $dylib /usr/lib/swift/$(basename $dylib)" + elif [[ "$dylib" = */bootstrapping1/* ]]; then + changeArgs+=" -change $dylib $lib/lib/swift/$(basename $dylib)" + fi + done + if [[ -n "$changeArgs" ]]; then + install_name_tool $changeArgs $file + fi + done + + wrapProgram $out/bin/swift-frontend \ + --prefix PATH : ${lib.makeBinPath runtimeDeps} + ''; + + passthru = { + inherit + swiftOs swiftArch + swiftModuleSubdir swiftLibSubdir + swiftStaticModuleSubdir swiftStaticLibSubdir; + + # Internal attr for the wrapper. + _wrapperParams = wrapperParams; + }; + + meta = { + description = "The Swift Programming Language"; + homepage = "https://github.com/apple/swift"; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + license = lib.licenses.asl20; + platforms = with lib.platforms; linux ++ darwin; + # Swift doesn't support 32-bit Linux, unknown on other platforms. + badPlatforms = lib.platforms.i686; + timeout = 86400; # 24 hours. + }; +} diff --git a/pkgs/development/compilers/swift/patches/0005-clang-toolchain-dir.patch b/pkgs/development/compilers/swift/compiler/patches/clang-toolchain-dir.patch similarity index 100% rename from pkgs/development/compilers/swift/patches/0005-clang-toolchain-dir.patch rename to pkgs/development/compilers/swift/compiler/patches/clang-toolchain-dir.patch diff --git a/pkgs/development/compilers/swift/compiler/patches/clang-wrap.patch b/pkgs/development/compilers/swift/compiler/patches/clang-wrap.patch new file mode 100644 index 0000000000000..9c6cafed3699c --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/clang-wrap.patch @@ -0,0 +1,18 @@ +Wrap the clang produced during the build + +--- a/tools/driver/CMakeLists.txt ++++ b/tools/driver/CMakeLists.txt +@@ -59,6 +59,13 @@ endif() + + add_dependencies(clang clang-resource-headers) + ++# Nix: wrap the clang build. ++add_custom_command( ++ TARGET clang POST_BUILD ++ COMMAND nix-swift-make-clang-wrapper $ ++ VERBATIM ++) ++ + if(NOT CLANG_LINKS_TO_CREATE) + set(CLANG_LINKS_TO_CREATE clang++ clang-cl clang-cpp) + endif() diff --git a/pkgs/development/compilers/swift/compiler/patches/llvm-module-cache.patch b/pkgs/development/compilers/swift/compiler/patches/llvm-module-cache.patch new file mode 100644 index 0000000000000..9a22d0482ea5c --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/llvm-module-cache.patch @@ -0,0 +1,30 @@ +The compiler fails if LLVM modules are enabled and it cannot write its module +cache. This patch detects and rejects the fake, non-existant $HOME used in Nix +builds. + +We could simply return false in `cache_directory`, but that completely disables +module caching, and may unnecessarily slow down builds. Instead, let it use +'/tmp/.cache'. + +--- a/lib/Support/Unix/Path.inc ++++ b/lib/Support/Unix/Path.inc +@@ -1380,6 +1380,9 @@ bool user_config_directory(SmallVectorImpl &result) { + if (!home_directory(result)) { + return false; + } ++ if (std::equal(result.begin(), result.end(), "/homeless-shelter")) { ++ return false; ++ } + append(result, ".config"); + return true; + } +@@ -1401,6 +1404,9 @@ bool cache_directory(SmallVectorImpl &result) { + if (!home_directory(result)) { + return false; + } ++ if (std::equal(result.begin(), result.end(), "/homeless-shelter")) { ++ system_temp_directory(true/*ErasedOnReboot*/, result); ++ } + append(result, ".cache"); + return true; + } diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-darwin-fix-bootstrap.patch b/pkgs/development/compilers/swift/compiler/patches/swift-darwin-fix-bootstrap.patch new file mode 100644 index 0000000000000..a87b90bd8ca7c --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-darwin-fix-bootstrap.patch @@ -0,0 +1,20 @@ +This patch fixes dylib references during bootstrapping. It's possible +`LIBSWIFT_BUILD_MODE=BOOTSTRAPPING` is not really well tested on Darwin, +because official builds don't use it. + +In the near future, Swift will require an existing Swift toolchain to +bootstrap, and we will likely have to replace this any way. + +--- a/stdlib/cmake/modules/AddSwiftStdlib.cmake ++++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake +@@ -1035,6 +1035,10 @@ function(add_swift_target_library_single target name) + set(install_name_dir "${SWIFTLIB_SINGLE_DARWIN_INSTALL_NAME_DIR}") + endif() + ++ if(DEFINED SWIFTLIB_SINGLE_BOOTSTRAPPING) ++ set(install_name_dir "${lib_dir}/${output_sub_dir}") ++ endif() ++ + set_target_properties("${target}" + PROPERTIES + INSTALL_NAME_DIR "${install_name_dir}") diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-darwin-plistbuddy-workaround.patch b/pkgs/development/compilers/swift/compiler/patches/swift-darwin-plistbuddy-workaround.patch new file mode 100644 index 0000000000000..a3cf4f60675cb --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-darwin-plistbuddy-workaround.patch @@ -0,0 +1,17 @@ +CMake tries to read a list field from SDKSettings.plist, but the output of +facebook/xcbuild PlistBuddy is incompatible with Apple's. + +Simply set the supported architectures to the one target architecture we're +building for. + +--- a/cmake/modules/SwiftConfigureSDK.cmake ++++ b/cmake/modules/SwiftConfigureSDK.cmake +@@ -189,7 +189,7 @@ macro(configure_sdk_darwin + endif() + + # Remove any architectures not supported by the SDK. +- remove_sdk_unsupported_archs(${name} ${xcrun_name} ${SWIFT_SDK_${prefix}_PATH} SWIFT_SDK_${prefix}_ARCHITECTURES) ++ set(SWIFT_SDK_${prefix}_ARCHITECTURES "@swiftArch@") + + list_intersect( + "${SWIFT_DARWIN_MODULE_ARCHS}" # lhs diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch b/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch new file mode 100644 index 0000000000000..e09d5162a93a4 --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch @@ -0,0 +1,21 @@ +--- a/lib/Driver/ToolChains.cpp ++++ b/lib/Driver/ToolChains.cpp +@@ -1475,7 +1475,17 @@ const char *ToolChain::getClangLinkerDriver( + + // If there is a linker driver in the toolchain folder, use that instead. + if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) +- LinkerDriver = Args.MakeArgString(tool.get()); ++ return Args.MakeArgString(tool.get()); ++ } ++ ++ // For Nix, prefer linking using the wrapped system clang, instead of using ++ // the unwrapped clang packaged with swift. The latter is unable to link, but ++ // we still want to use it for other purposes (clang importer). ++ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) { ++ llvm::SmallString<128> binDir(nixCC.getValue()); ++ llvm::sys::path::append(binDir, "bin"); ++ if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {binDir.str()})) ++ return Args.MakeArgString(tool.get()); + } + + return LinkerDriver; diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch b/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch new file mode 100644 index 0000000000000..a68326c580b12 --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch @@ -0,0 +1,67 @@ +Swift normally looks for the Clang resource dir in a subdir/symlink of its own +resource dir. We provide a symlink to the Swift build-time Clang as a default +there, but we also here patch two checks to try locate it via NIX_CC. + +The first (ClangImporter.cpp) happens when Swift code imports C modules. The +second (ToolChains.cpp) happens when Swift is used to link the final product. + +--- a/lib/ClangImporter/ClangImporter.cpp ++++ b/lib/ClangImporter/ClangImporter.cpp +@@ -68,6 +68,7 @@ + #include "llvm/Support/FileSystem.h" + #include "llvm/Support/Memory.h" + #include "llvm/Support/Path.h" ++#include "llvm/Support/Process.h" + #include "llvm/Support/YAMLParser.h" + #include "llvm/Support/YAMLTraits.h" + #include +@@ -809,6 +810,17 @@ importer::addCommonInvocationArguments( + + const std::string &overrideResourceDir = importerOpts.OverrideResourceDir; + if (overrideResourceDir.empty()) { ++ // Prefer the Clang resource directory from NIX_CC, to allow swapping in a ++ // different stdenv. ++ // TODO: Figure out how to provide a user override for this. Probably a ++ // niche use case, though, and for now a user can unset NIX_CC to work ++ // around it if necessary. ++ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) { ++ llvm::SmallString<128> resourceDir(nixCC.getValue()); ++ llvm::sys::path::append(resourceDir, "resource-root"); ++ invocationArgStrs.push_back("-resource-dir"); ++ invocationArgStrs.push_back(std::string(resourceDir.str())); ++ } else { + llvm::SmallString<128> resourceDir(searchPathOpts.RuntimeResourcePath); + + // Adjust the path to refer to our copy of the Clang resource directory +@@ -824,6 +836,7 @@ importer::addCommonInvocationArguments( + // Set the Clang resource directory to the path we computed. + invocationArgStrs.push_back("-resource-dir"); + invocationArgStrs.push_back(std::string(resourceDir.str())); ++ } // nixCC + } else { + invocationArgStrs.push_back("-resource-dir"); + invocationArgStrs.push_back(overrideResourceDir); +--- a/lib/Driver/ToolChains.cpp ++++ b/lib/Driver/ToolChains.cpp +@@ -1372,10 +1372,20 @@ void ToolChain::getClangLibraryPath(const ArgList &Args, + SmallString<128> &LibPath) const { + const llvm::Triple &T = getTriple(); + ++ // Nix: We provide a `clang` symlink in the default Swift resource root, but ++ // prefer detecting the Clang resource root via NIX_CC, to allow swapping in ++ // a different stdenv. However, always honor a user-provided `-resource-dir`. ++ auto nixCC = llvm::sys::Process::GetEnv("NIX_CC"); ++ if (nixCC && !Args.hasArgNoClaim(options::OPT_resource_dir)) { ++ LibPath.assign(nixCC.getValue()); ++ llvm::sys::path::append(LibPath, "resource-root"); ++ } else { + getResourceDirPath(LibPath, Args, /*Shared=*/true); + // Remove platform name. + llvm::sys::path::remove_filename(LibPath); +- llvm::sys::path::append(LibPath, "clang", "lib", ++ llvm::sys::path::append(LibPath, "clang"); ++ } // nixCC ++ llvm::sys::path::append(LibPath, "lib", + T.isOSDarwin() ? "darwin" + : getPlatformNameForTriple(T)); + } diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-prevent-sdk-dirs-warning.patch b/pkgs/development/compilers/swift/compiler/patches/swift-prevent-sdk-dirs-warning.patch new file mode 100644 index 0000000000000..987b99d745391 --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-prevent-sdk-dirs-warning.patch @@ -0,0 +1,39 @@ +Prevents a user-visible warning on every compilation: + + ld: warning: directory not found for option '-L.../MacOSX11.0.sdk/usr/lib/swift' + +--- a/lib/Driver/ToolChains.cpp ++++ b/lib/Driver/ToolChains.cpp +@@ -1455,9 +1455,11 @@ void ToolChain::getRuntimeLibraryPaths(SmallVectorImpl &runtimeLibP + runtimeLibPaths.push_back(std::string(scratchPath.str())); + } + ++ if (!SDKPath.startswith("@storeDir@")) { + scratchPath = SDKPath; + llvm::sys::path::append(scratchPath, "usr", "lib", "swift"); + runtimeLibPaths.push_back(std::string(scratchPath.str())); ++ } + } + } + +--- a/lib/Frontend/CompilerInvocation.cpp ++++ b/lib/Frontend/CompilerInvocation.cpp +@@ -185,7 +185,9 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, + RuntimeLibraryImportPaths.push_back(std::string(LibPath.str())); + } + +- LibPath = SearchPathOpts.getSDKPath(); ++ auto SDKPath = SearchPathOpts.getSDKPath(); ++ if (!SDKPath.startswith("@storeDir@")) { ++ LibPath = SDKPath; + llvm::sys::path::append(LibPath, "usr", "lib", "swift"); + if (!Triple.isOSDarwin()) { + // Use the non-architecture suffixed form with directory-layout +@@ -200,6 +202,7 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts, + llvm::sys::path::append(LibPath, swift::getMajorArchitectureName(Triple)); + } + RuntimeLibraryImportPaths.push_back(std::string(LibPath.str())); ++ } + } + SearchPathOpts.setRuntimeLibraryImportPaths(RuntimeLibraryImportPaths); + } diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-separate-lib.patch b/pkgs/development/compilers/swift/compiler/patches/swift-separate-lib.patch new file mode 100644 index 0000000000000..20d81a6e8296c --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-separate-lib.patch @@ -0,0 +1,26 @@ +Patch paths to use the separate 'lib' output. One of the things this patch +fixes is the output of `swift -frontend -print-target-info`, which swiftpm uses +to set rpath on Linux. + +The check if the executable path starts with 'out' is necessary for +bootstrapping, or the compiler will fail when run from the build directory. + +--- a/lib/Frontend/CompilerInvocation.cpp ++++ b/lib/Frontend/CompilerInvocation.cpp +@@ -49,11 +49,16 @@ swift::CompilerInvocation::CompilerInvocation() { + void CompilerInvocation::computeRuntimeResourcePathFromExecutablePath( + StringRef mainExecutablePath, bool shared, + llvm::SmallVectorImpl &runtimeResourcePath) { ++ if (mainExecutablePath.startswith("@storeDir@")) { ++ auto libPath = StringRef("@lib@"); ++ runtimeResourcePath.append(libPath.begin(), libPath.end()); ++ } else { + runtimeResourcePath.append(mainExecutablePath.begin(), + mainExecutablePath.end()); + + llvm::sys::path::remove_filename(runtimeResourcePath); // Remove /swift + llvm::sys::path::remove_filename(runtimeResourcePath); // Remove /bin ++ } + appendSwiftLibDir(runtimeResourcePath, shared); + } + diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-wrap.patch b/pkgs/development/compilers/swift/compiler/patches/swift-wrap.patch new file mode 100644 index 0000000000000..e4697f631e708 --- /dev/null +++ b/pkgs/development/compilers/swift/compiler/patches/swift-wrap.patch @@ -0,0 +1,46 @@ +Wrap the swift compiler produced during the build + +--- a/tools/driver/CMakeLists.txt ++++ b/tools/driver/CMakeLists.txt +@@ -16,6 +16,13 @@ if(${LIBSWIFT_BUILD_MODE} MATCHES "BOOTSTRAPPING.*") + swiftDriverTool + libswiftStub) + ++ # Nix: wrap the swift build. ++ add_custom_command( ++ TARGET swift-frontend-bootstrapping0 POST_BUILD ++ COMMAND nix-swift-make-swift-wrapper $ ++ VERBATIM ++ ) ++ + swift_create_post_build_symlink(swift-frontend-bootstrapping0 + SOURCE "swift-frontend${CMAKE_EXECUTABLE_SUFFIX}" + DESTINATION "swiftc${CMAKE_EXECUTABLE_SUFFIX}" +@@ -34,6 +41,13 @@ if(${LIBSWIFT_BUILD_MODE} MATCHES "BOOTSTRAPPING.*") + swiftDriverTool + libswift-bootstrapping1) + ++ # Nix: wrap the swift build. ++ add_custom_command( ++ TARGET swift-frontend-bootstrapping1 POST_BUILD ++ COMMAND nix-swift-make-swift-wrapper $ ++ VERBATIM ++ ) ++ + swift_create_post_build_symlink(swift-frontend-bootstrapping1 + SOURCE "swift-frontend${CMAKE_EXECUTABLE_SUFFIX}" + DESTINATION "swiftc${CMAKE_EXECUTABLE_SUFFIX}" +@@ -50,6 +64,13 @@ target_link_libraries(swift-frontend + swiftDriverTool + libswift) + ++# Nix: wrap the swift build. ++add_custom_command( ++ TARGET swift-frontend POST_BUILD ++ COMMAND nix-swift-make-swift-wrapper $ ++ VERBATIM ++) ++ + # Create a `swift-driver` executable adjacent to the `swift-frontend` executable + # to ensure that `swiftc` forwards to the standalone driver when invoked. + swift_create_early_driver_copies(swift-frontend) diff --git a/pkgs/development/compilers/swift/default.nix b/pkgs/development/compilers/swift/default.nix index 0ea6e7b075969..a51fa2805b765 100644 --- a/pkgs/development/compilers/swift/default.nix +++ b/pkgs/development/compilers/swift/default.nix @@ -1,475 +1,101 @@ -{ lib, stdenv -, cmake -, coreutils -, glibc -, gccForLibs -, which -, perl -, libedit -, ninja -, pkg-config -, sqlite -, libxml2 -, clang_13 -, python3 -, ncurses -, libuuid -, libxcrypt -, icu -, libgcc -, libblocksruntime -, curl -, rsync -, git -, libgit2 -, fetchFromGitHub -, makeWrapper -, gnumake -, file +{ lib +, pkgs +, newScope +, darwin +, llvmPackages_latest +, overrideCC }: let - # The Swift toolchain script builds projects with separate repos. By convention, some of them share - # the same version with the main Swift compiler project per release. We fetch these with - # `fetchSwiftRelease`. The rest have their own versions locked to each Swift release, as defined in the - # Swift compiler repo: - # utils/update_checkout/update_checkout-config.json. - # - # ... among projects listed in that file, we provide our own: - # - CMake - # - ninja - # - icu - # - # ... we'd like to include the following in the future: - # - stress-tester - # - integration-tests + self = rec { - versions = { - swift = "5.6.2"; - yams = "4.0.2"; - argumentParser = "1.0.3"; - format = "release/5.6"; - crypto = "1.1.5"; - nio = "2.31.2"; - nio-ssl = "2.15.0"; - }; + callPackage = newScope self; - fetchAppleRepo = { repo, rev, sha256 }: - fetchFromGitHub { - owner = "apple"; - inherit repo rev sha256; - name = "${repo}-${rev}-src"; - }; + # Current versions of Swift on Darwin require macOS SDK 10.15 at least. + # Re-export this so we can rely on the minimum Swift SDK elsewhere. + apple_sdk = pkgs.darwin.apple_sdk_11_0; - fetchSwiftRelease = { repo, sha256, fetchSubmodules ? false }: - fetchFromGitHub { - owner = "apple"; - inherit repo sha256 fetchSubmodules; - rev = "swift-${versions.swift}-RELEASE"; - name = "${repo}-${versions.swift}-src"; - }; + # Our current Clang on Darwin is v11, but we need at least v12. The + # following applies the newer Clang with the same libc overrides as + # `apple_sdk.stdenv`. + # + # If 'latest' becomes an issue, recommend replacing it with v14, which is + # currently closest to the official Swift builds. + clang = if pkgs.stdenv.isDarwin + then + llvmPackages_latest.clang.override rec { + libc = apple_sdk.Libsystem; + bintools = pkgs.bintools.override { inherit libc; }; + } + else + llvmPackages_latest.clang; - sources = { - # Projects that share `versions.swift` for each release. - - swift = fetchSwiftRelease { - repo = "swift"; - sha256 = "sha256-wiRXAXWEksJuy+YQQ+B7tzr2iLkSVkgV6o+wIz7yKJA="; - }; - cmark = fetchSwiftRelease { - repo = "swift-cmark"; - sha256 = "sha256-f0BoTs4HYdx/aJ9HIGCWMalhl8PvClWD6R4QK3qSgAw="; - }; - llbuild = fetchSwiftRelease { - repo = "swift-llbuild"; - sha256 = "sha256-SQ6V0zVshIYMjayx+ZpYuLijgQ89tqRnPlXBPf2FYqM="; - }; - driver = fetchSwiftRelease { - repo = "swift-driver"; - sha256 = "sha256-D5/C4Rbv5KIsKpy6YbuMxGIGaQkn80PD4Cp0l6bPKzY="; - }; - toolsSupportCore = fetchSwiftRelease { - repo = "swift-tools-support-core"; - sha256 = "sha256-FbtQCq1sSlzrskCrgzD4iYuo5eGaXrAUUxoNX/BiOfg="; - }; - swiftpm = fetchSwiftRelease { - repo = "swift-package-manager"; - sha256 = "sha256-esO4Swz3UYngbVgxoV+fkhSC0AU3IaxVjWkgK/s3x68="; - }; - syntax = fetchSwiftRelease { - repo = "swift-syntax"; - sha256 = "sha256-C9FPCtq49BvKXtTWWeReYWNrU70pHzT2DhAv3NiTbPU="; - }; - corelibsXctest = fetchSwiftRelease { - repo = "swift-corelibs-xctest"; - sha256 = "sha256-0hizfnKJaUUA+jXuXzXWk72FmlSyc+UGEf7BTLdJrx4="; - }; - corelibsFoundation = fetchSwiftRelease { - repo = "swift-corelibs-foundation"; - sha256 = "sha256-8sCL8Ia6yb6bRsJZ52gUJH0jN3lwClM573G8jgUdEhw="; - }; - corelibsLibdispatch = fetchSwiftRelease { - repo = "swift-corelibs-libdispatch"; - sha256 = "sha256-1tIskUMnfblnvZaFDQPUMBfWTmBYG98s7rEww7PwZO8="; - fetchSubmodules = true; - }; - indexstoreDb = fetchSwiftRelease { - repo = "indexstore-db"; - sha256 = "sha256-/PO4eMiASZN3pjFjBQ1r8vYwGRn6xm3SWaB2HDZlkPs="; - }; - sourcekitLsp = fetchSwiftRelease { - repo = "sourcekit-lsp"; - sha256 = "sha256-ttgUC4ZHD3P/xLHllEbACtHVrJ6HXqeVWccXcoPMkts="; - }; - llvmProject = fetchSwiftRelease { - repo = "llvm-project"; - sha256 = "sha256-YVs3lKV2RlaovpYkdGO+vzypolrmXmbKBBP4+osNMYw="; - }; - docc = fetchSwiftRelease { - repo = "swift-docc"; - sha256 = "sha256-rWiaNamZoHTO1bKpubxuT7m1IBOl7amT5M71mNauilY="; - }; - docc-render-artifact = fetchSwiftRelease { - repo = "swift-docc-render-artifact"; - sha256 = "sha256-AX+rtDLhq8drk7N6/hoH3fQioudmmTCnEhR45bME8uU="; - }; - docc-symbolkit = fetchSwiftRelease { - repo = "swift-docc-symbolkit"; - sha256 = "sha256-Xy1TQ5ucDW+MnkeOvVznsATBmwcQ3p1x+ofQ22ofk+o="; - }; - lmdb = fetchSwiftRelease { - repo = "swift-lmdb"; - sha256 = "sha256-i2GkWRWq1W5j8rF4PiHwWgT4Dur5FCY2o44HvUU3vtQ="; - }; - markdown = fetchSwiftRelease { - repo = "swift-markdown"; - sha256 = "sha256-XtFSBiNHhmULjS4OqSpMgUetLu3peRg7l6HpjwVsTj8="; + # Overrides that create a useful environment for swift packages, allowing + # packaging with `swiftPackages.callPackage`. These are similar to + # `apple_sdk_11_0.callPackage`, with our clang on top. + inherit (clang) bintools; + stdenv = overrideCC pkgs.stdenv clang; + darwin = pkgs.darwin.overrideScope (_: prev: { + inherit apple_sdk; + inherit (apple_sdk) Libsystem LibsystemCross libcharset libunwind objc4 configd IOKit Security; + CF = apple_sdk.CoreFoundation; + }); + xcodebuild = pkgs.xcbuild.override { + inherit (apple_sdk.frameworks) CoreServices CoreGraphics ImageIO; + inherit stdenv; + sdkVer = "10.15"; }; + xcbuild = xcodebuild; - cmark-gfm = fetchAppleRepo { - repo = "swift-cmark"; - rev = "swift-${versions.swift}-RELEASE-gfm"; - sha256 = "sha256-g28iKmMR2W0r1urf8Fk1HBxAp5OlonNYSVN3Ril66tQ="; + swift-unwrapped = callPackage ./compiler { + inherit (darwin) DarwinTools cctools sigtool; + inherit (apple_sdk) CLTools_Executables; + inherit (apple_sdk.frameworks) CoreServices Foundation Combine; }; - # Projects that have their own versions during each release - - argumentParser = fetchAppleRepo { - repo = "swift-argument-parser"; - rev = "${versions.argumentParser}"; - sha256 = "sha256-vNqkuAwSZNCWvwe6E5BqbXQdIbmIia0dENmmSQ9P8Mo="; - }; - format = fetchAppleRepo { - repo = "swift-format"; - rev = "${versions.format}"; - sha256 = "sha256-1f5sIrv9IbPB7Vnahq1VwH8gT41dcjWldRwvVEaMdto="; - }; - crypto = fetchAppleRepo { - repo = "swift-crypto"; - rev = "${versions.crypto}"; - sha256 = "sha256-jwxXQuOF+CnpLMwTZ2z52Fgx2b97yWzXiPTx0Ye8KCQ="; + swiftNoSwiftDriver = callPackage ./wrapper { + swift = swift-unwrapped; + useSwiftDriver = false; }; - nio = fetchAppleRepo { - repo = "swift-nio"; - rev = versions.nio; - sha256 = "sha256-FscOA/S7on31QCR/MZFjg4ZB3FGJ+rdptZ6MRZJXexE="; - }; - nio-ssl = fetchAppleRepo { - repo = "swift-nio-ssl"; - rev = versions.nio-ssl; - sha256 = "sha256-5QGkmkCOXhG3uOdf0bd3Fo1MFekB8/WcveBXGhtVZKo="; - }; - yams = fetchFromGitHub { - owner = "jpsim"; - repo = "Yams"; - rev = versions.yams; - sha256 = "sha256-cTkCAwxxLc35laOon1ZXXV8eAxX02oDolJyPauhZado="; - name = "Yams-${versions.yams}-src"; - }; - }; - - devInputs = [ - curl - glibc - icu - libblocksruntime - libedit - libgcc - libuuid - libxcrypt - libxml2 - ncurses - sqlite - ]; - - python = (python3.withPackages (ps: [ps.six])); - - cmakeFlags = [ - "-DGLIBC_INCLUDE_PATH=${stdenv.cc.libc.dev}/include" - "-DC_INCLUDE_DIRS=${lib.makeSearchPathOutput "dev" "include" devInputs}:${libxml2.dev}/include/libxml2" - "-DGCC_INSTALL_PREFIX=${gccForLibs}" - ]; - -in -stdenv.mkDerivation { - pname = "swift"; - version = versions.swift; - - nativeBuildInputs = [ - cmake - git - makeWrapper - ninja - perl - pkg-config - python - rsync - which - ]; - buildInputs = devInputs ++ [ - clang_13 - ]; - - # TODO: Revisit what needs to be propagated and how. - propagatedBuildInputs = [ - libgcc - libgit2 - python - ]; - propagatedUserEnvPkgs = [ git pkg-config ]; - - hardeningDisable = [ "format" ]; # for LLDB - - unpackPhase = '' - mkdir src - cd src - export SWIFT_SOURCE_ROOT=$PWD - - cp -r ${sources.swift} swift - cp -r ${sources.cmark} cmark - cp -r ${sources.llbuild} llbuild - cp -r ${sources.argumentParser} swift-argument-parser - cp -r ${sources.driver} swift-driver - cp -r ${sources.toolsSupportCore} swift-tools-support-core - cp -r ${sources.swiftpm} swiftpm - cp -r ${sources.syntax} swift-syntax - cp -r ${sources.corelibsXctest} swift-corelibs-xctest - cp -r ${sources.corelibsFoundation} swift-corelibs-foundation - cp -r ${sources.corelibsLibdispatch} swift-corelibs-libdispatch - cp -r ${sources.yams} yams - cp -r ${sources.indexstoreDb} indexstore-db - cp -r ${sources.sourcekitLsp} sourcekit-lsp - cp -r ${sources.format} swift-format - cp -r ${sources.crypto} swift-crypto - cp -r ${sources.llvmProject} llvm-project - cp -r ${sources.cmark-gfm} swift-cmark-gfm - cp -r ${sources.docc} swift-docc - cp -r ${sources.docc-render-artifact} swift-docc-render-artifact - cp -r ${sources.docc-symbolkit} swift-docc-symbolkit - cp -r ${sources.lmdb} swift-lmdb - cp -r ${sources.markdown} swift-markdown - cp -r ${sources.nio} swift-nio - cp -r ${sources.nio-ssl} swift-nio-ssl - chmod -R u+w . - ''; + Dispatch = if stdenv.isDarwin + then null # part of libsystem + else callPackage ./libdispatch { swift = swiftNoSwiftDriver; }; - patchPhase = '' - # Just patch all the things for now, we can focus this later. - patchShebangs $SWIFT_SOURCE_ROOT + Foundation = if stdenv.isDarwin + then apple_sdk.frameworks.Foundation + else callPackage ./foundation { swift = swiftNoSwiftDriver; }; - # TODO: eliminate use of env. - find -type f -print0 | xargs -0 sed -i \ - -e 's|/usr/bin/env|${coreutils}/bin/env|g' \ - -e 's|/usr/bin/make|${gnumake}/bin/make|g' \ - -e 's|/bin/mkdir|${coreutils}/bin/mkdir|g' \ - -e 's|/bin/cp|${coreutils}/bin/cp|g' \ - -e 's|/usr/bin/file|${file}/bin/file|g' - - # Build configuration patches. - patch -p1 -d swift -i ${./patches/0001-build-presets-linux-don-t-require-using-Ninja.patch} - patch -p1 -d swift -i ${./patches/0002-build-presets-linux-allow-custom-install-prefix.patch} - patch -p1 -d swift -i ${./patches/0003-build-presets-linux-don-t-build-extra-libs.patch} - patch -p1 -d swift -i ${./patches/0004-build-presets-linux-plumb-extra-cmake-options.patch} - patch -p1 -d swift -i ${./patches/0007-build-presets-linux-os-stdlib.patch} - substituteInPlace swift/cmake/modules/SwiftConfigureSDK.cmake \ - --replace '/usr/include' "${stdenv.cc.libc.dev}/include" - sed -i swift/utils/build-presets.ini \ - -e 's/^test-installable-package$/# \0/' \ - -e 's/^test$/# \0/' \ - -e 's/^validation-test$/# \0/' \ - -e 's/^long-test$/# \0/' \ - -e 's/^stress-test$/# \0/' \ - -e 's/^test-optimized$/# \0/' \ - -e 's/^swift-install-components=autolink.*$/\0;editor-integration/' - - # LLVM toolchain patches. - patch -p1 -d llvm-project/clang -i ${./patches/0005-clang-toolchain-dir.patch} - patch -p1 -d llvm-project/clang -i ${./patches/0006-clang-purity.patch} - substituteInPlace llvm-project/clang/lib/Driver/ToolChains/Linux.cpp \ - --replace 'SysRoot + "/lib' '"${glibc}/lib" "' \ - --replace 'SysRoot + "/usr/lib' '"${glibc}/lib" "' \ - --replace 'LibDir = "lib";' 'LibDir = "${glibc}/lib";' \ - --replace 'LibDir = "lib64";' 'LibDir = "${glibc}/lib";' \ - --replace 'LibDir = X32 ? "libx32" : "lib64";' 'LibDir = "${glibc}/lib";' - - # Substitute ncurses for curses in llbuild. - sed -i 's/curses/ncurses/' llbuild/*/*/CMakeLists.txt - sed -i 's/curses/ncurses/' llbuild/*/*/*/CMakeLists.txt - - # uuid.h is not part of glibc, but of libuuid. - sed -i 's|''${GLIBC_INCLUDE_PATH}/uuid/uuid.h|${libuuid.dev}/include/uuid/uuid.h|' swift/stdlib/public/Platform/glibc.modulemap.gyb - - # Support library build script patches. - PREFIX=''${out/#\/} - substituteInPlace swift/utils/swift_build_support/swift_build_support/products/benchmarks.py \ - --replace \ - "'--toolchain', toolchain_path," \ - "'--toolchain', '/build/install/$PREFIX'," - substituteInPlace swift/benchmark/scripts/build_script_helper.py \ - --replace \ - "swiftbuild_path = os.path.join(args.toolchain, \"usr\", \"bin\", \"swift-build\")" \ - "swiftbuild_path = os.path.join(args.toolchain, \"bin\", \"swift-build\")" - substituteInPlace swift-corelibs-xctest/build_script.py \ - --replace usr "$PREFIX" - - # Can be removed in later swift-docc versions, see - # https://github.com/apple/swift-docc/commit/bff70b847008f91ac729cfd299a85481eef3f581 - substituteInPlace swift-docc/build-script-helper.py \ - --replace \ - "subprocess.check_output(cmd, env=env).strip(), 'docc')" \ - "subprocess.check_output(cmd, env=env).strip().decode(), 'docc')" - - # Can be removed in later Swift versions, see - # https://github.com/apple/swift/pull/58755 - substituteInPlace swift/utils/process-stats-dir.py \ - --replace \ - "type=argparse.FileType('wb', 0)," \ - "type=argparse.FileType('w', 0)," - - # Apply Python 3 fix, see - # https://github.com/apple/swift/commit/ec6bc595092974628b27b114a472e84162261bbd - substituteInPlace swift/utils/swift_build_support/swift_build_support/productpipeline_list_builder.py \ - --replace \ - "filter(lambda x: x is not None, pipeline)" \ - "[p for p in pipeline if p is not None]" - ''; - - configurePhase = '' - cd .. - - mkdir build install - export SWIFT_BUILD_ROOT=$PWD/build - export SWIFT_INSTALL_DIR=$PWD/install - - export INSTALLABLE_PACKAGE=$PWD/swift.tar.gz - export NIX_ENFORCE_PURITY= - - cd $SWIFT_BUILD_ROOT - ''; - - buildPhase = '' - # Explicitly include C++ headers to prevent errors where stdlib.h is not found from cstdlib. - export NIX_CFLAGS_COMPILE="$(< ${clang_13}/nix-support/libcxx-cxxflags) $NIX_CFLAGS_COMPILE" - - # During the Swift build, a full local LLVM build is performed and the resulting clang is - # invoked. This compiler is not using the Nix wrappers, so it needs some help to find things. - export NIX_LDFLAGS_BEFORE="-rpath ${gccForLibs.lib}/lib -L${gccForLibs.lib}/lib $NIX_LDFLAGS_BEFORE" - - # However, we want to use the wrapped compiler whenever possible. - export CC="${clang_13}/bin/clang" - - $SWIFT_SOURCE_ROOT/swift/utils/build-script \ - --preset=buildbot_linux \ - installable_package=$INSTALLABLE_PACKAGE \ - install_prefix=$out \ - install_destdir=$SWIFT_INSTALL_DIR \ - extra_cmake_options="${lib.concatStringsSep "," cmakeFlags}" - ''; - - doCheck = true; - - checkInputs = [ file ]; - - checkPhase = '' - # Remove compiler build system tests which fail due to our modified default build profile and - # nixpkgs-provided version of CMake. - rm $SWIFT_SOURCE_ROOT/swift/validation-test/BuildSystem/infer_implies_install_all.test - rm $SWIFT_SOURCE_ROOT/swift/validation-test/BuildSystem/infer_dumps_deps_if_verbose_build.test - - # This test apparently requires Python 2 (strings are assumed to be bytes-like), but the build - # process overall now otherwise requires Python 3 (which is what we have updated to). A fix PR - # has been submitted upstream. - rm $SWIFT_SOURCE_ROOT/swift/validation-test/SIL/verify_all_overlays.py - - # TODO: consider fixing and re-adding. This test fails due to a non-standard "install_prefix". - rm $SWIFT_SOURCE_ROOT/swift/validation-test/Python/build_swift.swift - - # We cannot handle the SDK location being in "Weird Location" due to Nix isolation. - rm $SWIFT_SOURCE_ROOT/swift/test/DebugInfo/compiler-flags.swift - - # TODO: Fix issue with ld.gold invoked from script finding crtbeginS.o and crtendS.o. - rm $SWIFT_SOURCE_ROOT/swift/test/IRGen/ELF-remove-autolink-section.swift - - # The following two tests fail because we use don't use the bundled libicu: - # [SOURCE_DIR/utils/build-script] ERROR: can't find source directory for libicu (tried /build/src/icu) - rm $SWIFT_SOURCE_ROOT/swift/validation-test/BuildSystem/default_build_still_performs_epilogue_opts_after_split.test - rm $SWIFT_SOURCE_ROOT/swift/validation-test/BuildSystem/test_early_swift_driver_and_infer.swift - - # TODO: This test fails for some unknown reason - rm $SWIFT_SOURCE_ROOT/swift/test/Serialization/restrict-swiftmodule-to-revision.swift - - # This test was flaky in ofborg, see #186476 - rm $SWIFT_SOURCE_ROOT/swift/test/AutoDiff/compiler_crashers_fixed/sr14290-missing-debug-scopes-in-pullback-trampoline.swift - - # TODO: consider using stress-tester and integration-test. - - # Match the wrapped version of Swift to be installed. - export LIBRARY_PATH=${lib.makeLibraryPath [icu libgcc libuuid]}:$l - - checkTarget=check-swift-all-${stdenv.hostPlatform.parsed.kernel.name}-${stdenv.hostPlatform.parsed.cpu.name} - ninjaFlags='-C buildbot_linux/swift-${stdenv.hostPlatform.parsed.kernel.name}-${stdenv.hostPlatform.parsed.cpu.name}' - ninjaCheckPhase - ''; - - installPhase = '' - mkdir -p $out + # TODO: Apple distributes a binary XCTest with Xcode, but it is not part of + # CLTools (or SUS), so would have to figure out how to fetch it. The binary + # version has several extra features, like a test runner and ObjC support. + XCTest = callPackage ./xctest { + inherit (darwin) DarwinTools; + swift = swiftNoSwiftDriver; + }; - # Extract the generated tarball into the store. - tar xf $INSTALLABLE_PACKAGE -C $out --strip-components=3 ''${out/#\/} - find $out -type d -empty -delete + swiftpm = callPackage ./swiftpm { + inherit (darwin) DarwinTools cctools; + inherit (apple_sdk.frameworks) CryptoKit LocalAuthentication; + swift = swiftNoSwiftDriver; + }; - # Fix installation weirdness, also present in Appleā€™s official tarballs. - mv $out/local/include/indexstore $out/include - rmdir $out/local/include $out/local - rm -r $out/bin/sdk-module-lists $out/bin/swift-api-checker.py + swift-driver = callPackage ./swift-driver { + swift = swiftNoSwiftDriver; + }; - wrapProgram $out/bin/swift \ - --set CC $out/bin/clang \ - --suffix C_INCLUDE_PATH : $out/lib/swift/clang/include \ - --suffix CPLUS_INCLUDE_PATH : $out/lib/swift/clang/include \ - --suffix LIBRARY_PATH : ${lib.makeLibraryPath [icu libgcc libuuid]} \ - --suffix PATH : ${lib.makeBinPath [ stdenv.cc.bintools ]} + swift = callPackage ./wrapper { + swift = swift-unwrapped; + }; - wrapProgram $out/bin/swiftc \ - --set CC $out/bin/clang \ - --suffix C_INCLUDE_PATH : $out/lib/swift/clang/include \ - --suffix CPLUS_INCLUDE_PATH : $out/lib/swift/clang/include \ - --suffix LIBRARY_PATH : ${lib.makeLibraryPath [icu libgcc libuuid]} \ - --suffix PATH : ${lib.makeBinPath [ stdenv.cc.bintools ]} - ''; + sourcekit-lsp = callPackage ./sourcekit-lsp { + inherit (apple_sdk.frameworks) CryptoKit LocalAuthentication; + }; - # Hack to avoid build and install directories in RPATHs. - preFixup = "rm -rf $SWIFT_BUILD_ROOT $SWIFT_INSTALL_DIR"; + swift-docc = callPackage ./swift-docc { + inherit (apple_sdk.frameworks) CryptoKit LocalAuthentication; + }; - meta = with lib; { - description = "The Swift Programming Language"; - homepage = "https://github.com/apple/swift"; - maintainers = with maintainers; [ dtzWill trepetti dduan trundle ]; - license = licenses.asl20; - # Swift doesn't support 32-bit Linux, unknown on other platforms. - platforms = platforms.linux; - badPlatforms = platforms.i686; - timeout = 86400; # 24 hours. }; -} + +in self diff --git a/pkgs/development/compilers/swift/foundation/default.nix b/pkgs/development/compilers/swift/foundation/default.nix new file mode 100644 index 0000000000000..efb35bd74c9fe --- /dev/null +++ b/pkgs/development/compilers/swift/foundation/default.nix @@ -0,0 +1,61 @@ +# TODO: We already package the CoreFoundation component of Foundation in: +# pkgs/os-specific/darwin/swift-corelibs/corefoundation.nix +# This is separate because the CF build is completely different and part of +# stdenv. Merging the two was kept outside of the scope of Swift work. + +{ lib +, stdenv +, callPackage +, cmake +, ninja +, swift +, Dispatch +, icu +, libxml2 +, curl +}: + +let + sources = callPackage ../sources.nix { }; +in stdenv.mkDerivation { + pname = "swift-corelibs-foundation"; + + inherit (sources) version; + src = sources.swift-corelibs-foundation; + + outputs = [ "out" "dev" ]; + + nativeBuildInputs = [ cmake ninja swift ]; + buildInputs = [ icu libxml2 curl ]; + propagatedBuildInputs = [ Dispatch ]; + + preConfigure = '' + # Fails to build with -D_FORTIFY_SOURCE. + NIX_HARDENING_ENABLE=''${NIX_HARDENING_ENABLE/fortify/} + ''; + + postInstall = '' + # Split up the output. + mkdir $dev + mv $out/lib/swift/${swift.swiftOs} $out/swiftlibs + mv $out/lib/swift $dev/include + mkdir $out/lib/swift + mv $out/swiftlibs $out/lib/swift/${swift.swiftOs} + + # Provide a CMake module. This is primarily used to glue together parts of + # the Swift toolchain. Modifying the CMake config to do this for us is + # otherwise more trouble. + mkdir -p $dev/lib/cmake/Foundation + export dylibExt="${stdenv.hostPlatform.extensions.sharedLibrary}" + export swiftOs="${swift.swiftOs}" + substituteAll ${./glue.cmake} $dev/lib/cmake/Foundation/FoundationConfig.cmake + ''; + + meta = { + description = "Core utilities, internationalization, and OS independence for Swift"; + homepage = "https://github.com/apple/swift-corelibs-foundation"; + platforms = lib.platforms.linux; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/compilers/swift/foundation/glue.cmake b/pkgs/development/compilers/swift/foundation/glue.cmake new file mode 100644 index 0000000000000..a34984d19f047 --- /dev/null +++ b/pkgs/development/compilers/swift/foundation/glue.cmake @@ -0,0 +1,8 @@ +add_library(Foundation SHARED IMPORTED) +set_property(TARGET Foundation PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libFoundation@dylibExt@") + +add_library(FoundationNetworking SHARED IMPORTED) +set_property(TARGET FoundationNetworking PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libFoundationNetworking@dylibExt@") + +add_library(FoundationXML SHARED IMPORTED) +set_property(TARGET FoundationXML PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libFoundationXML@dylibExt@") diff --git a/pkgs/development/compilers/swift/libdispatch/default.nix b/pkgs/development/compilers/swift/libdispatch/default.nix new file mode 100644 index 0000000000000..4a0616ded5ac5 --- /dev/null +++ b/pkgs/development/compilers/swift/libdispatch/default.nix @@ -0,0 +1,42 @@ +{ lib +, stdenv +, callPackage +, cmake +, ninja +, useSwift ? true, swift +}: + +let + sources = callPackage ../sources.nix { }; +in stdenv.mkDerivation { + pname = "swift-corelibs-libdispatch"; + + inherit (sources) version; + src = sources.swift-corelibs-libdispatch; + + outputs = [ "out" "dev" "man" ]; + + nativeBuildInputs = [ cmake ] + ++ lib.optionals useSwift [ ninja swift ]; + + patches = [ ./disable-swift-overlay.patch ]; + + cmakeFlags = lib.optional useSwift "-DENABLE_SWIFT=ON"; + + postInstall = '' + # Provide a CMake module. This is primarily used to glue together parts of + # the Swift toolchain. Modifying the CMake config to do this for us is + # otherwise more trouble. + mkdir -p $dev/lib/cmake/dispatch + export dylibExt="${stdenv.hostPlatform.extensions.sharedLibrary}" + substituteAll ${./glue.cmake} $dev/lib/cmake/dispatch/dispatchConfig.cmake + ''; + + meta = { + description = "Grand Central Dispatch"; + homepage = "https://github.com/apple/swift-corelibs-libdispatch"; + platforms = lib.platforms.linux; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ cmm dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/compilers/swift/libdispatch/disable-swift-overlay.patch b/pkgs/development/compilers/swift/libdispatch/disable-swift-overlay.patch new file mode 100644 index 0000000000000..0ea1869d5528d --- /dev/null +++ b/pkgs/development/compilers/swift/libdispatch/disable-swift-overlay.patch @@ -0,0 +1,35 @@ +Enabling Swift support is normally intended for building an overlay for a +Swift SDK, which changes the installation layout. Prevent this. + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -287,7 +287,7 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/config.h.in" + add_compile_definitions($<$,$>:HAVE_CONFIG_H>) + + +-if(ENABLE_SWIFT) ++if(0) + set(INSTALL_TARGET_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>/$" CACHE PATH "Path where the libraries will be installed") + set(INSTALL_DISPATCH_HEADERS_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>/dispatch" CACHE PATH "Path where the headers will be installed for libdispatch") + set(INSTALL_BLOCK_HEADERS_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>/Block" CACHE PATH "Path where the headers will be installed for the blocks runtime") +--- a/man/CMakeLists.txt ++++ b/man/CMakeLists.txt +@@ -1,6 +1,6 @@ + + # TODO(compnerd) add symlinks +-if(NOT ENABLE_SWIFT) ++if(1) + install(FILES + dispatch.3 + dispatch_after.3 +--- a/src/swift/CMakeLists.txt ++++ b/src/swift/CMakeLists.txt +@@ -47,7 +47,7 @@ get_swift_host_arch(swift_arch) + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule + ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftdoc +- DESTINATION ${INSTALL_TARGET_DIR}/${swift_arch}) ++ DESTINATION ${INSTALL_TARGET_DIR}/swift) + set_property(GLOBAL APPEND PROPERTY DISPATCH_EXPORTS swiftDispatch) + install(TARGETS swiftDispatch + EXPORT dispatchExports diff --git a/pkgs/development/compilers/swift/libdispatch/glue.cmake b/pkgs/development/compilers/swift/libdispatch/glue.cmake new file mode 100644 index 0000000000000..dd696dc61085f --- /dev/null +++ b/pkgs/development/compilers/swift/libdispatch/glue.cmake @@ -0,0 +1,5 @@ +add_library(dispatch SHARED IMPORTED) +set_property(TARGET dispatch PROPERTY IMPORTED_LOCATION "@out@/lib/libdispatch@dylibExt@") + +add_library(swiftDispatch SHARED IMPORTED) +set_property(TARGET swiftDispatch PROPERTY IMPORTED_LOCATION "@out@/lib/libswiftDispatch@dylibExt@") diff --git a/pkgs/development/compilers/swift/patches/0001-build-presets-linux-don-t-require-using-Ninja.patch b/pkgs/development/compilers/swift/patches/0001-build-presets-linux-don-t-require-using-Ninja.patch deleted file mode 100644 index 6c42921cd2338..0000000000000 --- a/pkgs/development/compilers/swift/patches/0001-build-presets-linux-don-t-require-using-Ninja.patch +++ /dev/null @@ -1,13 +0,0 @@ -Don't build Ninja, we use our own. - ---- a/utils/build-presets.ini -+++ b/utils/build-presets.ini -@@ -779,7 +779,7 @@ swiftpm - - dash-dash - --build-ninja -+# build-ninja - install-llvm - install-swift - install-lldb diff --git a/pkgs/development/compilers/swift/patches/0002-build-presets-linux-allow-custom-install-prefix.patch b/pkgs/development/compilers/swift/patches/0002-build-presets-linux-allow-custom-install-prefix.patch deleted file mode 100644 index 0b4c2cc55c4fe..0000000000000 --- a/pkgs/development/compilers/swift/patches/0002-build-presets-linux-allow-custom-install-prefix.patch +++ /dev/null @@ -1,13 +0,0 @@ -Use custom install prefix. - ---- a/utils/build-presets.ini -+++ b/utils/build-presets.ini -@@ -788,7 +788,7 @@ - install-swiftpm - install-xctest - install-libicu --install-prefix=/usr -+install-prefix=%(install_prefix)s - install-libcxx - install-sourcekit-lsp - build-swift-static-stdlib diff --git a/pkgs/development/compilers/swift/patches/0003-build-presets-linux-don-t-build-extra-libs.patch b/pkgs/development/compilers/swift/patches/0003-build-presets-linux-don-t-build-extra-libs.patch deleted file mode 100644 index eb522ac96f7e9..0000000000000 --- a/pkgs/development/compilers/swift/patches/0003-build-presets-linux-don-t-build-extra-libs.patch +++ /dev/null @@ -1,23 +0,0 @@ -Disable targets, where we use Nix packages. - ---- a/utils/build-presets.ini -+++ b/utils/build-presets.ini -@@ -818,8 +818,6 @@ - swiftpm - swift-driver - xctest --libicu --libcxx - swiftdocc - - # build-ninja -@@ -830,9 +828,7 @@ - install-swiftpm - install-swift-driver - install-xctest --install-libicu - install-prefix=%(install_prefix)s --install-libcxx - install-sourcekit-lsp - install-swiftdocc - build-swift-static-stdlib diff --git a/pkgs/development/compilers/swift/patches/0004-build-presets-linux-plumb-extra-cmake-options.patch b/pkgs/development/compilers/swift/patches/0004-build-presets-linux-plumb-extra-cmake-options.patch deleted file mode 100644 index 3cacdfc0c55e7..0000000000000 --- a/pkgs/development/compilers/swift/patches/0004-build-presets-linux-plumb-extra-cmake-options.patch +++ /dev/null @@ -1,13 +0,0 @@ -Plumb extra-cmake-options. - ---- a/utils/build-presets.ini -+++ b/utils/build-presets.ini -@@ -812,6 +812,8 @@ - # Path to the .tar.gz package we would create. - installable-package=%(installable_package)s - -+extra-cmake-options=%(extra_cmake_options)s -+ - [preset: buildbot_linux] - mixin-preset=mixin_linux_installation - build-subdir=buildbot_linux diff --git a/pkgs/development/compilers/swift/patches/0006-clang-purity.patch b/pkgs/development/compilers/swift/patches/0006-clang-purity.patch deleted file mode 100644 index 928c1db6dee87..0000000000000 --- a/pkgs/development/compilers/swift/patches/0006-clang-purity.patch +++ /dev/null @@ -1,16 +0,0 @@ -Apply the "purity" patch (updated for 5.4.2). - ---- a/lib/Driver/ToolChains/Gnu.cpp -+++ b/lib/Driver/ToolChains/Gnu.cpp -@@ -488,11 +488,5 @@ - if (Args.hasArg(options::OPT_rdynamic)) - CmdArgs.push_back("-export-dynamic"); -- -- if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) { -- CmdArgs.push_back("-dynamic-linker"); -- CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) + -- ToolChain.getDynamicLinker(Args))); -- } - } - - CmdArgs.push_back("-o"); diff --git a/pkgs/development/compilers/swift/patches/0007-build-presets-linux-os-stdlib.patch b/pkgs/development/compilers/swift/patches/0007-build-presets-linux-os-stdlib.patch deleted file mode 100644 index 46da01635540e..0000000000000 --- a/pkgs/development/compilers/swift/patches/0007-build-presets-linux-os-stdlib.patch +++ /dev/null @@ -1,13 +0,0 @@ -Use os-stdlib in tests. - ---- a/utils/build-presets.ini -+++ b/utils/build-presets.ini -@@ -872,7 +872,7 @@ - indexstore-db - sourcekit-lsp - swiftdocc --lit-args=-v --time-tests -+lit-args=-v --time-tests --param use_os_stdlib - - # rdar://problem/31454823 - lldb-test-swift-only diff --git a/pkgs/development/compilers/swift/sourcekit-lsp/default.nix b/pkgs/development/compilers/swift/sourcekit-lsp/default.nix new file mode 100644 index 0000000000000..deb82de20add2 --- /dev/null +++ b/pkgs/development/compilers/swift/sourcekit-lsp/default.nix @@ -0,0 +1,72 @@ +{ lib +, stdenv +, callPackage +, swift +, swiftpm +, swiftpm2nix +, Foundation +, XCTest +, sqlite +, ncurses +, CryptoKit +, LocalAuthentication +}: +let + sources = callPackage ../sources.nix { }; + generated = swiftpm2nix.helpers ./generated; + + # On Darwin, we only want ncurses in the linker search path, because headers + # are part of libsystem. Adding its headers to the search path causes strange + # mixing and errors. + # TODO: Find a better way to prevent this conflict. + ncursesInput = if stdenv.isDarwin then ncurses.out else ncurses; +in +stdenv.mkDerivation { + pname = "sourcekit-lsp"; + + inherit (sources) version; + src = sources.sourcekit-lsp; + + nativeBuildInputs = [ swift swiftpm ]; + buildInputs = [ + Foundation + XCTest + sqlite + ncursesInput + ] + ++ lib.optionals stdenv.isDarwin [ CryptoKit LocalAuthentication ]; + + configurePhase = generated.configure + '' + swiftpmMakeMutable indexstore-db + patch -p1 -d .build/checkouts/indexstore-db -i ${./patches/indexstore-db-macos-target.patch} + + # This toggles a section specific to Xcode XCTest, which doesn't work on + # Darwin, where we also use swift-corelibs-xctest. + substituteInPlace Sources/LSPTestSupport/PerfTestCase.swift \ + --replace '#if os(macOS)' '#if false' + + # Required to link with swift-corelibs-xctest on Darwin. + export SWIFTTSC_MACOS_DEPLOYMENT_TARGET=10.12 + ''; + + # TODO: BuildServerBuildSystemTests fails + #doCheck = true; + + installPhase = '' + binPath="$(swiftpmBinPath)" + mkdir -p $out/bin + cp $binPath/sourcekit-lsp $out/bin/ + ''; + + # Canary to verify output of our Swift toolchain does not depend on the Swift + # compiler itself. (Only its 'lib' output.) + disallowedRequisites = [ swift.swift ]; + + meta = { + description = "Language Server Protocol implementation for Swift and C-based languages"; + homepage = "https://github.com/apple/sourcekit-lsp"; + platforms = with lib.platforms; linux ++ darwin; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/compilers/swift/sourcekit-lsp/generated/default.nix b/pkgs/development/compilers/swift/sourcekit-lsp/generated/default.nix new file mode 100644 index 0000000000000..2c822a2ead372 --- /dev/null +++ b/pkgs/development/compilers/swift/sourcekit-lsp/generated/default.nix @@ -0,0 +1,16 @@ +# This file was generated by swiftpm2nix. +{ + workspaceStateFile = ./workspace-state.json; + hashes = { + "indexstore-db" = "005vvkrncgpryzrn0hzgsapflpyga0n7152b2b565wislpx90cwl"; + "swift-argument-parser" = "1jph9w7lk9nr20fsv2c8p4hisx3dda817fh7pybd0r0j1jwa9nmw"; + "swift-collections" = "0l0pv16zil3n7fac7mdf5qxklxr5rwiig5bixgca1ybq7arlnv7i"; + "swift-crypto" = "020b8q4ss2k7a65r5dgh59z40i6sn7ij1allxkh8c8a9d0jzn313"; + "swift-driver" = "0nblvs47kh2hl1l70rmrbablx4m5i27w8l3dfrv2h7zccqr8jl0a"; + "swift-llbuild" = "1bvqbj8ji72ilh3ah2mw411jwzbbjxjyasa6sg4b8da0kqia4021"; + "swift-package-manager" = "16qvk14f1l0hf5bphx6qk51nn9d36a2iw5v3sgkvmqi8h7l4kqg5"; + "swift-system" = "0402hkx2q2dv27gccnn8ma79ngvwiwzkhcv4zlcdldmy6cgi0px7"; + "swift-tools-support-core" = "1ryd5iyx5mfv8bhyq3bf08z7nv886chzzqnmwaj16r2cry9yml7c"; + "Yams" = "11abhcfkmqm3cmh7vp7rqzvxd1zj02j2866a2pp6v9m89456xb76"; + }; +} diff --git a/pkgs/development/compilers/swift/sourcekit-lsp/generated/workspace-state.json b/pkgs/development/compilers/swift/sourcekit-lsp/generated/workspace-state.json new file mode 100644 index 0000000000000..4e8625ed0d6a3 --- /dev/null +++ b/pkgs/development/compilers/swift/sourcekit-lsp/generated/workspace-state.json @@ -0,0 +1,178 @@ +{ + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "indexstore-db", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/indexstore-db.git", + "name": "IndexStoreDB" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "2ff1c0491248cd958a2ac05da9aa613eb27a8eeb" + }, + "name": "sourceControlCheckout" + }, + "subpath": "indexstore-db" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-argument-parser.git", + "name": "swift-argument-parser" + }, + "state": { + "checkoutState": { + "revision": "e394bf350e38cb100b6bc4172834770ede1b7232", + "version": "1.0.3" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-argument-parser" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-collections", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-collections.git", + "name": "swift-collections" + }, + "state": { + "checkoutState": { + "revision": "f504716c27d2e5d4144fa4794b12129301d17729", + "version": "1.0.3" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-collections" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-crypto", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-crypto.git", + "name": "swift-crypto" + }, + "state": { + "checkoutState": { + "revision": "ddb07e896a2a8af79512543b1c7eb9797f8898a5", + "version": "1.1.7" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-crypto" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-driver", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-driver.git", + "name": "swift-driver" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "6c71f58f89d65eb79f1f6b32a707ddc39cec5ad6" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-driver" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-llbuild", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-llbuild.git", + "name": "llbuild" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "d99c31577c60a247b065d29289a44fbdd141e2be" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-llbuild" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-package-manager", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-package-manager.git", + "name": "SwiftPM" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "f04ad469a6053d713c2fb854fbeb27ee3e6c9dee" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-package-manager" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-system", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-system.git", + "name": "swift-system" + }, + "state": { + "checkoutState": { + "revision": "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version": "1.1.1" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-system" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "main", + "revision": "0220fc394f2ae820eeacd754fb2c7ce211e9979e" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "01835dc202670b5bb90d07f3eae41867e9ed29f6", + "version": "5.0.1" + }, + "name": "sourceControlCheckout" + }, + "subpath": "Yams" + } + ] + }, + "version": 5 +} diff --git a/pkgs/development/compilers/swift/sourcekit-lsp/patches/indexstore-db-macos-target.patch b/pkgs/development/compilers/swift/sourcekit-lsp/patches/indexstore-db-macos-target.patch new file mode 100644 index 0000000000000..53e790874d5d2 --- /dev/null +++ b/pkgs/development/compilers/swift/sourcekit-lsp/patches/indexstore-db-macos-target.patch @@ -0,0 +1,12 @@ +Raise the deployment target of IndexStoreDB so it can link against our XCTest. + +--- a/Package.swift ++++ b/Package.swift +@@ -4,6 +4,7 @@ import PackageDescription + + let package = Package( + name: "IndexStoreDB", ++ platforms: [.macOS("10.12")], + products: [ + .library( + name: "IndexStoreDB", diff --git a/pkgs/development/compilers/swift/sources.nix b/pkgs/development/compilers/swift/sources.nix new file mode 100644 index 0000000000000..9c28c683406e7 --- /dev/null +++ b/pkgs/development/compilers/swift/sources.nix @@ -0,0 +1,33 @@ +{ lib, fetchFromGitHub }: + +let + + # These packages are all part of the Swift toolchain, and have a single + # upstream version that should match. We also list the hashes here so a basic + # version upgrade touches only this file. + version = "5.7"; + hashes = { + llvm-project = "sha256-uW6dEAFaDOlHXnq8lFYxrKNLRPEukauZJxX4UCpWpIY="; + sourcekit-lsp = "sha256-uA3a+kAqI+XFzkDFEJ8XuRTgfYqacEuTsOU289Im+0Y="; + swift = "sha256-n8WVQYinAyIj4wmQnDhvPsH+t8ydANkGbjFJ6blfHOY="; + swift-cmark = "sha256-f0BoTs4HYdx/aJ9HIGCWMalhl8PvClWD6R4QK3qSgAw="; + swift-corelibs-foundation = "sha256-6XUSC6759dcG24YapWicjRzUnmVVe0QPSsLEw4sQNjI="; + swift-corelibs-libdispatch = "sha256-1qbXiC1k9+T+L6liqXKg6EZXqem6KEEx8OctuL4Kb2o="; + swift-corelibs-xctest = "sha256-qLUO9/3tkJWorDMEHgHd8VC3ovLLq/UWXJWMtb6CMN0="; + swift-docc = "sha256-WlXJMAnrlVPCM+iCIhG0Gyho76BsC2yVBEpX3m/WiIQ="; + swift-docc-render-artifact = "sha256-ttdurN/K7OX+I4577jG3YGeRs+GLUTc7BiiEZGmFD+s="; + swift-driver = "sha256-sk7XWXYR1MGPEeVxA6eA/vxhN6Gq16iD1RHpVstL3zE="; + swift-experimental-string-processing = "sha256-Ar9fQWi8bYSvGErrS0SWrxIxwEwCjsYIZcWweZ8bV28="; + swift-package-manager = "sha256-MZah+/XfeK46YamxwuE3Kiv+u5bj7VmjEh6ztDF+0j4="; + }; + + # Create fetch derivations. + sources = lib.mapAttrs (repo: hash: fetchFromGitHub { + owner = "apple"; + inherit repo; + rev = "swift-${version}-RELEASE"; + name = "${repo}-${version}-src"; + hash = hashes.${repo}; + }) hashes; + +in sources // { inherit version; } diff --git a/pkgs/development/compilers/swift/swift-docc/default.nix b/pkgs/development/compilers/swift/swift-docc/default.nix new file mode 100644 index 0000000000000..f85512f840711 --- /dev/null +++ b/pkgs/development/compilers/swift/swift-docc/default.nix @@ -0,0 +1,53 @@ +{ lib +, stdenv +, callPackage +, swift +, swiftpm +, swiftpm2nix +, Foundation +, XCTest +, CryptoKit +, LocalAuthentication +}: +let + sources = callPackage ../sources.nix { }; + generated = swiftpm2nix.helpers ./generated; +in +stdenv.mkDerivation { + pname = "swift-docc"; + + inherit (sources) version; + src = sources.swift-docc; + # TODO: We could build this from `apple/swift-docc-render` source, but that + # repository is not tagged. + renderArtifact = sources.swift-docc-render-artifact; + + nativeBuildInputs = [ swift swiftpm ]; + buildInputs = [ Foundation XCTest ] + ++ lib.optionals stdenv.isDarwin [ CryptoKit LocalAuthentication ]; + + configurePhase = generated.configure; + + # TODO: Tests depend on indexstore-db being provided by an existing Swift + # toolchain. (ie. looks for `../lib/libIndexStore.so` relative to swiftc. + #doCheck = true; + + installPhase = '' + binPath="$(swiftpmBinPath)" + mkdir -p $out/bin $out/share/docc + cp $binPath/docc $out/bin/ + ln -s $renderArtifact/dist $out/share/docc/render + ''; + + # Canary to verify output of our Swift toolchain does not depend on the Swift + # compiler itself. (Only its 'lib' output.) + disallowedRequisites = [ swift.swift ]; + + meta = { + description = "Documentation compiler for Swift"; + homepage = "https://github.com/apple/swift-docc"; + platforms = with lib.platforms; linux ++ darwin; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/compilers/swift/swift-docc/generated/default.nix b/pkgs/development/compilers/swift/swift-docc/generated/default.nix new file mode 100644 index 0000000000000..bcd873a44f89d --- /dev/null +++ b/pkgs/development/compilers/swift/swift-docc/generated/default.nix @@ -0,0 +1,15 @@ +# This file was generated by swiftpm2nix. +{ + workspaceStateFile = ./workspace-state.json; + hashes = { + "swift-argument-parser" = "070gip241dgn3d0nxgwxva4vp6kbnf11g01q5yaq6kmflcmz58f2"; + "swift-cmark" = "0xfchdgls3070z16in8ks69y8fpiajmyk7lmp5h7ym7164isa6bb"; + "swift-crypto" = "0h054rq14jyg94aiymmp37vqz60a13dlczp5g09pln724j4ypv92"; + "swift-docc-plugin" = "11d6nhi139yzk1lxxrixsbgyj1bnvmh40wj30y725q83nqq49ljh"; + "swift-docc-symbolkit" = "14hb2wc09hisf2r2yny17z28z0m58cf4lnqaczad2x2hk4s1iayi"; + "swift-lmdb" = "1m5y6x2vs1wflcv2c57rx87gh12sy0hkwy5iy9inxmda2mcs8qcb"; + "swift-markdown" = "09270bfrwlp904cma29hsbhr1p25v8kwgvhcfi7lg2av7aaknd97"; + "swift-nio" = "04bvay94b34ynmlvgyl9a7f431l3cf8k2zr483spv8mvyh1hxiqn"; + "swift-nio-ssl" = "1ak4aldilmz0pnfgbwq1x4alr38nfyvx2pz7p2vi2plf82da80g5"; + }; +} diff --git a/pkgs/development/compilers/swift/swift-docc/generated/workspace-state.json b/pkgs/development/compilers/swift/swift-docc/generated/workspace-state.json new file mode 100644 index 0000000000000..ced9a6df956c0 --- /dev/null +++ b/pkgs/development/compilers/swift/swift-docc/generated/workspace-state.json @@ -0,0 +1,161 @@ +{ + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-argument-parser", + "name": "swift-argument-parser" + }, + "state": { + "checkoutState": { + "revision": "d2930e8fcf9c33162b9fcc1d522bc975e2d4179b", + "version": "1.0.1" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-argument-parser" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-cmark", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-cmark.git", + "name": "cmark-gfm" + }, + "state": { + "checkoutState": { + "branch": "release/5.7-gfm", + "revision": "792c1c3326327515ce9bf64c44196b7f4daab9a6" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-cmark" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-crypto", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-crypto.git", + "name": "swift-crypto" + }, + "state": { + "checkoutState": { + "revision": "9680b7251cd2be22caaed8f1468bd9e8915a62fb", + "version": "1.1.2" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-crypto" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-docc-plugin", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-docc-plugin", + "name": "SwiftDocCPlugin" + }, + "state": { + "checkoutState": { + "revision": "3303b164430d9a7055ba484c8ead67a52f7b74f6", + "version": "1.0.0" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-docc-plugin" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-docc-symbolkit", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-docc-symbolkit", + "name": "SymbolKit" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "8682202025906dce29a8b04f9263f40ba87b89d8" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-docc-symbolkit" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-lmdb", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-lmdb.git", + "name": "CLMDB" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "6ea45a7ebf6d8f72bd299dfcc3299e284bbb92ee" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-lmdb" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-markdown", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-markdown.git", + "name": "swift-markdown" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "d6cd065a7e4b6c3fad615dcd39890e095a2f63a2" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-markdown" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-nio", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-nio.git", + "name": "swift-nio" + }, + "state": { + "checkoutState": { + "revision": "1d425b0851ffa2695d488cce1d68df2539f42500", + "version": "2.31.2" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-nio" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-nio-ssl", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-nio-ssl.git", + "name": "swift-nio-ssl" + }, + "state": { + "checkoutState": { + "revision": "2e74773972bd6254c41ceeda827f229bccbf1c0f", + "version": "2.15.0" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-nio-ssl" + } + ] + }, + "version": 5 +} diff --git a/pkgs/development/compilers/swift/swift-driver/default.nix b/pkgs/development/compilers/swift/swift-driver/default.nix new file mode 100644 index 0000000000000..60fe2aeb9c92d --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/default.nix @@ -0,0 +1,77 @@ +{ lib +, stdenv +, callPackage +, fetchpatch +, swift +, swiftpm +, swiftpm2nix +, Foundation +, XCTest +, sqlite +, ncurses +, substituteAll +}: +let + sources = callPackage ../sources.nix { }; + generated = swiftpm2nix.helpers ./generated; + + # On Darwin, we only want ncurses in the linker search path, because headers + # are part of libsystem. Adding its headers to the search path causes strange + # mixing and errors. + # TODO: Find a better way to prevent this conflict. + ncursesInput = if stdenv.isDarwin then ncurses.out else ncurses; +in +stdenv.mkDerivation { + pname = "swift-driver"; + + inherit (sources) version; + src = sources.swift-driver; + + nativeBuildInputs = [ swift swiftpm ]; + buildInputs = [ + Foundation + XCTest + sqlite + ncursesInput + ]; + + patches = [ + ./patches/nix-resource-root.patch + ./patches/disable-catalyst.patch + ./patches/linux-fix-linking.patch + # TODO: Replace with branch patch once merged: + # https://github.com/apple/swift-driver/pull/1197 + (fetchpatch { + url = "https://github.com/apple/swift-driver/commit/d3ef9cdf4871a58eddec7ff0e28fe611130da3f9.patch"; + hash = "sha256-eVBaKN6uzj48ZnHtwGV0k5ChKjak1tDCyE+wTdyGq2c="; + }) + # Prevent a warning about SDK directories we don't have. + (substituteAll { + src = ./patches/prevent-sdk-dirs-warnings.patch; + inherit (builtins) storeDir; + }) + ]; + + configurePhase = generated.configure; + + # TODO: Tests depend on indexstore-db being provided by an existing Swift + # toolchain. (ie. looks for `../lib/libIndexStore.so` relative to swiftc. + #doCheck = true; + + # TODO: Darwin-specific installation includes more, but not sure why. + installPhase = '' + binPath="$(swiftpmBinPath)" + mkdir -p $out/bin + for executable in swift-driver swift-help swift-build-sdk-interfaces; do + cp $binPath/$executable $out/bin/ + done + ''; + + meta = { + description = "Swift compiler driver"; + homepage = "https://github.com/apple/swift-driver"; + platforms = with lib.platforms; linux ++ darwin; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/compilers/swift/swift-driver/generated/default.nix b/pkgs/development/compilers/swift/swift-driver/generated/default.nix new file mode 100644 index 0000000000000..c5ee8a8c90cb9 --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/generated/default.nix @@ -0,0 +1,11 @@ +# This file was generated by swiftpm2nix. +{ + workspaceStateFile = ./workspace-state.json; + hashes = { + "swift-argument-parser" = "11did5snqj8chcbdbiyx84mpif940ls2pr1iikwivvfp63i248hm"; + "swift-llbuild" = "07zbp2dyfqd1bnyg7snpr9brn40jf22ivly5v10mql3hrg76a18h"; + "swift-system" = "0402hkx2q2dv27gccnn8ma79ngvwiwzkhcv4zlcdldmy6cgi0px7"; + "swift-tools-support-core" = "1vabl1z5sm2lrd75f5c781rkrq0liinpjvnrjr6i6r8cqrp0q5jb"; + "Yams" = "1893y13sis2aimi1a5kgkczbf06z4yig054xb565yg2xm13srb45"; + }; +} diff --git a/pkgs/development/compilers/swift/swift-driver/generated/workspace-state.json b/pkgs/development/compilers/swift/swift-driver/generated/workspace-state.json new file mode 100644 index 0000000000000..7671303387ec8 --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/generated/workspace-state.json @@ -0,0 +1,93 @@ +{ + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-argument-parser.git", + "name": "swift-argument-parser" + }, + "state": { + "checkoutState": { + "revision": "e1465042f195f374b94f915ba8ca49de24300a0d", + "version": "1.0.2" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-argument-parser" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-llbuild", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-llbuild.git", + "name": "llbuild" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "564424db5fdb62dcb5d863bdf7212500ef03a87b" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-llbuild" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-system", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-system.git", + "name": "swift-system" + }, + "state": { + "checkoutState": { + "revision": "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version": "1.1.1" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-system" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "afc0938503bac012f76ceb619d031f63edc4c5f7" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "sourceControlCheckout" + }, + "subpath": "Yams" + } + ] + }, + "version": 5 +} diff --git a/pkgs/development/compilers/swift/swift-driver/patches/disable-catalyst.patch b/pkgs/development/compilers/swift/swift-driver/patches/disable-catalyst.patch new file mode 100644 index 0000000000000..b9eb23f21061d --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/patches/disable-catalyst.patch @@ -0,0 +1,17 @@ +Tries to parse SDKSettings.plist looking for a Catalyst version map, but we +don't currently support this. + +--- a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift ++++ b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift +@@ -297,11 +297,7 @@ public final class DarwinToolchain: Toolchain { + debugDescription: "Malformed version string") + } + self.version = version +- if self.canonicalName.hasPrefix("macosx") { +- self.versionMap = try keyedContainer.decode(VersionMap.self, forKey: .versionMap) +- } else { + self.versionMap = VersionMap() +- } + } + + diff --git a/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch b/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch new file mode 100644 index 0000000000000..c0cfe2b7d225d --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch @@ -0,0 +1,40 @@ +--- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift ++++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +@@ -9,6 +9,7 @@ + // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors + // + //===----------------------------------------------------------------------===// ++import Foundation + import TSCBasic + import SwiftOptions + +@@ -116,7 +117,20 @@ extension GenericUnixToolchain { + // just using `clang` and avoid a dependency on the C++ runtime. + let clangTool: Tool = + parsedOptions.hasArgument(.enableExperimentalCxxInterop) ? .clangxx : .clang +- var clangPath = try getToolPath(clangTool) ++ ++ // For Nix, prefer linking using the wrapped system clang, instead of using ++ // the unwrapped clang packaged with swift. The latter is unable to link, but ++ // we still want to use it for other purposes (clang importer). ++ var clangPath: AbsolutePath ++ let env = ProcessInfo.processInfo.environment ++ if let nixCC = env["NIX_CC"], ++ let binPath = try? AbsolutePath(validating: "\(nixCC)/bin"), ++ let tool = lookupExecutablePath(filename: parsedOptions.hasArgument(.enableExperimentalCxxInterop) ++ ? "clang++" : "clang", ++ searchPaths: [binPath]) { ++ clangPath = tool ++ } else { ++ clangPath = try getToolPath(clangTool) + if let toolsDirPath = parsedOptions.getLastArgument(.toolsDirectory) { + // FIXME: What if this isn't an absolute path? + let toolsDir = try AbsolutePath(validating: toolsDirPath.asSingle) +@@ -132,6 +146,7 @@ extension GenericUnixToolchain { + commandLine.appendFlag("-B") + commandLine.appendPath(toolsDir) + } ++ } // nixCC + + // Executables on Linux get -pie + if targetTriple.os == .linux && linkerOutputType == .executable { diff --git a/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch b/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch new file mode 100644 index 0000000000000..6c3ae87d68c98 --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch @@ -0,0 +1,28 @@ +Swift normally looks for the Clang resource dir in a subdir/symlink of its own +resource dir. We provide a symlink to the Swift build-time Clang as a default +there, but we also here patch a check to try locate it via NIX_CC. + +--- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift ++++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift +@@ -9,6 +9,7 @@ + // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors + // + //===----------------------------------------------------------------------===// ++import Foundation + import TSCBasic + import SwiftOptions + +@@ -24,6 +25,13 @@ extension Toolchain { + for targetInfo: FrontendTargetInfo, + parsedOptions: inout ParsedOptions + ) throws -> VirtualPath { ++ let env = ProcessInfo.processInfo.environment ++ if let nixCC = env["NIX_CC"] { ++ return try VirtualPath(path: nixCC) ++ .appending(components: "resource-root", "lib", ++ targetInfo.target.triple.platformName(conflatingDarwin: true)!) ++ } ++ + return VirtualPath.lookup(targetInfo.runtimeResourcePath.path) + .appending(components: "clang", "lib", + targetInfo.target.triple.platformName(conflatingDarwin: true)!) diff --git a/pkgs/development/compilers/swift/swift-driver/patches/prevent-sdk-dirs-warnings.patch b/pkgs/development/compilers/swift/swift-driver/patches/prevent-sdk-dirs-warnings.patch new file mode 100644 index 0000000000000..6080865ebe37a --- /dev/null +++ b/pkgs/development/compilers/swift/swift-driver/patches/prevent-sdk-dirs-warnings.patch @@ -0,0 +1,16 @@ +Prevents a user-visible warning on every compilation: + + ld: warning: directory not found for option '-L.../MacOSX11.0.sdk/usr/lib/swift' + +--- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift ++++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift +@@ -50,7 +50,9 @@ extension Toolchain { + result.append(sdkPath.appending(components: "System", "iOSSupport", "usr", "lib", "swift")) + } + ++ if sdkPath.absolutePath?.pathString.starts(with: "@storeDir@") == false { + result.append(sdkPath.appending(components: "usr", "lib", "swift")) ++ } + } + + return result diff --git a/pkgs/development/compilers/swift/swiftpm/cmake-glue.nix b/pkgs/development/compilers/swift/swiftpm/cmake-glue.nix new file mode 100644 index 0000000000000..f297eafd389b1 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/cmake-glue.nix @@ -0,0 +1,90 @@ +# SwiftPM dependencies are normally not installed using CMake, and only provide +# CMake modules to link them together in a build tree. We have separate +# derivations, so need a real install step. Here we provide our own minimal +# CMake modules to install along with the build products. +{ lib, stdenv, swift }: +let + + inherit (stdenv.hostPlatform) extensions; + + # This file exports shell snippets for use in postInstall. + mkInstallScript = module: template: '' + mkdir -p $out/lib/cmake/${module} + ( + export staticLibExt="${extensions.staticLibrary}" + export sharedLibExt="${extensions.sharedLibrary}" + export swiftOs="${swift.swiftOs}" + substituteAll \ + ${builtins.toFile "${module}Config.cmake" template} \ + $out/lib/cmake/${module}/${module}Config.cmake + ) + ''; + +in lib.mapAttrs mkInstallScript { + SwiftSystem = '' + add_library(SwiftSystem::SystemPackage STATIC IMPORTED) + set_property(TARGET SwiftSystem::SystemPackage PROPERTY IMPORTED_LOCATION "@out@/lib/swift_static/@swiftOs@/libSystemPackage@staticLibExt@") + ''; + + SwiftCollections = '' + add_library(SwiftCollections::Collections STATIC IMPORTED) + set_property(TARGET SwiftCollections::Collections PROPERTY IMPORTED_LOCATION "@out@/lib/swift_static/@swiftOs@/libCollections@staticLibExt@") + + add_library(SwiftCollections::DequeModule STATIC IMPORTED) + set_property(TARGET SwiftCollections::DequeModule PROPERTY IMPORTED_LOCATION "@out@/lib/swift_static/@swiftOs@/libDequeModule@staticLibExt@") + + add_library(SwiftCollections::OrderedCollections STATIC IMPORTED) + set_property(TARGET SwiftCollections::OrderedCollections PROPERTY IMPORTED_LOCATION "@out@/lib/swift_static/@swiftOs@/libOrderedCollections@staticLibExt@") + ''; + + TSC = '' + add_library(TSCLibc SHARED IMPORTED) + set_property(TARGET TSCLibc PROPERTY IMPORTED_LOCATION "@out@/lib/libTSCLibc@sharedLibExt@") + + add_library(TSCBasic SHARED IMPORTED) + set_property(TARGET TSCBasic PROPERTY IMPORTED_LOCATION "@out@/lib/libTSCBasic@sharedLibExt@") + + add_library(TSCUtility SHARED IMPORTED) + set_property(TARGET TSCUtility PROPERTY IMPORTED_LOCATION "@out@/lib/libTSCUtility@sharedLibExt@") + ''; + + ArgumentParser = '' + add_library(ArgumentParser SHARED IMPORTED) + set_property(TARGET ArgumentParser PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libArgumentParser@sharedLibExt@") + + add_library(ArgumentParserToolInfo SHARED IMPORTED) + set_property(TARGET ArgumentParserToolInfo PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libArgumentParserToolInfo@sharedLibExt@") + ''; + + Yams = '' + add_library(CYaml SHARED IMPORTED) + set_property(TARGET CYaml PROPERTY IMPORTED_LOCATION "@out@/lib/libCYaml@sharedLibExt@") + + add_library(Yams SHARED IMPORTED) + set_property(TARGET Yams PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libYams@sharedLibExt@") + ''; + + LLBuild = '' + add_library(libllbuild SHARED IMPORTED) + set_property(TARGET libllbuild PROPERTY IMPORTED_LOCATION "@out@/lib/libllbuild@sharedLibExt@") + + add_library(llbuildSwift SHARED IMPORTED) + set_property(TARGET llbuildSwift PROPERTY IMPORTED_LOCATION "@out@/lib/swift/pm/llbuild/libllbuildSwift@sharedLibExt@") + ''; + + SwiftDriver = '' + add_library(SwiftDriver SHARED IMPORTED) + set_property(TARGET SwiftDriver PROPERTY IMPORTED_LOCATION "@out@/lib/libSwiftDriver@sharedLibExt@") + + add_library(SwiftDriverExecution SHARED IMPORTED) + set_property(TARGET SwiftDriverExecution PROPERTY IMPORTED_LOCATION "@out@/lib/libSwiftDriverExecution@sharedLibExt@") + + add_library(SwiftOptions SHARED IMPORTED) + set_property(TARGET SwiftOptions PROPERTY IMPORTED_LOCATION "@out@/lib/libSwiftOptions@sharedLibExt@") + ''; + + SwiftCrypto = '' + add_library(Crypto SHARED IMPORTED) + set_property(TARGET Crypto PROPERTY IMPORTED_LOCATION "@out@/lib/swift/@swiftOs@/libCrypto@sharedLibExt@") + ''; +} diff --git a/pkgs/development/compilers/swift/swiftpm/default.nix b/pkgs/development/compilers/swift/swiftpm/default.nix new file mode 100644 index 0000000000000..67198a3c25844 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/default.nix @@ -0,0 +1,418 @@ +{ lib +, stdenv +, callPackage +, cmake +, ninja +, git +, swift +, swiftpm2nix +, Foundation +, XCTest +, sqlite +, ncurses +, substituteAll +, runCommandLocal +, makeWrapper +, DarwinTools # sw_vers +, cctools # vtool +, xcbuild +, CryptoKit +, LocalAuthentication +}: + +let + + inherit (swift) swiftOs swiftModuleSubdir swiftStaticModuleSubdir; + sharedLibraryExt = stdenv.hostPlatform.extensions.sharedLibrary; + + sources = callPackage ../sources.nix { }; + generated = swiftpm2nix.helpers ./generated; + cmakeGlue = callPackage ./cmake-glue.nix { }; + + # Common attributes for the bootstrap swiftpm and the final swiftpm. + commonAttrs = { + inherit (sources) version; + src = sources.swift-package-manager; + nativeBuildInputs = [ makeWrapper ]; + # Required at run-time for the host platform to build package manifests. + propagatedBuildInputs = [ Foundation ]; + patches = [ + ./patches/cmake-disable-rpath.patch + ./patches/disable-sandbox.patch + ./patches/fix-clang-cxx.patch + (substituteAll { + src = ./patches/disable-xctest.patch; + inherit (builtins) storeDir; + }) + (substituteAll { + src = ./patches/fix-stdlib-path.patch; + inherit (builtins) storeDir; + swiftLib = swift.swift.lib; + }) + ]; + postPatch = '' + # The location of xcrun is hardcoded. We need PATH lookup instead. + find Sources -name '*.swift' | xargs sed -i -e 's|/usr/bin/xcrun|xcrun|g' + + # Patch the location where swiftpm looks for its API modules. + substituteInPlace Sources/PackageModel/UserToolchain.swift \ + --replace \ + 'librariesPath = applicationPath.parentDirectory' \ + "librariesPath = AbsolutePath(\"$out\")" + ''; + }; + + # Tools invoked by swiftpm at run-time. + runtimeDeps = [ git ] + ++ lib.optionals stdenv.isDarwin [ + xcbuild.xcrun + # vtool is used to determine a minimum deployment target. This is part of + # cctools, but adding that as a build input puts an unwrapped linker in + # PATH, and breaks builds. This small derivation exposes just vtool. + (runCommandLocal "vtool" { } '' + mkdir -p $out/bin + ln -s ${cctools}/bin/vtool $out/bin/vtool + '') + ]; + + # Common attributes for the bootstrap derivations. + mkBootstrapDerivation = attrs: stdenv.mkDerivation (attrs // { + nativeBuildInputs = (attrs.nativeBuildInputs or [ ]) + ++ [ cmake ninja swift ] + ++ lib.optionals stdenv.isDarwin [ DarwinTools ]; + + buildInputs = (attrs.buildInputs or [ ]) + ++ [ Foundation ]; + + postPatch = (attrs.postPatch or "") + + lib.optionalString stdenv.isDarwin '' + # On Darwin only, Swift uses arm64 as cpu arch. + if [ -e cmake/modules/SwiftSupport.cmake ]; then + substituteInPlace cmake/modules/SwiftSupport.cmake \ + --replace '"aarch64" PARENT_SCOPE' '"arm64" PARENT_SCOPE' + fi + ''; + + preConfigure = (attrs.preConfigure or "") + + '' + # Builds often don't set a target, and our default minimum macOS deployment + # target on x86_64-darwin is too low. Harmless on non-Darwin. + export MACOSX_DEPLOYMENT_TARGET=10.15.4 + ''; + + postInstall = (attrs.postInstall or "") + + lib.optionalString stdenv.isDarwin '' + # The install name of libraries is incorrectly set to lib/ (via our + # CMake setup hook) instead of lib/swift/. This'd be easily fixed by + # fixDarwinDylibNames, but some builds create libraries that reference + # eachother, and we also have to fix those references. + dylibs="$(find $out/lib/swift* -name '*.dylib')" + changes="" + for dylib in $dylibs; do + changes+=" -change $(otool -D $dylib | tail -n 1) $dylib" + done + for dylib in $dylibs; do + install_name_tool -id $dylib $changes $dylib + done + ''; + + cmakeFlags = (attrs.cmakeFlags or [ ]) + ++ [ + # Some builds link to libraries within the same build. Make sure these + # create references to $out. None of our builds run their own products, + # so we don't have to account for that scenario. + "-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON" + ]; + }); + + # On Darwin, we only want ncurses in the linker search path, because headers + # are part of libsystem. Adding its headers to the search path causes strange + # mixing and errors. + # TODO: Find a better way to prevent this conflict. + ncursesInput = if stdenv.isDarwin then ncurses.out else ncurses; + + # Derivations for bootstrapping dependencies using CMake. + # This is based on the `swiftpm/Utilities/bootstrap` script. + # + # Some of the installation steps here are a bit hacky, because it seems like + # these packages were not really meant to be installed using CMake. The + # regular swiftpm bootstrap simply refers to the source and build + # directories. The advantage of separate builds is that we can more easily + # link libs together using existing Nixpkgs infra. + # + # In the end, we don't expose these derivations, and they only exist during + # the bootstrap phase. The final swiftpm derivation does not depend on them. + + swift-system = mkBootstrapDerivation { + name = "swift-system"; + src = generated.sources.swift-system; + + postInstall = cmakeGlue.SwiftSystem + + lib.optionalString (!stdenv.isDarwin) '' + # The cmake rules apparently only use the Darwin install convention. + # Fix up the installation so the module can be found on non-Darwin. + mkdir -p $out/${swiftStaticModuleSubdir} + mv $out/lib/swift_static/${swiftOs}/*.swiftmodule $out/${swiftStaticModuleSubdir}/ + ''; + }; + + swift-collections = mkBootstrapDerivation { + name = "swift-collections"; + src = generated.sources.swift-collections; + + postPatch = '' + # Only builds static libs on Linux, but this installation difference is a + # hassle. Because this installation is temporary for the bootstrap, may + # as well build static libs everywhere. + sed -i -e '/BUILD_SHARED_LIBS/d' CMakeLists.txt + ''; + + postInstall = cmakeGlue.SwiftCollections + + lib.optionalString (!stdenv.isDarwin) '' + # The cmake rules apparently only use the Darwin install convention. + # Fix up the installation so the module can be found on non-Darwin. + mkdir -p $out/${swiftStaticModuleSubdir} + mv $out/lib/swift_static/${swiftOs}/*.swiftmodule $out/${swiftStaticModuleSubdir}/ + ''; + }; + + swift-tools-support-core = mkBootstrapDerivation { + name = "swift-tools-support-core"; + src = generated.sources.swift-tools-support-core; + + buildInputs = [ + swift-system + sqlite + ]; + + postInstall = cmakeGlue.TSC + '' + # Swift modules are not installed. + mkdir -p $out/${swiftModuleSubdir} + cp swift/*.swift{module,doc} $out/${swiftModuleSubdir}/ + + # Static libs are not installed. + cp lib/*.a $out/lib/ + + # Headers are not installed. + mkdir -p $out/include + cp -r ../Sources/TSCclibc/include $out/include/TSC + ''; + }; + + swift-argument-parser = mkBootstrapDerivation { + name = "swift-argument-parser"; + src = generated.sources.swift-argument-parser; + + buildInputs = [ ncursesInput sqlite ]; + + cmakeFlags = [ + "-DBUILD_TESTING=NO" + "-DBUILD_EXAMPLES=NO" + ]; + + postInstall = cmakeGlue.ArgumentParser + + lib.optionalString stdenv.isLinux '' + # Fix rpath so ArgumentParserToolInfo can be found. + patchelf --add-rpath "$out/lib/swift/${swiftOs}" \ + $out/lib/swift/${swiftOs}/libArgumentParser.so + ''; + }; + + Yams = mkBootstrapDerivation { + name = "Yams"; + src = generated.sources.Yams; + + # Conflicts with BUILD file on case-insensitive filesystems. + cmakeBuildDir = "_build"; + + postInstall = cmakeGlue.Yams; + }; + + llbuild = mkBootstrapDerivation { + name = "llbuild"; + src = generated.sources.swift-llbuild; + + nativeBuildInputs = lib.optional stdenv.isDarwin xcbuild; + buildInputs = [ ncursesInput sqlite ]; + + patches = [ + ./patches/llbuild-cmake-disable-rpath.patch + ]; + + postPatch = '' + # Substitute ncurses for curses. + find . -name CMakeLists.txt | xargs sed -i -e 's/curses/ncurses/' + + # Use absolute install names instead of rpath. + substituteInPlace \ + products/libllbuild/CMakeLists.txt \ + products/llbuildSwift/CMakeLists.txt \ + --replace '@rpath' "$out/lib" + + # This subdirectory is enabled for Darwin only, but requires ObjC XCTest + # (and only Swift XCTest is open source). + substituteInPlace perftests/CMakeLists.txt \ + --replace 'add_subdirectory(Xcode/' '#add_subdirectory(Xcode/' + ''; + + cmakeFlags = [ + "-DLLBUILD_SUPPORT_BINDINGS=Swift" + ]; + + postInstall = cmakeGlue.LLBuild + '' + # Install module map. + cp ../products/libllbuild/include/module.modulemap $out/include + + # Swift modules are not installed. + mkdir -p $out/${swiftModuleSubdir} + cp products/llbuildSwift/*.swift{module,doc} $out/${swiftModuleSubdir}/ + ''; + }; + + swift-driver = mkBootstrapDerivation { + name = "swift-driver"; + src = generated.sources.swift-driver; + + buildInputs = [ + Yams + llbuild + swift-system + swift-argument-parser + swift-tools-support-core + ]; + + postInstall = cmakeGlue.SwiftDriver + '' + # Swift modules are not installed. + mkdir -p $out/${swiftModuleSubdir} + cp swift/*.swift{module,doc} $out/${swiftModuleSubdir}/ + ''; + }; + + swift-crypto = mkBootstrapDerivation { + name = "swift-crypto"; + src = generated.sources.swift-crypto; + + postPatch = '' + substituteInPlace CMakeLists.txt \ + --replace /usr/bin/ar $NIX_CC/bin/ar + ''; + + postInstall = cmakeGlue.SwiftCrypto + '' + # Static libs are not installed. + cp lib/*.a $out/lib/ + + # Headers are not installed. + cp -r ../Sources/CCryptoBoringSSL/include $out/include + ''; + }; + + # Build a bootrapping swiftpm using CMake. + swiftpm-bootstrap = mkBootstrapDerivation (commonAttrs // { + pname = "swiftpm-bootstrap"; + + buildInputs = [ + llbuild + swift-argument-parser + swift-collections + swift-crypto + swift-driver + swift-system + swift-tools-support-core + ]; + + cmakeFlags = [ + "-DUSE_CMAKE_INSTALL=ON" + ]; + + postInstall = '' + for program in $out/bin/swift-*; do + wrapProgram $program --prefix PATH : ${lib.makeBinPath runtimeDeps} + done + ''; + }); + +# Build the final swiftpm with the bootstrapping swiftpm. +in stdenv.mkDerivation (commonAttrs // { + pname = "swiftpm"; + + nativeBuildInputs = commonAttrs.nativeBuildInputs ++ [ + swift + swiftpm-bootstrap + ]; + buildInputs = [ + ncursesInput + sqlite + XCTest + ] + ++ lib.optionals stdenv.isDarwin [ + CryptoKit + LocalAuthentication + ]; + + configurePhase = generated.configure + '' + # Functionality provided by Xcode XCTest, but not available in + # swift-corelibs-xctest. + swiftpmMakeMutable swift-tools-support-core + substituteInPlace .build/checkouts/swift-tools-support-core/Sources/TSCTestSupport/XCTestCasePerf.swift \ + --replace 'canImport(Darwin)' 'false' + + # Prevent a warning about SDK directories we don't have. + swiftpmMakeMutable swift-driver + patch -p1 -d .build/checkouts/swift-driver -i ${substituteAll { + src = ../swift-driver/patches/prevent-sdk-dirs-warnings.patch; + inherit (builtins) storeDir; + }} + ''; + + buildPhase = '' + # Required to link with swift-corelibs-xctest on Darwin. + export SWIFTTSC_MACOS_DEPLOYMENT_TARGET=10.12 + + TERM=dumb swift-build -c release + ''; + + # TODO: Tests depend on indexstore-db being provided by an existing Swift + # toolchain. (ie. looks for `../lib/libIndexStore.so` relative to swiftc. + #doCheck = true; + #checkPhase = '' + # TERM=dumb swift-test -c release + #''; + + # The following is dervied from Utilities/bootstrap, see install_swiftpm. + installPhase = '' + binPath="$(swift-build --show-bin-path -c release)" + + mkdir -p $out/bin $out/lib/swift + + cp $binPath/swift-package $out/bin/ + wrapProgram $out/bin/swift-package \ + --prefix PATH : ${lib.makeBinPath runtimeDeps} + for tool in swift-build swift-test swift-run swift-package-collection; do + ln -s $out/bin/swift-package $out/bin/$tool + done + + installSwiftpmModule() { + mkdir -p $out/lib/swift/pm/$2 + cp $binPath/lib$1${sharedLibraryExt} $out/lib/swift/pm/$2/ + + if [[ -f $binPath/$1.swiftinterface ]]; then + cp $binPath/$1.swiftinterface $out/lib/swift/pm/$2/ + else + cp -r $binPath/$1.swiftmodule $out/lib/swift/pm/$2/ + fi + cp $binPath/$1.swiftdoc $out/lib/swift/pm/$2/ + } + installSwiftpmModule PackageDescription ManifestAPI + installSwiftpmModule PackagePlugin PluginAPI + ''; + + setupHook = ./setup-hook.sh; + + meta = { + description = "The Package Manager for the Swift Programming Language"; + homepage = "https://github.com/apple/swift-package-manager"; + platforms = with lib.platforms; linux ++ darwin; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +}) diff --git a/pkgs/development/compilers/swift/swiftpm/generated/default.nix b/pkgs/development/compilers/swift/swiftpm/generated/default.nix new file mode 100644 index 0000000000000..978aee7455dcf --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/generated/default.nix @@ -0,0 +1,14 @@ +# This file was generated by swiftpm2nix. +{ + workspaceStateFile = ./workspace-state.json; + hashes = { + "swift-argument-parser" = "1jph9w7lk9nr20fsv2c8p4hisx3dda817fh7pybd0r0j1jwa9nmw"; + "swift-collections" = "0l0pv16zil3n7fac7mdf5qxklxr5rwiig5bixgca1ybq7arlnv7i"; + "swift-crypto" = "020b8q4ss2k7a65r5dgh59z40i6sn7ij1allxkh8c8a9d0jzn313"; + "swift-driver" = "1lcb5wqragc74nd0fjnk47lyph9hs0i9cps1mplvp2i91yzjqk05"; + "swift-llbuild" = "07zbp2dyfqd1bnyg7snpr9brn40jf22ivly5v10mql3hrg76a18h"; + "swift-system" = "0402hkx2q2dv27gccnn8ma79ngvwiwzkhcv4zlcdldmy6cgi0px7"; + "swift-tools-support-core" = "1vabl1z5sm2lrd75f5c781rkrq0liinpjvnrjr6i6r8cqrp0q5jb"; + "Yams" = "1893y13sis2aimi1a5kgkczbf06z4yig054xb565yg2xm13srb45"; + }; +} diff --git a/pkgs/development/compilers/swift/swiftpm/generated/workspace-state.json b/pkgs/development/compilers/swift/swiftpm/generated/workspace-state.json new file mode 100644 index 0000000000000..26219857c1779 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/generated/workspace-state.json @@ -0,0 +1,144 @@ +{ + "object": { + "artifacts": [], + "dependencies": [ + { + "basedOn": null, + "packageRef": { + "identity": "swift-argument-parser", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-argument-parser.git", + "name": "swift-argument-parser" + }, + "state": { + "checkoutState": { + "revision": "e394bf350e38cb100b6bc4172834770ede1b7232", + "version": "1.0.3" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-argument-parser" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-collections", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-collections.git", + "name": "swift-collections" + }, + "state": { + "checkoutState": { + "revision": "f504716c27d2e5d4144fa4794b12129301d17729", + "version": "1.0.3" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-collections" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-crypto", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-crypto.git", + "name": "swift-crypto" + }, + "state": { + "checkoutState": { + "revision": "ddb07e896a2a8af79512543b1c7eb9797f8898a5", + "version": "1.1.7" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-crypto" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-driver", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-driver.git", + "name": "swift-driver" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "82b274af66cfbb8f3131677676517b34d01e30fd" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-driver" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-llbuild", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-llbuild.git", + "name": "llbuild" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "564424db5fdb62dcb5d863bdf7212500ef03a87b" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-llbuild" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-system", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-system.git", + "name": "swift-system" + }, + "state": { + "checkoutState": { + "revision": "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version": "1.1.1" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-system" + }, + { + "basedOn": null, + "packageRef": { + "identity": "swift-tools-support-core", + "kind": "remoteSourceControl", + "location": "https://github.com/apple/swift-tools-support-core.git", + "name": "swift-tools-support-core" + }, + "state": { + "checkoutState": { + "branch": "release/5.7", + "revision": "afc0938503bac012f76ceb619d031f63edc4c5f7" + }, + "name": "sourceControlCheckout" + }, + "subpath": "swift-tools-support-core" + }, + { + "basedOn": null, + "packageRef": { + "identity": "yams", + "kind": "remoteSourceControl", + "location": "https://github.com/jpsim/Yams.git", + "name": "Yams" + }, + "state": { + "checkoutState": { + "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa", + "version": "4.0.6" + }, + "name": "sourceControlCheckout" + }, + "subpath": "Yams" + } + ] + }, + "version": 5 +} diff --git a/pkgs/development/compilers/swift/swiftpm/patches/cmake-disable-rpath.patch b/pkgs/development/compilers/swift/swiftpm/patches/cmake-disable-rpath.patch new file mode 100644 index 0000000000000..9aeba452f9e80 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/cmake-disable-rpath.patch @@ -0,0 +1,36 @@ +Disable rpath for the bootstrap build with CMake. + +--- a/Sources/PackageDescription/CMakeLists.txt ++++ b/Sources/PackageDescription/CMakeLists.txt +@@ -31,14 +31,11 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin) + set(SWIFT_INTERFACE_PATH ${CMAKE_BINARY_DIR}/pm/ManifestAPI/PackageDescription.swiftinterface) + target_compile_options(PackageDescription PUBLIC + $<$:-emit-module-interface-path$${SWIFT_INTERFACE_PATH}>) +- target_link_options(PackageDescription PRIVATE +- "SHELL:-Xlinker -install_name -Xlinker @rpath/libPackageDescription.dylib") + endif() + + set_target_properties(PackageDescription PROPERTIES + Swift_MODULE_NAME PackageDescription + Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/pm/ManifestAPI +- INSTALL_NAME_DIR \\@rpath + OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pm/ManifestAPI + OUTPUT_NAME PackageDescription + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pm/ManifestAPI +--- a/Sources/PackagePlugin/CMakeLists.txt ++++ b/Sources/PackagePlugin/CMakeLists.txt +@@ -29,14 +29,11 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin) + set(SWIFT_INTERFACE_PATH ${CMAKE_BINARY_DIR}/pm/PluginAPI/PackagePlugin.swiftinterface) + target_compile_options(PackagePlugin PUBLIC + $<$:-emit-module-interface-path$${SWIFT_INTERFACE_PATH}>) +- target_link_options(PackagePlugin PRIVATE +- "SHELL:-Xlinker -install_name -Xlinker @rpath/libPackagePlugin.dylib") + endif() + + set_target_properties(PackagePlugin PROPERTIES + Swift_MODULE_NAME PackagePlugin + Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/pm/PluginAPI +- INSTALL_NAME_DIR \\@rpath + OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pm/PluginAPI + OUTPUT_NAME PackagePlugin + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pm/PluginAPI diff --git a/pkgs/development/compilers/swift/swiftpm/patches/disable-sandbox.patch b/pkgs/development/compilers/swift/swiftpm/patches/disable-sandbox.patch new file mode 100644 index 0000000000000..406e1d68d0e42 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/disable-sandbox.patch @@ -0,0 +1,21 @@ +Nix may already sandbox the build, in which case sandbox_apply will fail. + +--- a/Sources/Basics/Sandbox.swift ++++ b/Sources/Basics/Sandbox.swift +@@ -30,12 +30,14 @@ public enum Sandbox { + readOnlyDirectories: [AbsolutePath] = [] + ) -> [String] { + #if os(macOS) ++ let env = ProcessInfo.processInfo.environment ++ if env["NIX_BUILD_TOP"] == nil || env["IN_NIX_SHELL"] != nil { + let profile = macOSSandboxProfile(strictness: strictness, writableDirectories: writableDirectories, readOnlyDirectories: readOnlyDirectories) + return ["/usr/bin/sandbox-exec", "-p", profile] + command +- #else ++ } ++ #endif + // rdar://40235432, rdar://75636874 tracks implementing sandboxes for other platforms. + return command +- #endif + } + + /// Basic strictness level of a sandbox applied to a command line. diff --git a/pkgs/development/compilers/swift/swiftpm/patches/disable-xctest.patch b/pkgs/development/compilers/swift/swiftpm/patches/disable-xctest.patch new file mode 100644 index 0000000000000..e24d154d29873 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/disable-xctest.patch @@ -0,0 +1,48 @@ +XCTest is not fully open-source, only the Swift library parts. We don't have a +command-line runner available, so disable support. + +--- a/Sources/Commands/TestingSupport.swift ++++ b/Sources/Commands/TestingSupport.swift +@@ -60,7 +60,7 @@ enum TestingSupport { + /// - Returns: Array of TestSuite + static func getTestSuites(fromTestAt path: AbsolutePath, swiftTool: SwiftTool, swiftOptions: SwiftToolOptions) throws -> [TestSuite] { + // Run the correct tool. +- #if os(macOS) ++ #if false + let data: String = try withTemporaryFile { tempFile in + let args = [try TestingSupport.xctestHelperPath(swiftTool: swiftTool).pathString, path.pathString, tempFile.path.pathString] + var env = try TestingSupport.constructTestEnvironment(toolchain: try swiftTool.getToolchain(), options: swiftOptions, buildParameters: swiftTool.buildParametersForTest()) +--- a/Sources/swiftpm-xctest-helper/main.swift ++++ b/Sources/swiftpm-xctest-helper/main.swift +@@ -9,8 +9,11 @@ + */ + + #if os(macOS) +-import XCTest + import func Darwin.C.exit ++print("Not supported in Nix.") ++exit(1) ++#if false ++import XCTest + + /// A helper tool to get list of tests from a XCTest Bundle on macOS. + /// +@@ -132,6 +135,7 @@ do { + exit(1) + } + ++#endif // nix + #else + + #if os(Windows) +--- a/Sources/PackageModel/Destination.swift ++++ b/Sources/PackageModel/Destination.swift +@@ -174,7 +174,7 @@ public struct Destination: Encodable, Equatable { + arguments: ["/usr/bin/xcrun", "--sdk", "macosx", "--show-sdk-platform-path"], + environment: environment).spm_chomp() + +- if let platformPath = platformPath, !platformPath.isEmpty { ++ if let platformPath = platformPath, !platformPath.isEmpty && !platformPath.starts(with: "@storeDir@") { + // For XCTest framework. + let fwk = AbsolutePath(platformPath).appending( + components: "Developer", "Library", "Frameworks") diff --git a/pkgs/development/compilers/swift/swiftpm/patches/fix-clang-cxx.patch b/pkgs/development/compilers/swift/swiftpm/patches/fix-clang-cxx.patch new file mode 100644 index 0000000000000..60c4e33eb154f --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/fix-clang-cxx.patch @@ -0,0 +1,121 @@ +Swiftpm may invoke clang, not clang++, to compile C++. Our cc-wrapper also +doesn't pick up the arguments that enable C++ compilation in this case. Patch +swiftpm to properly invoke clang++. + +--- a/Sources/Build/LLBuildManifestBuilder.swift ++++ b/Sources/Build/LLBuildManifestBuilder.swift +@@ -782,7 +782,7 @@ extension LLBuildManifestBuilder { + + args += ["-c", path.source.pathString, "-o", path.object.pathString] + +- let clangCompiler = try buildParameters.toolchain.getClangCompiler().pathString ++ let clangCompiler = try buildParameters.toolchain.getClangCompiler(isCXX: isCXX).pathString + args.insert(clangCompiler, at: 0) + + let objectFileNode: Node = .file(path.object) +--- a/Sources/PackageModel/Destination.swift ++++ b/Sources/PackageModel/Destination.swift +@@ -153,7 +153,7 @@ public struct Destination: Encodable, Equatable { + + var extraCPPFlags: [String] = [] + #if os(macOS) +- extraCPPFlags += ["-lc++"] ++ extraCPPFlags += ["-lc++", "-lc++abi"] + #elseif os(Windows) + extraCPPFlags += [] + #else +--- a/Sources/PackageModel/Toolchain.swift ++++ b/Sources/PackageModel/Toolchain.swift +@@ -20,7 +20,7 @@ public protocol Toolchain { + var macosSwiftStdlib: AbsolutePath { get } + + /// Path of the `clang` compiler. +- func getClangCompiler() throws -> AbsolutePath ++ func getClangCompiler(isCXX: Bool) throws -> AbsolutePath + + // FIXME: This is a temporary API until index store is widely available in + // the OSS clang compiler. This API should not used for any other purpose. +--- a/Sources/PackageModel/UserToolchain.swift ++++ b/Sources/PackageModel/UserToolchain.swift +@@ -57,7 +57,7 @@ public final class UserToolchain: Toolchain { + /// Only use search paths, do not fall back to `xcrun`. + let useXcrun: Bool + +- private var _clangCompiler: AbsolutePath? ++ private var _clangCompiler: [Bool: AbsolutePath] = [:] + + private let environment: EnvironmentVariables + +@@ -150,29 +150,31 @@ public final class UserToolchain: Toolchain { + } + + /// Returns the path to clang compiler tool. +- public func getClangCompiler() throws -> AbsolutePath { ++ public func getClangCompiler(isCXX: Bool) throws -> AbsolutePath { + // Check if we already computed. +- if let clang = self._clangCompiler { ++ if let clang = self._clangCompiler[isCXX] { + return clang + } + + // Check in the environment variable first. +- if let toolPath = UserToolchain.lookup(variable: "CC", searchPaths: self.envSearchPaths, environment: environment) { +- self._clangCompiler = toolPath ++ let envVar = isCXX ? "CXX" : "CC"; ++ if let toolPath = UserToolchain.lookup(variable: envVar, searchPaths: self.envSearchPaths, environment: environment) { ++ self._clangCompiler[isCXX] = toolPath + return toolPath + } + + // Then, check the toolchain. ++ let tool = isCXX ? "clang++" : "clang"; + do { +- if let toolPath = try? UserToolchain.getTool("clang", binDir: self.destination.binDir) { +- self._clangCompiler = toolPath ++ if let toolPath = try? UserToolchain.getTool(tool, binDir: self.destination.binDir) { ++ self._clangCompiler[isCXX] = toolPath + return toolPath + } + } + + // Otherwise, lookup it up on the system. +- let toolPath = try UserToolchain.findTool("clang", envSearchPaths: self.envSearchPaths, useXcrun: useXcrun) +- self._clangCompiler = toolPath ++ let toolPath = try UserToolchain.findTool(tool, envSearchPaths: self.envSearchPaths, useXcrun: useXcrun) ++ self._clangCompiler[isCXX] = toolPath + return toolPath + } + +--- a/Sources/SPMBuildCore/BuildParameters.swift ++++ b/Sources/SPMBuildCore/BuildParameters.swift +@@ -342,7 +342,7 @@ private struct _Toolchain: Encodable { + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(toolchain.swiftCompilerPath, forKey: .swiftCompiler) +- try container.encode(toolchain.getClangCompiler(), forKey: .clangCompiler) ++ try container.encode(toolchain.getClangCompiler(isCXX: false), forKey: .clangCompiler) + + try container.encode(toolchain.extraCCFlags, forKey: .extraCCFlags) + try container.encode(toolchain.extraCPPFlags, forKey: .extraCPPFlags) +--- a/Sources/XCBuildSupport/XcodeBuildSystem.swift ++++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift +@@ -172,7 +172,7 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem { + // Generate a table of any overriding build settings. + var settings: [String: String] = [:] + // An error with determining the override should not be fatal here. +- settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString ++ settings["CC"] = try? buildParameters.toolchain.getClangCompiler(isCXX: false).pathString + // Always specify the path of the effective Swift compiler, which was determined in the same way as for the native build system. + settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString + settings["LIBRARY_SEARCH_PATHS"] = "$(inherited) \(buildParameters.toolchain.toolchainLibDir.pathString)" +--- a/Tests/BuildTests/MockBuildTestHelper.swift ++++ b/Tests/BuildTests/MockBuildTestHelper.swift +@@ -15,7 +15,7 @@ struct MockToolchain: PackageModel.Toolchain { + #else + let extraCPPFlags: [String] = ["-lstdc++"] + #endif +- func getClangCompiler() throws -> AbsolutePath { ++ func getClangCompiler(isCXX: Bool) throws -> AbsolutePath { + return AbsolutePath("/fake/path/to/clang") + } + diff --git a/pkgs/development/compilers/swift/swiftpm/patches/fix-stdlib-path.patch b/pkgs/development/compilers/swift/swiftpm/patches/fix-stdlib-path.patch new file mode 100644 index 0000000000000..327ccf37e4253 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/fix-stdlib-path.patch @@ -0,0 +1,23 @@ +Swiftpm looks for the Swift stdlib relative to the swift compiler, but that's a +wrapper in our case. It wants to add the stdlib to the rpath, which is +necessary for back-deployment of some features. + +--- a/Sources/PackageModel/Toolchain.swift ++++ b/Sources/PackageModel/Toolchain.swift +@@ -43,10 +43,16 @@ extension Toolchain { + } + + public var macosSwiftStdlib: AbsolutePath { ++ if swiftCompilerPath.pathString.starts(with: "@storeDir@") { ++ return AbsolutePath("@swiftLib@/lib/swift/macosx") ++ } + return AbsolutePath("../../lib/swift/macosx", relativeTo: resolveSymlinks(swiftCompilerPath)) + } + + public var toolchainLibDir: AbsolutePath { ++ if swiftCompilerPath.pathString.starts(with: "@storeDir@") { ++ return AbsolutePath("@swiftLib@/lib") ++ } + // FIXME: Not sure if it's better to base this off of Swift compiler or our own binary. + return AbsolutePath("../../lib", relativeTo: resolveSymlinks(swiftCompilerPath)) + } diff --git a/pkgs/development/compilers/swift/swiftpm/patches/llbuild-cmake-disable-rpath.patch b/pkgs/development/compilers/swift/swiftpm/patches/llbuild-cmake-disable-rpath.patch new file mode 100644 index 0000000000000..785e82cc34b6d --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/patches/llbuild-cmake-disable-rpath.patch @@ -0,0 +1,14 @@ +Specifying `-platform_version` targeting macos before 10.15 causes cctools ld +to link with `@rpath`. This may have something to do with Swift ABI stability. + +--- a/products/llbuildSwift/CMakeLists.txt ++++ b/products/llbuildSwift/CMakeLists.txt +@@ -22,7 +17,7 @@ endif() + + # TODO(compnerd) move both of these outside of the CMake into the invocation + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) +- add_compile_options(-target ${CMAKE_OSX_ARCHITECTURES}-apple-macosx10.10) ++ add_compile_options(-target ${CMAKE_OSX_ARCHITECTURES}-apple-macosx10.15) + if(NOT CMAKE_OSX_SYSROOT STREQUAL "") + add_compile_options(-sdk ${CMAKE_OSX_SYSROOT}) + endif() diff --git a/pkgs/development/compilers/swift/swiftpm/setup-hook.sh b/pkgs/development/compilers/swift/swiftpm/setup-hook.sh new file mode 100644 index 0000000000000..160fbb1ccca31 --- /dev/null +++ b/pkgs/development/compilers/swift/swiftpm/setup-hook.sh @@ -0,0 +1,60 @@ +# Build using 'swift-build'. +swiftpmBuildPhase() { + runHook preBuild + + local buildCores=1 + if [ "${enableParallelBuilding-1}" ]; then + buildCores="$NIX_BUILD_CORES" + fi + + local flagsArray=( + -j $buildCores + -c "${swiftpmBuildConfig-release}" + $swiftpmFlags "${swiftpmFlagsArray[@]}" + ) + + echoCmd 'build flags' "${flagsArray[@]}" + TERM=dumb swift-build "${flagsArray[@]}" + + runHook postBuild +} + +if [ -z "${dontUseSwiftpmBuild-}" ] && [ -z "${buildPhase-}" ]; then + buildPhase=swiftpmBuildPhase +fi + +# Check using 'swift-test'. +swiftpmCheckPhase() { + runHook preCheck + + local buildCores=1 + if [ "${enableParallelBuilding-1}" ]; then + buildCores="$NIX_BUILD_CORES" + fi + + local flagsArray=( + -j $buildCores + -c "${swiftpmBuildConfig-release}" + $swiftpmFlags "${swiftpmFlagsArray[@]}" + ) + + echoCmd 'check flags' "${flagsArray[@]}" + TERM=dumb swift-test "${flagsArray[@]}" + + runHook postCheck +} + +if [ -z "${dontUseSwiftpmCheck-}" ] && [ -z "${checkPhase-}" ]; then + checkPhase=swiftpmCheckPhase +fi + +# Helper used to find the binary output path. +# Useful for performing the installPhase of swiftpm packages. +swiftpmBinPath() { + local flagsArray=( + -c "${swiftpmBuildConfig-release}" + $swiftpmFlags "${swiftpmFlagsArray[@]}" + ) + + swift-build --show-bin-path "${flagsArray[@]}" +} diff --git a/pkgs/development/compilers/swift/wrapper/default.nix b/pkgs/development/compilers/swift/wrapper/default.nix new file mode 100644 index 0000000000000..a7d16cc2471af --- /dev/null +++ b/pkgs/development/compilers/swift/wrapper/default.nix @@ -0,0 +1,58 @@ +{ lib +, stdenv +, swift +, useSwiftDriver ? true, swift-driver +}: + +stdenv.mkDerivation (swift._wrapperParams // { + pname = "swift-wrapper"; + inherit (swift) version meta; + + outputs = [ "out" "man" ]; + + # Wrapper and setup hook variables. + inherit swift; + inherit (swift) + swiftOs swiftArch + swiftModuleSubdir swiftLibSubdir + swiftStaticModuleSubdir swiftStaticLibSubdir; + swiftDriver = if useSwiftDriver + then "${swift-driver}/bin/swift-driver" else ""; + + passAsFile = [ "buildCommand" ]; + buildCommand = '' + mkdir -p $out/bin $out/nix-support + + # Symlink all Swift binaries first. + # NOTE: This specifically omits clang binaries. We want to hide these for + # private use by Swift only. + ln -s -t $out/bin/ $swift/bin/swift* + + # Replace specific binaries with wrappers. + for executable in swift swiftc swift-frontend; do + export prog=$swift/bin/$executable + rm $out/bin/$executable + substituteAll '${./wrapper.sh}' $out/bin/$executable + chmod a+x $out/bin/$executable + done + + ${lib.optionalString useSwiftDriver '' + # Symlink swift-driver executables. + ln -s -t $out/bin/ ${swift-driver}/bin/* + ''} + + ln -s ${swift.man} $man + + # This link is here because various tools (swiftpm) check for stdlib + # relative to the swift compiler. It's fine if this is for build-time + # stuff, but we should patch all cases were it would end up in an output. + ln -s ${swift.lib}/lib $out/lib + + substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook + ''; + + passthru = { + inherit swift; + inherit (swift) swiftOs swiftArch swiftModuleSubdir swiftLibSubdir; + }; +}) diff --git a/pkgs/development/compilers/swift/wrapper/setup-hook.sh b/pkgs/development/compilers/swift/wrapper/setup-hook.sh new file mode 100644 index 0000000000000..398f19977f667 --- /dev/null +++ b/pkgs/development/compilers/swift/wrapper/setup-hook.sh @@ -0,0 +1,28 @@ +# Add import paths for build inputs. +swiftWrapper_addImports () { + # Include subdirectories following both the Swift platform convention, and + # a simple `lib/swift` for Nix convenience. + for subdir in @swiftModuleSubdir@ @swiftStaticModuleSubdir@ lib/swift; do + if [[ -d "$1/$subdir" ]]; then + export NIX_SWIFTFLAGS_COMPILE+=" -I $1/$subdir" + fi + done + for subdir in @swiftLibSubdir@ @swiftStaticLibSubdir@ lib/swift; do + if [[ -d "$1/$subdir" ]]; then + export NIX_LDFLAGS+=" -L $1/$subdir" + fi + done +} + +addEnvHooks "$targetOffset" swiftWrapper_addImports + +# Use a postHook here because we rely on NIX_CC, which is set by the cc-wrapper +# setup hook, so delay until we're sure it was run. +swiftWrapper_postHook () { + # On Darwin, libc also contains Swift modules. + if [[ -e "$NIX_CC/nix-support/orig-libc" ]]; then + swiftWrapper_addImports "$(<$NIX_CC/nix-support/orig-libc)" + fi +} + +postHooks+=(swiftWrapper_postHook) diff --git a/pkgs/development/compilers/swift/wrapper/wrapper.sh b/pkgs/development/compilers/swift/wrapper/wrapper.sh new file mode 100644 index 0000000000000..0c56e63b6f29e --- /dev/null +++ b/pkgs/development/compilers/swift/wrapper/wrapper.sh @@ -0,0 +1,291 @@ +#! @shell@ +# NOTE: This wrapper is derived from cc-wrapper.sh, and is hopefully somewhat +# diffable with the original, so changes can be merged if necessary. +set -eu -o pipefail +o posix +shopt -s nullglob + +if (( "${NIX_DEBUG:-0}" >= 7 )); then + set -x +fi + +cc_wrapper="${NIX_CC:-@default_cc_wrapper@}" + +source $cc_wrapper/nix-support/utils.bash + +expandResponseParams "$@" + +# Check if we should wrap this Swift invocation at all, and how. Specifically, +# there are some internal tools we don't wrap, plus swift-frontend doesn't link +# and doesn't understand linker flags. This follows logic in +# `lib/DriverTool/driver.cpp`. +prog=@prog@ +progName="$(basename "$prog")" +firstArg="${params[0]:-}" +isFrontend=0 +isRepl=0 + +# These checks follow `shouldRunAsSubcommand`. +if [[ "$progName" == swift ]]; then + case "$firstArg" in + "" | -* | *.* | */* | repl) + ;; + *) + exec "swift-$firstArg" "${params[@]:1}" + ;; + esac +fi + +# These checks follow the first part of `run_driver`. +# +# NOTE: The original function short-circuits, but we can't here, because both +# paths must be wrapped. So we use an 'isFrontend' flag instead. +case "$firstArg" in + -frontend) + isFrontend=1 + # Ensure this stays the first argument. + params=( "${params[@]:1}" ) + extraBefore+=( "-frontend" ) + ;; + -modulewrap) + # Don't wrap this integrated tool. + exec "$prog" "${params[@]}" + ;; + repl) + isRepl=1 + params=( "${params[@]:1}" ) + ;; + --driver-mode=*) + ;; + *) + if [[ "$progName" == swift-frontend ]]; then + isFrontend=1 + fi + ;; +esac + +# For many tasks, Swift reinvokes swift-driver, the new driver implementation +# written in Swift. It needs some help finding the executable, though, and +# reimplementing the logic here is little effort. These checks follow +# `shouldDisallowNewDriver`. +if [[ + $isFrontend = 0 && + -n "@swiftDriver@" && + -z "${SWIFT_USE_OLD_DRIVER:-}" && + ( "$progName" == "swift" || "$progName" == "swiftc" ) +]]; then + prog=@swiftDriver@ + # Driver mode must be the very first argument. + extraBefore+=( "--driver-mode=$progName" ) + if [[ $isRepl = 1 ]]; then + extraBefore+=( "-repl" ) + fi + + # Ensure swift-driver invokes the unwrapped frontend (instead of finding + # the wrapped one via PATH), because we don't have to wrap a second time. + export SWIFT_DRIVER_SWIFT_FRONTEND_EXEC="@swift@/bin/swift-frontend" + + # Ensure swift-driver can find the LLDB with Swift support for the REPL. + export SWIFT_DRIVER_LLDB_EXEC="@swift@/bin/lldb" +fi + +path_backup="$PATH" + +# That @-vars are substituted separately from bash evaluation makes +# shellcheck think this, and others like it, are useless conditionals. +# shellcheck disable=SC2157 +if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then + PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin" +fi + +# Parse command line options and set several variables. +# For instance, figure out if linker flags should be passed. +# GCC prints annoying warnings when they are not needed. +isCxx=0 +dontLink=$isFrontend + +for p in "${params[@]}"; do + case "$p" in + -enable-cxx-interop) + isCxx=1 ;; + esac +done + +# NOTE: We don't modify these for Swift, but sourced scripts may use them. +cxxInclude=1 +cxxLibrary=1 +cInclude=1 + +linkType=$(checkLinkType "${params[@]}") + +# Optionally filter out paths not refering to the store. +if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "$NIX_STORE" ]]; then + kept=() + nParams=${#params[@]} + declare -i n=0 + while (( "$n" < "$nParams" )); do + p=${params[n]} + p2=${params[n+1]:-} # handle `p` being last one + n+=1 + + skipNext=false + path="" + case "$p" in + -[IL]/*) path=${p:2} ;; + -[IL]) path=$p2 skipNext=true ;; + esac + + if [[ -n $path ]] && badPath "$path"; then + skip "$path" + $skipNext && n+=1 + continue + fi + + kept+=("$p") + done + # Old bash empty array hack + params=(${kept+"${kept[@]}"}) +fi + +# Flirting with a layer violation here. +if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then + source @bintools@/nix-support/add-flags.sh +fi + +# Put this one second so libc ldflags take priority. +if [ -z "${NIX_CC_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then + source $cc_wrapper/nix-support/add-flags.sh +fi + +if [[ "$isCxx" = 1 ]]; then + if [[ "$cxxInclude" = 1 ]]; then + NIX_CFLAGS_COMPILE_@suffixSalt@+=" $NIX_CXXSTDLIB_COMPILE_@suffixSalt@" + fi + if [[ "$cxxLibrary" = 1 ]]; then + NIX_CFLAGS_LINK_@suffixSalt@+=" $NIX_CXXSTDLIB_LINK_@suffixSalt@" + fi +fi + +source $cc_wrapper/nix-support/add-hardening.sh + +# Add the flags for the C compiler proper. +addCFlagsToList() { + declare -n list="$1" + shift + + for ((i = 1; i <= $#; i++)); do + local val="${!i}" + case "$val" in + # Pass through using -Xcc, but also convert to Swift -I. + # These have slightly different meaning for Clang, but Swift + # doesn't have exact equivalents. + -isystem | -idirafter) + i=$((i + 1)) + list+=("-Xcc" "$val" "-Xcc" "${!i}" "-I" "${!i}") + ;; + # Simple rename. + -iframework) + i=$((i + 1)) + list+=("-Fsystem" "${!i}") + ;; + # Pass through verbatim. + -I | -Fsystem) + i=$((i + 1)) + list+=("${val}" "${!i}") + ;; + -I* | -L* | -F*) + list+=("${val}") + ;; + # Pass through using -Xcc. + *) + list+=("-Xcc" "$val") + ;; + esac + done +} +for i in ${NIX_SWIFTFLAGS_COMPILE:-}; do + extraAfter+=("$i") +done +for i in ${NIX_SWIFTFLAGS_COMPILE_BEFORE:-}; do + extraBefore+=("$i") +done +addCFlagsToList extraAfter $NIX_CFLAGS_COMPILE_@suffixSalt@ +addCFlagsToList extraBefore ${hardeningCFlags[@]+"${hardeningCFlags[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@ + +if [ "$dontLink" != 1 ]; then + + # Add the flags that should only be passed to the compiler when + # linking. + addCFlagsToList extraAfter $(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@) + + # Add the flags that should be passed to the linker (and prevent + # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again). + for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do + extraBefore+=("-Xlinker" "$i") + done + if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then + extraBefore+=("-Xlinker" "-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@") + fi + for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do + if [ "${i:0:3}" = -L/ ]; then + extraAfter+=("$i") + else + extraAfter+=("-Xlinker" "$i") + fi + done + export NIX_LINK_TYPE_@suffixSalt@=$linkType +fi + +# TODO: If we ever need to expand functionality of this hook, it may no longer +# be compatible with Swift. Right now, it is only used on Darwin to force +# -target, which also happens to work with Swift. +if [[ -e $cc_wrapper/nix-support/add-local-cc-cflags-before.sh ]]; then + source $cc_wrapper/nix-support/add-local-cc-cflags-before.sh +fi + +# May need to transform the triple injected by the above. +for ((i = 1; i < ${#extraBefore[@]}; i++)); do + if [[ "${extraBefore[i]}" = -target ]]; then + i=$((i + 1)) + # On Darwin only, need to change 'aarch64' to 'arm64'. + extraBefore[i]="${extraBefore[i]/aarch64-apple-/arm64-apple-}" + # On Darwin, Swift requires the triple to be annotated with a version. + # TODO: Assumes macOS. + extraBefore[i]="${extraBefore[i]/-apple-darwin/-apple-macosx${MACOSX_DEPLOYMENT_TARGET:-11.0}}" + break + fi +done + +# As a very special hack, if the arguments are just `-v', then don't +# add anything. This is to prevent `gcc -v' (which normally prints +# out the version number and returns exit code 0) from printing out +# `No input files specified' and returning exit code 1. +if [ "$*" = -v ]; then + extraAfter=() + extraBefore=() +fi + +# Optionally print debug info. +if (( "${NIX_DEBUG:-0}" >= 1 )); then + # Old bash workaround, see ld-wrapper for explanation. + echo "extra flags before to $prog:" >&2 + printf " %q\n" ${extraBefore+"${extraBefore[@]}"} >&2 + echo "original flags to $prog:" >&2 + printf " %q\n" ${params+"${params[@]}"} >&2 + echo "extra flags after to $prog:" >&2 + printf " %q\n" ${extraAfter+"${extraAfter[@]}"} >&2 +fi + +PATH="$path_backup" +# Old bash workaround, see above. + +if (( "${NIX_CC_USE_RESPONSE_FILE:-@use_response_file_by_default@}" >= 1 )); then + exec "$prog" @<(printf "%q\n" \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"}) +else + exec "$prog" \ + ${extraBefore+"${extraBefore[@]}"} \ + ${params+"${params[@]}"} \ + ${extraAfter+"${extraAfter[@]}"} +fi diff --git a/pkgs/development/compilers/swift/xctest/default.nix b/pkgs/development/compilers/swift/xctest/default.nix new file mode 100644 index 0000000000000..c8003d8486f10 --- /dev/null +++ b/pkgs/development/compilers/swift/xctest/default.nix @@ -0,0 +1,55 @@ +{ lib +, stdenv +, callPackage +, cmake +, ninja +, swift +, Foundation +, DarwinTools +}: + +let + sources = callPackage ../sources.nix { }; +in stdenv.mkDerivation { + pname = "swift-corelibs-xctest"; + + inherit (sources) version; + src = sources.swift-corelibs-xctest; + + outputs = [ "out" ]; + + nativeBuildInputs = [ cmake ninja swift ] + ++ lib.optional stdenv.isDarwin DarwinTools; # sw_vers + buildInputs = [ Foundation ]; + + postPatch = lib.optionalString stdenv.isDarwin '' + # On Darwin only, Swift uses arm64 as cpu arch. + substituteInPlace cmake/modules/SwiftSupport.cmake \ + --replace '"aarch64" PARENT_SCOPE' '"arm64" PARENT_SCOPE' + ''; + + preConfigure = '' + # On aarch64-darwin, our minimum target is 11.0, but we can target lower, + # and some dependants require a lower target. Harmless on non-Darwin. + export MACOSX_DEPLOYMENT_TARGET=10.12 + ''; + + cmakeFlags = lib.optional stdenv.isDarwin "-DUSE_FOUNDATION_FRAMEWORK=ON"; + + postInstall = lib.optionalString stdenv.isDarwin '' + # Darwin normally uses the Xcode version of XCTest. Installing + # swift-corelibs-xctest is probably not officially supported, but we have + # no alternative. Fix up the installation here. + mv $out/lib/swift/darwin/${swift.swiftArch}/* $out/lib/swift/darwin + rmdir $out/lib/swift/darwin/${swift.swiftArch} + mv $out/lib/swift/darwin $out/lib/swift/${swift.swiftOs} + ''; + + meta = { + description = "Framework for writing unit tests in Swift"; + homepage = "https://github.com/apple/swift-corelibs-xctest"; + platforms = lib.platforms.all; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + }; +} diff --git a/pkgs/development/libraries/swift-corelibs-libdispatch/default.nix b/pkgs/development/libraries/swift-corelibs-libdispatch/default.nix deleted file mode 100644 index 76cc0d3e30ef9..0000000000000 --- a/pkgs/development/libraries/swift-corelibs-libdispatch/default.nix +++ /dev/null @@ -1,42 +0,0 @@ -{ lib -, clangStdenv -, fetchFromGitHub -, cmake -, ninja -, libbsd -, libsystemtap -}: - -let - version = "5.5"; -in clangStdenv.mkDerivation { - pname = "swift-corelibs-libdispatch"; - inherit version; - - outputs = [ "out" "dev" "man" ]; - - src = fetchFromGitHub { - owner = "apple"; - repo = "swift-corelibs-libdispatch"; - rev = "swift-${version}-RELEASE"; - sha256 = "sha256-MbLgmS6qRSRT+2dGqbYTNb5MTM4Wz/grDXFk1kup+jk="; - }; - - nativeBuildInputs = [ - cmake - ninja - ]; - - buildInputs = [ - libbsd - libsystemtap - ]; - - meta = { - description = "Grand Central Dispatch"; - homepage = "https://github.com/apple/swift-corelibs-libdispatch"; - platforms = lib.platforms.linux; - license = lib.licenses.asl20; - maintainers = [ lib.maintainers.cmm ]; - }; -} diff --git a/pkgs/development/tools/swiftpm2nix/default.nix b/pkgs/development/tools/swiftpm2nix/default.nix new file mode 100644 index 0000000000000..25d6b06ef98bb --- /dev/null +++ b/pkgs/development/tools/swiftpm2nix/default.nix @@ -0,0 +1,25 @@ +{ lib, stdenv, callPackage, makeWrapper, jq, nix-prefetch-git }: + +stdenv.mkDerivation { + name = "swiftpm2nix"; + + nativeBuildInputs = [ makeWrapper ]; + + dontUnpack = true; + + installPhase = '' + install -vD ${./swiftpm2nix.sh} $out/bin/swiftpm2nix + wrapProgram $out/bin/$name \ + --prefix PATH : ${lib.makeBinPath [ jq nix-prefetch-git ]} \ + ''; + + preferLocalBuild = true; + + passthru = callPackage ./support.nix { }; + + meta = { + description = "Generate a Nix expression to fetch swiftpm dependencies"; + maintainers = with lib.maintainers; [ dtzWill trepetti dduan trundle stephank ]; + platforms = lib.platforms.all; + }; +} diff --git a/pkgs/development/tools/swiftpm2nix/support.nix b/pkgs/development/tools/swiftpm2nix/support.nix new file mode 100644 index 0000000000000..94076517ebfcf --- /dev/null +++ b/pkgs/development/tools/swiftpm2nix/support.nix @@ -0,0 +1,56 @@ +{ lib, fetchgit, formats }: +with lib; +let + json = formats.json { }; +in rec { + + # Derive a pin file from workspace state. + mkPinFile = workspaceState: + assert workspaceState.version == 5; + json.generate "Package.resolved" { + version = 1; + object.pins = map (dep: { + package = dep.packageRef.name; + repositoryURL = dep.packageRef.location; + state = dep.state.checkoutState; + }) workspaceState.object.dependencies; + }; + + # Make packaging helpers from swiftpm2nix generated output. + helpers = generated: let + inherit (import generated) workspaceStateFile hashes; + workspaceState = builtins.fromJSON (builtins.readFile workspaceStateFile); + pinFile = mkPinFile workspaceState; + in rec { + + # Create fetch expressions for dependencies. + sources = listToAttrs ( + map (dep: nameValuePair dep.subpath (fetchgit { + url = dep.packageRef.location; + rev = dep.state.checkoutState.revision; + sha256 = hashes.${dep.subpath}; + })) workspaceState.object.dependencies + ); + + # Configure phase snippet for use in packaging. + configure = '' + mkdir -p .build/checkouts + ln -sf ${pinFile} ./Package.resolved + install -m 0600 ${workspaceStateFile} ./.build/workspace-state.json + '' + + concatStrings (mapAttrsToList (name: src: '' + ln -s '${src}' '.build/checkouts/${name}' + '') sources) + + '' + # Helper that makes a swiftpm dependency mutable by copying the source. + swiftpmMakeMutable() { + local orig="$(readlink .build/checkouts/$1)" + rm .build/checkouts/$1 + cp -r "$orig" .build/checkouts/$1 + chmod -R u+w .build/checkouts/$1 + } + ''; + + }; + +} diff --git a/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh b/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh new file mode 100755 index 0000000000000..72051b4e448df --- /dev/null +++ b/pkgs/development/tools/swiftpm2nix/swiftpm2nix.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Generates a Nix expression to fetch swiftpm dependencies, and a +# configurePhase snippet to prepare a working directory for swift-build. + +set -eu -o pipefail +shopt -s lastpipe + +stateFile=".build/workspace-state.json" +if [[ ! -f "$stateFile" ]]; then + echo >&2 "Missing $stateFile. Run 'swift package resolve' first." + exit 1 +fi + +if [[ "$(jq .version $stateFile)" != "5" ]]; then + echo >&2 "Unsupported $stateFile version" + exit 1 +fi + +# Iterate dependencies and prefetch. +hashes="" +jq -r '.object.dependencies[] | "\(.subpath) \(.packageRef.location) \(.state.checkoutState.revision)"' $stateFile \ +| while read -r name url rev; do + echo >&2 "-- Fetching $name" + sha256="$(nix-prefetch-git $url $rev | jq -r .sha256)" + hashes+=" + \"$name\" = \"$sha256\";" + echo >&2 +done +hashes+=$'\n'" " + +# Generate output. +mkdir -p nix +# Copy the workspace state, but clear 'artifacts'. +jq '.object.artifacts = []' < $stateFile > nix/workspace-state.json +# Build an expression for fetching sources, and preparing the working directory. +cat > nix/default.nix << EOF +# This file was generated by swiftpm2nix. +{ + workspaceStateFile = ./workspace-state.json; + hashes = {$hashes}; +} +EOF +echo >&2 "-- Generated ./nix" diff --git a/pkgs/development/tools/xcbuild/sdks.nix b/pkgs/development/tools/xcbuild/sdks.nix index 5ff3ca6808dc8..e1b8254d7fd89 100644 --- a/pkgs/development/tools/xcbuild/sdks.nix +++ b/pkgs/development/tools/xcbuild/sdks.nix @@ -2,7 +2,7 @@ , writeText, version, xcodePlatform }: let - inherit (lib.generators) toPlist; + inherit (lib.generators) toPlist toJSON; SDKSettings = { CanonicalName = sdkName; @@ -22,6 +22,7 @@ in runCommand "SDKs" {} '' sdk=$out/${sdkName}.sdk install -D ${writeText "SDKSettings.plist" (toPlist {} SDKSettings)} $sdk/SDKSettings.plist + install -D ${writeText "SDKSettings.json" (toJSON {} SDKSettings)} $sdk/SDKSettings.json install -D ${writeText "SystemVersion.plist" (toPlist {} SystemVersion)} $sdk/System/Library/CoreServices/SystemVersion.plist ln -s $sdk $sdk/usr diff --git a/pkgs/development/tools/xcbuild/wrapper.nix b/pkgs/development/tools/xcbuild/wrapper.nix index 2dbea4e3833ae..35eddd40f859a 100644 --- a/pkgs/development/tools/xcbuild/wrapper.nix +++ b/pkgs/development/tools/xcbuild/wrapper.nix @@ -77,7 +77,7 @@ while [ $# -gt 0 ]; do --toolchain | -toolchain) shift ;; --find | -find | -f) shift - command -v $1 ;; + command -v $1 || exit 1 ;; --log | -log) ;; # noop --verbose | -verbose) ;; # noop --no-cache | -no-cache) ;; # noop diff --git a/pkgs/os-specific/darwin/apple-sdk-11.0/apple_sdk.nix b/pkgs/os-specific/darwin/apple-sdk-11.0/apple_sdk.nix index b7666fe31cdb1..ee384fb121333 100644 --- a/pkgs/os-specific/darwin/apple-sdk-11.0/apple_sdk.nix +++ b/pkgs/os-specific/darwin/apple-sdk-11.0/apple_sdk.nix @@ -45,12 +45,20 @@ let cp -r ${MacOSX-SDK}${standardFrameworkPath name private} $out/Library/Frameworks + if [[ -d ${MacOSX-SDK}/usr/lib/swift/${name}.swiftmodule ]]; then + mkdir -p $out/lib/swift + cp -r -t $out/lib/swift \ + ${MacOSX-SDK}/usr/lib/swift/${name}.swiftmodule \ + ${MacOSX-SDK}/usr/lib/swift/libswift${name}.tbd + fi + # Fix and check tbd re-export references chmod u+w -R $out find $out -name '*.tbd' -type f | while read tbd; do echo "Fixing re-exports in $tbd" rewrite-tbd \ -p ${standardFrameworkPath name private}/:$out/Library/Frameworks/${name}.framework/ \ + -p /usr/lib/swift/:$out/lib/swift/ \ ${mkDepsRewrites deps} \ -r ${builtins.storeDir} \ "$tbd" @@ -163,6 +171,15 @@ in rec { # Seems to be appropriate given https://developer.apple.com/forums/thread/666686 JavaVM = super.JavaNativeFoundation; + + CoreVideo = lib.overrideDerivation super.CoreVideo (drv: { + installPhase = drv.installPhase + '' + # When used as a module, complains about a missing import for + # Darwin.C.stdint. Apparently fixed in later SDKs. + awk -i inplace '/CFBase.h/ { print "#include " } { print }' \ + $out/Library/Frameworks/CoreVideo.framework/Headers/CVBase.h + ''; + }); }; bareFrameworks = ( diff --git a/pkgs/os-specific/darwin/apple-sdk-11.0/default.nix b/pkgs/os-specific/darwin/apple-sdk-11.0/default.nix index 42109062b72d0..53f8bf0b502b5 100644 --- a/pkgs/os-specific/darwin/apple-sdk-11.0/default.nix +++ b/pkgs/os-specific/darwin/apple-sdk-11.0/default.nix @@ -3,16 +3,7 @@ , xar, cpio, python3, pbzx }: let - MacOSX-SDK = stdenvNoCC.mkDerivation rec { - pname = "MacOSX-SDK"; - version = "11.0.0"; - - # https://swscan.apple.com/content/catalogs/others/index-11-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog - src = fetchurl { - url = "http://swcdn.apple.com/content/downloads/46/21/001-89745-A_56FM390IW5/v1um2qppgfdnam2e9cdqcqu2r6k8aa3lis/CLTools_macOSNMOS_SDK.pkg"; - sha256 = "0n425smj4q1vxbza8fzwnk323fyzbbq866q32w288c44hl5yhwsf"; - }; - + mkSusDerivation = args: stdenvNoCC.mkDerivation (args // { dontBuild = true; darwinDontCodeSign = true; @@ -24,16 +15,45 @@ let pbzx $src | cpio -idm ''; + passthru = { + inherit (args) version; + }; + }); + + MacOSX-SDK = mkSusDerivation { + pname = "MacOSX-SDK"; + version = "11.0.0"; + + # https://swscan.apple.com/content/catalogs/others/index-11-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog + src = fetchurl { + url = "http://swcdn.apple.com/content/downloads/46/21/001-89745-A_56FM390IW5/v1um2qppgfdnam2e9cdqcqu2r6k8aa3lis/CLTools_macOSNMOS_SDK.pkg"; + sha256 = "0n425smj4q1vxbza8fzwnk323fyzbbq866q32w288c44hl5yhwsf"; + }; + installPhase = '' cd Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk mkdir $out cp -r System usr $out/ ''; + }; - passthru = { - inherit version; + CLTools_Executables = mkSusDerivation { + pname = "CLTools_Executables"; + version = "11.0.0"; + + # https://swscan.apple.com/content/catalogs/others/index-11-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog + src = fetchurl { + url = "http://swcdn.apple.com/content/downloads/46/21/001-89745-A_56FM390IW5/v1um2qppgfdnam2e9cdqcqu2r6k8aa3lis/CLTools_Executables.pkg"; + sha256 = "0nvb1qx7l81l2wcl8wvgbpsg5rcn51ylhivqmlfr2hrrv3zrrpl0"; }; + + installPhase = '' + cd Library/Developer/CommandLineTools + + mkdir $out + cp -r Library usr $out/ + ''; }; callPackage = newScope (packages // pkgs.darwin // { inherit MacOSX-SDK; }); @@ -43,7 +63,7 @@ let # TODO: this is nice to be private. is it worth the callPackage above? # Probably, I don't think that callPackage costs much at all. - inherit MacOSX-SDK; + inherit MacOSX-SDK CLTools_Executables; Libsystem = callPackage ./libSystem.nix {}; LibsystemCross = pkgs.darwin.Libsystem; diff --git a/pkgs/os-specific/darwin/apple-sdk-11.0/frameworks.nix b/pkgs/os-specific/darwin/apple-sdk-11.0/frameworks.nix index 8c2a9a4d5484c..2cf1c5dd0fc88 100644 --- a/pkgs/os-specific/darwin/apple-sdk-11.0/frameworks.nix +++ b/pkgs/os-specific/darwin/apple-sdk-11.0/frameworks.nix @@ -75,7 +75,7 @@ FileProviderUI = {}; FinderSync = {}; ForceFeedback = { inherit IOKit; }; - Foundation = { inherit ApplicationServices CoreFoundation Security SystemConfiguration libobjc; }; + Foundation = { inherit ApplicationServices CoreFoundation Security SystemConfiguration Combine libobjc; }; GLKit = {}; GLUT = { inherit OpenGL; }; GSS = {}; @@ -169,7 +169,7 @@ Speech = {}; SpriteKit = {}; StoreKit = {}; - SwiftUI = {}; + SwiftUI = { inherit AppKit DeveloperToolsSupport UniformTypeIdentifiers; }; SyncServices = {}; System = {}; SystemConfiguration = { inherit Security; }; diff --git a/pkgs/os-specific/darwin/apple-sdk-11.0/libSystem.nix b/pkgs/os-specific/darwin/apple-sdk-11.0/libSystem.nix index 0297f8897f12d..7be670425d7af 100644 --- a/pkgs/os-specific/darwin/apple-sdk-11.0/libSystem.nix +++ b/pkgs/os-specific/darwin/apple-sdk-11.0/libSystem.nix @@ -26,7 +26,7 @@ stdenvNoCC.mkDerivation { ]; installPhase = '' - mkdir -p $out/{include,lib} + mkdir -p $out/{include,lib/swift} for dir in $includeDirs; do from=${MacOSX-SDK}/usr/include/$dir @@ -57,6 +57,13 @@ stdenvNoCC.mkDerivation { $out/lib done + for name in os Dispatch; do + cp -dr \ + ${MacOSX-SDK}/usr/lib/swift/$name.swiftmodule \ + ${MacOSX-SDK}/usr/lib/swift/libswift$name.tbd \ + $out/lib/swift + done + for f in $csu; do from=${MacOSX-SDK}/usr/lib/$f if [ -e "$from" ]; then @@ -71,6 +78,7 @@ stdenvNoCC.mkDerivation { rewrite-tbd \ -c /usr/lib/libsystem.dylib:$out/lib/libsystem.dylib \ -p /usr/lib/system/:$out/lib/system/ \ + -p /usr/lib/swift/:$out/lib/swift/ \ -r ${builtins.storeDir} \ "$tbd" done diff --git a/pkgs/os-specific/darwin/apple-sdk-11.0/libobjc.nix b/pkgs/os-specific/darwin/apple-sdk-11.0/libobjc.nix index 63ef2a1c263e0..9288097ef3699 100644 --- a/pkgs/os-specific/darwin/apple-sdk-11.0/libobjc.nix +++ b/pkgs/os-specific/darwin/apple-sdk-11.0/libobjc.nix @@ -8,14 +8,17 @@ let self = stdenvNoCC.mkDerivation { dontBuild = true; installPhase = '' - mkdir -p $out/{include,lib} + mkdir -p $out/{include,lib/swift} cp -r ${MacOSX-SDK}/usr/include/objc $out/include cp ${MacOSX-SDK}/usr/lib/libobjc* $out/lib + cp -r ${MacOSX-SDK}/usr/lib/swift/ObjectiveC.swiftmodule $out/lib/swift + cp ${MacOSX-SDK}/usr/lib/swift/libswiftObjectiveC.tbd $out/lib/swift ''; passthru = { tbdRewrites = { const."/usr/lib/libobjc.A.dylib" = "${self}/lib/libobjc.A.dylib"; + const."/usr/lib/swift/libswiftObjectiveC.dylib" = "${self}/lib/swift/libswiftObjectiveC.dylib"; }; }; }; in self diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 4111e2ba03fba..e38850a768acd 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -15775,7 +15775,10 @@ with pkgs; svdtools = callPackage ../development/embedded/svdtools { }; - swift = callPackage ../development/compilers/swift { }; + swiftPackages = recurseIntoAttrs (callPackage ../development/compilers/swift { }); + inherit (swiftPackages) swift swiftpm sourcekit-lsp; + + swiftpm2nix = callPackage ../development/tools/swiftpm2nix { }; swiProlog = callPackage ../development/compilers/swi-prolog { openssl = openssl_1_1; @@ -38582,7 +38585,7 @@ with pkgs; mictray = callPackage ../tools/audio/mictray { }; - swift-corelibs-libdispatch = callPackage ../development/libraries/swift-corelibs-libdispatch { }; + swift-corelibs-libdispatch = swiftPackages.Dispatch; swaysettings = callPackage ../applications/misc/swaysettings { };