-
Notifications
You must be signed in to change notification settings - Fork 199
[DNM][WIP] Implement Windows toolchain #419
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
Changes from 17 commits
9fcd3f2
9076ab2
2c9716b
8b7b0df
3c0feb3
633801d
59877f1
4b69ec6
31d2556
d8c4f60
ed1b8c2
4bd5495
7e82541
46785ab
660a709
b1e5ef9
e270919
aa908ad
a3ca4ab
5d38461
204f061
6909152
aa427ed
58c6f7a
9d308f1
a666df9
d48e3e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors | ||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
|
@@ -50,7 +50,11 @@ extension Toolchain { | |
result.append(sdkPath.appending(components: "System", "iOSSupport", "usr", "lib", "swift")) | ||
} | ||
|
||
result.append(sdkPath.appending(components: "usr", "lib", "swift")) | ||
if (triple.isWindows) { | ||
result.append(sdkPath.appending(components: "usr", "lib", "swift", "windows")) | ||
} else { | ||
Comment on lines
+53
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this used to find the correct path to the runtime, or something else maybe? I know in a few other places we append There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I referred to the current layout of Windows toolchain and SDK, which is slightly different from other platforms. I think we need to unify SDK layout for the convenience of cross-compilation (and to eliminate differences across platforms), how do you think @compnerd ? |
||
result.append(sdkPath.appending(components: "usr", "lib", "swift")) | ||
} | ||
} | ||
|
||
return result | ||
|
@@ -225,3 +229,5 @@ extension DarwinToolchain { | |
} | ||
|
||
} | ||
|
||
// TODO: Implement `addArgsToLinkStdlib` for `WindowsToolchain`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
//===---------------- WindowsToolchain+LinkerSupport.swift ----------------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
import TSCBasic | ||
import SwiftOptions | ||
|
||
extension WindowsToolchain { | ||
public func addPlatformSpecificLinkerArgs( | ||
to commandLine: inout [Job.ArgTemplate], | ||
parsedOptions: inout ParsedOptions, | ||
linkerOutputType: LinkOutputType, | ||
inputs: [TypedVirtualPath], | ||
outputFile: VirtualPath, | ||
shouldUseInputFileList: Bool, | ||
lto: LTOKind?, | ||
sanitizers: Set<Sanitizer>, | ||
targetInfo: FrontendTargetInfo | ||
) throws -> AbsolutePath { | ||
let targetTriple = targetInfo.target.triple | ||
|
||
switch linkerOutputType { | ||
case .dynamicLibrary: | ||
commandLine.appendFlags("-Xlinker", "-dll") | ||
stevapple marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fallthrough | ||
case .executable: | ||
if !targetTriple.triple.isEmpty { | ||
commandLine.appendFlag("-target") | ||
commandLine.appendFlag(targetTriple.triple) | ||
} | ||
// Configure the toolchain. | ||
// | ||
// By default use the system `clang` to perform the link. We use `clang` for | ||
// the driver here because we do not wish to select a particular C++ runtime. | ||
// Furthermore, until C++ interop is enabled, we cannot have a dependency on | ||
// C++ code from pure Swift code. If linked libraries are C++ based, they | ||
// should properly link C++. In the case of static linking, the user can | ||
// explicitly specify the C++ runtime to link against. This is particularly | ||
// important for platforms like android where as it is a Linux platform, the | ||
// default C++ runtime is `libstdc++` which is unsupported on the target but | ||
// as the builds are usually cross-compiled from Linux, libstdc++ is going to | ||
// be present. This results in linking the wrong version of libstdc++ | ||
// generating invalid binaries. It is also possible to use different C++ | ||
// runtimes than the default C++ runtime for the platform (e.g. libc++ on | ||
// Windows rather than msvcprt). When C++ interop is enabled, we will need to | ||
// surface this via a driver flag. For now, opt for the simpler approach of | ||
// just using `clang` and avoid a dependency on the C++ runtime. | ||
var clangPath = try getToolPath(.clang) | ||
if let toolsDirPath = parsedOptions.getLastArgument(.toolsDirectory) { | ||
// FIXME: What if this isn't an absolute path? | ||
let toolsDir = try AbsolutePath(validating: toolsDirPath.asSingle) | ||
|
||
// If there is a clang in the toolchain folder, use that instead. | ||
if let tool = lookupExecutablePath(filename: "clang.exe", searchPaths: [toolsDir]) { | ||
clangPath = tool | ||
} | ||
|
||
// Look for binutils in the toolchain folder. | ||
commandLine.appendFlag("-B") | ||
commandLine.appendPath(toolsDir) | ||
} | ||
|
||
let linker: String | ||
if let arg = parsedOptions.getLastArgument(.useLd) { | ||
linker = arg.asSingle | ||
} else { | ||
linker = "link" | ||
} | ||
commandLine.appendFlag("-fuse-ld=\(linker)") | ||
|
||
if let crt = parsedOptions.getLastArgument(.libc) { | ||
switch crt.asSingle { | ||
case "MT": commandLine.appendFlags("-Xlinker", "-defaultlib:libcmt") | ||
case "MTd": commandLine.appendFlags("-Xlinker", "-defaultlib:libcmtd") | ||
case "MD": commandLine.appendFlags("-Xlinker", "-defaultlib:msvcrt") | ||
case "MDd": commandLine.appendFlags("-Xlinker", "-defaultlib:msvcrtd") | ||
default: fatalError("Invalid C runtime value should be filtered") | ||
} | ||
} else { | ||
commandLine.appendFlags("-Xlinker", "-defaultlib:msvcrt") | ||
} | ||
|
||
let staticStdlib = parsedOptions.hasFlag(positive: .staticStdlib, | ||
negative: .noStaticStdlib, | ||
default: false) | ||
let staticExecutable = parsedOptions.hasFlag(positive: .staticExecutable, | ||
negative: .noStaticExecutable, | ||
default: false) | ||
let hasRuntimeArgs = !(staticStdlib || staticExecutable) | ||
|
||
let runtimePaths = try runtimeLibraryPaths( | ||
for: targetInfo, | ||
parsedOptions: &parsedOptions, | ||
sdkPath: targetInfo.sdkPath?.path, | ||
isShared: hasRuntimeArgs | ||
) | ||
|
||
guard let swiftrtPath = targetInfo.sdkPath?.path | ||
.appending( | ||
components: "usr", "lib", "swift", "windows", | ||
targetTriple.archName, | ||
"swiftrt.obj") else { | ||
throw ToolchainValidationError.sdkNotFound | ||
} | ||
commandLine.appendPath(swiftrtPath) | ||
|
||
let inputFiles: [Job.ArgTemplate] = inputs.compactMap { input in | ||
// Autolink inputs are handled specially | ||
if input.type == .autolink { | ||
return .responseFilePath(input.file) | ||
} else if input.type == .object { | ||
return .path(input.file) | ||
} else { | ||
return nil | ||
} | ||
} | ||
commandLine.append(contentsOf: inputFiles) | ||
|
||
let fSystemArgs = parsedOptions.arguments(for: .F, .Fsystem) | ||
for opt in fSystemArgs { | ||
if opt.option == .Fsystem { | ||
commandLine.appendFlag("-iframework") | ||
} else { | ||
commandLine.appendFlag(.F) | ||
} | ||
commandLine.appendPath(try VirtualPath(path: opt.argument.asSingle)) | ||
} | ||
|
||
// Add the runtime library link paths. | ||
for path in runtimePaths { | ||
commandLine.appendFlag(.L) | ||
commandLine.appendPath(path.appending(component: targetTriple.archName)) | ||
} | ||
|
||
if hasRuntimeArgs { | ||
commandLine.appendFlag("-lswiftCore") | ||
} | ||
|
||
// Explicitly pass the target to the linker | ||
commandLine.appendFlags("-target", targetTriple.triple) | ||
stevapple marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Delegate to Clang for sanitizers. It will figure out the correct linker | ||
// options. | ||
if linkerOutputType == .executable && !sanitizers.isEmpty { | ||
let sanitizerNames = sanitizers | ||
.map { $0.rawValue } | ||
.sorted() // Sort so we get a stable, testable order | ||
.joined(separator: ",") | ||
commandLine.appendFlag("-fsanitize=\(sanitizerNames)") | ||
|
||
// The TSan runtime depends on the blocks runtime and libdispatch. | ||
if sanitizers.contains(.thread) { | ||
commandLine.appendFlag("-lBlocksRuntime") | ||
commandLine.appendFlag("-ldispatch") | ||
} | ||
} | ||
|
||
// Run clang++ in verbose mode if "-v" is set | ||
try commandLine.appendLast(.v, from: &parsedOptions) | ||
|
||
// These custom arguments should be right before the object file at the | ||
// end. | ||
try commandLine.append( | ||
contentsOf: parsedOptions.arguments(in: .linkerOption) | ||
) | ||
try commandLine.appendAllArguments(.Xlinker, from: &parsedOptions) | ||
try commandLine.appendAllArguments(.XclangLinker, from: &parsedOptions) | ||
|
||
// This should be the last option, for convenience in checking output. | ||
commandLine.appendFlag(.o) | ||
commandLine.appendPath(outputFile) | ||
return clangPath | ||
case .staticLibrary: | ||
commandLine.append(.joinedOptionAndPath("-out:", outputFile)) | ||
commandLine.append(contentsOf: inputs.map { .path($0.file) }) | ||
stevapple marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return try getToolPath(.staticLinker(lto)) | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.