diff --git a/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift b/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift index c33f124..d5090e5 100644 --- a/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift +++ b/Sources/SwiftSDKGenerator/Artifacts/DownloadableArtifacts.swift @@ -14,7 +14,7 @@ import struct Foundation.URL import struct SystemPackage.FilePath /// Information about the OS for which the artifact is built, if it's downloaded as prebuilt. -private enum ArtifactOS: Hashable { +enum ArtifactOS: Hashable { init(_ tripleOS: Triple.OS, _ versions: VersionsConfiguration) { switch tripleOS { case .linux: @@ -24,7 +24,7 @@ private enum ArtifactOS: Hashable { case .wasi: self = .wasi case .win32: - self = .windows + self = .windows } } diff --git a/Sources/SwiftSDKGenerator/Generator/LocalSwiftSDKGenerator.swift b/Sources/SwiftSDKGenerator/Generator/LocalSwiftSDKGenerator.swift index 345e1c8..68a0140 100644 --- a/Sources/SwiftSDKGenerator/Generator/LocalSwiftSDKGenerator.swift +++ b/Sources/SwiftSDKGenerator/Generator/LocalSwiftSDKGenerator.swift @@ -344,6 +344,21 @@ public final class LocalSwiftSDKGenerator: SwiftSDKGenerator { } } + public func buildCMakeProject(_ projectPath: FilePath, options: String) async throws -> FilePath { + try await Shell.run( + """ + PATH='/bin:/usr/bin:\(Self.homebrewPrefix)/bin' \ + cmake -B build -G Ninja -S llvm -DCMAKE_BUILD_TYPE=Release \(options) + """, + currentDirectory: projectPath + ) + + let buildDirectory = projectPath.appending("build") + try await Shell.run("PATH='/bin:/usr/bin:\(Self.homebrewPrefix)/bin' ninja", currentDirectory: buildDirectory) + + return buildDirectory + } + public func inTemporaryDirectory( _ closure: @Sendable (LocalSwiftSDKGenerator, FilePath) async throws -> T ) async throws -> T { diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Build.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Build.swift new file mode 100644 index 0000000..d3c73e4 --- /dev/null +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Build.swift @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2022-2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SystemPackage + +extension SwiftSDKGenerator { + func buildLLD(llvmSourcesDirectory: FilePath) async throws -> FilePath { + let buildDirectory = try await self.buildCMakeProject( + llvmSourcesDirectory, + options: "-DLLVM_ENABLE_PROJECTS=lld -DLLVM_TARGETS_TO_BUILD=\(self.targetTriple.cpu.llvmTargetConventionName)" + ) + + return buildDirectory.appending("bin").appending("lld") + } +} diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift index a548f3b..b48aa3f 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Download.swift @@ -42,12 +42,12 @@ extension SwiftSDKGenerator { print("Using these URLs for downloads:") + for artifact in downloadableArtifacts.allItems { + print(artifact.remoteURL) + } + // FIXME: some code duplication is necessary due to https://github.com/apple/swift-async-algorithms/issues/226 if shouldUseDocker { - for artifact in [downloadableArtifacts.hostSwift, downloadableArtifacts.hostLLVM] { - print(artifact.remoteURL) - } - let stream = combineLatest(hostSwiftProgressStream, hostLLVMProgressStream) .throttle(for: .seconds(1)) @@ -56,13 +56,6 @@ extension SwiftSDKGenerator { report(progress: llvmProgress, for: downloadableArtifacts.hostLLVM) } } else { - for artifact in [ - downloadableArtifacts.hostSwift, - downloadableArtifacts.hostLLVM, - downloadableArtifacts.targetSwift, - ] { - print(artifact.remoteURL) - } let targetSwiftProgressStream = client.streamDownloadProgress(for: downloadableArtifacts.targetSwift) .removeDuplicates(by: didProgressChangeSignificantly) diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Unpack.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Unpack.swift index 492c693..a7e5df7 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Unpack.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator+Unpack.swift @@ -70,16 +70,34 @@ extension SwiftSDKGenerator { logGenerationStep("Unpacking and copying `lld` linker...") let downloadableArtifacts = self.downloadableArtifacts let pathsConfiguration = self.pathsConfiguration + let targetOS = self.targetTriple.os try await inTemporaryDirectory { fileSystem, tmpDir in + let llvmArtifact = downloadableArtifacts.hostLLVM try await fileSystem.untar( - file: downloadableArtifacts.hostLLVM.localPath, + file: llvmArtifact.localPath, into: tmpDir, stripComponents: 1 ) + + let unpackedLLDPath = if llvmArtifact.isPrebuilt { + tmpDir.appending("bin/lld") + } else { + try await self.buildLLD(llvmSourcesDirectory: tmpDir) + } + + let toolchainLLDPath = switch targetOS { + case .linux: + pathsConfiguration.toolchainBinDirPath.appending("ld.lld") + case .wasi: + pathsConfiguration.toolchainBinDirPath.appending("wasm-ld") + default: + fatalError() + } + try fileSystem.copy( - from: tmpDir.appending("bin/lld"), - to: pathsConfiguration.toolchainBinDirPath.appending("ld.lld") + from: unpackedLLDPath, + to: toolchainLLDPath ) } } diff --git a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift index dd19303..c88a057 100644 --- a/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift +++ b/Sources/SwiftSDKGenerator/Generator/SwiftSDKGenerator.swift @@ -33,6 +33,7 @@ public protocol SwiftSDKGenerator: AnyObject { func untar(file: FilePath, into directoryPath: FilePath, stripComponents: Int?) async throws func unpack(file: FilePath, into directoryPath: FilePath) async throws func rsync(from source: FilePath, to destination: FilePath) async throws + func buildCMakeProject(_ projectPath: FilePath, options: String) async throws -> FilePath static func isChecksumValid(artifact: DownloadableArtifacts.Item, isVerbose: Bool) async throws -> Bool diff --git a/Sources/SwiftSDKGenerator/PlatformModels/Triple.swift b/Sources/SwiftSDKGenerator/PlatformModels/Triple.swift index 170c6bf..850ce37 100644 --- a/Sources/SwiftSDKGenerator/PlatformModels/Triple.swift +++ b/Sources/SwiftSDKGenerator/PlatformModels/Triple.swift @@ -34,6 +34,14 @@ public struct Triple: CustomStringConvertible { case .x86_64: "x86_64" } } + + /// Returns the value of `cpu` converted to a convention used by `LLVM_TARGETS_TO_BUILD` CMake setting. + var llvmTargetConventionName: String { + switch self { + case .x86_64: "X86" + case .arm64: "AArch64" + } + } } enum Vendor: String {