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

Swift 6, SwiftUnicodeDataTables, Other Improvements #106

Merged
merged 35 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f02b1a1
Require Swift 6 and tools v6
STREGA Nov 22, 2024
f59cc8c
Fix build error
STREGA Nov 22, 2024
1b9a1cd
Remove pdc flag skip-unown
STREGA Nov 22, 2024
b218c21
Add build flag for linking swiftUnicodeDataTables
STREGA Nov 22, 2024
5487962
Improve swift toolchain lookup
STREGA Nov 22, 2024
3da4f21
Use clang in swift toolchain
STREGA Nov 22, 2024
308950f
Improve product module lookup
STREGA Nov 22, 2024
c7507ce
Add documentation
STREGA Nov 22, 2024
7d668b3
Fix build errors
STREGA Nov 22, 2024
71deeab
Merge branch 'main' into pr-106
STREGA Nov 22, 2024
ff65025
Chip away at deprecations
STREGA Nov 22, 2024
d06f150
Remove merge conflict junk
STREGA Nov 22, 2024
284285c
Add hack for SwiftUnicodeDataTables
STREGA Nov 23, 2024
8f09d95
Use chosen Playdate SDK
STREGA Nov 23, 2024
161c980
Show built pdx path in build output
STREGA Nov 23, 2024
e7ecb21
Improve build output
STREGA Nov 23, 2024
f010184
Add swiftUnicodeDataTables source as a module
STREGA Nov 24, 2024
02ec121
Export so symbols are available
STREGA Nov 24, 2024
e36411f
Remove linking hacks
STREGA Nov 24, 2024
03ba34d
Fix deprecations
STREGA Dec 2, 2024
7ef11ad
Add support for C/C++ modules
STREGA Dec 5, 2024
3400681
Fix deprecation
STREGA Dec 5, 2024
40d706f
Link compiled Clang libraries
STREGA Dec 5, 2024
1002f1a
Continue Add support for C/C++ modules
STREGA Dec 6, 2024
7000f69
Remove unused var
STREGA Dec 6, 2024
14e885d
Use Task
STREGA Dec 6, 2024
93a99ac
Remove explicit cxx language mode
STREGA Dec 10, 2024
9294bd3
Remove debug symbols from pdx
STREGA Dec 10, 2024
3691abc
Verify file exists first
STREGA Dec 10, 2024
02825fa
Fix flag order
STREGA Dec 10, 2024
924e684
Increase output clarity
STREGA Dec 10, 2024
f54bbfb
Remove trailing slash
STREGA Dec 10, 2024
88efbcd
Remove tmp debug output
STREGA Dec 10, 2024
196db71
Revert fix flag order
STREGA Dec 10, 2024
f15263f
Add output note
STREGA Dec 10, 2024
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
Prev Previous commit
Next Next commit
Continue Add support for C/C++ modules
  • Loading branch information
STREGA committed Dec 6, 2024
commit 1002f1a33bf103b4ca3d97b064d5afccfef3ca31
6 changes: 4 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ let package = Package(
]
),
.target(
name: "SwiftUnicodeDataTables"
name: "SwiftUnicodeDataTables",
cxxSettings: [
.define("SWIFT_STDLIB_ENABLE_UNICODE_DATA")
]
),
.plugin(
name: "PDCPlugin",
Expand All @@ -38,7 +41,6 @@ let package = Package(
),
],
swiftLanguageModes: [.v6],
cLanguageStandard: .c11,
cxxLanguageStandard: .cxx11
)

Expand Down
137 changes: 106 additions & 31 deletions Plugins/PDCPlugin/PDCPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@
let relativeURL: URL
let sourcefiles: [String]

