From 868642b673042f9f58f0ff9ab096bdada932cbda Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 27 Oct 2018 23:04:11 +0200 Subject: [PATCH 1/5] [MinGW-w64] druntime: Fix 32-bit _chkstk alias target --- runtime/druntime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime b/runtime/druntime index 4afc0547278..a3073c4fa9a 160000 --- a/runtime/druntime +++ b/runtime/druntime @@ -1 +1 @@ -Subproject commit 4afc0547278e4dae1941101f5d39f76374dce144 +Subproject commit a3073c4fa9aaf54d6c665a0f108cd561019ed2fe From 761922fdd4bc35f1877620cbce55df457ec5d47a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 27 Oct 2018 23:16:35 +0200 Subject: [PATCH 2/5] AppVeyor: Build with clang (incl. LLVM) When experimenting with the MinGW-w64 based libs, there was a problem - an undefined reference to function `_(_)chkstk`, emitted by LLVM for stack probing (e.g., after an `alloca`) and not provided by MinGW-w64. Initially, I used the symbol exported by ntdll.dll; normal user apps aren't supposed to depend on that system DLL though, and it also led to duplicate symbols for 32-bit code. After some digging, I found that LLVM's builtins compiler-rt library contains 2 implementations (1 MS-compatible, 1 for MinGW/Cygwin, both with different names than the MS one). Our library didn't contain it though, so I digged deeper. I found the culprit in the builtins CMake script; when using an MSVC toolchain, the builtins lib on Windows only contains very few C files and none of the various ASM ones, because they use AT&T syntax. So I decided to try building LLVM & compiler-rt with clang instead. That works fine, but I had to fix the CMake script, as the ASM files are excluded for MS-*compatible* toolchains, incl. clang. So I forked compiler-rt to fix this and some more annoyances. When compiling LLVM with clang-cl, the LLVM C++ compile flags include some clang-specific ones, so building LDC with MSVC didn't work. While that can be fixed at some point (stripping the clang-specific ones), I decided to build LDC (and the C/ASM files in our default libs) with clang too. That required some adaptations, as it started out with > 5k warnings. ;) So this commit switches to clang for compiling C/C++/ASM, but still uses Microsoft's linker. --- appveyor.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 7801a650853..727ec199387 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -87,7 +87,7 @@ install: #echo 'Using LLVM with enabled assertions' #$assertsSuffix = '-withAsserts' } - appveyor DownloadFile "https://github.com/ldc-developers/llvm/releases/download/ldc-v$Env:LLVM_VERSION/llvm-$Env:LLVM_VERSION-windows-$Env:APPVEYOR_JOB_ARCH$assertsSuffix.7z" -FileName llvm.7z + appveyor DownloadFile "https://github.com/ldc-developers/llvm/releases/download/ldc-v$Env:LLVM_VERSION/llvm-$Env:LLVM_VERSION-windows-$Env:APPVEYOR_JOB_ARCH$assertsSuffix-clang.7z" -FileName llvm.7z - md llvm - cd llvm - 7z x ..\llvm.7z > nul @@ -98,6 +98,8 @@ install: - set PATH=%CD%\llvm\bin;%CD%\ninja;%CD%\make;C:\Program Files\Git\usr\bin;%PATH% - if "%APPVEYOR_BUILD_WORKER_IMAGE:~-4%" == "2017" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%APPVEYOR_JOB_ARCH% - if "%APPVEYOR_BUILD_WORKER_IMAGE:~-4%" == "2015" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %APPVEYOR_JOB_ARCH% + # Let CMake configure 64-bit clang-cl for 32-bit code emission + - if "%APPVEYOR_JOB_ARCH%" == "x86" ( set "CFLAGS=-m32" && set "CXXFLAGS=-m32" && set "ASMFLAGS=-m32" ) # Print environment info - set - msbuild /version @@ -113,13 +115,13 @@ build_script: # Build bootstrap LDC - md bootstrap - cd bootstrap - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ROOT_DIR=c:/projects/llvm ..\ldc + - cmake -G Ninja -DCMAKE_C_COMPILER:PATH=clang-cl.exe -DCMAKE_CXX_COMPILER:PATH=clang-cl.exe -DCMAKE_BUILD_TYPE=Release -DLLVM_ROOT_DIR=c:/projects/llvm ..\ldc - ninja -j2 all - cd .. # Build LDC and stdlib unittest runners - md ninja-ldc - cd ninja-ldc - - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release %EXTRA_CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX=c:\projects\ldc2-%APPVEYOR_JOB_ARCH% -DINCLUDE_INSTALL_DIR=c:/projects/ldc2-%APPVEYOR_JOB_ARCH%/import -DLLVM_ROOT_DIR=c:/projects/llvm -DD_COMPILER=c:\projects\bootstrap\bin\ldmd2.exe ..\ldc + - cmake -G Ninja -DCMAKE_C_COMPILER:PATH=clang-cl.exe -DCMAKE_CXX_COMPILER:PATH=clang-cl.exe -DCMAKE_BUILD_TYPE=Release %EXTRA_CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX=c:\projects\ldc2-%APPVEYOR_JOB_ARCH% -DINCLUDE_INSTALL_DIR=c:/projects/ldc2-%APPVEYOR_JOB_ARCH%/import -DLLVM_ROOT_DIR=c:/projects/llvm -DD_COMPILER=c:\projects\bootstrap\bin\ldmd2.exe ..\ldc - ninja -j2 all all-test-runners #---------------------------------# From bdfc0f9b07badceac5975b8151767ba0ccb5e542 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 29 Oct 2018 00:16:09 +0100 Subject: [PATCH 3/5] MSVC: Default to the internal 'toolchain' (-link-internally + MinGW-w64 libs) --- driver/linker-msvc.cpp | 19 ++++++++++++++----- driver/linker.cpp | 16 ++++++++++++++-- driver/linker.h | 6 ++++++ packaging/README.txt | 41 +++++++++++++++++++++++++++-------------- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/driver/linker-msvc.cpp b/driver/linker-msvc.cpp index 1477e14ce58..9725c67a4a1 100644 --- a/driver/linker-msvc.cpp +++ b/driver/linker-msvc.cpp @@ -85,8 +85,11 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath, fatal(); } + const bool useInternalToolchain = useInternalToolchainForMSVC(); + #ifdef _WIN32 - windows::setupMsvcEnvironment(); + if (!useInternalToolchain) + windows::setupMsvcEnvironment(); #endif // build arguments @@ -172,12 +175,18 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath, } // lib dirs - for (const char *dir_c : ConfigFile::instance.libDirs()) { + const auto &libDirs = ConfigFile::instance.libDirs(); + for (const char *dir_c : libDirs) { const llvm::StringRef dir(dir_c); if (!dir.empty()) args.push_back(("/LIBPATH:" + dir).str()); } + if (useInternalToolchain && !libDirs.empty()) { + args.push_back( + (llvm::Twine("/LIBPATH:") + *libDirs.begin() + "/mingw").str()); + } + // default libs for (const auto &name : defaultLibNames) { args.push_back(name + ".lib"); @@ -212,9 +221,9 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath, logstr << "\n"; // FIXME where's flush ? #if LDC_WITH_LLD - if (useInternalLLDForLinking()) { - const auto fullArgs = - getFullArgs("lld-link", args, global.params.verbose); + if (useInternalLLDForLinking() || + (useInternalToolchain && opts::linker.empty() && !opts::isUsingLTO())) { + const auto fullArgs = getFullArgs("lld-link", args, global.params.verbose); #if LDC_LLVM_VER >= 600 const bool success = lld::coff::link(fullArgs, /*CanExitEarly=*/false); diff --git a/driver/linker.cpp b/driver/linker.cpp index 6033c6c02e9..079d5901886 100644 --- a/driver/linker.cpp +++ b/driver/linker.cpp @@ -182,11 +182,23 @@ bool linkAgainstSharedDefaultLibs() { ////////////////////////////////////////////////////////////////////////////// +bool useInternalToolchainForMSVC() { +#ifndef _WIN32 + return true; +#else + return !getenv("VSINSTALLDIR") && !getenv("LDC_VSDIR"); +#endif +} + llvm::StringRef getMscrtLibName() { llvm::StringRef name = mscrtlib; if (name.empty()) { - // default to static release variant - name = linkFullyStatic() != llvm::cl::BOU_FALSE ? "libcmt" : "msvcrt"; + if (useInternalToolchainForMSVC()) { + name = "vcruntime140"; + } else { + // default to static release variant + name = linkFullyStatic() != llvm::cl::BOU_FALSE ? "libcmt" : "msvcrt"; + } } return name; } diff --git a/driver/linker.h b/driver/linker.h index 6a8713e509a..936cca532a6 100644 --- a/driver/linker.h +++ b/driver/linker.h @@ -39,6 +39,12 @@ llvm::cl::boolOrDefault linkFullyStatic(); */ bool linkAgainstSharedDefaultLibs(); +/** + * Indicates whether the internal 'toolchain' (-link-internally and MinGW-w64 + * libs) is to be used for MSVC targets. + */ +bool useInternalToolchainForMSVC(); + /** * Returns the name of the MS C runtime library to link with. */ diff --git a/packaging/README.txt b/packaging/README.txt index 80f7afb82aa..3a922922309 100644 --- a/packaging/README.txt +++ b/packaging/README.txt @@ -1,24 +1,37 @@ -This is a prebuilt binary package for LDC, the LLVM-based D compiler. +This is a standalone (DMD-style) binary package for LDC, the LLVM-based D +compiler. No installation is required, simply use the executables in the 'bin' subfolder. -Just make sure you have a Microsoft Visual C++ 2015 or 2017 installation, either -via Visual Studio or via the stand-alone Visual C++ Build Tools, both freely -available from Microsoft. LDC relies on the MS linker (unless using -'-link-internally') and on the MSVCRT + WinSDK libraries. The compiler configuration file is etc\ldc2.conf and can be easily customized to your liking, e.g., adding implicit command-line options and setting up cross- compilation. -The LDC package is portable and should be able to detect your (latest) Visual -C++ installation automatically. -By setting the LDC_VSDIR environment variable to an existing Visual Studio -directory, you can instruct LDC to use a specific Visual C++ installation. -If run in a 'VS Native/Cross Tools Command Prompt' (i.e., if the environment -variable VSINSTALLDIR is set), LDC skips the Visual C++ detection. This saves -about one second for each linking operation, but linking will be restricted to -the selected target (=> no cross-linking support via '-m32' in a x64 command -prompt). +The LDC package is portable and ships with LLD, the LLVM linker, as well as +WinSDK & Visual C++ runtime (import) libraries based on MinGW-w64. In order to +run the generated binaries, a Visual C++ 2015 runtime installation is required +(vcruntime140.dll, ucrtbase.dll etc.). + +In case you prefer an official Microsoft toolchain for linking (Visual C++ 2015 +or newer), e.g., to link with the static Microsoft libraries (and thus avoid the +dependency on the Visual C++ runtime installation for your users), you have the +following options: + +* Run LDC in a 'VS Native/Cross Tools Command Prompt' (LDC checks whether the + VSINSTALLDIR environment variable is set). + LDC assumes the environment variables are all set up appropriately. +* Set the LDC_VSDIR environment variable to some Visual Studio/Visual C++ Build + Tools installation directory, e.g., + 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community'. + LDC will invoke a batch file provided by VS to set up the environment + variables for the selected 32/64-bit target platform, which adds an overhead + of about 1 second for each linking operation. + You can also set LDC_VSDIR to some non-existing dummy path; LDC will try to + auto-detect your latest Visual C++ installation in that case. +* Set up the etc\ldc2.conf config file and specify the path to the linker + ('-linker=', or use '-link-internally') as well as the directories + containing the MS libs ('-L/LIBPATH: -L/LIBPATH: ...'; check out + the LIB environment variable in a VS tools command prompt). For further information, including on how to report bugs, please refer to the LDC wiki: http://wiki.dlang.org/LDC. From 59c4727ead74f3f8091b5a55080ff422c70a7aac Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 29 Oct 2018 00:28:08 +0100 Subject: [PATCH 4/5] AppVeyor: Bundle MinGW-w64-based libs Using a package generated via the tool and C/ASM sources in the new https://github.com/ldc-developers/mingw-w64-libs repo, based on MinGW-w64 v6.0.0. --- appveyor.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 727ec199387..6d753773e0c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -168,6 +168,20 @@ after_test: } # Now rename the installation dir to test portability. ren "$ldcInstallDir" ldc2-install + # Include MinGW-w64-based libs + - ps: | + cd c:\projects + $ldcInstallDir = 'c:\projects\ldc2-install' + mkdir mingw-w64-libs + cd mingw-w64-libs + appveyor DownloadFile "https://github.com/ldc-developers/mingw-w64-libs/releases/download/v6.0.0-rc.1/mingw-w64-libs-v6.0.0-rc.1.7z" -FileName mingw-w64-libs.7z + 7z x mingw-w64-libs.7z > $null + If ($Env:APPVEYOR_JOB_ARCH -eq 'x64') { + cp -r lib64 "$ldcInstallDir\lib\mingw" + } Else { + cp -r lib32 "$ldcInstallDir\lib\mingw" + } + cd .. # Hello world integration test with LTO (x64 only) - ps: | If ($Env:APPVEYOR_JOB_ARCH -eq 'x64') { From ef04326dedc7e045da274851de69057de1925efe Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 29 Oct 2018 01:35:30 +0100 Subject: [PATCH 5/5] lit-tests: Forward env variables VSINSTALLDIR, PATH and LIB on Windows In order not to fallback to the MinGW libs, which are most likely not available at testing time. Use the MSVC toolchain used for building instead, by forwarding the minimum set of required variables. This also greatly reduces the overall runtime of these tests, as the VS installation isn't auto-detected (incl. env variables setup) for every single linking operation. --- tests/lit.site.cfg.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/lit.site.cfg.in b/tests/lit.site.cfg.in index fadb390496a..4897ae705dd 100644 --- a/tests/lit.site.cfg.in +++ b/tests/lit.site.cfg.in @@ -63,6 +63,11 @@ env_cxx = os.environ.get('CXX', '') if env_cxx: config.environment['CXX'] = env_cxx +if (platform.system() == 'Windows'): + config.environment['VSINSTALLDIR'] = os.environ['VSINSTALLDIR'] + config.environment['PATH'] = os.environ['PATH'] + config.environment['LIB'] = os.environ['LIB'] + # Define available features so that we can disable tests depending on LLVM version config.available_features.add("llvm%d" % config.llvm_version) # LLVM version history: 3.9, 4.0, 5.0, ...