Skip to content

[driver] Implement a Windows toolchain for cross-compiling #13236

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

Merged
merged 1 commit into from
Apr 18, 2018

Conversation

troughton
Copy link
Contributor

@troughton troughton commented Dec 3, 2017

In this PR, I've implemented an initial Windows toolchain that has been tested to work in cross-compiling from Linux to Windows.

When combined with #13140, this enables an invocation like:

swift -target x86_64-unknown-windows-msvc -use-ld=lld main.swift -o SwiftTest.exe

to produce a Windows executable (note that the executable itself will still run into separate issues).

I've followed the pattern of the GenericUnix toolchain here, which does mean there's currently a fair amount of code duplication. I don't know how much will need to change for native builds, and nor do I know how many of the extra arguments (such as ASAN or producing a static executable) will work as-is. However, I thought that Windows is sufficiently different enough from the existing OSes to justify its own toolchain and expect it to diverge further as it is expanded, making this a good starting point.

Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should split out the implementation into a new .cpp.

return (Twine("clang_rt.")
+ Sanitizer + "-"
+ Triple.getArchName()
+ (shared ? ".dll" : ".lib")).str();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that this is right. You never link against the .dll but rather the .lib.

getRuntimeLibraryPath(Dir, Args, TC);
// Remove platform name.
llvm::sys::path::remove_filename(Dir);
llvm::sys::path::append(Dir, "clang", "lib", "windows");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this effectively getClangLibraryPathOnWindows?

Arguments.push_back("-lc++");
// Add explicit dependency on -lc++abi, as -lc++ doesn't re-export
// all RTTI-related symbols that are used.
Arguments.push_back("-lc++abi");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the assumption on the library names here and the spelling for the argument? Furthermore, Windows doesn't use libc++abi ever but rather vcruntime.


addPathEnvironmentVariableIfNeeded(II.ExtraEnvironment, "PATH",
":", options::OPT_L, context.Args,
runtimeLibraryPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do this, this way (via the environment). We use use -libpath or -L.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't work for the interpreter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing this is probably out of scope for the PR as I'm only able to test cross-compiling at the moment, so testing the interpreter isn't an option.

Arguments.push_back(
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));

return {"swift-autolink-extract", Arguments};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels wrong. We shouldn't be using swift-autolink-extract on Windows at all. We have auto-linking support, and we should make that work instead.

if (!VCToolsDir.empty()) {
Arguments.push_back("-Xlinker");
Arguments.push_back(context.Args.MakeArgString("/LIBPATH:" + llvm::Twine(VCToolsInstallDir)
+ "/Lib/" + tripleWinArchName));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous point of -L.

+ "/Lib/" + llvm::Twine(UCRTVer) + "/ucrt/" + tripleWinArchName));
Arguments.push_back("-Xlinker");
Arguments.push_back(context.Args.MakeArgString("/LIBPATH:" + llvm::Twine(UCRTDir)
+ "/Lib/" + llvm::Twine(UCRTVer) + "/um/" + tripleWinArchName));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And again

Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath));
}

// Add any autolinking scripts to the arguments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous point about auto-linking.

}
else {
Arguments.push_back(context.Args.MakeArgString(SharedRuntimeLibPath));
Arguments.push_back("-lswiftCore");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be the absolute path to the swiftCore.lib as that is in a well defined location I believe.

Arguments.push_back("-lswiftCore");
}

// Explicitly pass the target to the linker
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be to the driver, the linker does not read the target.

@compnerd compnerd requested a review from jrose-apple December 3, 2017 23:00
@troughton
Copy link
Contributor Author

@compnerd Okay, I'll start making those adjustments. Just a note that whenever there's a 'why have you done this' it's because I started with the GenericUnix toolchain and just tweaked until it worked; this was just a starting point and I was fulling expecting further changes.

@troughton
Copy link
Contributor Author

@jrose-apple Would you want this split out into a separate CPP file, and, if so, should the GenericUnix and Darwin toolchains also have their own CPP files?

