Skip to content

Commit b45e400

Browse files
MaxDesiatovFranzBusch
authored andcommitted
1 parent 7a927cd commit b45e400

31 files changed

+372
-50
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ Package.resolved
2020
.vscode
2121
Utilities/InstalledSwiftPMConfiguration/config.json
2222
.devcontainer
23+
Fixtures/BinaryLibraries/Static/Package1/Simple.artifactbundle/build
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// swift-tools-version: 6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "Package1",
7+
targets: [
8+
.executableTarget(
9+
name: "Example",
10+
dependencies: [
11+
"Simple",
12+
"Wrapper"
13+
]
14+
),
15+
.target(
16+
name: "Wrapper",
17+
dependencies: [
18+
"Simple"
19+
]
20+
),
21+
.binaryTarget(
22+
name: "Simple",
23+
path: "Simple.artifactbundle"
24+
),
25+
]
26+
)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
SRC_FILES := $(wildcard *.c)
2+
3+
# Define architectures and platforms
4+
ARCHS := x86_64 arm64
5+
PLATFORMS := macos linux
6+
7+
# Define output directories
8+
BUILD_DIR := build
9+
DIST_DIR := dist
10+
11+
# Platform-specific settings
12+
MACOS_SDK := $(shell xcrun --sdk macosx --show-sdk-path 2>/dev/null || echo "")
13+
MACOS_MIN_VERSION := 10.15
14+
15+
# Compiler flags
16+
COMMON_FLAGS := -O2
17+
18+
# Platform and architecture specific flags
19+
MACOS_X86_64_FLAGS := -target x86_64-apple-macos$(MACOS_MIN_VERSION) -isysroot $(MACOS_SDK)
20+
MACOS_ARM64_FLAGS := -target arm64-apple-macos$(MACOS_MIN_VERSION) -isysroot $(MACOS_SDK)
21+
LINUX_X86_64_FLAGS := -target x86_64-unknown-linux-gnu
22+
LINUX_ARM64_FLAGS := -target aarch64-unknown-linux-gnu
23+
24+
.PHONY: all clean macos linux universal
25+
26+
all: macos linux
27+
28+
# Create necessary directories
29+
$(BUILD_DIR):
30+
mkdir -p $(BUILD_DIR)/macos/x86_64
31+
mkdir -p $(BUILD_DIR)/macos/arm64
32+
mkdir -p $(BUILD_DIR)/linux/x86_64
33+
mkdir -p $(BUILD_DIR)/linux/arm64
34+
35+
$(DIST_DIR):
36+
mkdir -p $(DIST_DIR)/macos
37+
mkdir -p $(DIST_DIR)/linux
38+
39+
# macOS x86_64 build
40+
$(BUILD_DIR)/macos/x86_64/%.o: %.c | $(BUILD_DIR)
41+
clang $(COMMON_FLAGS) $(MACOS_X86_64_FLAGS) -c -o $@ $<
42+
43+
# macOS arm64 build
44+
$(BUILD_DIR)/macos/arm64/%.o: %.c | $(BUILD_DIR)
45+
clang $(COMMON_FLAGS) $(MACOS_ARM64_FLAGS) -c -o $@ $<
46+
47+
# Linux x86_64 build
48+
$(BUILD_DIR)/linux/x86_64/%.o: %.c | $(BUILD_DIR)
49+
clang $(COMMON_FLAGS) $(LINUX_X86_64_FLAGS) -c -o $@ $<
50+
51+
# Linux arm64 build
52+
$(BUILD_DIR)/linux/arm64/%.o: %.c | $(BUILD_DIR)
53+
clang $(COMMON_FLAGS) $(LINUX_ARM64_FLAGS) -c -o $@ $<
54+
55+
# Define object files for each platform and architecture
56+
MACOS_X86_64_OBJ_FILES := $(patsubst %.c,$(BUILD_DIR)/macos/x86_64/%.o,$(SRC_FILES))
57+
MACOS_ARM64_OBJ_FILES := $(patsubst %.c,$(BUILD_DIR)/macos/arm64/%.o,$(SRC_FILES))
58+
LINUX_X86_64_OBJ_FILES := $(patsubst %.c,$(BUILD_DIR)/linux/x86_64/%.o,$(SRC_FILES))
59+
LINUX_ARM64_OBJ_FILES := $(patsubst %.c,$(BUILD_DIR)/linux/arm64/%.o,$(SRC_FILES))
60+
61+
# Create individual architecture libraries
62+
$(DIST_DIR)/macos/libSimple_x86_64.a: $(MACOS_X86_64_OBJ_FILES) | $(DIST_DIR)
63+
llvm-ar rc $@ $^
64+
65+
$(DIST_DIR)/macos/libSimple_arm64.a: $(MACOS_ARM64_OBJ_FILES) | $(DIST_DIR)
66+
llvm-ar rc $@ $^
67+
68+
$(DIST_DIR)/linux/libSimple_x86_64.a: $(LINUX_X86_64_OBJ_FILES) | $(DIST_DIR)
69+
llvm-ar rc $@ $^
70+
71+
$(DIST_DIR)/linux/libSimple_arm64.a: $(LINUX_ARM64_OBJ_FILES) | $(DIST_DIR)
72+
llvm-ar rc $@ $^
73+
74+
# Create universal binary for macOS
75+
$(DIST_DIR)/macos/libSimple.a: $(DIST_DIR)/macos/libSimple_x86_64.a $(DIST_DIR)/macos/libSimple_arm64.a
76+
lipo -create -output $@ $^
77+
78+
# For Linux, we'll provide separate libraries since lipo is macOS-specific
79+
linux: $(DIST_DIR)/linux/libSimple_x86_64.a $(DIST_DIR)/linux/libSimple_arm64.a
80+
@echo "Linux libraries built in $(DIST_DIR)/linux/"
81+
@echo "Note: For Linux, use the architecture-specific libraries as needed."
82+
83+
macos: $(DIST_DIR)/macos/libSimple.a
84+
@echo "macOS universal library built at $(DIST_DIR)/macos/libSimple.a"
85+
86+
clean:
87+
rm -rf $(BUILD_DIR) $(DIST_DIR)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo(void);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Simple {
2+
header "simple.h"
3+
export *
4+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"schemaVersion": "1.0",
3+
"artifacts": {
4+
"simple": {
5+
"type": "staticLibrary",
6+
"version": "1.0.0",
7+
"variants": [
8+
{
9+
"path": "dist/macOS/libSimple.a",
10+
"supportedTriples": ["arm64-apple-macosx", "x86_64-apple-macosx"],
11+
"staticLibraryMetadata": {
12+
"headerPaths": ["include"],
13+
"moduleMapPath": "include/simple.modulemap"
14+
}
15+
},
16+
{
17+
"path": "dist/linux/libSimple_arm64.a",
18+
"supportedTriples": ["aarch64-unknown-linux-gnu"],
19+
"staticLibraryMetadata": {
20+
"headerPaths": ["include"],
21+
"moduleMapPath": "include/simple.modulemap"
22+
}
23+
},
24+
{
25+
"path": "dist/linux/libSimple_x86_64.a",
26+
"supportedTriples": ["x86_64-unknown-linux-gnu"],
27+
"staticLibraryMetadata": {
28+
"headerPaths": ["include"],
29+
"moduleMapPath": "include/simple.modulemap"
30+
}
31+
}
32+
]
33+
}
34+
}
35+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo(void) { return 42; }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Simple
2+
import Wrapper
3+
4+
@main
5+
struct Example {
6+
static func main() {
7+
print(foo())
8+
print(bar())
9+
}
10+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int bar(void);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "simple.h"
2+
3+
int bar(void) { return foo(); }

Sources/Build/BuildPlan/BuildPlan+Clang.swift

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,22 @@ extension BuildPlan {
4848
clangTarget.additionalFlags += ["-fmodule-map-file=\(target.moduleMapPath.pathString)"]
4949
clangTarget.additionalFlags += try pkgConfig(for: target).cFlags
5050
case let target as BinaryModule:
51-
if case .xcframework = target.kind {
51+
switch target.kind {
52+
case .unknown:
53+
break
54+
case .artifactsArchive:
55+
let libraries = try self.parseLibraryArtifactsArchive(for: target, triple: clangTarget.buildParameters.triple)
56+
for library in libraries {
57+
library.headersPaths.forEach {
58+
clangTarget.additionalFlags += ["-I", $0.pathString]
59+
}
60+
if let moduleMapPath = library.moduleMapPath {
61+
clangTarget.additionalFlags += ["-fmodule-map-file=\(moduleMapPath)"]
62+
}
63+
64+
clangTarget.libraryBinaryPaths.insert(library.libraryPath)
65+
}
66+
case .xcframework:
5267
let libraries = try self.parseXCFramework(for: target, triple: clangTarget.buildParameters.triple)
5368
for library in libraries {
5469
library.headersPaths.forEach {
@@ -57,9 +72,9 @@ extension BuildPlan {
5772
clangTarget.libraryBinaryPaths.insert(library.libraryPath)
5873
}
5974
}
75+
6076
default: continue
6177
}
6278
}
6379
}
64-
6580
}

Sources/Build/BuildPlan/BuildPlan+Product.swift

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import class PackageModel.SwiftModule
2626
import class PackageModel.SystemLibraryModule
2727
import struct SPMBuildCore.BuildParameters
2828
import struct SPMBuildCore.ExecutableInfo
29+
import struct SPMBuildCore.LibraryInfo
2930
import func TSCBasic.topologicalSort
3031

3132
extension BuildPlan {
@@ -50,7 +51,7 @@ extension BuildPlan {
5051
} else if binaryPath.basename.starts(with: "lib") {
5152
buildProduct.additionalFlags += ["-l\(binaryPath.basenameWithoutExt.dropFirst(3))"]
5253
} else {
53-
self.observabilityScope.emit(error: "unexpected binary framework")
54+
self.observabilityScope.emit(error: "unexpected binary name at \(binaryPath). Static libraries should be prefixed with lib")
5455
}
5556
}
5657

@@ -297,10 +298,20 @@ extension BuildPlan {
297298
libraryBinaryPaths.insert(library.libraryPath)
298299
}
299300
case .artifactsArchive:
300-
let tools = try self.parseArtifactsArchive(
301+
let tools = try self.parseExecutableArtifactsArchive(
301302
for: binaryTarget, triple: productDescription.buildParameters.triple
302303
)
303-
tools.forEach { availableTools[$0.name] = $0.executablePath }
304+
for tool in tools {
305+
availableTools[tool.name] = tool.executablePath
306+
}
307+
308+
let libraries = try self.parseLibraryArtifactsArchive(
309+
for: binaryTarget,
310+
triple: productDescription.buildParameters.triple
311+
)
312+
for library in libraries {
313+
libraryBinaryPaths.insert(library.libraryPath)
314+
}
304315
case .unknown:
305316
throw InternalError("unknown binary target '\(module.name)' type")
306317
}
@@ -330,10 +341,16 @@ extension BuildPlan {
330341
}
331342

332343
/// Extracts the artifacts from an artifactsArchive
333-
private func parseArtifactsArchive(for binaryTarget: BinaryModule, triple: Triple) throws -> [ExecutableInfo] {
334-
try self.externalExecutablesCache.memoize(key: binaryTarget) {
335-
let execInfos = try binaryTarget.parseArtifactArchives(for: triple, fileSystem: self.fileSystem)
344+
private func parseExecutableArtifactsArchive(for module: BinaryModule, triple: Triple) throws -> [ExecutableInfo] {
345+
try self.externalExecutablesCache.memoize(key: module) {
346+
let execInfos = try module.parseExecutableArtifactArchives(for: triple, fileSystem: self.fileSystem)
336347
return execInfos.filter { !$0.supportedTriples.isEmpty }
337348
}
338349
}
350+
351+
func parseLibraryArtifactsArchive(for module: BinaryModule, triple: Triple) throws -> [LibraryInfo] {
352+
try self.externalLibrariesCache.memoize(key: module) {
353+
try module.parseLibraryArtifactArchives(for: triple, fileSystem: self.fileSystem)
354+
}
355+
}
339356
}

Sources/Build/BuildPlan/BuildPlan+Swift.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,24 @@ extension BuildPlan {
4343
swiftTarget.additionalFlags += ["-Xcc", "-fmodule-map-file=\(target.moduleMapPath.pathString)"]
4444
swiftTarget.additionalFlags += try pkgConfig(for: target).cFlags
4545
case let target as BinaryModule:
46-
if case .xcframework = target.kind {
46+
switch target.kind {
47+
case .unknown:
48+
break
49+
case .artifactsArchive:
50+
let libraries = try self.parseLibraryArtifactsArchive(for: target, triple: swiftTarget.buildParameters.triple)
51+
for library in libraries {
52+
library.headersPaths.forEach {
53+
swiftTarget.additionalFlags += ["-I", $0.pathString, "-Xcc", "-I", "-Xcc", $0.pathString]
54+
}
55+
if let moduleMapPath = library.moduleMapPath {
56+
// We need to pass the module map if there is one. If there is none Swift cannot import it but
57+
// this might still be valid
58+
swiftTarget.additionalFlags += ["-Xcc", "-fmodule-map-file=\(moduleMapPath)"]
59+
}
60+
61+
swiftTarget.libraryBinaryPaths.insert(library.libraryPath)
62+
}
63+
case .xcframework:
4764
let libraries = try self.parseXCFramework(for: target, triple: swiftTarget.buildParameters.triple)
4865
for library in libraries {
4966
library.headersPaths.forEach {

Sources/Build/BuildPlan/BuildPlan.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
256256
private var pkgConfigCache = [SystemLibraryModule: (cFlags: [String], libs: [String])]()
257257

258258
/// Cache for library information.
259-
private var externalLibrariesCache = [BinaryModule: [LibraryInfo]]()
259+
var externalLibrariesCache = [BinaryModule: [LibraryInfo]]()
260260

261261
/// Cache for tools information.
262262
var externalExecutablesCache = [BinaryModule: [ExecutableInfo]]()

Sources/PackageLoading/ManifestLoader+Validation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import TSCUtility
1818

1919
public struct ManifestValidator {
2020
static var supportedLocalBinaryDependencyExtensions: [String] {
21-
["zip"] + BinaryModule.Kind.allCases.filter{ $0 != .unknown }.map { $0.fileExtension }
21+
Set(["zip"] + BinaryModule.Kind.allCases.filter { !$0.isUnknown }.map { $0.fileExtension }).sorted()
2222
}
2323
static var supportedRemoteBinaryDependencyExtensions: [String] {
24-
["zip", "artifactbundleindex"]
24+
["artifactbundleindex", "zip"]
2525
}
2626

2727
private let manifest: Manifest

0 commit comments

Comments
 (0)