Skip to content

Commit c1be12f

Browse files
authored
Fix dladdr issue on non-Darwin platform (#194)
* Update Package.swift * Fix Linux platform dladdr issue
1 parent fa7a092 commit c1be12f

File tree

5 files changed

+93
-59
lines changed

5 files changed

+93
-59
lines changed

Package.swift

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ func envEnable(_ key: String, default defaultValue: Bool = false) -> Bool {
1717
}
1818
}
1919

20+
// MARK: - Env and Config
21+
22+
let isXcodeEnv = Context.environment["__CFBundleIdentifier"] == "com.apple.dt.Xcode"
23+
24+
// Xcode use clang as linker which supports "-iframework" while SwiftPM use swiftc as linker which supports "-Fsystem"
25+
let systemFrameworkSearchFlag = isXcodeEnv ? "-iframework" : "-Fsystem"
26+
27+
let swiftBinPath = Context.environment["_"] ?? "/usr/bin/swift"
28+
let swiftBinURL = URL(fileURLWithPath: swiftBinPath)
29+
let SDKPath = swiftBinURL.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent().path
30+
let includePath = SDKPath.appending("/usr/lib/swift")
31+
32+
var sharedCSettings: [CSetting] = [
33+
.unsafeFlags(["-I", includePath], .when(platforms: .nonDarwinPlatforms)),
34+
.define("__COREFOUNDATION_FORSWIFTFOUNDATIONONLY__", to: "1", .when(platforms: .nonDarwinPlatforms)),
35+
.define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])),
36+
]
37+
2038
var sharedSwiftSettings: [SwiftSetting] = [
2139
.enableUpcomingFeature("BareSlashRegexLiterals"),
2240
.enableUpcomingFeature("InternalImportsByDefault"),
@@ -25,54 +43,27 @@ var sharedSwiftSettings: [SwiftSetting] = [
2543
.swiftLanguageMode(.v5),
2644
]
2745

46+
// MARK: - [env] OPENGRAPH_TARGET_RELEASE
47+
2848
let releaseVersion = Context.environment["OPENSWIFTUI_TARGET_RELEASE"].flatMap { Int($0) } ?? 2024
49+
sharedCSettings.append(.define("OPENSWIFTUI_RELEASE", to: "\(releaseVersion)"))
2950
sharedSwiftSettings.append(.define("OPENSWIFTUI_RELEASE_\(releaseVersion)"))
3051
if releaseVersion >= 2021 {
3152
for year in 2021 ... releaseVersion {
3253
sharedSwiftSettings.append(.define("OPENSWIFTUI_SUPPORT_\(year)_API"))
3354
}
3455
}
3556

36-
let platforms: [SupportedPlatform] = switch releaseVersion {
37-
case 2024: // iOS 18.0
38-
[
39-
.iOS(.v18),
40-
.macOS(.v15),
41-
.macCatalyst(.v18),
42-
.tvOS(.v18),
43-
.watchOS(.v10),
44-
.visionOS(.v2),
45-
]
46-
case 2021: // iOS 15.5
47-
[
48-
.iOS(.v15),
49-
.macOS(.v12),
50-
.macCatalyst(.v15),
51-
.tvOS(.v15),
52-
.watchOS(.v7),
53-
]
54-
default:
55-
[
56-
.iOS(.v13),
57-
.macOS(.v10_15),
58-
.macCatalyst(.v13),
59-
.tvOS(.v13),
60-
.watchOS(.v7), // WKApplicationMain is available for watchOS 7.0+
61-
.visionOS(.v1),
62-
]
63-
}
64-
65-
let isXcodeEnv = Context.environment["__CFBundleIdentifier"] == "com.apple.dt.Xcode"
66-
67-
// Xcode use clang as linker which supports "-iframework" while SwiftPM use swiftc as linker which supports "-Fsystem"
68-
let systemFrameworkSearchFlag = isXcodeEnv ? "-iframework" : "-Fsystem"
57+
// MARK: - [env] OPENSWIFTUI_DEVELOPMENT
6958

7059
let development = envEnable("OPENSWIFTUI_DEVELOPMENT")
7160

7261
if development {
7362
sharedSwiftSettings.append(.define("OPENSWIFTUI_DEVELOPMENT"))
7463
}
7564

65+
// MARK: - [env] OPENSWIFTUI_WERROR
66+
7667
let warningsAsErrorsCondition = envEnable("OPENSWIFTUI_WERROR", default: isXcodeEnv && development)
7768
if warningsAsErrorsCondition {
7869
// Hold off the werror feature as we can't avoid the concurrency warning.
@@ -82,6 +73,12 @@ if warningsAsErrorsCondition {
8273
// sharedSwiftSettings.append(.unsafeFlags(["-Wwarning", "concurrency"]))
8374
}
8475

76+
// MARK: - [env] OPENSWIFTUI_BRIDGE_FRAMEWORK
77+
78+
let bridgeFramework = Context.environment["OPENSWIFTUI_BRIDGE_FRAMEWORK"] ?? "SwiftUI"
79+
80+
// MARK: - Targets
81+
8582
// NOTE:
8683
// In macOS: Mac Catalyst App will use macOS-varient build of SwiftUI.framework in /System/Library/Framework and iOS varient of SwiftUI.framework in /System/iOSSupport/System/Library/Framework
8784
// Add `|| Mac Catalyst` check everywhere in `OpenSwiftUICore` and `OpenSwiftUI_SPI`.
@@ -113,7 +110,6 @@ let openSwiftUIExtensionTarget = Target.target(
113110
swiftSettings: sharedSwiftSettings
114111
)
115112

116-
let bridgeFramework = Context.environment["OPENSWIFTUI_BRIDGE_FRAMEWORK"] ?? "SwiftUI"
117113
let openSwiftUIBridgeTarget = Target.target(
118114
name: "OpenSwiftUIBridge",
119115
dependencies: [
@@ -168,11 +164,6 @@ let openSwiftUIBridgeTestTarget = Target.testTarget(
168164
swiftSettings: sharedSwiftSettings
169165
)
170166

171-
let swiftBinPath = Context.environment["_"] ?? "/usr/bin/swift"
172-
let swiftBinURL = URL(fileURLWithPath: swiftBinPath)
173-
let SDKPath = swiftBinURL.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent().path
174-
let includePath = SDKPath.appending("/usr/lib/swift")
175-
176167
// Workaround iOS CI build issue (We need to disable this on iOS CI)
177168
let supportMultiProducts: Bool = envEnable("OPENSWIFTUI_SUPPORT_MULTI_PRODUCTS", default: true)
178169

@@ -189,7 +180,6 @@ if supportMultiProducts {
189180

190181
let package = Package(
191182
name: "OpenSwiftUI",
192-
platforms: platforms,
193183
products: products,
194184
dependencies: [
195185
.package(url: "https://github.com/apple/swift-numerics.git", from: "1.0.2"),
@@ -207,19 +197,12 @@ let package = Package(
207197
.target(
208198
name: "OpenSwiftUI_SPI",
209199
publicHeadersPath: ".",
210-
cSettings: [
211-
.unsafeFlags(["-I", includePath], .when(platforms: .nonDarwinPlatforms)),
212-
.define("__COREFOUNDATION_FORSWIFTFOUNDATIONONLY__", to: "1", .when(platforms: .nonDarwinPlatforms)),
213-
.define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])),
214-
]
200+
cSettings: sharedCSettings
215201
),
216202
.target(
217203
name: "COpenSwiftUI",
218204
publicHeadersPath: ".",
219-
cSettings: [
220-
.unsafeFlags(["-I", includePath], .when(platforms: .nonDarwinPlatforms)),
221-
.define("__COREFOUNDATION_FORSWIFTFOUNDATIONONLY__", to: "1", .when(platforms: .nonDarwinPlatforms)),
222-
.define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])),
205+
cSettings: sharedCSettings + [
223206
.headerSearchPath("../OpenSwiftUI_SPI"),
224207
]
225208
),
@@ -315,6 +298,15 @@ if renderBoxCondition {
315298
openSwiftUIBridgeTestTarget.addRBSettings()
316299
}
317300

301+
if attributeGraphCondition || renderBoxCondition {
302+
let release = Context.environment["DARWIN_PRIVATE_FRAMEWORKS_TARGET_RELEASE"].flatMap { Int($0) } ?? 2024
303+
package.platforms = switch release {
304+
case 2024: [.iOS(.v18), .macOS(.v15), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v10), .visionOS(.v2)]
305+
case 2021: [.iOS(.v15), .macOS(.v12), .macCatalyst(.v15), .tvOS(.v15), .watchOS(.v7)]
306+
default: nil
307+
}
308+
}
309+
318310
if useLocalDeps {
319311
package.dependencies += [
320312
.package(path: "../OpenGraph"),

Sources/OpenSwiftUICore/Util/Tracing.swift

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,26 @@ package struct Tracing {
3434
if let cachedName = moduleLookupCache.value[nominalDescriptor] {
3535
return cachedName
3636
} else {
37-
#if canImport(Darwin)
38-
var info = Dl_info()
39-
guard dladdr(nominalDescriptor, &info) != 0 else {
37+
// Use C Shims layer to import dladdr since we can't call it on non-Darwin Swift platform
38+
// See https://forums.swift.org/t/dladdr-and-the-clang-importer/26379/11
39+
//
40+
// var info = Dl_info()
41+
// guard dladdr(nominalDescriptor, &info) != 0 else {
42+
// return unknown
43+
// }
44+
// let pathName = info.dli_fname
45+
46+
guard let pathName = getSymbolPathName(nominalDescriptor) else {
4047
return unknown
4148
}
42-
let name = (String(cString: info.dli_fname) as NSString).lastPathComponent
43-
moduleLookupCache.value[nominalDescriptor] = name
44-
return name
49+
let path = String(cString: pathName)
50+
#if canImport(Darwin)
51+
let libraryName = (path as NSString).lastPathComponent
4552
#else
46-
// TODO: [Easy] Add a C layer to import dladdr on non-Darwin Swift platform
47-
// See https://forums.swift.org/t/dladdr-and-the-clang-importer/26379/11
48-
return unknown
53+
let libraryName = URL(filePath: path).lastPathComponent
4954
#endif
55+
moduleLookupCache.value[nominalDescriptor] = libraryName
56+
return libraryName
5057
}
5158
}
5259

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//
2+
// OpenSwiftUI_CSymbols.c
3+
// OpenSwiftUI_SPI
4+
5+
#ifdef __linux__
6+
#define _GNU_SOURCE
7+
#endif
8+
9+
#include "OpenSwiftUI_CSymbols.h"
10+
#include <dlfcn.h>
11+
12+
const char * getSymbolPathName(const void *address) {
13+
Dl_info info;
14+
int result = dladdr(address, &info);
15+
if (result == 0) {
16+
return NULL;
17+
}
18+
return info.dli_fname;
19+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//
2+
// OpenSwiftUI_CSymbols.h
3+
// OpenSwiftUI_SPI
4+
5+
#ifndef OpenSwiftUI_CSymbols_h
6+
#define OpenSwiftUI_CSymbols_h
7+
8+
#include "OpenSwiftUIBase.h"
9+
10+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
11+
12+
const char * _Nullable getSymbolPathName(const void *address);
13+
14+
OPENSWIFTUI_ASSUME_NONNULL_END
15+
16+
#endif /* OpenSwiftUI_CSymbols_h */

Tests/OpenSwiftUICoreTests/Util/TracingTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct TracingTests {
2323
}
2424

2525
@Test(
26-
.disabled(if: !attributeGraphEnabled, "OGTypeNominalDescriptor is not implemented yet"),
26+
.enabled(if: swiftToolchainSupported),
2727
arguments: [
2828
(type: Int.self as Any.Type, libraryNames: ["libswiftCore.dylib"]),
2929
(type: String.self as Any.Type, libraryNames: ["libswiftCore.dylib"]),

0 commit comments

Comments
 (0)