Skip to content

Commit e932198

Browse files
authored
Merge pull request #24849 from compnerd/msvc-runtime-library
Driver: introduce new `-libc` option for Windows
2 parents 2ad3cac + 7514adf commit e932198

File tree

11 files changed

+159
-18
lines changed

11 files changed

+159
-18
lines changed

CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,20 @@ set(SWIFT_STDLIB_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
173173
"Build type for the Swift standard library and SDK overlays [Debug, RelWithDebInfo, Release, MinSizeRel]")
174174
set_property(CACHE SWIFT_STDLIB_BUILD_TYPE PROPERTY
175175
STRINGS "Debug" "RelWithDebInfo" "Release" "MinSizeRel")
176+
# Allow the user to specify the standard library CMAKE_MSVC_RUNTIME_LIBRARY
177+
# value. The following values are valid:
178+
# - MultiThreaded (/MT)
179+
# - MultiThreadedDebug (/MTd)
180+
# - MultiThreadedDLL (/MD)
181+
# - MultiThreadedDebugDLL (/MDd)
182+
if(CMAKE_BUILD_TYPE STREQUAL Debug)
183+
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default MultiThreadedDebugDLL)
184+
else()
185+
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default MultiThreadedDLL)
186+
endif()
187+
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY
188+
${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default}
189+
CACHE STRING "MSVC Runtime Library for the standard library")
176190

177191
is_build_type_optimized("${SWIFT_STDLIB_BUILD_TYPE}" swift_optimized)
178192
if(swift_optimized)

cmake/modules/AddSwift.cmake

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,6 @@ function(_add_variant_swift_compile_flags
400400
list(APPEND result "-D" "SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS")
401401
endif()
402402

403-
if(sdk STREQUAL WINDOWS)
404-
list(APPEND result "-Xcc" "-D_MT")
405-
# TODO(compnerd) handle /MT /MTd
406-
list(APPEND result "-Xcc" "-D_DLL")
407-
endif()
408-
409403
set("${result_var_name}" "${result}" PARENT_SCOPE)
410404
endfunction()
411405

@@ -873,13 +867,8 @@ function(_add_swift_library_single target name)
873867
if("${SWIFTLIB_SINGLE_ARCHITECTURE}" MATCHES arm)
874868
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE)
875869
endif()
876-
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;oldnames)
877-
# TODO(compnerd) handle /MT and /MTd
878-
if(CMAKE_BUILD_TYPE MATCHES Debug)
879-
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;msvcrtd)
880-
else()
881-
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;msvcrt)
882-
endif()
870+
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
871+
-libc;${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY})
883872
endif()
884873

885874
# FIXME: don't actually depend on the libraries in SWIFTLIB_SINGLE_LINK_LIBRARIES,

include/swift/Driver/Driver.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,18 @@ class OutputInfo {
8787
Immediate,
8888
};
8989

90+
enum class MSVCRuntime {
91+
MultiThreaded,
92+
MultiThreadedDebug,
93+
MultiThreadedDLL,
94+
MultiThreadedDebugDLL,
95+
};
96+
9097
/// The mode in which the driver should invoke the frontend.
9198
Mode CompilerMode = Mode::StandardCompile;
9299

100+
Optional<MSVCRuntime> RuntimeVariant = llvm::None;
101+
93102
/// The output type which should be used for compile actions.
94103
file_types::ID CompilerOutputType = file_types::ID::TY_INVALID;
95104

include/swift/Option/Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,8 @@ def enable_app_extension : Flag<["-"], "application-extension">,
455455
Flags<[FrontendOption, NoInteractiveOption]>,
456456
HelpText<"Restrict code to those available for App Extensions">;
457457

458+
def libc : Separate<["-"], "libc">, HelpText<"libc runtime library to use">;
459+
458460
// Linker options
459461

460462
def linker_option_Group : OptionGroup<"<linker-specific options>">;

lib/Driver/Driver.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,31 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
16501650

16511651
}
16521652

1653+
if (TC.getTriple().isOSWindows()) {
1654+
if (const Arg *A = Args.getLastArg(options::OPT_libc)) {
1655+
OI.RuntimeVariant =
1656+
llvm::StringSwitch<Optional<OutputInfo::MSVCRuntime>>(A->getValue())
1657+
.Cases("MD", "MultiThreadedDLL", "shared-ucrt",
1658+
OutputInfo::MSVCRuntime::MultiThreadedDLL)
1659+
.Cases("MDd", "MultiThreadedDebugDLL", "shared-debug-ucrt",
1660+
OutputInfo::MSVCRuntime::MultiThreadedDebugDLL)
1661+
.Cases("MT", "MultiThreaded", "static-ucrt",
1662+
OutputInfo::MSVCRuntime::MultiThreaded)
1663+
.Cases("MTd", "MultiThreadedDebug", "static-debug-ucrt",
1664+
OutputInfo::MSVCRuntime::MultiThreadedDebug)
1665+
.Default(llvm::None);
1666+
if (!OI.RuntimeVariant)
1667+
Diags.diagnose({}, diag::error_invalid_arg_value, A->getSpelling(),
1668+
A->getValue());
1669+
} else {
1670+
// NOTE: default to `/MD`. This is different from `cl`'s default
1671+
// behaviour of `/MT` on the command line, however, Visual Studio 2015 and
1672+
// newer will default `/MD` as well. Furthermore, this is far more useful
1673+
// of a mode since the `/MT` mode requires that everything is statically
1674+
// linked.
1675+
OI.RuntimeVariant = OutputInfo::MSVCRuntime::MultiThreadedDLL;
1676+
}
1677+
}
16531678
}
16541679