for (const Arg *arg : context.Args.filtered(options::OPT_F,
options::OPT_Fsystem)) {
if (arg->getOption().matches(options::OPT_Fsystem))
Arguments.push_back("-iframework");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we ever get frameworks being passed to the linker in a Windows context?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing that is interesting about a framework is the fact that they have a particular layout. I don't see a strong reason to not forward those along to clang and have clang just transliterate them into the appropriate -I and -L options.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably does make sense to split up ToolChains.cpp at this point. That should happen in a no-functionality-change commit, though, and that can be after this PR.

ArgStringList &Arguments,
StringRef Sanitizer,
const ToolChain &TC,
bool shared = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: misaligned arguments here, and the close paren should follow the last argument instead of going on the next line.

ToolChain::InvocationInfo
toolchains::Windows::constructInvocation(const InterpretJobAction &job,
const JobContext &context) const {
InvocationInfo II = ToolChain::constructInvocation(job, context);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this now that you're inheriting directly from ToolChain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is vestigial because @compnerd had you remove the LD_LIBRARY_PATH trick. Unfortunately we'll need to come up with something similar for Windows if we want the interpreter to work with -L. We're probably not doing the right thing on Windows anyway, though (dlopen).


// Configure the toolchain.
// By default, use the system clang++ to link.
const char * Clang = "clang++";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has there been any discussion about using cl directly? Do we get any benefit from using Clang?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are tradeoffs to each approach. With cl, the user doesn't need Clang installed, but Clang does provide things like ASAN that MSVC is missing. If we also might end up with a dependency on Compiler-RT (see #13234) then it'd probably be worth sticking with Clang.

As for using the clang-cl vs. clang driver: I don't have any strong opinions there. I suppose there'd be some benefit in consistency with other platforms, but if the consensus is that clang-cl is preferred I can easily switch over the commands.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose one option would be to use clang-cl by default and fallback to cl if Clang isn't installed.


StringRef tripleWinArchName;
switch (getTriple().getArch()) {
case llvm::Triple::x86:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: case labels are not indented in LLVM style.

StringRef UCRTVer(UCRTVersion);

if (!UCRTDir.empty() && !UCRTVer.empty()) {
Arguments.push_back("-L");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: accidental double-indent here.

Arguments.push_back(context.Args.MakeArgString(StaticRuntimeLibPath));

SmallString<128> linkFilePath = StaticRuntimeLibPath;
llvm::sys::path::append(linkFilePath, "static-executable-args.lnk");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work on Windows?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static stdlib isn't currently building on Windows, but thinking about it more I think we'd end up passing the same arguments here whether we're building static or shared, so this section should be removed. @compnerd, thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant linker scripts in general, but that's also a reasonable question.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I made a similar point when I looked through this, that the invocation should be similar.

@jrose-apple linker scripts are not supported on Windows, but this isn't a linker script, it is a response file, which is supported (link and lld both support it, and those are the only viable linkers atm).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, of course. Thanks, Saleem.

}

// Explicitly pass the target to the driver
Arguments.push_back(context.Args.MakeArgString("--target=" + getTriple().str()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already have this above.

Arguments.push_back(context.Args.MakeArgString(LibProfile));
Arguments.push_back(context.Args.MakeArgString(
Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do all of these things work on Windows?

@@ -1690,7 +1954,7 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
Arguments.push_back("-lswiftCore");
}

// Explicitly pass the target to the linker
// Explicitly pass the target to the driver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the driver" means "the Swift driver" in this context. If you don't like "the linker", please just say "Clang" here.

bool shared = true
) {
// Sanitizer runtime libraries requires C++.
Arguments.push_back("-lc++");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't everything need C++, not just the sanitizers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is copied across from the Darwin implementation. I haven't had a chance (yet) to test the sanitisers, but everything else works fine without the -lc++ flag – it might not even be necessary with the sanitisers.

In general, do we want to err on the side of 'untested but might work', or 'only present if it's guaranteed to work,' considering there's a lot on Windows that won't be able to be tested properly for a while?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thoughts are that no one will ever remove something unnecessary, but they will add what's necessary. Therefore I'd rather err on the minimal side.

@troughton
Copy link
Contributor Author

I've just run clang-format and applied the changes to the Windows sections of the file, so some comments above might be marked as outdated when they're still relevant. I should note that there's a lot of inconsistencies in this file in terms of formatting (of which my changes inherited a few), so it might be worth running clang-format through it all in the process of splitting it up.

@@ -1104,6 +1113,12 @@ getSanitizerRuntimeLibNameForDarwin(StringRef Sanitizer,
+ (shared ? "_dynamic.dylib" : ".a")).str();
}

static std::string getSanitizerRuntimeLibNameForWindows(
StringRef Sanitizer, const llvm::Triple &Triple, bool shared = true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shared is an unused parameter.

return llvm::make_unique<toolchains::Cygwin>(driver, target);
} else {
return llvm::make_unique<toolchains::Windows>(driver, target);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary braces.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This matches the target.isAndroid conditional above. What's the Swift project style on this? Should I change both of them to remove the braces?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're based on LLVM style, which says no braces for single-line if-statements. We swing pretty heavily on the side of having them whenever it's a grey area, though:

  • If you have comments inside the body, provide the braces.
  • If the line wraps, people usually provide the braces.
  • If another branch of the if has braces, people usually add braces to all of them.
  • If the condition wraps, sometimes people provide braces.

const ToolChain &TC,
bool shared = true) {
// Sanitizer runtime libraries requires C++.
Arguments.push_back("-lc++");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This naming is still wrong. Plus, what if Im using msvcprt for the C++ runtime?

if (auto toolchainClang =
llvm::sys::findProgramByName("clang++", {toolchainPath})) {
Clang = context.Args.MakeArgString(toolchainClang.get());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use clang++, we shouldn't be adding the C++ runtime link.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should always do a findProgramByName for clang++. That way when you do -v you can see which clang is being used.

} else if (context.Args.hasFlag(options::OPT_static_stdlib,
options::OPT_no_static_stdlib, false)) {
staticStdlib = true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialize the variables at declaration time rather than the separate conditional?

bool staticExecutable = context.Args.hasFlag(
options::OPT_static_executable, options::OPT_no_static_executable, false);
bool staticStdlib = context.Args.hasFlag(
options::OPT_static_stdlib, options::OPT_no_static_stdlib, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't exactly equivalent: previously staticExecutable implied !staticStdlib. But that doesn't actually make sense to me; shouldn't it be the other way around?

@troughton
Copy link
Contributor Author

troughton commented Dec 6, 2017

I was playing around with the different options and seeing if I could test the different -static-executable and -static-stdlib flags and came to the conclusion that it's probably best to leave both out of this PR. The static standard library isn't building correctly yet on Windows and I'm not confident enough in my understanding on how linking works on Windows to justify keeping that code path in.

With regards to the .lnk files, I believe they're not getting produced correctly on anything other than Linux at the moment, but when they are there for Windows the code should be able to be copied pretty much verbatim from the GenericUnix toolchain.

I believe I've addressed the other concerns. Whether we should be using cl or clang++ is an open discussion point, but for now, since clang++ is the only supported option, I'm leaving in the flags for the various sanitisers and for optimisation profile generation. I see no reason why they wouldn't work, although they're again hard to test in a cross-compile environment.

@compnerd
Copy link
Member

compnerd commented Dec 6, 2017

Can you please add some tests to ensure that the various codepaths generate the proper tool invocations?

@troughton
Copy link
Contributor Author

Sure. I've briefly looked through test/Driver and there's quite a lot in there – this is the first functionality I've added to Swift so I'm not familiar with the all the testing commands and output check tools. Is there anywhere in particular you could point me to for other platforms that would be a good starting point?

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some tests to add to / steal from:

  • Driver/linker.swift has a bunch of simple link lines just to test that we get to linking at all
  • Driver/linker-autolink-extract.swift probably works unmodified with a Windows triple
  • Driver/sdk.swift could be relevant
  • Driver/sanitizers.swift is probably worth adding to, since you included sanitizer logic here

const JobContext &context) const {
InvocationInfo II = ToolChain::constructInvocation(job, context);

return II;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just take this out if we're not going to be doing anything with it right now.

@troughton
Copy link
Contributor Author

troughton commented Dec 7, 2017

I've added tests in those files and fixed a couple of other small issues I've found. All of the tests pass locally. Is there anywhere I've missed coverage?

@troughton
Copy link
Contributor Author

Checking back on this PR - are we okay to merge this?

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from my end. Saleem?

@@ -139,7 +139,7 @@ OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
}

// Sanitizers are only supported on Linux or Darwin.
if (!(Triple.isOSDarwin() || Triple.isOSLinux())) {
if (!(Triple.isOSDarwin() || Triple.isOSLinux() || Triple.isOSWindows())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment here is no longer valid?

Copy link
Contributor Author

@troughton troughton Jan 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now changed this to "Check that we're one of the known supported targets for sanitizers."

@@ -1025,6 +1025,15 @@ static void getClangLibraryPathOnDarwin(SmallVectorImpl<char> &libPath,
llvm::sys::path::append(libPath, "clang", "lib", "darwin");
}

static void getClangLibraryPathOnWindows(SmallVectorImpl<char> &libPath,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to think this needs refactoring, but I won't make you do it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be happy to take a look at splitting up this file and refactoring some of the common functionality in an NFC follow-up PR – I think there's some fairly straightforward things that would help.

@troughton troughton force-pushed the windows-toolchain-pr branch from e2e36aa to 5cbc83c Compare January 30, 2018 23:08
@troughton
Copy link
Contributor Author

troughton commented Feb 1, 2018

I've updated this PR to include static linking support, since I now have that working locally on Windows. I also added swiftrt.o to the linker invocation since that's now required for COFF binaries to correctly initialise.

Note that it's not possible to directly test the static linking (as per test/Driver/static-stdlib) yet since there are still some changes to be made before building the static libraries actually works. I've tested the invocations locally with some workarounds, though.

I can squash these commits before it's merged if that's helpful.

@troughton troughton force-pushed the windows-toolchain-pr branch from ac026e1 to 3ec1f9e Compare February 2, 2018 23:12
@troughton
Copy link
Contributor Author

@compnerd Does this look okay to you now?

@troughton
Copy link
Contributor Author

@jrose-apple If @compnerd doesn't have any complaints, are we okay to merge this? There've been a couple of small changes (static linking support and adding the COFF registration object) since you likely last looked at it.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see anything that raises any flags for me. Yes, if Saleem's good I'm good. Thanks, Thomas.

getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);

// Since Windows has separate libraries per architecture, link against the
// architecture specific version of the static library.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should getRuntimeStaticLibraryPath just do this? Are there places where we call it and need it to not do this?

Copy link
Contributor Author

@troughton troughton Feb 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows is the only place we currently add the arch that I can see. I think on Darwin universal binaries are produced and copied to the lib/swift_static/platform folder; on Linux, I think the current assumption is that only one architecture will ever be present per platform, and so just using the copied libraries is fine (although probably not technically correct).

On Windows, the files in that folder are (currently) just the static libraries for whichever arch was built last, so linking against that is definitely incorrect.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think that's @zbowling's #13108. I think that pushes the arch up into getRuntimeStaticLibraryPath for everyone, so this would become redundant. But I'm not sure what state that PR is in, since we didn't get back to Zac very quickly and he hasn't touched it but then @alblue poked it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks right. Once that's merged we can remove the extra code here and just use getRuntimeStaticLibraryPathWithArch instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, sorry. I've been busying in a bit of freeze with all the code I posted in all the PRs in December to take them and try and cut and stabilize a usable toolchain to ship in Fuchsia. Everything is getting to a good place with that toolchain so I should have more time to switch back and rebase all my PRs to get them ready to land upstream easier (and so I can get a new toolchain going with changes since the 4.1 branch).

+ getTriple().getArchName()));

Arguments.push_back("-Xlinker");
Arguments.push_back("/NODEFAULTLIB:libcmt");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you leave a comment for why this is necessary?

Copy link
Contributor Author

@troughton troughton Feb 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done; I've been specific to the degree I understand the problem, which I admit is not fully.

I'm not actually certain it'll be necessary in the future (it may just be an artefact of how static libraries are currently produced for Windows), but for now adding that flag avoids the mentioned issues. @compnerd would probably have a better idea as to why it's needed.

As an example, some of the errors it avoids are:

/usr/bin/lld-link: error: swiftCore.lib(Exclusivity.cpp.o): undefined symbol: __imp__wassert
/usr/bin/lld-link: warning: swiftCore.lib(Metadata.cpp.o): locally defined symbol imported: free (defined in libucrt.lib(free.obj))

@compnerd
Copy link
Member

@troughton - any chance you can rebase/squash the patches into a coherent patch?

@troughton
Copy link
Contributor Author

@compnerd I'll take a look – I should have some time to do that today. While you're around, can you quickly look at the /NODEFAULTLIB:libcmt flag and confirm that it should be necessary? It was definitely needed last time I built, but that could be because of issues/flags elsewhere in the build that have since been resolved.

@troughton troughton force-pushed the windows-toolchain-pr branch 4 times, most recently from 814501a to 23308c8 Compare April 17, 2018 03:58
@troughton
Copy link
Contributor Author

troughton commented Apr 17, 2018

@compnerd Provided this all looks okay to you, we should be ready to test and merge.

@troughton troughton force-pushed the windows-toolchain-pr branch from 23308c8 to 7ff63b9 Compare April 17, 2018 04:17
Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clang-format the diff

}
if (!Linker.empty()) {
Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The braces are unnecessary.

if (auto toolchainClang =
llvm::sys::findProgramByName("clang++", {toolchainPath})) {
Clang = context.Args.MakeArgString(toolchainClang.get());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should always do a findProgramByName for clang++. That way when you do -v you can see which clang is being used.

//
// To avoid this, we specify that libcmt should not be linked against.
Arguments.push_back("-Xlinker");
Arguments.push_back("/NODEFAULTLIB:libcmt");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems wrong. We should be building with -MT or -MD appropriately.

Copy link
Contributor Author

@troughton troughton Apr 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this for now. Removing it will break building apps (in my case), but I think its presence is symptomatic of a bigger issue: how do we decide which library is appropriate?

Currently, it's whatever the standard library is linked against, but I don't think that's right; rather, it should be determined based on the product we're building. Is the right solution to build the standard library with undefined symbols that are resolved once it's linked with the final Swift executable/library?

}

if (!context.OI.SDKPath.empty()) {
Arguments.push_back("--sysroot");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like it won't work. The toolchain for x86_64-unknown-windows-msvc does not support --sysroot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've replaced --sysroot with -I.

@compnerd
Copy link
Member

Pretty excited about this, I think that this will help with getting the IRGen tests passing, and I can look into fixing the rest of the Driver tests as well.

@troughton troughton force-pushed the windows-toolchain-pr branch from 7ff63b9 to d99bb5d Compare April 17, 2018 23:27
@compnerd
Copy link
Member

Let's go ahead and merge this and then we can improve it from there.

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 68a8ff6e1fe74219443424890b506d5d23f32807

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 68a8ff6e1fe74219443424890b506d5d23f32807

@troughton troughton force-pushed the windows-toolchain-pr branch from d99bb5d to 509b1ff Compare April 18, 2018 00:32
@troughton
Copy link
Contributor Author

The build failure above appears to be unrelated, but I'd missed a test when I changed --sysroot to -I; the above commit was just fixing that.

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - d99bb5db25dc61e8966a7dbccebd1bdfa0bff29c

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - d99bb5db25dc61e8966a7dbccebd1bdfa0bff29c

@troughton troughton force-pushed the windows-toolchain-pr branch from 509b1ff to d0be952 Compare April 18, 2018 03:25
@troughton troughton force-pushed the windows-toolchain-pr branch from d0be952 to 5bb6ac2 Compare April 18, 2018 03:26
@troughton
Copy link
Contributor Author

troughton commented Apr 18, 2018

The linker-autolink-extract test failed on Linux due to the added Windows lines; I was actually testing something that isn't yet implemented, and missed it because I've been running the test suite on macOS (which passed).

I've removed the changes to the linker-autolink-extract test. swift-autolink-extract not being implemented doesn't prevent correctly building programs for Windows.

@compnerd
Copy link
Member

swift-autolink-extract should not even exist on Windows. That is a result of missing functionality in Linux. In fact, I have pending working to remove that from Linux even.

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 509b1ffe420d46a70f1d5bafe83e0f8c09cccc41

@compnerd
Copy link
Member

@swift-ci please test

@compnerd compnerd merged commit bc34e34 into swiftlang:master Apr 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants