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

Integrate LLD for MSVC targets; prepare for other targets #2142

Merged
merged 10 commits into from
Jun 4, 2017

Conversation

kinke
Copy link
Member

@kinke kinke commented May 26, 2017

No description provided.

@kinke kinke changed the title Move static lib generation from driver/linker.cpp to driver/archiver.cpp Move static lib generation from driver/linker.cpp to driver/archiver.cpp [NFC] May 26, 2017
@kinke kinke changed the title Move static lib generation from driver/linker.cpp to driver/archiver.cpp [NFC] Split up driver/linker.cpp [NFC] May 26, 2017
@kinke kinke force-pushed the archiver branch 2 times, most recently from 94d5ce6 to e0b34e2 Compare May 26, 2017 23:37
@kinke kinke changed the title Split up driver/linker.cpp [NFC] Split up driver/linker.cpp and prepare for (L)LD May 27, 2017
…_LLD

Results in a 7.5% bigger RelWithDebInfo ldc2.exe on Win64 with LLVM 3.9.1.

LLD is currently enforced when building with LDC_WITH_LLD=ON. And LLD
still doesn't support debuginfo (.pdb) generation for MSVC targets.
@kinke
Copy link
Member Author

kinke commented May 27, 2017

Alright, I just tested directly cross-compiling and -linking from Linux x64 to Win64. It works without much hassle.

  1. Build this PR, using CMake option -DLDC_WITH_LLD=ON (edit: not required anymore), with a recent LLVM incl. LLD (I used the current release_40 branch for both LLVM and LLD on Ubuntu 16.04).
  2. Copy over system libs and object files from a Visual C++ installation. I used Visual C++ 2015 x64 Update 3 with the latest Win10 SDK. I merged all .{lib,obj} files in most directories specified in the LIB environment variable (VS tools command prompt) into a single new directory, renamed all those files to lowercase (most Linux filesystems are case-sensitive) and packed them to an archive. Raw size nearly 0.5 GB, .tar.xz about 32 MB.
  3. Copy over LDC runtime files, e.g., from the latest Win64 release package (all files in the lib64 subdirectory).
  4. Tweak the LDC config by adding a section like this (note the -L lib directories [edit:] and the additional -link-internally switch):
x86_64-pc-windows-msvc:
{
    // default switches injected before all explicit command-line switches
    switches = [
        "-I/home/martin/ldc/runtime/druntime/src",
        "-I/home/martin/ldc/runtime/profile-rt/d",
        "-I/home/martin/ldc/runtime/phobos",
        "-L-L/home/martin/Downloads/libs_msvc14_x64",
        "-L-L/home/martin/Downloads/ldc2-1.3.0-beta1-win64-msvc/lib64", 
        "-link-internally",
        "-defaultlib=phobos2-ldc,druntime-ldc",
        "-debuglib=phobos2-ldc-debug,druntime-ldc-debug"
    ];
};

You'll then be able to produce Win64 executables and DLLs by simply using the -mtriple=x86_64-pc-windows-msvc switch with LDC. I produced a Phobos-hello-world and a dmd-testsuite runnable\eh.d executable, copied them over to my Windows box and they worked.

@kinke
Copy link
Member Author

kinke commented May 27, 2017

This also means that if we are allowed to redistribute the MS libs, we could provide a self-sufficient package for Windows, similar to the DMD package, without relying on any Visual C++ installation (and well basically depending on nothing at all except for Windows these days - no libconfig, no shared C runtime, no external linker & libs, ...). A self-sufficient Win64-only package (no 32-bit libs) would be a ~50 MB download, just to give you an idea.

@kinke kinke changed the title Split up driver/linker.cpp and prepare for (L)LD [WIP] Integrate LLD for MSVC targets; prepare for other targets May 27, 2017
@dnadlinger
Copy link
Member

Nice! Do you know what the licensing situation is on the MS libraries?

@dnadlinger
Copy link
Member

dnadlinger commented May 27, 2017

How big is the impact of LDC_WITH_LLD=ON? I'd be keen to keep the number of options to a minimum (that is, turn on the LLD code by default as soon as it is merged).

@kinke
Copy link
Member Author

kinke commented May 27, 2017

Do you know what the licensing situation is on the MS libraries?

Nope, no idea.

How big is the impact of LDC_WITH_LLD=ON?

Size-wise for the ldc2 executable currently +7.5% with just the COFF output capability (Win64, RelWithDebInfo, LLVM & LLD 3.9.1). Mach-O and ELF still to come.
It's just a quick hack for now so that I don't need to check the LLVM version and LLD availability.

@kinke kinke changed the title [WIP] Integrate LLD for MSVC targets; prepare for other targets Integrate LLD for MSVC targets; prepare for other targets May 28, 2017
@kinke
Copy link
Member Author

kinke commented May 28, 2017

I got rid of LDC_WITH_LLD as user-provided CMake option and try to detect LLVM 3.9+ incl. LLD headers & libs now instead.
AppVeyor produces LLD-enabled LDC builds and so does Travis for LLVM 4.0 (Linux and OS X), but LLD isn't tested as it's opt-in via -internal-linker for now (still experimental, no .pdb support etc.).
[I updated the instructions above accordingly.]

staticFlag("static", llvm::cl::ZeroOrMore,
llvm::cl::desc("Create a statically linked binary, including "
"all system dependencies"));

#if LDC_WITH_LLD
static llvm::cl::opt<bool>
useInternalLinker("internal-linker", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
Copy link
Member

@dnadlinger dnadlinger May 28, 2017

Choose a reason for hiding this comment

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

Maybe -link-internally or something like that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed.

if(MSVC)
list(APPEND LDC_LINKERFLAG_LIST lldCOFF.lib lldCore.lib lldDriver.lib)
else()
set(LDC_LINKERFLAG_LIST "-llldCOFF;-llldCore;-llldDriver;${LDC_LINKERFLAG_LIST}")
Copy link
Member

Choose a reason for hiding this comment

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

Is there an equivalent of llvm-config for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not that I've seen, in fact I didn't find anything about how to embed LLD via CMake. On Linux the order matters (even inbetween these 3 new libs), so I put them in front. As the LLD libs don't have the LLVM prefix, we can't specify them in find_package()...

CMakeLists.txt Outdated
#
set(LDC_WITH_LLD OFF)
if(LDC_LLVM_VER GREATER 308)
if(EXISTS "${LLVM_INCLUDE_DIRS}/lld/Driver/Driver.h")
Copy link
Member

Choose a reason for hiding this comment

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

Maybe just use the standard CMake header search functionality? ${LLVM_INCLUDE_DIRS}/… (with the plural) looks quite wrong.

Copy link
Member Author

Choose a reason for hiding this comment

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

CHECK_INCLUDE_FILE() didn't work (although there's a previous line with include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) - no extra include dirs appear to be used for the check).

Copy link
Member

Choose a reason for hiding this comment

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

Does CMAKE_REQUIRED_INCLUDES do the trick?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep it does.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm it doesn't for Travis (LLVM 4.0). :/

Copy link
Member Author

@kinke kinke May 29, 2017

Choose a reason for hiding this comment

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

gcc needs an additional -std=c++11 flag; fixed now.
Edit: Dammit, clang (Travis OSX) still fails.
Edit2: Works with clang 3.8 here in my VM.

Copy link
Member Author

Choose a reason for hiding this comment

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

Damn, I missed that the first Travis OSX job now uses the SPIRV LLVM which apparently doesn't feature LLD. So all good, LLD is dectected correctly for the other job.

}

for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
addSwitch(global.params.linkswitches->data[i]);
Copy link
Member

Choose a reason for hiding this comment

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

This is probably code that existed before, but you can use (*global.params.linkswitches)[i] or our range-based for wrapper.

@kinke
Copy link
Member Author

kinke commented May 29, 2017

Yesterday I tried integrating LLD for ELF and Mach-O targets as well. Sadly, there's an unknown number of conflicting command-line options then (which only show up after linking, when running LDC; additionally, only the first conflicting option is shown as I had to find out). I renamed the -dwarf-version one, but then -march popped up and I stopped, as I guess that wasn't all. [I experimented on Win64 with LLD 3.9.]

Oh and the ldc2.exe size grew by about 20% compared to LDC without LLD at all.

And infer CMake LDC_WITH_LLD automatically based on availability of LLVM
3.9+ with LLD headers & libs.
@JohanEngelen
Copy link
Member

(about cmdline options: I think it'd be best to someday go the Clang route: put all LLVM options behind a -mllvm switch)

@JohanEngelen
Copy link
Member

Very cool work btw!

@kinke
Copy link
Member Author

kinke commented May 30, 2017

The problem is that LLD's ELF/LTO.cpp drags in an LLVM header with quite a number of command-line options, quite a few colliding with our duplicates, but also many new options; at least some would also make sense for LDC.

The include has been removed in LLD master, but it's there for 3.9 and 4.0.
Edit: Nope, just moved here.

@kinke
Copy link
Member Author

kinke commented Jun 2, 2017

I quickly looked into using that shared LLVM header ourselves (in a separate .cpp, so that it's only pulled in if it's not already via LLD), but what's required is a hack. The actually required shared utility functions (setting up a TargetMachine's TargetOptions according to all codegen command-line options etc. - very handy) are all marked as static (linkage), so one can't 'export' them directly. LLD master has its own little .cpp file including the LLVM header and augmenting it with their external wrappers in the lld namespace. They use it to prevent conflicts inside LLD itself. ;)
Unfortunately, for us this means that we'd have to forward to these external LLD wrappers for LDC_WITH_LLD (edit: oh I think they only 'exported' a subset of the utility functions, not all we'd need), and otherwise include the LLVM header and implement the wrappers ourselves. And as soon as we want to integrate another LLVM project including that header, with its own wrapper functions in some unknown namespace, it goes boom.

@kinke kinke force-pushed the archiver branch 2 times, most recently from 7533746 to 2acddf9 Compare June 2, 2017 20:39
@kinke kinke merged commit 2008400 into ldc-developers:master Jun 4, 2017
@kinke kinke deleted the archiver branch June 4, 2017 02:02
@Laeeth
Copy link

Laeeth commented Jun 22, 2017

licensing
https://www.visualstudio.com/en-us/productinfo/2015-redistribution-vs#visual-c-runtime

or you could just include a little call to download and install vcredist* as a script in the repo. (older versions usually require logging in with MS account, unfortunately, but curl should pick up latest one ). I don't know if vcredist installer works on wine.

@kinke
Copy link
Member Author

kinke commented Jun 22, 2017

We don't need to redistribute the DLLs (easy enough to install and only needed when running binaries created with non-default -mscrtlib=msvcrt[d]); it's about the static and import .lib files.

@MartinNowak
Copy link
Contributor

They do support static linking, so one would think that their license supported some form of redistribution.
But non of those lib files are in Visual Studio 2015 Redistribution List.

@d-random-contributor
Copy link

They allow redistribution of libraries after they are run through linker :)

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.

None yet

6 participants