16551680
OutputInfo::Mode

lib/Driver/ToolChains.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,47 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
261261
arguments.push_back("-color-diagnostics");
262262
}
263263

264+
static void addRuntimeLibraryFlags(const OutputInfo &OI,
265+
ArgStringList &Arguments) {
266+
if (!OI.RuntimeVariant)
267+
return;
268+
269+
const OutputInfo::MSVCRuntime RT = OI.RuntimeVariant.getValue();
270+
271+
Arguments.push_back("-autolink-library");
272+
Arguments.push_back("oldnames");
273+
274+
Arguments.push_back("-autolink-library");
275+
switch (RT) {
276+
default: llvm_unreachable("invalid MSVC runtime library");
277+
case OutputInfo::MSVCRuntime::MultiThreaded:
278+
Arguments.push_back("libcmt");
279+
break;
280+
281+
case OutputInfo::MSVCRuntime::MultiThreadedDebug:
282+
Arguments.push_back("libcmtd");
283+
break;
284+
285+
case OutputInfo::MSVCRuntime::MultiThreadedDLL:
286+
Arguments.push_back("msvcrt");
287+
break;
288+
289+
case OutputInfo::MSVCRuntime::MultiThreadedDebugDLL:
290+
Arguments.push_back("msvcrtd");
291+
break;
292+
}
293+
294+
// NOTE(compnerd) we do not support /ML and /MLd
295+
Arguments.push_back("-Xcc");
296+
Arguments.push_back("-D_MT");
297+
298+
if (RT == OutputInfo::MSVCRuntime::MultiThreadedDLL ||
299+
RT == OutputInfo::MSVCRuntime::MultiThreadedDebugDLL) {
300+
Arguments.push_back("-Xcc");
301+
Arguments.push_back("-D_DLL");
302+
}
303+
}
304+
264305
ToolChain::InvocationInfo
265306
ToolChain::constructInvocation(const CompileJobAction &job,
266307
const JobContext &context) const {
@@ -301,6 +342,7 @@ ToolChain::constructInvocation(const CompileJobAction &job,
301342

302343
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
303344
Arguments);
345+
addRuntimeLibraryFlags(context.OI, Arguments);
304346

305347
// Pass along an -import-objc-header arg, replacing the argument with the name
306348
// of any input PCH to the current action if one is present.
@@ -614,6 +656,8 @@ ToolChain::constructInvocation(const InterpretJobAction &job,
614656

615657
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
616658
Arguments);
659+
addRuntimeLibraryFlags(context.OI, Arguments);
660+
617661
context.Args.AddLastArg(Arguments, options::OPT_import_objc_header);
618662

619663
context.Args.AddLastArg(Arguments, options::OPT_parse_sil);
@@ -825,6 +869,8 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job,
825869

826870
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
827871
Arguments);
872+
addRuntimeLibraryFlags(context.OI, Arguments);
873+
828874
addOutputsOfType(Arguments, context.Output, context.Args,
829875
file_types::TY_SwiftModuleDocFile, "-emit-module-doc-path");
830876
addOutputsOfType(Arguments, context.Output, context.Args,
@@ -908,8 +954,11 @@ ToolChain::constructInvocation(const REPLJobAction &job,
908954
ArgStringList FrontendArgs;
909955
for (auto &s : getDriver().getSwiftProgramArgs())
910956
FrontendArgs.push_back(s.c_str());
957+
911958
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
912959
FrontendArgs);
960+
addRuntimeLibraryFlags(context.OI, FrontendArgs);
961+
913962
context.Args.AddLastArg(FrontendArgs, options::OPT_import_objc_header);
914963
context.Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework,
915964
options::OPT_L);
@@ -994,6 +1043,8 @@ ToolChain::constructInvocation(const GeneratePCHJobAction &job,
9941043

9951044
addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
9961045
Arguments);
1046+
addRuntimeLibraryFlags(context.OI, Arguments);
1047+
9971048
addOutputsOfType(Arguments, context.Output, context.Args,
9981049
file_types::TY_SerializedDiagnostics,
9991050
"-serialize-diagnostics-path");

lib/Driver/WindowsToolChains.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
100100
Arguments.push_back(context.Args.MakeArgString(Target));
101101
}
102102

103+
// Rely on `-libc` to correctly identify the MSVC Runtime Library. We use
104+
// `-nostartfiles` as that limits the difference to just the
105+
// `-defaultlib:libcmt` which is passed unconditionally with the `clang++`
106+
// driver rather than the `clang-cl` driver.
107+
Arguments.push_back("-nostartfiles");
108+
103109
SmallString<128> SharedRuntimeLibPath;
104110
getRuntimeLibraryPath(SharedRuntimeLibPath, context.Args,
105111
/*Shared=*/true);