func moduleName(for dest: BuildDestination) -> String {
return "\(name.lowercased())_\(dest)"
func moduleName(for dest: BuildDestination) -> String {
if case .clang(_,_) = type {
return "\(name)_\(dest)"
}else{
return "\(name.lowercased())_\(dest)"
}
}

func modulePath(for dest: BuildDestination) -> String {
func moduleFilename(for dest: BuildDestination) -> String {
let suffix = switch type {
case .product:
"o"
Expand All @@ -37,7 +41,15 @@
case .clang(_, _):
"a"
}
return relativeURL.appending(path: "\(moduleName(for: dest)).\(suffix)").path(percentEncoded: false)
if case .clang(_,_) = type {
return "lib\(moduleName(for: dest)).\(suffix)"
}else{
return "\(moduleName(for: dest)).\(suffix)"
}
}

func modulePath(for dest: BuildDestination) -> String {
return relativeURL.appending(path: moduleFilename(for: dest)).path(percentEncoded: false)
}

func moduleObjectsURL(for dest: BuildDestination) -> URL {
Expand All @@ -55,7 +67,7 @@
var arguments = ArgumentExtractor(arguments)
let verbose = arguments.extractFlag(named: "verbose") > 0
let clean = arguments.extractFlag(named: "clean") > 0
let disableSwiftUnicodeDataTables = true//arguments.extractFlag(named: "disableSwiftUnicodeDataTables") > 0

Check warning on line 70 in Plugins/PDCPlugin/PDCPlugin.swift

View workflow job for this annotation

GitHub Actions / Build

initialization of immutable value 'disableSwiftUnicodeDataTables' was never used; consider replacing with assignment to '_' or removing it

if clean {
let items = try FileManager.default.contentsOfDirectory(atPath: context.pluginWorkDirectoryURL.path(percentEncoded: false))
Expand Down Expand Up @@ -147,6 +159,15 @@
}
}
}
var headerSearchPaths: [String] = sourceModule.headerSearchPaths
for headersURL in [sourceModule.directoryURL.appending(path: "src")] {
var isDirectory: ObjCBool = false
if FileManager.default.fileExists(atPath: headersURL.path(percentEncoded: false), isDirectory: &isDirectory) {
if isDirectory.boolValue == true {
headerSearchPaths.append(headersURL.path(percentEncoded: false))
}
}
}
var sourceFiles: [String] = sourceModule.sourceFiles(withSuffix: "c").map({
$0.url.path(percentEncoded: false)
})
Expand All @@ -156,7 +177,7 @@
_productDependencies.append(
ModuleBuildRequest(
name: sourceModule.name,
type: .clang(publicHeaderSearchPaths, sourceModule.headerSearchPaths),
type: .clang(publicHeaderSearchPaths, headerSearchPaths),
relativeURL: modulesURL,
sourcefiles: sourceFiles
)
Expand Down Expand Up @@ -198,7 +219,9 @@
"/../../../../arm-none-eabi/include"
].map { "/usr/local/playdate/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1" + $0 }

let cFlags = gccIncludePaths.flatMap { ["-I", $0] }
let cFlags = gccIncludePaths.flatMap { ["-I", $0] } + [
"-DSWIFT_STDLIB_ENABLE_UNICODE_DATA=1"
]

let swiftFlags = cFlags.flatMap { ["-Xcc", $0] } + [
"-O",
Expand Down Expand Up @@ -241,14 +264,38 @@
var linkedLibraries: [String] = []
for module in productDependencies {
if case .clang(let publicHeaders, _) = module.type {
guard module.sourcefiles.isEmpty == false else {continue}
for path in publicHeaders {

Check warning on line 268 in Plugins/PDCPlugin/PDCPlugin.swift

View workflow job for this annotation

GitHub Actions / Build

immutable value 'path' was never used; consider replacing with '_' or removing it
linkedLibraries.append("-L\(module.modulePath(for: destination))")
linkedLibraries.append("-l\(module.moduleName(for: destination))")
}
}
}
return linkedLibraries
}

@Sendable func getLinkedLibraryObjects(for destination: BuildDestination) -> [String] {
var objectFiles: [String] = []
for module in productDependencies {
if case .clang(let publicHeaders, _) = module.type {
guard module.sourcefiles.isEmpty == false else {continue}
for path in publicHeaders {

Check warning on line 281 in Plugins/PDCPlugin/PDCPlugin.swift

View workflow job for this annotation

GitHub Actions / Build

immutable value 'path' was never used; consider replacing with '_' or removing it
let url = modulesURL.appending(path: module.moduleName(for: destination))
do {
let files = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
for file in files {
if file.pathExtension == "o" {
objectFiles.append(file.path(percentEncoded: false))
}
}
}catch{
continue
}
}
}
}
return objectFiles
}

let cFlagsDevice = mcFlags + ["-falign-functions=16", "-fshort-enums"]

let swiftFlagsDevice = cFlagsDevice.flatMap { ["-Xcc", $0] } + [
Expand All @@ -262,7 +309,7 @@
// No manual flags
] + getSwiftModuleAliases(for: .simulator) + getCIncludes(for: .simulator)

print("Flags:", swiftFlagsSimulator)
print("Flags:", getLinkedLibraries(for: .simulator))
// MARK: - CLI

@Sendable func cc(_ arguments: [String]) throws {
Expand Down Expand Up @@ -332,6 +379,20 @@
process.waitUntilExit()
guard process.terminationStatus == 0 else { throw Error.arFailed(exitCode: process.terminationStatus) }
}

@Sendable func ranlib(workingDir: String? = nil, _ arguments: [String]) throws {
let ar = try context.tool(named: "ranlib")
let process = Process()
process.executableURL = URL(filePath: ar.url.path(percentEncoded: false))
if let workingDir {
process.currentDirectoryURL = URL(fileURLWithPath: workingDir)
}
process.arguments = arguments
if verbose { process.print() }
try process.run()
process.waitUntilExit()
guard process.terminationStatus == 0 else { throw Error.arFailed(exitCode: process.terminationStatus) }
}

func pdc(_ arguments: [String]) throws {
let process = Process()
Expand Down Expand Up @@ -440,38 +501,42 @@
}

@Sendable func buildDeviceModule(_ module: ModuleBuildRequest) async throws {
try await Task {
print("building \(module.moduleName(for: .device))")
// try await Task {
switch module.type {
case .product:
print("building \(module.moduleName(for: .device)) (pdex.elf)")
// $(productName)_device.o
try swiftc(swiftFlags + swiftFlagsDevice + module.sourcefiles + [
"-c", "-o", module.modulePath(for: .device)
])

print("building pdex.elf")
var ccObjects: [String] = [
let ccObjects: [String] = [
setup,
module.modulePath(for: .device)
]
] + getLinkedLibraryObjects(for: .device)
try cc(ccObjects + mcFlags + [
"-T\(playdateSDK)/C_API/buildsupport/link_map.ld",
"-Wl,-Map=\(context.pluginWorkDirectoryURL.appending(path: "pdex.map").path(percentEncoded: false)),--cref,--gc-sections,--no-warn-mismatch,--emit-relocs",
"-o", sourceURL.appending(path: "pdex.elf").path(percentEncoded: false),
] + getLinkedLibraries(for: .device))
])
case .swift:
try swiftc(swiftFlags + swiftFlagsSimulator + module.sourcefiles + [
"-module-name", module.moduleName(for: .simulator), "-emit-module", "-emit-module-path", module.modulePath(for: .simulator)
print("building \(module.moduleName(for: .device)) (Swift)")
try swiftc(swiftFlags + swiftFlagsDevice + module.sourcefiles + [
"-module-name", module.moduleName(for: .device), "-emit-module", "-emit-module-path", module.modulePath(for: .device)
])
case .clang(let publicHeaderSearchPaths, let headerSearchPaths):
print("building \(module.moduleName(for: .device)) (C/C++)")
guard module.sourcefiles.isEmpty == false else {return}
let objectsPath = module.moduleObjectsURL(for: .device).path(percentEncoded: false)
if FileManager.default.fileExists(atPath: objectsPath) == false {
try FileManager.default.createDirectory(atPath: objectsPath, withIntermediateDirectories: true, attributes: nil)
}
var objectFiles: [String] = []
objectFiles.reserveCapacity(module.sourcefiles.count)
var headerSearchPathFlags: [String] = publicHeaderSearchPaths
var headerSearchPathFlags: [String] = []
for path in publicHeaderSearchPaths {
headerSearchPathFlags.append("-I")
headerSearchPathFlags.append(path)
}
for path in headerSearchPaths {
headerSearchPathFlags.append("-I")
headerSearchPathFlags.append(path)
Expand All @@ -480,52 +545,62 @@
let sourceFileURL = URL(fileURLWithPath: sourceFile)
let objectFileURL = module.moduleObjectsURL(for: .device).appending(path: sourceFileURL.deletingPathExtension().appendingPathExtension("o").lastPathComponent)
let objectFilePath = objectFileURL.path(percentEncoded: false)
try clang(headerSearchPathFlags + [
try cc(mcFlags + cFlags + headerSearchPathFlags + [
"-fno-exceptions",
"-c",
sourceFileURL.path(percentEncoded: false),
"-o",
objectFilePath,
sourceFileURL.path(percentEncoded: false)
])
objectFiles.append(objectFilePath)
}
try ar(["cr", module.modulePath(for: .device)] + objectFiles)
try ar(["rcs", module.modulePath(for: .device)] + objectFiles)
try ranlib([module.modulePath(for: .device)])
}
}.value
// }.value
}

@Sendable func buildSimulatorModule(_ module: ModuleBuildRequest) async throws {
print("building \(module.moduleName(for: .simulator))")
try await Task {

// try await Task {
switch module.type {
case .product:
print("building \(module.moduleName(for: .simulator)) (pdex.dylib)")
// $(productName)_simulator.o
try swiftc(swiftFlags + swiftFlagsSimulator + module.sourcefiles + [
"-c", "-o", module.modulePath(for: .simulator)
])
print("building pdex.dylib")
try clang([
"-nostdlib", "-dead_strip",
"-Wl,-exported_symbol,_eventHandlerShim", "-Wl,-exported_symbol,_eventHandler",
module.modulePath(for: .simulator), "-dynamiclib", "-rdynamic", "-lm",
"-DTARGET_SIMULATOR=1", "-DTARGET_EXTENSION=1",
"-I", ".",
"-I", "\(playdateSDK)/C_API",
"-L\(modulesURL.path(percentEncoded: false))",
] + getLinkedLibraries(for: .simulator) + [
"-o", sourceURL.appending(path: "pdex.dylib").path(percentEncoded: false),
"\(playdateSDK)/C_API/buildsupport/setup.c",
] + getLinkedLibraries(for: .simulator))
])
case .swift:
print("building \(module.moduleName(for: .simulator)) (Swift)")
try swiftc(swiftFlags + swiftFlagsSimulator + module.sourcefiles + [
"-module-name", module.moduleName(for: .simulator), "-emit-module", "-emit-module-path", module.modulePath(for: .simulator)
])
case .clang(let publicHeaderSearchPaths, let headerSearchPaths):
print("building \(module.moduleName(for: .simulator)) (C/C++)")
guard module.sourcefiles.isEmpty == false else {return}
let objectsPath = module.moduleObjectsURL(for: .simulator).path(percentEncoded: false)
if FileManager.default.fileExists(atPath: objectsPath) == false {
try FileManager.default.createDirectory(atPath: objectsPath, withIntermediateDirectories: true, attributes: nil)
}
var objectFiles: [String] = []
objectFiles.reserveCapacity(module.sourcefiles.count)
var headerSearchPathFlags: [String] = publicHeaderSearchPaths
var headerSearchPathFlags: [String] = []
for path in publicHeaderSearchPaths {
headerSearchPathFlags.append("-I")
headerSearchPathFlags.append(path)
}
for path in headerSearchPaths {
headerSearchPathFlags.append("-I")
headerSearchPathFlags.append(path)
Expand All @@ -534,17 +609,17 @@
let sourceFileURL = URL(fileURLWithPath: sourceFile)
let objectFileURL = module.moduleObjectsURL(for: .simulator).appending(path: sourceFileURL.deletingPathExtension().appendingPathExtension("o").lastPathComponent)
let objectFilePath = objectFileURL.path(percentEncoded: false)
try clang(headerSearchPathFlags + [
try clang(headerSearchPathFlags + cFlags + [
"-c",
"-o",
objectFilePath,
sourceFileURL.path(percentEncoded: false)
])
objectFiles.append(objectFilePath)
}
try ar(["cr", module.modulePath(for: .simulator)] + objectFiles)
try ar(["rcs", module.modulePath(for: .simulator)] + objectFiles)
}
}.value
// }.value
}

for dep in productDependencies {
Expand Down
4 changes: 0 additions & 4 deletions Sources/PlaydateKit/Playdate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
@_exported
public import CPlaydate

@_documentation(visibility: private)
@_exported
import SwiftUnicodeDataTables

// MARK: - Playdate

public enum Playdate {
Expand Down
Loading