Add -mscrtlib cmdline option and support -static on Windows (#2041)

The default MS C runtime library doesn't depend on the `LINK_WITH_MSVCRT`
CMake variable anymore.

The user can freely choose among the 4 variants libcmt[d] / msvcrt[d] via
-mscrtlib or choose between static/dynamic release variant via -static.

LDC keeps on defaulting to the static release C runtime, so
`-static=false` or `-mscrtlib=msvcrt[d]` must be used explicitly in order
to link against the runtime DLLs.
This commit is contained in:
kinke 2017-04-09 01:17:28 +02:00 committed by GitHub
parent 1dfe11c961
commit a5139499a3
4 changed files with 44 additions and 27 deletions

View file

@ -210,11 +210,9 @@ Where:\n\
" -map generate linker .map file\n" " -map generate linker .map file\n"
#endif #endif
" -mcpu=<id> generate instructions for architecture identified by 'id'\n\ " -mcpu=<id> generate instructions for architecture identified by 'id'\n\
-mcpu=? list all architecture options\n" -mcpu=? list all architecture options\n\
#if 0 -mscrtlib=<name> MS C runtime library to reference from main/WinMain/DllMain\n\
" -mscrtlib=<name> MS C runtime library to reference from main/WinMain/DllMain\n" -mv=<package.module>=<filespec> use <filespec> as source file for <package.module>\n\
#endif
" -mv=<package.module>=<filespec> use <filespec> as source file for <package.module>\n\
-noboundscheck no array bounds checking (deprecated, use -boundscheck=off)\n\ -noboundscheck no array bounds checking (deprecated, use -boundscheck=off)\n\
-O optimize\n\ -O optimize\n\
-o- do not write object file\n\ -o- do not write object file\n\
@ -421,9 +419,10 @@ void translateArgs(size_t originalArgc, char **originalArgv,
*/ */
else if (strcmp(p + 1, "m32mscoff") == 0) { else if (strcmp(p + 1, "m32mscoff") == 0) {
ldcArgs.push_back("-m32"); ldcArgs.push_back("-m32");
} else if (strncmp(p + 1, "mscrtlib=", 9) == 0) { }
goto Lnot_in_ldc; /* -mscrtlib
} else if (strcmp(p + 1, "profile") == 0) { */
else if (strcmp(p + 1, "profile") == 0) {
goto Lnot_in_ldc; goto Lnot_in_ldc;
} }
/* -v /* -v

View file

@ -39,6 +39,12 @@ static llvm::cl::opt<bool> staticFlag(
"Create a statically linked binary, including all system dependencies"), "Create a statically linked binary, including all system dependencies"),
llvm::cl::ZeroOrMore); llvm::cl::ZeroOrMore);
static llvm::cl::opt<std::string> mscrtlib(
"mscrtlib",
llvm::cl::desc(
"MS C runtime library to link against (libcmt[d] / msvcrt[d])"),
llvm::cl::value_desc("name"), llvm::cl::ZeroOrMore);
static llvm::cl::opt<std::string> static llvm::cl::opt<std::string>
ltoLibrary("flto-binary", ltoLibrary("flto-binary",
llvm::cl::desc("Set the linker LTO plugin library file (e.g. " llvm::cl::desc("Set the linker LTO plugin library file (e.g. "
@ -280,7 +286,7 @@ static void appendObjectFiles(std::vector<std::string> &args) {
static std::string gExePath; static std::string gExePath;
static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) { static int linkObjToBinaryGcc(bool sharedLib) {
Logger::println("*** Linking executable ***"); Logger::println("*** Linking executable ***");
// find gcc for linking // find gcc for linking
@ -317,7 +323,7 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
args.push_back("-shared"); args.push_back("-shared");
} }
if (fullyStatic) { if (staticFlag) {
args.push_back("-static"); args.push_back("-static");
} }
@ -489,6 +495,26 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static void addMscrtLibs(std::vector<std::string> &args) {
llvm::StringRef mscrtlibName = mscrtlib;
if (mscrtlibName.empty()) {
// default to static release variant
mscrtlibName =
staticFlag || staticFlag.getNumOccurrences() == 0 ? "libcmt" : "msvcrt";
}
args.push_back(("/DEFAULTLIB:" + mscrtlibName).str());
const bool isStatic = mscrtlibName.startswith_lower("libcmt");
const bool isDebug =
mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib");
const llvm::StringRef prefix = isStatic ? "lib" : "";
const llvm::StringRef suffix = isDebug ? "d" : "";
args.push_back(("/DEFAULTLIB:" + prefix + "vcruntime" + suffix).str());
}
static int linkObjToBinaryMSVC(bool sharedLib) { static int linkObjToBinaryMSVC(bool sharedLib) {
Logger::println("*** Linking executable ***"); Logger::println("*** Linking executable ***");
@ -528,6 +554,9 @@ static int linkObjToBinaryMSVC(bool sharedLib) {
args.push_back("/OPT:ICF"); args.push_back("/OPT:ICF");
} }
// add C runtime libs
addMscrtLibs(args);
// specify creation of DLL // specify creation of DLL
if (sharedLib) { if (sharedLib) {
args.push_back("/DLL"); args.push_back("/DLL");
@ -604,11 +633,10 @@ static int linkObjToBinaryMSVC(bool sharedLib) {
int linkObjToBinary() { int linkObjToBinary() {
if (global.params.targetTriple->isWindowsMSVCEnvironment()) { if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
// TODO: Choose dynamic/static MSVCRT version based on staticFlag?
return linkObjToBinaryMSVC(global.params.dll); return linkObjToBinaryMSVC(global.params.dll);
} }
return linkObjToBinaryGcc(global.params.dll, staticFlag); return linkObjToBinaryGcc(global.params.dll);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View file

@ -15,9 +15,6 @@ set(BUILD_SHARED_LIBS AUTO CACHE STRING
set(D_FLAGS -w CACHE STRING "Runtime build flags, separated by ;") set(D_FLAGS -w CACHE STRING "Runtime build flags, separated by ;")
set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime build flags (debug libraries), separated by ;") set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime build flags (debug libraries), separated by ;")
set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime build flags (release libraries), separated by ;") set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime build flags (release libraries), separated by ;")
if(MSVC)
set(LINK_WITH_MSVCRT OFF CACHE BOOL "Link with MSVCRT.lib (DLL) instead of LIBCMT.lib (static)")
endif()
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
@ -246,17 +243,10 @@ endforeach()
# of what the user chose for LDC itself. # of what the user chose for LDC itself.
# 1) Set up CMAKE_C_FLAGS_RELEASE # 1) Set up CMAKE_C_FLAGS_RELEASE
if(MSVC) if(MSVC)
if(NOT LINK_WITH_MSVCRT) # Omit all references to the default C runtime libs.
string(REGEX REPLACE "(^| )[/-]MD( |$)" "\\2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # We want to be able to link against all 4 C runtime variants (libcmt[d] / msvcrt[d]).
if(NOT CMAKE_C_FLAGS_RELEASE MATCHES "(^| )[/-]MT( |$)") string(REGEX REPLACE "(^| )[/-]M[TD]d?( |$)" "\\2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
append("/MT" CMAKE_C_FLAGS_RELEASE) append("/MT /Zl" CMAKE_C_FLAGS_RELEASE)
endif()
else()
string(REGEX REPLACE "(^| )[/-]MT( |$)" "\\2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
if(NOT CMAKE_C_FLAGS_RELEASE MATCHES "(^| )[/-]MD( |$)")
append("/MD" CMAKE_C_FLAGS_RELEASE)
endif()
endif()
# warning C4996: zlib uses 'deprecated' POSIX names # warning C4996: zlib uses 'deprecated' POSIX names
append("/wd4996" CMAKE_C_FLAGS_RELEASE) append("/wd4996" CMAKE_C_FLAGS_RELEASE)
endif() endif()

@ -1 +1 @@
Subproject commit d91c32d44def323910a5e22d9a9739997f80b893 Subproject commit 8414f932691e01dc6c174b88f67ffd6e21ba7fcc