Skip to content

Add custom toolchain to generated project #3140

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

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions test/internal/custom_toolchain/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# buildifier: disable=bzl-visibility
load("//xcodeproj/internal:custom_toolchain.bzl", "custom_toolchain")

# Example swiftc override for testing
filegroup(
name = "test_swiftc",
srcs = ["test_swiftc.sh"],
visibility = ["//visibility:public"],
)

# Test target for custom_toolchain
custom_toolchain(
name = "test_toolchain",
overrides = {
":test_swiftc": "swiftc",
},
toolchain_name = "TestCustomToolchain",
)

# Add a simple test rule that depends on the toolchain
sh_test(
name = "custom_toolchain_test",
srcs = ["custom_toolchain_test.sh"],
args = ["$(location :test_toolchain)"],
data = [":test_toolchain"],
)
46 changes: 46 additions & 0 deletions test/internal/custom_toolchain/custom_toolchain_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash

set -euo pipefail

# The first argument should be the path to the toolchain directory
TOOLCHAIN_DIR="$1"

echo "Verifying toolchain at: $TOOLCHAIN_DIR"

# Check that the toolchain directory exists
if [[ ! -d "$TOOLCHAIN_DIR" ]]; then
echo "ERROR: Toolchain directory does not exist: $TOOLCHAIN_DIR"
exit 1
fi

# Check that ToolchainInfo.plist exists
if [[ ! -f "$TOOLCHAIN_DIR/ToolchainInfo.plist" ]]; then
echo "ERROR: ToolchainInfo.plist not found in toolchain"
exit 1
fi

# Check for correct identifiers in the plist
if ! grep -q "TestCustomToolchain" "$TOOLCHAIN_DIR/ToolchainInfo.plist"; then
echo "ERROR: ToolchainInfo.plist doesn't contain TestCustomToolchain"
exit 1
fi

# Check that our custom swiftc is properly linked/copied
if [[ ! -f "$TOOLCHAIN_DIR/usr/bin/swiftc" ]]; then
echo "ERROR: swiftc not found in toolchain"
exit 1
fi

# Ensure swiftc is executable
if [[ ! -x "$TOOLCHAIN_DIR/usr/bin/swiftc" ]]; then
echo "ERROR: swiftc is not executable"
exit 1
fi

# Test if the swiftc actually runs
if ! "$TOOLCHAIN_DIR/usr/bin/swiftc" --version > /dev/null 2>&1; then
echo "WARN: swiftc doesn't run correctly, but this is expected in tests"
fi

echo "Custom toolchain validation successful!"
exit 0
11 changes: 11 additions & 0 deletions test/internal/custom_toolchain/test_swiftc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

# This is a test script that simulates a custom Swift compiler
# It will be used as an override in the custom toolchain

# Print inputs for debugging
echo "Custom swiftc called with args: $@" >&2

