Skip to content

Commit a39f398

Browse files
authored
Repair the Windows SwiftPM build (#5068)
* Repair the Windows SwiftPM build * Update XCTSkip message
1 parent e0f1615 commit a39f398

File tree

7 files changed

+148
-106
lines changed

7 files changed

+148
-106
lines changed

Package.swift

+59-11
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,20 @@ let platformsWithThreads: [Platform] = [
1414
.linux,
1515
.windows,
1616
]
17-
var dispatchIncludeFlags: [CSetting]
17+
18+
var dispatchIncludeFlags: [CSetting] = []
1819
if let environmentPath = Context.environment["DISPATCH_INCLUDE_PATH"] {
19-
dispatchIncludeFlags = [.unsafeFlags([
20+
dispatchIncludeFlags.append(.unsafeFlags([
2021
"-I\(environmentPath)",
2122
"-I\(environmentPath)/Block"
22-
])]
23+
]))
2324
} else {
24-
dispatchIncludeFlags = [
25+
dispatchIncludeFlags.append(
2526
.unsafeFlags([
2627
"-I/usr/lib/swift",
2728
"-I/usr/lib/swift/Block"
2829
], .when(platforms: [.linux, .android]))
29-
]
30+
)
3031
if let sdkRoot = Context.environment["SDKROOT"] {
3132
dispatchIncludeFlags.append(.unsafeFlags([
3233
"-I\(sdkRoot)usr\\include",
@@ -35,10 +36,55 @@ if let environmentPath = Context.environment["DISPATCH_INCLUDE_PATH"] {
3536
}
3637
}
3738

39+
var libxmlIncludeFlags: [CSetting] = []
40+
if let environmentPath = Context.environment["LIBXML_INCLUDE_PATH"] {
41+
libxmlIncludeFlags = [
42+
.unsafeFlags([
43+
"-I\(environmentPath)"
44+
]),
45+
.define("LIBXML_STATIC")
46+
]
47+
}
48+
49+
var curlIncludeFlags: [CSetting] = []
50+
if let environmentPath = Context.environment["CURL_INCLUDE_PATH"] {
51+
curlIncludeFlags = [
52+
.unsafeFlags([
53+
"-I\(environmentPath)"
54+
]),
55+
.define("CURL_STATICLIB")
56+
]
57+
}
58+
59+
var curlLinkFlags: [LinkerSetting] = [
60+
.linkedLibrary("libcurl.lib", .when(platforms: [.windows])),
61+
.linkedLibrary("zlibstatic.lib", .when(platforms: [.windows]))
62+
]
63+
if let environmentPath = Context.environment["CURL_LIBRARY_PATH"] {
64+
curlLinkFlags.append(.unsafeFlags([
65+
"-L\(environmentPath)"
66+
]))
67+
}
68+
if let environmentPath = Context.environment["ZLIB_LIBRARY_PATH"] {
69+
curlLinkFlags.append(.unsafeFlags([
70+
"-L\(environmentPath)"
71+
]))
72+
}
73+
74+
var libxmlLinkFlags: [LinkerSetting] = [
75+
.linkedLibrary("libxml2s.lib", .when(platforms: [.windows]))
76+
]
77+
if let environmentPath = Context.environment["LIBXML2_LIBRARY_PATH"] {
78+
libxmlLinkFlags.append(.unsafeFlags([
79+
"-L\(environmentPath)"
80+
]))
81+
}
82+
3883
let coreFoundationBuildSettings: [CSetting] = [
3984
.headerSearchPath("internalInclude"),
4085
.define("DEBUG", .when(configuration: .debug)),
4186
.define("CF_BUILDING_CF"),
87+
.define("CF_WINDOWS_EXECUTABLE_INITIALIZER", .when(platforms: [.windows])), // Ensure __CFInitialize is run even when statically linked into an executable
4288
.define("DEPLOYMENT_ENABLE_LIBDISPATCH", .when(platforms: platformsWithThreads)),
4389
.define("DEPLOYMENT_RUNTIME_SWIFT"),
4490
.define("HAVE_STRUCT_TIMESPEC"),
@@ -216,25 +262,27 @@ let package = Package(
216262
name: "_CFXMLInterface",
217263
dependencies: [
218264
"CoreFoundation",
219-
"Clibxml2",
265+
.target(name: "Clibxml2", condition: .when(platforms: [.linux])),
220266
],
221267
path: "Sources/_CFXMLInterface",
222268
exclude: [
223269
"CMakeLists.txt"
224270
],
225-
cSettings: interfaceBuildSettings
271+
cSettings: interfaceBuildSettings + libxmlIncludeFlags,
272+
linkerSettings: libxmlLinkFlags
226273
),
227274
.target(
228275
name: "_CFURLSessionInterface",
229276
dependencies: [
230277
"CoreFoundation",
231-
"Clibcurl",
278+
.target(name: "Clibcurl", condition: .when(platforms: [.linux])),
232279
],
233280
path: "Sources/_CFURLSessionInterface",
234281
exclude: [
235282
"CMakeLists.txt"
236283
],
237-
cSettings: interfaceBuildSettings
284+
cSettings: interfaceBuildSettings + curlIncludeFlags,
285+
linkerSettings: curlLinkFlags
238286
),
239287
.systemLibrary(
240288
name: "Clibxml2",
@@ -292,8 +340,8 @@ let package = Package(
292340
"Foundation",
293341
"FoundationXML",
294342
"FoundationNetworking",
295-
.targetItem(name: "XCTest", condition: .when(platforms: [.linux])),
296-
"xdgTestHelper"
343+
"XCTest",
344+
.target(name: "xdgTestHelper", condition: .when(platforms: [.linux]))
297345
],
298346
resources: [
299347
.copy("Foundation/Resources")

Sources/CoreFoundation/CFRuntime.c

+10
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,16 @@ static CFBundleRef RegisterCoreFoundationBundle(void) {
13801380
#define DLL_THREAD_DETACH 3
13811381
#define DLL_PROCESS_DETACH 0
13821382

1383+
#if CF_WINDOWS_EXECUTABLE_INITIALIZER
1384+
static void __CFWindowsExecutableInitializer(void) __attribute__ ((constructor)) __attribute__ ((used));
1385+
1386+
void __CFWindowsExecutableInitializer(void) {
1387+
static CFBundleRef cfBundle = NULL;
1388+
__CFInitialize();
1389+
cfBundle = RegisterCoreFoundationBundle();
1390+
}
1391+
#endif
1392+
13831393
int DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID pReserved ) {
13841394
static CFBundleRef cfBundle = NULL;
13851395
if (dwReason == DLL_PROCESS_ATTACH) {

Sources/_CFURLSessionInterface/CFURLSessionInterface.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
///
1919
//===----------------------------------------------------------------------===//
2020

21-
#include "CFURLSessionInterface.h"
2221
#include "CFInternal.h"
22+
#include "CFURLSessionInterface.h"
2323
#include "CFString.h"
2424
#include <curl/curl.h>
2525

Tests/Foundation/TestBundle.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,16 @@ internal func testBundleName() -> String {
4242
return testBundle().infoDictionary!["CFBundleName"] as! String
4343
}
4444

45-
internal func xdgTestHelperURL() -> URL {
45+
internal func xdgTestHelperURL() throws -> URL {
46+
#if os(Windows)
47+
// Adding the xdgTestHelper as a dependency of TestFoundation causes its object files (including the main function) to be linked into the test runner executable as well
48+
// While this works on Linux due to special linker functionality, this doesn't work on Windows and results in a collision between the two main symbols
49+
// SwiftPM also cannot support depending on this executable (to ensure it is built) without also linking its objects into the test runner
50+
// For those reasons, using the xdgTestHelper on Windows is currently unsupported and tests that rely on it must be skipped
51+
throw XCTSkip("xdgTestHelper is not supported during testing on Windows (test executables are not supported by SwiftPM on Windows)")
52+
#else
4653
testBundle().bundleURL.deletingLastPathComponent().appendingPathComponent("xdgTestHelper")
54+
#endif
4755
}
4856

4957

Tests/Foundation/TestFileManager.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ class TestFileManager : XCTestCase {
12511251
environment[entry.key] = entry.value
12521252
}
12531253

1254-
let helper = xdgTestHelperURL()
1254+
let helper = try xdgTestHelperURL()
12551255
let (stdout, _) = try runTask([ helper.path, "--nspathfor", method, identifier ],
12561256
environment: environment)
12571257

Tests/Foundation/TestHTTPCookieStorage.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class TestHTTPCookieStorage: XCTestCase {
334334

335335
// Test by setting the environmental variable
336336
let task = Process()
337-
task.executableURL = xdgTestHelperURL()
337+
task.executableURL = try xdgTestHelperURL()
338338
task.arguments = ["--xdgcheck"]
339339
var environment = ProcessInfo.processInfo.environment
340340
let testPath = NSHomeDirectory() + "/TestXDG"

0 commit comments

Comments
 (0)