Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add support for Xcode 14 swift-driver integration #206

Draft
wants to merge 33 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
db0f1da
Scaffold for swift-frontend wrapper
polac24 May 21, 2023
0b04bb0
Add Context
polac24 May 21, 2023
69fe92e
Generalize Swiftc
polac24 May 22, 2023
6dcfb9d
Refactoring to an abstract swiftc
polac24 May 23, 2023
dd36876
Deleting unused files
polac24 May 23, 2023
5b2e2e3
--amend
polac24 May 23, 2023
69d4946
Cleanup
polac24 May 23, 2023
bcfeaa6
Fix tests
polac24 May 24, 2023
4b35318
Fix linter
polac24 May 24, 2023
202e507
Move XCSwiftcFrontendMain.swift
polac24 May 24, 2023
6a78b4e
Fix linters
polac24 May 24, 2023
9b8c0de
Fix linters
polac24 May 24, 2023
b24a252
Fix linter
polac24 May 24, 2023
501ef19
Add feature flag for frontent integration
polac24 May 24, 2023
62e518f
Add pre/postbuild cleanup
polac24 May 24, 2023
b6b63bd
Wrap critical section in swiftFrontendOrchestrator
polac24 May 25, 2023
623bbb6
Add unitial tests
polac24 May 25, 2023
6c3db27
Do not cache build context from swift-frontend
polac24 May 25, 2023
85bdb47
Add max timeout for a locking
polac24 May 26, 2023
33e8270
Zip with symbolic links
polac24 May 26, 2023
de5e25d
Switch Standalone to the swift-frontend integration
polac24 May 26, 2023
623967c
Add driver integration to integrator
polac24 May 26, 2023
6ee9a10
Use swift-frontend
polac24 May 26, 2023
5c2d0d0
Align fallback swiftc
polac24 May 26, 2023
bfd4f97
Use swift-frontend from Xcode
polac24 May 26, 2023
eb4da75
Validate early
polac24 May 27, 2023
23a67da
--amend
polac24 May 27, 2023
de4bb40
Cleanup
polac24 May 27, 2023
df34ae7
Split log
polac24 May 28, 2023
6869838
Fix suffix
polac24 May 28, 2023
afa0236
Emit modules dependencies
polac24 May 28, 2023
d95da61
Support driver in cocoapods integration
polac24 May 29, 2023
4a46d57
Add -supplementary-output-file-map
polac24 May 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ let package = Package(
name: "xcswiftc",
dependencies: ["XCRemoteCache"]
),
.target(
name: "xcswift-frontend",
dependencies: ["XCRemoteCache"]
),
.target(
name: "xclibtoolSupport",
dependencies: ["XCRemoteCache"]
Expand Down Expand Up @@ -69,6 +73,7 @@ let package = Package(
dependencies: [
"xcprebuild",
"xcswiftc",
"xcswift-frontend",
"xclibtool",
"xcpostbuild",
"xcprepare",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ Note: This step is not required if at least one of these is true:
| `custom_rewrite_envs` | A list of extra ENVs that should be used as placeholders in the dependency list. ENV rewrite process is optimistic - does nothing if an ENV is not defined in the pre/postbuild process. | `[]` | ⬜️ |
| `irrelevant_dependencies_paths` | Regexes of files that should not be included in a list of dependencies. Warning! Add entries here with caution - excluding dependencies that are relevant might lead to a target overcaching. The regex can match either partially or fully the filepath, e.g. `\\.modulemap$` will exclude all `.modulemap` files. | `[]` | ⬜️ |
| `gracefully_handle_missing_common_sha` | If true, do not fail `prepare` if cannot find the most recent common commits with the primary branch. That might be useful on CI, where a shallow clone is used and cloning depth is not big enough to fetch a commit from a primary branch | `false` | ⬜️ |
| `enable_swift_driver_integration` | Enable experimental integration with swift driver, added in Xcode 13 | `false` | ⬜️ |

## Backend cache server

Expand Down
13 changes: 10 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ DERIVED_DATA_DIR = File.join('.build').freeze
RELEASES_ROOT_DIR = File.join('releases').freeze

EXECUTABLE_NAME = 'XCRemoteCache'
EXECUTABLE_NAMES = ['xclibtool', 'xcpostbuild', 'xcprebuild', 'xcprepare', 'xcswiftc', 'xcld', 'xcldplusplus', 'xclipo']
EXECUTABLE_NAMES = ['xclibtool', 'xcpostbuild', 'xcprebuild', 'xcprepare', 'xcswiftc', 'swiftc', 'xcswift-frontend', 'swift-frontend', 'xcld', 'xcldplusplus', 'xclipo']
PROJECT_NAME = 'XCRemoteCache'

SWIFTLINT_ENABLED = true
Expand Down Expand Up @@ -59,6 +59,10 @@ task :build, [:configuration, :arch, :sdks, :is_archive] do |task, args|

# Path of the executable looks like: `.build/(debug|release)/XCRemoteCache`
build_path_base = File.join(DERIVED_DATA_DIR, args.configuration)
# swift-frontent integration requires that the SWIFT_EXEC is `swiftc` so create
# a symbolic link between swiftc->xcswiftc and swift-frontend->xcswift-frontend
system("cd #{build_path_base} && ln -s xcswiftc swiftc")
system("cd #{build_path_base} && ln -s xcswift-frontend swift-frontend")
sdk_build_paths = EXECUTABLE_NAMES.map {|e| File.join(build_path_base, e)}

build_paths.push(sdk_build_paths)
Expand Down Expand Up @@ -130,7 +134,9 @@ def create_release_zip(build_paths)
# Create and move files into the release directory
mkdir_p release_dir
build_paths.each {|p|
cp_r p, release_dir
# -r for recursive
# -P for copying symbolic link as is
system("cp -rP #{p} #{release_dir}")
}

output_artifact_basename = "#{PROJECT_NAME}.zip"
Expand All @@ -139,7 +145,8 @@ def create_release_zip(build_paths)
# -X: no extras (uid, gid, file times, ...)
# -x: exclude .DS_Store
# -r: recursive
system("zip -X -x '*.DS_Store' -r #{output_artifact_basename} .") or abort "zip failure"
# -y: to store symbolic links (used for swiftc -> xcswiftc)
system("zip -X -x '*.DS_Store' -r -y #{output_artifact_basename} .") or abort "zip failure"
# List contents of zip file
system("unzip -l #{output_artifact_basename}") or abort "unzip failure"
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ public struct PostbuildContext {
var publicHeadersFolderPath: URL?
/// XCRemoteCache is explicitly disabled
let disabled: Bool
/// The LLBUILD_BUILD_ID ENV that describes the compilation identifier
/// it is used in the swift-frontend flow
let llbuildIdLockFile: URL
}

extension PostbuildContext {
Expand Down Expand Up @@ -149,5 +152,7 @@ extension PostbuildContext {
publicHeadersFolderPath = builtProductsDir.appendingPathComponent(publicHeadersPath)
}
disabled = try env.readEnv(key: "XCRC_DISABLED") ?? false
let llbuildId: String = try env.readEnv(key: "LLBUILD_BUILD_ID")
llbuildIdLockFile = XCSwiftFrontend.generateLlbuildIdSharedLock(llbuildId: llbuildId, tmpDir: targetTempDir)
}
}
1 change: 1 addition & 0 deletions Sources/XCRemoteCache/Commands/Postbuild/XCPostbuild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class XCPostbuild {
dependenciesWriter: FileDependenciesWriter.init,
dependenciesReader: FileDependenciesReader.init,
markerWriter: NoopMarkerWriter.init,
llbuildLockFile: context.llbuildIdLockFile,
fileManager: fileManager
)

Expand Down
5 changes: 5 additions & 0 deletions Sources/XCRemoteCache/Commands/Prebuild/PrebuildContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public struct PrebuildContext {
let overlayHeadersPath: URL
/// XCRemoteCache is explicitly disabled
let disabled: Bool
/// The LLBUILD_BUILD_ID ENV that describes the compilation identifier
/// it is used in the swift-frontend flow
let llbuildIdLockFile: URL
}

extension PrebuildContext {
Expand All @@ -72,5 +75,7 @@ extension PrebuildContext {
/// Note: The file has yaml extension, even it is in the json format
overlayHeadersPath = targetTempDir.appendingPathComponent("all-product-headers.yaml")
disabled = try env.readEnv(key: "XCRC_DISABLED") ?? false
let llbuildId: String = try env.readEnv(key: "LLBUILD_BUILD_ID")
llbuildIdLockFile = XCSwiftFrontend.generateLlbuildIdSharedLock(llbuildId: llbuildId, tmpDir: targetTempDir)
}
}
1 change: 1 addition & 0 deletions Sources/XCRemoteCache/Commands/Prebuild/XCPrebuild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class XCPrebuild {
dependenciesWriter: FileDependenciesWriter.init,
dependenciesReader: FileDependenciesReader.init,
markerWriter: lazyMarkerWriterFactory,
llbuildLockFile: context.llbuildIdLockFile,
fileManager: fileManager
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import Foundation

typealias BuildSettings = [String: Any]

struct BuildSettingsIntegrateAppenderOption: OptionSet {
let rawValue: Int

static let disableSwiftDriverIntegration = BuildSettingsIntegrateAppenderOption(rawValue: 1 << 0)
}
// Manages Xcode build settings
protocol BuildSettingsIntegrateAppender {
/// Appends XCRemoteCache-specific build settings
Expand All @@ -35,18 +40,28 @@ class XcodeProjBuildSettingsIntegrateAppender: BuildSettingsIntegrateAppender {
private let repoRoot: URL
private let fakeSrcRoot: URL
private let sdksExclude: [String]
private let options: BuildSettingsIntegrateAppenderOption

init(mode: Mode, repoRoot: URL, fakeSrcRoot: URL, sdksExclude: [String]) {
init(
mode: Mode,
repoRoot: URL,
fakeSrcRoot: URL,
sdksExclude: [String],
options: BuildSettingsIntegrateAppenderOption
) {
self.mode = mode
self.repoRoot = repoRoot
self.fakeSrcRoot = fakeSrcRoot
self.sdksExclude = sdksExclude
self.options = options
}

func appendToBuildSettings(buildSettings: BuildSettings, wrappers: XCRCBinariesPaths) -> BuildSettings {
var result = buildSettings
setBuildSetting(buildSettings: &result, key: "SWIFT_EXEC", value: wrappers.swiftc.path )
setBuildSetting(buildSettings: &result, key: "SWIFT_USE_INTEGRATED_DRIVER", value: "NO" )
if options.contains(.disableSwiftDriverIntegration) {
setBuildSetting(buildSettings: &result, key: "SWIFT_USE_INTEGRATED_DRIVER", value: "NO" )
}
// When generating artifacts, no need to shell-out all compilation commands to our wrappers
if case .consumer = mode {
setBuildSetting(buildSettings: &result, key: "CC", value: wrappers.cc.path )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ extension IntegrateContext {
env: [String: String],
binariesDir: URL,
fakeSrcRoot: String,
outputPath: String?
outputPath: String?,
useFontendIntegration: Bool
) throws {
projectPath = URL(fileURLWithPath: input)
let srcRoot = projectPath.deletingLastPathComponent()
Expand All @@ -47,10 +48,11 @@ extension IntegrateContext {
configOverride = URL(fileURLWithPath: configOverridePath, relativeTo: srcRoot)
output = outputPath.flatMap(URL.init(fileURLWithPath:))
self.fakeSrcRoot = URL(fileURLWithPath: fakeSrcRoot)
let swiftcBinaryName = useFontendIntegration ? "swiftc" : "xcswiftc"
binaries = XCRCBinariesPaths(
prepare: binariesDir.appendingPathComponent("xcprepare"),
cc: binariesDir.appendingPathComponent("xccc"),
swiftc: binariesDir.appendingPathComponent("xcswiftc"),
swiftc: binariesDir.appendingPathComponent(swiftcBinaryName),
libtool: binariesDir.appendingPathComponent("xclibtool"),
lipo: binariesDir.appendingPathComponent("xclipo"),
ld: binariesDir.appendingPathComponent("xcld"),
Expand Down
12 changes: 10 additions & 2 deletions Sources/XCRemoteCache/Commands/Prepare/Integrate/XCIntegrate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ public class XCIntegrate {
env: env,
binariesDir: binariesDir,
fakeSrcRoot: fakeSrcRoot,
outputPath: output
outputPath: output,
useFontendIntegration: config.enableSwifDriverIntegration
)
let configurationOracle = IncludeExcludeOracle(
excludes: configurationsExclude.integrateArrayArguments,
Expand All @@ -98,11 +99,18 @@ public class XCIntegrate {
excludes: targetsExclude.integrateArrayArguments,
includes: targetsInclude.integrateArrayArguments
)
let buildSettingsAppenderOptions: BuildSettingsIntegrateAppenderOption
if config.enableSwifDriverIntegration {
buildSettingsAppenderOptions = []
} else {
buildSettingsAppenderOptions = [.disableSwiftDriverIntegration]
}
let buildSettingsAppender = XcodeProjBuildSettingsIntegrateAppender(
mode: context.mode,
repoRoot: context.repoRoot,
fakeSrcRoot: context.fakeSrcRoot,
sdksExclude: sdksExclude.integrateArrayArguments
sdksExclude: sdksExclude.integrateArrayArguments,
options: buildSettingsAppenderOptions
)
let lldbPatcher: LLDBInitPatcher
switch lldbMode {
Expand Down
Loading