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