# In a real override, you would do something meaningful with the args
# For testing, just exit successfully
exit 0
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ def write_pbxproj_prefix_test_suite(name):
"some/path/to/index_import",
# resolvedRepositoriesFile
"some/path/to/resolved_repositories_file",
# customToolchainID
"com.rules_xcodeproj.BazelRulesXcodeProj.16B40",
# minimumXcodeVersion
"14.2.1",
# importIndexBuildIndexstores
Expand Down Expand Up @@ -332,6 +334,8 @@ def write_pbxproj_prefix_test_suite(name):
"some/path/to/index_import",
# resolvedRepositoriesFile
"some/path/to/resolved_repositories_file",
# customToolchainID
"com.rules_xcodeproj.BazelRulesXcodeProj.16B40",
# minimumXcodeVersion
"14.2.1",
# importIndexBuildIndexstores
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ extension Generator.CreateBuildFileObject {
settings = #"settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; "#
case .compileStub, .source:
settings = ""
case .product, .watchKitExtension:
case .product, .watchKitExtension, .framework:
// Handled in `CreateProductBuildFileObject` and
// `CreateProductObject`
preconditionFailure()
Expand Down
2 changes: 0 additions & 2 deletions tools/generators/legacy/src/Generator/CreateProject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ $(PROJECT_TEMP_DIR)/$(BAZEL_PACKAGE_BIN_DIR)/$(COMPILE_TARGET_NAME)
"LD": "$(BAZEL_INTEGRATION_DIR)/ld",
"LDPLUSPLUS": "$(BAZEL_INTEGRATION_DIR)/ld",
"LIBTOOL": "$(BAZEL_INTEGRATION_DIR)/libtool",
"SWIFT_EXEC": "$(BAZEL_INTEGRATION_DIR)/swiftc",
"SWIFT_USE_INTEGRATED_DRIVER": false,
"TAPI_EXEC": "/usr/bin/true",
], uniquingKeysWith: { _, r in r })
} else {
Expand Down
2 changes: 0 additions & 2 deletions tools/generators/legacy/test/CreateProjectTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,9 @@ $(BUILD_DIR)/$(BAZEL_PACKAGE_BIN_DIR)
"RULES_XCODEPROJ_BUILD_MODE": "bazel",
"SRCROOT": directories.workspace.string,
"SUPPORTS_MACCATALYST": false,
"SWIFT_EXEC": "$(BAZEL_INTEGRATION_DIR)/swiftc",
"TAPI_EXEC": "/usr/bin/true",
"SWIFT_OBJC_INTERFACE_HEADER_NAME": "",
"SWIFT_OPTIMIZATION_LEVEL": "-Onone",
"SWIFT_USE_INTEGRATED_DRIVER": false,
"SWIFT_VERSION": "5.0",
"TARGET_TEMP_DIR": """
$(PROJECT_TEMP_DIR)/$(BAZEL_PACKAGE_BIN_DIR)/$(COMPILE_TARGET_NAME)
Expand Down
2 changes: 2 additions & 0 deletions tools/generators/lib/PBXProj/src/BuildPhase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public enum BuildPhase {
case sources
case copySwiftGeneratedHeader
case embedAppExtensions
case linkBinaryWithLibraries

public var name: String {
switch self {
Expand All @@ -16,6 +17,7 @@ Copy Bazel Outputs / Generate Bazel Dependencies (Index Build)
case .sources: return "Sources"
case .copySwiftGeneratedHeader: return "Copy Swift Generated Header"
case .embedAppExtensions: return "Embed App Extensions"
case .linkBinaryWithLibraries: return "Frameworks"
}
}
}
13 changes: 13 additions & 0 deletions tools/generators/lib/PBXProj/src/Identifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ FF01000000000000000001\#(byteHexStrings[index]!) \#
/// The product reference for a target.
case product = "P"

/// The framework reference for a target in libraries to link build phase.
case framework = "f"

/// A normal file referenced in a `BuildPhase.sources` build phase.
case source = "0"

Expand Down Expand Up @@ -186,6 +189,14 @@ FF01000000000000000001\#(byteHexStrings[index]!) \#
return #"""
\#(subIdentifier.shard)00\#(subIdentifier.hash)0000000000FF \#
/* \#(subIdentifier.path.path) */
"""#

case .framework:
let basename = subIdentifier.path.path
.split(separator: "/").last!
return #"""
\#(subIdentifier.shard)A8\#(subIdentifier.hash) \#
/* \#(basename) in Frameworks */
"""#

case .compileStub:
Expand Down Expand Up @@ -535,6 +546,7 @@ private extension Identifiers.BuildFiles.FileType {
var buildPhase: BuildPhase {
switch self {
case .product: preconditionFailure() // product reference used as build file
case .framework: return .linkBinaryWithLibraries
case .source: return .sources
case .nonArcSource: return .sources
case .compileStub: return .sources
Expand Down Expand Up @@ -566,6 +578,7 @@ extension BuildPhase {
case .sources: return "06"
case .copySwiftGeneratedHeader: return "07"
case .embedAppExtensions: return "08"
case .linkBinaryWithLibraries: return "09"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,24 @@ extension Generator.CalculatePlatformVariantBuildSettings {
)
}

buildSettings.append(
.init(
key: "LIBRARY_SEARCH_PATHS",
value: (
platformVariant.librarySearchPaths
.map {
let path = $0.path.split(separator: "/").dropFirst().joined(separator: "/")
return "\"$(BAZEL_OUT)/\(path)\""
} + [
"\"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/16/lib/darwin\""
]
)
.sorted()
.joined(separator: " ")
.pbxProjEscaped
)
)

buildSettings.append(contentsOf: platformVariant.buildSettingsFromFile)

return buildSettings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extension Generator.CalculatePlatformVariants {
) {
var srcs: [[BazelPath]] = []
var nonArcSrcs: [[BazelPath]] = []
var librariesToLinkPaths: [[BazelPath]] = []
var excludableFilesKeysWithValues: [(TargetID, Set<BazelPath>)] = []
for id in ids {
let targetArguments = try targetArguments.value(
Expand All @@ -68,6 +69,7 @@ extension Generator.CalculatePlatformVariants {

srcs.append(targetArguments.srcs)
nonArcSrcs.append(targetArguments.nonArcSrcs)
librariesToLinkPaths.append(targetArguments.librariesToLinkPaths)

excludableFilesKeysWithValues.append(
(
Expand Down Expand Up @@ -134,14 +136,16 @@ extension Generator.CalculatePlatformVariants {
.flatMap { unitTestHosts[$0] },
dSYMPathsBuildSetting:
targetArguments.dSYMPathsBuildSetting.isEmpty ?
nil : targetArguments.dSYMPathsBuildSetting
nil : targetArguments.dSYMPathsBuildSetting,
librarySearchPaths: Set(targetArguments.librarySearchPaths)
)
)
}

let consolidatedInputs = Target.ConsolidatedInputs(
srcs: consolidatePaths(srcs),
nonArcSrcs: consolidatePaths(nonArcSrcs)
nonArcSrcs: consolidatePaths(nonArcSrcs),
librariesToLinkPaths: consolidatePaths(librariesToLinkPaths)
)

return (platformVariants, allConditionalFiles, consolidatedInputs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private extension Platform {
}
}

private extension String {
extension String {
var quoteIfNeeded: String {
guard !contains(" ") else {
return #""\#(self)""#
Expand Down
Loading