nixpkgs/pkgs/development/compilers/swift/default.nix

405 lines
13 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ lib, stdenv
, cmake
, coreutils
, glibc
, gccForLibs
, which
, perl
, libedit
, ninja
, pkg-config
, sqlite
, swig
, libxml2
, clang_10
, python3
, ncurses
, libuuid
, libbsd
, icu
, libgcc
, autoconf
, libtool
, automake
, libblocksruntime
, curl
, rsync
, git
, libgit2
, fetchFromGitHub
, fetchpatch
, makeWrapper
, gnumake
, file
}:
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
versions = {
swift = "5.5.3";
yams = "4.0.2";
argumentParser = "0.4.3";
format = "swift-5.5-branch";
crypto = "1.1.5";
};
fetchAppleRepo = { repo, rev, sha256 }:
fetchFromGitHub {
owner = "apple";
inherit repo rev sha256;
name = "${repo}-${rev}-src";
};
fetchSwiftRelease = { repo, sha256, fetchSubmodules ? false }:
fetchFromGitHub {
owner = "apple";
inherit repo sha256 fetchSubmodules;
rev = "swift-${versions.swift}-RELEASE";
name = "${repo}-${versions.swift}-src";
};
sources = {
# Projects that share `versions.swift` for each release.
swift = fetchSwiftRelease {
repo = "swift";
sha256 = "0ma96sfvwiv2f4qhzrvcwxi9igzd80930gnaw4r7ra4w190cnag7";
};
cmark = fetchSwiftRelease {
repo = "swift-cmark";
sha256 = "0340j9x2n40yx61ma2pgqfbn3a9ijrh20iwzd1zxqq87rr76hh3z";
};
llbuild = fetchSwiftRelease {
repo = "swift-llbuild";
sha256 = "1xmiv7yp9r9iscx3fc3zdp25mriz134k9ny2rchxzi4kifz8h0zc";
};
driver = fetchSwiftRelease {
repo = "swift-driver";
sha256 = "1pb7fidgdqxzragqkillkv03vdilrwmcx6x2r4czqvdqj37gy6b6";
};
toolsSupportCore = fetchSwiftRelease {
repo = "swift-tools-support-core";
sha256 = "0a63193nycir4lffvmb3ky8cfly5kdr2libki2gx4fn6fxmb3a2f";
};
swiftpm = fetchSwiftRelease {
repo = "swift-package-manager";
sha256 = "0z90mg837jzwh516pypn48r3wsjf0lqymsyigdhgr7j2sgcckrr1";
};
syntax = fetchSwiftRelease {
repo = "swift-syntax";
sha256 = "0kdgh9a8n28yh12hj8lbz2j66ag83l0lcfyfdg7zdr614zs6i3p1";
};
corelibsXctest = fetchSwiftRelease {
repo = "swift-corelibs-xctest";
sha256 = "12fp3xzsqwcrmyc55h91d3dm64wn3wln47x2fl7sj0s8cn7q12b3";
};
corelibsFoundation = fetchSwiftRelease {
repo = "swift-corelibs-foundation";
sha256 = "06gkdliihl1l86jx5khzwkjmjk45fq290x033rscramzcdxh7d1b";
};
corelibsLibdispatch = fetchSwiftRelease {
repo = "swift-corelibs-libdispatch";
sha256 = "1bim5x9z9bqfgs6gdm4nlz1zrwl2x7xh4dn6i5md9ygsplr4ibzf";
fetchSubmodules = true;
};
indexstoreDb = fetchSwiftRelease {
repo = "indexstore-db";
sha256 = "1l1xlzf5kx7x80kf4b7r36glv0jc64d08d1688kmzjq1cfgn6gm2";
};
sourcekitLsp = fetchSwiftRelease {
repo = "sourcekit-lsp";
sha256 = "00fcmd7x5v62n6ajsc0dmzwz6nzy2p72mcs9w6p90adcx7pffqkn";
};
llvmProject = fetchSwiftRelease {
repo = "llvm-project";
sha256 = "18rn5xg5hpxxsacs0ygjmjpzpc8pq85898kknzc0s0z5m55h45z8";
};
# Projects that have their own versions during each release
argumentParser = fetchAppleRepo {
repo = "swift-argument-parser";
rev = "${versions.argumentParser}";
sha256 = "1jkq72fphxzsnynjxk72azp0iz5r2ji7adxrz6w1y2a19pgjdqrp";
};
format = fetchAppleRepo {
repo = "swift-format";
rev = "${versions.format}";
sha256 = "1hg888ps3fk23q2zf6djkvxyk6zndqvwypmy0s800hmnyf0hzgv4";
};
crypto = fetchAppleRepo {
repo = "swift-crypto";
rev = "${versions.crypto}";
sha256 = "0918pj3x3wgli3bnrjbvpzck2n6qz5n6f4yc5kljky45wd15f34g";
};
yams = fetchFromGitHub {
owner = "jpsim";
repo = "Yams";
rev = versions.yams;
sha256 = "1nk9b7l6m3wwjkl81npl2l1iwpsxaxb9za53jpwwsbbi1h1h4fbi";
name = "Yams-${versions.yams}-src";
};
};
devInputs = [
curl
glibc
icu
libblocksruntime
libbsd
libedit
libgcc
libuuid
libxml2
ncurses
sqlite
swig
];
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 = [
autoconf
automake
cmake
git
libtool
makeWrapper
ninja
perl
pkg-config
python
rsync
which
];
buildInputs = devInputs ++ [
clang_10
];
# 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
chmod -R u+w .
'';
patchPhase = ''
# Just patch all the things for now, we can focus this later.
patchShebangs $SWIFT_SOURCE_ROOT
# 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}
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}
patch -p1 -d llvm-project/compiler-rt -i ${../llvm/common/compiler-rt/libsanitizer-no-cyclades-11.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"
'';
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_10}/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_10}/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
# 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
# Extract the generated tarball into the store.
tar xf $INSTALLABLE_PACKAGE -C $out --strip-components=3 ''${out/#\/}
find $out -type d -empty -delete
# Fix installation weirdness, also present in Apples 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
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]}
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]}
'';
# Hack to avoid build and install directories in RPATHs.
preFixup = "rm -rf $SWIFT_BUILD_ROOT $SWIFT_INSTALL_DIR";
meta = with lib; {
description = "The Swift Programming Language";
homepage = "https://github.com/apple/swift";
maintainers = with maintainers; [ dtzWill trepetti dduan ];
license = licenses.asl20;
# Swift doesn't support 32-bit Linux, unknown on other platforms.
platforms = platforms.linux;
badPlatforms = platforms.i686;
timeout = 86400; # 24 hours.
};
}