test/DebugInfo/debug_prefix_map.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ func square(_ n: Int) -> Int {
99
}
1010

1111
// CHECK: !DIFile(filename: "/var/empty/debug_prefix_map.swift"
12-
// CHECK: !DIModule(scope: null, name: "Globals", includePath: "/var/empty{{(/|\\5C)}}Globals.swiftmodule"
12+
// CHECK: !DIModule(scope: null, name: "Globals", {{.*}}includePath: "/var/empty{{(/|\\5C)}}Globals.swiftmodule"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// -- check that invalid values are flagged
2+
// RUN: not %swiftc_driver -target x86_64-unknown-windows-msvc -libc MLd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-INVALID
3+
// CHECK-INVALID: error: invalid value 'MLd' in '-libc'
4+
5+
// -- check that cross-compilation still succeeds
6+
// RUN: %swiftc_driver -target x86_64-unknown-linux-gnu -c %s -###
7+
8+
// -- check flags for /MD
9+
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MD -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MD
10+
// CHECK-MD: -autolink-library oldnames -autolink-library msvcrt -Xcc -D_MT -Xcc -D_DLL
11+
12+
// -- check flags for /MDd
13+
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MDd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MDd
14+
// CHECK-MDd: -autolink-library oldnames -autolink-library msvcrtd -Xcc -D_MT -Xcc -D_DLL
15+
16+
// -- check flags for /MT
17+
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MT -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MT
18+
// CHECK-MT: -autolink-library oldnames -autolink-library libcmt -Xcc -D_MT
19+
// CHECK-MT-NOT: -D_DLL
20+
21+
// -- check flags for /MTd
22+
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MTd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MTd
23+
// CHECK-MTd: -autolink-library oldnames -autolink-library libcmtd -Xcc -D_MT
24+
// CHECK-MTd-NOT: -D_DLL
25+

test/lit.cfg

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,15 @@ config.substitutions.append( ('%mcp_opt', mcp_opt) )
374374
config.substitutions.append( ('%swift_driver_plain', "%r" % config.swift) )
375375
config.substitutions.append( ('%swiftc_driver_plain', "%r" % config.swiftc) )
376376
if kIsWindows:
377-
config.substitutions.append( ('%swift_driver', "%r %s %s %s" % (config.swift, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
378-
config.substitutions.append( ('%swiftc_driver', "%r %s %s %s" % (config.swiftc, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
377+
config.substitutions.append( ('%swift_driver',
378+
"%r %s %s %s -libc %s" % (config.swift, mcp_opt,
379+
config.swift_test_options,
380+
config.swift_driver_test_options,
381+
config.swift_stdlib_msvc_runtime)) )
382+
config.substitutions.append( ('%swiftc_driver',
383+
"%r %s %s %s" % (config.swiftc, mcp_opt,
384+
config.swift_test_options,
385+
config.swift_driver_test_options)) )
379386
else:
380387
config.substitutions.append( ('%swift_driver', "env SDKROOT= %r %s %s %s" % (config.swift, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
381388
config.substitutions.append( ('%swiftc_driver', "env SDKROOT= %r %s %s %s" % (config.swiftc, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
@@ -870,10 +877,11 @@ elif run_os in ['windows-msvc']:
870877
config.target_runtime = 'native'
871878

872879
config.target_build_swift = \
873-
('%r -target %s %s %s %s %s -Xlinker -nodefaultlib:libcmt' % \
880+
('%r -target %s %s %s %s %s -libc %s' % \
874881
(config.swiftc, config.variant_triple, resource_dir_opt, \
875882
config.swift_test_options, config.swift_driver_test_options,\
876-
swift_execution_tests_extra_flags))
883+
swift_execution_tests_extra_flags, \
884+
config.swift_stdlib_msvc_runtime))
877885

878886
config.target_run = ''
879887

test/lit.site.cfg.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ config.variant_triple = "@VARIANT_TRIPLE@"
2727
config.variant_sdk = "@VARIANT_SDK@"
2828
config.variant_suffix = "@VARIANT_SUFFIX@"
2929
config.swiftlib_dir = "@LIT_SWIFTLIB_DIR@"
30+
config.swift_stdlib_msvc_runtime = None
31+
if "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreaded":
32+
config.swift_stdlib_msvc_runtime = 'MT'
33+
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebug":
34+
config.swift_stdlib_msvc_runtime = 'MTd'
35+
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDLL":
36+
config.swift_stdlib_msvc_runtime = 'MD'
37+
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebugDLL":
38+
config.swift_stdlib_msvc_runtime = 'MDd'
39+
else:
40+
assert(False)
41+
3042
config.swift_test_results_dir = \
3143
lit_config.params.get("swift_test_results_dir", "@SWIFT_TEST_RESULTS_DIR@")
3244
config.darwin_xcrun_toolchain = "@SWIFT_DARWIN_XCRUN_TOOLCHAIN@"

0 commit comments

Comments
 (0)