at master 15 kB view raw
1{ 2 lib, 3 stdenv, 4 callPackage, 5 fetchpatch, 6 cmake, 7 ninja, 8 git, 9 swift, 10 swiftpm2nix, 11 Foundation, 12 XCTest, 13 pkg-config, 14 sqlite, 15 ncurses, 16 replaceVars, 17 runCommandLocal, 18 makeWrapper, 19 DarwinTools, # sw_vers 20 cctools, # vtool 21 xcbuild, 22}: 23 24let 25 26 inherit (swift) swiftOs swiftModuleSubdir swiftStaticModuleSubdir; 27 sharedLibraryExt = stdenv.hostPlatform.extensions.sharedLibrary; 28 29 sources = callPackage ../sources.nix { }; 30 generated = swiftpm2nix.helpers ./generated; 31 cmakeGlue = callPackage ./cmake-glue.nix { }; 32 33 # Common attributes for the bootstrap swiftpm and the final swiftpm. 34 commonAttrs = { 35 inherit (sources) version; 36 src = sources.swift-package-manager; 37 nativeBuildInputs = [ makeWrapper ]; 38 # Required at run-time for the host platform to build package manifests. 39 propagatedBuildInputs = [ Foundation ]; 40 patches = [ 41 ./patches/cmake-disable-rpath.patch 42 ./patches/cmake-fix-quoting.patch 43 ./patches/disable-index-store.patch 44 ./patches/disable-sandbox.patch 45 ./patches/disable-xctest.patch 46 ./patches/fix-clang-cxx.patch 47 ./patches/nix-pkgconfig-vars.patch 48 (replaceVars ./patches/fix-stdlib-path.patch { 49 inherit (builtins) storeDir; 50 swiftLib = swift.swift.lib; 51 }) 52 ]; 53 postPatch = '' 54 # The location of xcrun is hardcoded. We need PATH lookup instead. 55 find Sources -name '*.swift' | xargs sed -i -e 's|/usr/bin/xcrun|xcrun|g' 56 57 # Patch the location where swiftpm looks for its API modules. 58 substituteInPlace Sources/PackageModel/UserToolchain.swift \ 59 --replace \ 60 'librariesPath = applicationPath.parentDirectory' \ 61 "librariesPath = AbsolutePath(\"$out\")" 62 63 # Fix case-sensitivity issues. 64 # Upstream PR: https://github.com/apple/swift-package-manager/pull/6500 65 substituteInPlace Sources/CMakeLists.txt \ 66 --replace \ 67 'packageCollectionsSigning' \ 68 'PackageCollectionsSigning' 69 substituteInPlace Sources/PackageCollectionsSigning/CMakeLists.txt \ 70 --replace \ 71 'SubjectPublickeyInfo' \ 72 'SubjectPublicKeyInfo' 73 substituteInPlace Sources/PackageCollections/CMakeLists.txt \ 74 --replace \ 75 'FilepackageCollectionsSourcesStorage' \ 76 'FilePackageCollectionsSourcesStorage' 77 ''; 78 }; 79 80 # Tools invoked by swiftpm at run-time. 81 runtimeDeps = [ 82 git 83 ] 84 ++ lib.optionals stdenv.hostPlatform.isDarwin [ 85 xcbuild.xcrun 86 # These tools are part of cctools, but adding that as a build input puts 87 # an unwrapped linker in PATH, and breaks builds. This small derivation 88 # exposes just the tools we need: 89 # - vtool is used to determine a minimum deployment target. 90 # - libtool is used to build static libraries. 91 (runCommandLocal "swiftpm-cctools" { } '' 92 mkdir -p $out/bin 93 ln -s ${cctools}/bin/vtool $out/bin/vtool 94 ln -s ${cctools}/bin/libtool $out/bin/libtool 95 '') 96 ]; 97 98 # Common attributes for the bootstrap derivations. 99 mkBootstrapDerivation = 100 attrs: 101 stdenv.mkDerivation ( 102 attrs 103 // { 104 nativeBuildInputs = 105 (attrs.nativeBuildInputs or [ ]) 106 ++ [ 107 cmake 108 ninja 109 swift 110 ] 111 ++ lib.optionals stdenv.hostPlatform.isDarwin [ DarwinTools ]; 112 113 buildInputs = (attrs.buildInputs or [ ]) ++ [ Foundation ]; 114 115 postPatch = 116 (attrs.postPatch or "") 117 + lib.optionalString stdenv.hostPlatform.isDarwin '' 118 # On Darwin only, Swift uses arm64 as cpu arch. 119 if [ -e cmake/modules/SwiftSupport.cmake ]; then 120 substituteInPlace cmake/modules/SwiftSupport.cmake \ 121 --replace '"aarch64" PARENT_SCOPE' '"arm64" PARENT_SCOPE' 122 fi 123 ''; 124 125 postInstall = 126 (attrs.postInstall or "") 127 + lib.optionalString stdenv.hostPlatform.isDarwin '' 128 # The install name of libraries is incorrectly set to lib/ (via our 129 # CMake setup hook) instead of lib/swift/. This'd be easily fixed by 130 # fixDarwinDylibNames, but some builds create libraries that reference 131 # eachother, and we also have to fix those references. 132 dylibs="$(find $out/lib/swift* -name '*.dylib')" 133 changes="" 134 for dylib in $dylibs; do 135 changes+=" -change $(otool -D $dylib | tail -n 1) $dylib" 136 done 137 for dylib in $dylibs; do 138 install_name_tool -id $dylib $changes $dylib 139 done 140 ''; 141 142 cmakeFlags = (attrs.cmakeFlags or [ ]) ++ [ 143 # Some builds link to libraries within the same build. Make sure these 144 # create references to $out. None of our builds run their own products, 145 # so we don't have to account for that scenario. 146 "-DCMAKE_BUILD_WITH_INSTALL_NAME_DIR=ON" 147 ]; 148 } 149 ); 150 151 # On Darwin, we only want ncurses in the linker search path, because headers 152 # are part of libsystem. Adding its headers to the search path causes strange 153 # mixing and errors. 154 # TODO: Find a better way to prevent this conflict. 155 ncursesInput = if stdenv.hostPlatform.isDarwin then ncurses.out else ncurses; 156 157 # Derivations for bootstrapping dependencies using CMake. 158 # This is based on the `swiftpm/Utilities/bootstrap` script. 159 # 160 # Some of the installation steps here are a bit hacky, because it seems like 161 # these packages were not really meant to be installed using CMake. The 162 # regular swiftpm bootstrap simply refers to the source and build 163 # directories. The advantage of separate builds is that we can more easily 164 # link libs together using existing Nixpkgs infra. 165 # 166 # In the end, we don't expose these derivations, and they only exist during 167 # the bootstrap phase. The final swiftpm derivation does not depend on them. 168 169 swift-system = mkBootstrapDerivation { 170 name = "swift-system"; 171 src = generated.sources.swift-system; 172 173 postInstall = 174 cmakeGlue.SwiftSystem 175 + lib.optionalString (!stdenv.hostPlatform.isDarwin) '' 176 # The cmake rules apparently only use the Darwin install convention. 177 # Fix up the installation so the module can be found on non-Darwin. 178 mkdir -p $out/${swiftStaticModuleSubdir} 179 mv $out/lib/swift_static/${swiftOs}/*.swiftmodule $out/${swiftStaticModuleSubdir}/ 180 ''; 181 }; 182 183 swift-collections = mkBootstrapDerivation { 184 name = "swift-collections"; 185 src = generated.sources.swift-collections; 186 187 postPatch = '' 188 # Only builds static libs on Linux, but this installation difference is a 189 # hassle. Because this installation is temporary for the bootstrap, may 190 # as well build static libs everywhere. 191 sed -i -e '/BUILD_SHARED_LIBS/d' CMakeLists.txt 192 ''; 193 194 postInstall = 195 cmakeGlue.SwiftCollections 196 + lib.optionalString (!stdenv.hostPlatform.isDarwin) '' 197 # The cmake rules apparently only use the Darwin install convention. 198 # Fix up the installation so the module can be found on non-Darwin. 199 mkdir -p $out/${swiftStaticModuleSubdir} 200 mv $out/lib/swift_static/${swiftOs}/*.swiftmodule $out/${swiftStaticModuleSubdir}/ 201 ''; 202 }; 203 204 # Part of this patch fixes for glibc 2.39: glibc patch 64b1a44183a3094672ed304532bedb9acc707554 205 # marks the `FILE*` argument to a few functions including `ferror` & `fread` as non-null. However 206 # the code passes an `Optional<T>` to these functions. 207 # This patch uses a `guard` which effectively unwraps the type (or throws an exception). 208 swift-tools-support-core-glibc-fix = fetchpatch { 209 url = "https://github.com/apple/swift-tools-support-core/commit/990afca47e75cce136d2f59e464577e68a164035.patch"; 210 hash = "sha256-PLzWsp+syiUBHhEFS8+WyUcSae5p0Lhk7SSRdNvfouE="; 211 includes = [ "Sources/TSCBasic/FileSystem.swift" ]; 212 }; 213 214 swift-tools-support-core = mkBootstrapDerivation { 215 name = "swift-tools-support-core"; 216 src = generated.sources.swift-tools-support-core; 217 218 patches = [ 219 swift-tools-support-core-glibc-fix 220 ]; 221 222 buildInputs = [ 223 swift-system 224 sqlite 225 ]; 226 227 postInstall = cmakeGlue.TSC + '' 228 # Swift modules are not installed. 229 mkdir -p $out/${swiftModuleSubdir} 230 cp swift/*.swift{module,doc} $out/${swiftModuleSubdir}/ 231 232 # Static libs are not installed. 233 cp lib/*.a $out/lib/ 234 235 # Headers are not installed. 236 mkdir -p $out/include 237 cp -r ../Sources/TSCclibc/include $out/include/TSC 238 ''; 239 }; 240 241 swift-argument-parser = mkBootstrapDerivation { 242 name = "swift-argument-parser"; 243 src = generated.sources.swift-argument-parser; 244 245 buildInputs = [ 246 ncursesInput 247 sqlite 248 ]; 249 250 cmakeFlags = [ 251 "-DBUILD_TESTING=NO" 252 "-DBUILD_EXAMPLES=NO" 253 ]; 254 255 postInstall = 256 cmakeGlue.ArgumentParser 257 + lib.optionalString stdenv.hostPlatform.isLinux '' 258 # Fix rpath so ArgumentParserToolInfo can be found. 259 patchelf --add-rpath "$out/lib/swift/${swiftOs}" \ 260 $out/lib/swift/${swiftOs}/libArgumentParser.so 261 ''; 262 }; 263 264 Yams = mkBootstrapDerivation { 265 name = "Yams"; 266 src = generated.sources.Yams; 267 268 # Conflicts with BUILD file on case-insensitive filesystems. 269 cmakeBuildDir = "_build"; 270 271 postInstall = cmakeGlue.Yams; 272 }; 273 274 llbuild = mkBootstrapDerivation { 275 name = "llbuild"; 276 src = generated.sources.swift-llbuild; 277 278 nativeBuildInputs = lib.optional stdenv.hostPlatform.isDarwin xcbuild; 279 buildInputs = [ 280 ncursesInput 281 sqlite 282 ]; 283 284 patches = [ 285 ./patches/llbuild-cmake-disable-rpath.patch 286 ]; 287 288 postPatch = '' 289 # Substitute ncurses for curses. 290 find . -name CMakeLists.txt | xargs sed -i -e 's/curses/ncurses/' 291 292 # Use absolute install names instead of rpath. 293 substituteInPlace \ 294 products/libllbuild/CMakeLists.txt \ 295 products/llbuildSwift/CMakeLists.txt \ 296 --replace '@rpath' "$out/lib" 297 298 # This subdirectory is enabled for Darwin only, but requires ObjC XCTest 299 # (and only Swift XCTest is open source). 300 substituteInPlace perftests/CMakeLists.txt \ 301 --replace 'add_subdirectory(Xcode/' '#add_subdirectory(Xcode/' 302 ''; 303 304 cmakeFlags = [ 305 "-DLLBUILD_SUPPORT_BINDINGS=Swift" 306 ]; 307 308 postInstall = cmakeGlue.LLBuild + '' 309 # Install module map. 310 cp ../products/libllbuild/include/module.modulemap $out/include 311 312 # Swift modules are not installed. 313 mkdir -p $out/${swiftModuleSubdir} 314 cp products/llbuildSwift/*.swift{module,doc} $out/${swiftModuleSubdir}/ 315 ''; 316 }; 317 318 swift-driver = mkBootstrapDerivation { 319 name = "swift-driver"; 320 src = generated.sources.swift-driver; 321 322 buildInputs = [ 323 Yams 324 llbuild 325 swift-system 326 swift-argument-parser 327 swift-tools-support-core 328 ]; 329 330 postPatch = '' 331 # Tries to link against CYaml, but that's private. 332 substituteInPlace Sources/SwiftDriver/CMakeLists.txt \ 333 --replace CYaml "" 334 ''; 335 336 postInstall = cmakeGlue.SwiftDriver + '' 337 # Swift modules are not installed. 338 mkdir -p $out/${swiftModuleSubdir} 339 cp swift/*.swift{module,doc} $out/${swiftModuleSubdir}/ 340 ''; 341 }; 342 343 swift-crypto = mkBootstrapDerivation { 344 name = "swift-crypto"; 345 src = generated.sources.swift-crypto; 346 347 postPatch = '' 348 # Fix use of hardcoded tool paths on Darwin. 349 substituteInPlace CMakeLists.txt \ 350 --replace /usr/bin/ar $NIX_CC/bin/ar 351 substituteInPlace CMakeLists.txt \ 352 --replace /usr/bin/ranlib $NIX_CC/bin/ranlib 353 ''; 354 355 postInstall = cmakeGlue.SwiftCrypto + '' 356 # Static libs are not installed. 357 cp lib/*.a $out/lib/ 358 359 # Headers are not installed. 360 cp -r ../Sources/CCryptoBoringSSL/include $out/include 361 ''; 362 }; 363 364 # Build a bootrapping swiftpm using CMake. 365 swiftpm-bootstrap = mkBootstrapDerivation ( 366 commonAttrs 367 // { 368 pname = "swiftpm-bootstrap"; 369 370 buildInputs = [ 371 llbuild 372 sqlite 373 swift-argument-parser 374 swift-collections 375 swift-crypto 376 swift-driver 377 swift-system 378 swift-tools-support-core 379 ]; 380 381 cmakeFlags = [ 382 "-DUSE_CMAKE_INSTALL=ON" 383 ]; 384 385 postInstall = '' 386 for program in $out/bin/swift-*; do 387 wrapProgram $program --prefix PATH : ${lib.makeBinPath runtimeDeps} 388 done 389 ''; 390 } 391 ); 392 393in 394# Build the final swiftpm with the bootstrapping swiftpm. 395stdenv.mkDerivation ( 396 commonAttrs 397 // { 398 pname = "swiftpm"; 399 400 nativeBuildInputs = commonAttrs.nativeBuildInputs ++ [ 401 pkg-config 402 swift 403 swiftpm-bootstrap 404 ]; 405 buildInputs = [ 406 ncursesInput 407 sqlite 408 XCTest 409 ]; 410 411 configurePhase = generated.configure + '' 412 # Functionality provided by Xcode XCTest, but not available in 413 # swift-corelibs-xctest. 414 swiftpmMakeMutable swift-tools-support-core 415 substituteInPlace .build/checkouts/swift-tools-support-core/Sources/TSCTestSupport/XCTestCasePerf.swift \ 416 --replace 'canImport(Darwin)' 'false' 417 patch -p1 -d .build/checkouts/swift-tools-support-core -i ${swift-tools-support-core-glibc-fix} 418 419 # Prevent a warning about SDK directories we don't have. 420 swiftpmMakeMutable swift-driver 421 patch -p1 -d .build/checkouts/swift-driver -i ${ 422 replaceVars ../swift-driver/patches/prevent-sdk-dirs-warnings.patch { 423 inherit (builtins) storeDir; 424 } 425 } 426 ''; 427 428 buildPhase = '' 429 TERM=dumb swift-build -c release 430 ''; 431 432 # TODO: Tests depend on indexstore-db being provided by an existing Swift 433 # toolchain. (ie. looks for `../lib/libIndexStore.so` relative to swiftc. 434 #doCheck = true; 435 #checkPhase = '' 436 # TERM=dumb swift-test -c release 437 #''; 438 439 # The following is derived from Utilities/bootstrap, see install_swiftpm. 440 installPhase = '' 441 binPath="$(swift-build --show-bin-path -c release)" 442 443 mkdir -p $out/bin $out/lib/swift 444 445 cp $binPath/swift-package-manager $out/bin/swift-package 446 wrapProgram $out/bin/swift-package \ 447 --prefix PATH : ${lib.makeBinPath runtimeDeps} 448 for tool in swift-build swift-test swift-run swift-package-collection swift-experimental-destination; do 449 ln -s $out/bin/swift-package $out/bin/$tool 450 done 451 452 installSwiftpmModule() { 453 mkdir -p $out/lib/swift/pm/$2 454 cp $binPath/lib$1${sharedLibraryExt} $out/lib/swift/pm/$2/ 455 456 if [[ -f $binPath/$1.swiftinterface ]]; then 457 cp $binPath/$1.swiftinterface $out/lib/swift/pm/$2/ 458 else 459 cp -r $binPath/$1.swiftmodule $out/lib/swift/pm/$2/ 460 fi 461 cp $binPath/$1.swiftdoc $out/lib/swift/pm/$2/ 462 } 463 installSwiftpmModule PackageDescription ManifestAPI 464 installSwiftpmModule PackagePlugin PluginAPI 465 ''; 466 467 setupHook = ./setup-hook.sh; 468 469 meta = { 470 description = "Package Manager for the Swift Programming Language"; 471 homepage = "https://github.com/apple/swift-package-manager"; 472 platforms = with lib.platforms; linux ++ darwin; 473 license = lib.licenses.asl20; 474 teams = [ lib.teams.swift ]; 475 }; 476 } 477)