depot/third_party/nixpkgs/pkgs/development/compilers/swift/swiftpm/default.nix
Default email a0cb138ada Project import generated by Copybara.
GitOrigin-RevId: a100acd7bbf105915b0004427802286c37738fef
2023-02-02 18:25:31 +00:00

419 lines
13 KiB
Nix

{ 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-index-store.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 ];
};
})