Skip to content

Driver: introduce new -libc option for Windows #24849

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
May 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ set(SWIFT_STDLIB_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Build type for the Swift standard library and SDK overlays [Debug, RelWithDebInfo, Release, MinSizeRel]")
set_property(CACHE SWIFT_STDLIB_BUILD_TYPE PROPERTY
STRINGS "Debug" "RelWithDebInfo" "Release" "MinSizeRel")
# Allow the user to specify the standard library CMAKE_MSVC_RUNTIME_LIBRARY
# value. The following values are valid:
# - MultiThreaded (/MT)
# - MultiThreadedDebug (/MTd)
# - MultiThreadedDLL (/MD)
# - MultiThreadedDebugDLL (/MDd)
if(CMAKE_BUILD_TYPE STREQUAL Debug)
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default MultiThreadedDebugDLL)
else()
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default MultiThreadedDLL)
endif()
set(SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY
${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY_default}
CACHE STRING "MSVC Runtime Library for the standard library")

is_build_type_optimized("${SWIFT_STDLIB_BUILD_TYPE}" swift_optimized)
if(swift_optimized)
Expand Down
15 changes: 2 additions & 13 deletions cmake/modules/AddSwift.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,6 @@ function(_add_variant_swift_compile_flags
list(APPEND result "-D" "SWIFT_ENABLE_RUNTIME_FUNCTION_COUNTERS")
endif()

if(sdk STREQUAL WINDOWS)
list(APPEND result "-Xcc" "-D_MT")
# TODO(compnerd) handle /MT /MTd
list(APPEND result "-Xcc" "-D_DLL")
endif()

set("${result_var_name}" "${result}" PARENT_SCOPE)
endfunction()

Expand Down Expand Up @@ -873,13 +867,8 @@ function(_add_swift_library_single target name)
if("${SWIFTLIB_SINGLE_ARCHITECTURE}" MATCHES arm)
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE)
endif()
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;oldnames)
# TODO(compnerd) handle /MT and /MTd
if(CMAKE_BUILD_TYPE MATCHES Debug)
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;msvcrtd)
else()
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-autolink-library;-Xfrontend;msvcrt)
endif()
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS
-libc;${SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY})
endif()

# FIXME: don't actually depend on the libraries in SWIFTLIB_SINGLE_LINK_LIBRARIES,
Expand Down
9 changes: 9 additions & 0 deletions include/swift/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,18 @@ class OutputInfo {
Immediate,
};

enum class MSVCRuntime {
MultiThreaded,
MultiThreadedDebug,
MultiThreadedDLL,
MultiThreadedDebugDLL,
};

/// The mode in which the driver should invoke the frontend.
Mode CompilerMode = Mode::StandardCompile;

Optional<MSVCRuntime> RuntimeVariant = llvm::None;

/// The output type which should be used for compile actions.
file_types::ID CompilerOutputType = file_types::ID::TY_INVALID;

Expand Down
2 changes: 2 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ def enable_app_extension : Flag<["-"], "application-extension">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Restrict code to those available for App Extensions">;

def libc : Separate<["-"], "libc">, HelpText<"libc runtime library to use">;

// Linker options

def linker_option_Group : OptionGroup<"<linker-specific options>">;
Expand Down
25 changes: 25 additions & 0 deletions lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1650,6 +1650,31 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,

}

if (TC.getTriple().isOSWindows()) {
if (const Arg *A = Args.getLastArg(options::OPT_libc)) {
OI.RuntimeVariant =
llvm::StringSwitch<Optional<OutputInfo::MSVCRuntime>>(A->getValue())
.Cases("MD", "MultiThreadedDLL", "shared-ucrt",
OutputInfo::MSVCRuntime::MultiThreadedDLL)
.Cases("MDd", "MultiThreadedDebugDLL", "shared-debug-ucrt",
OutputInfo::MSVCRuntime::MultiThreadedDebugDLL)
.Cases("MT", "MultiThreaded", "static-ucrt",
OutputInfo::MSVCRuntime::MultiThreaded)
.Cases("MTd", "MultiThreadedDebug", "static-debug-ucrt",
OutputInfo::MSVCRuntime::MultiThreadedDebug)
.Default(llvm::None);
if (!OI.RuntimeVariant)
Diags.diagnose({}, diag::error_invalid_arg_value, A->getSpelling(),
A->getValue());
} else {
// NOTE: default to `/MD`. This is different from `cl`'s default
// behaviour of `/MT` on the command line, however, Visual Studio 2015 and
// newer will default `/MD` as well. Furthermore, this is far more useful
// of a mode since the `/MT` mode requires that everything is statically
// linked.
OI.RuntimeVariant = OutputInfo::MSVCRuntime::MultiThreadedDLL;
}
}
}

OutputInfo::Mode
Expand Down
51 changes: 51 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,47 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
arguments.push_back("-color-diagnostics");
}

static void addRuntimeLibraryFlags(const OutputInfo &OI,
ArgStringList &Arguments) {
if (!OI.RuntimeVariant)
return;

const OutputInfo::MSVCRuntime RT = OI.RuntimeVariant.getValue();

Arguments.push_back("-autolink-library");
Arguments.push_back("oldnames");

Arguments.push_back("-autolink-library");
switch (RT) {
default: llvm_unreachable("invalid MSVC runtime library");
case OutputInfo::MSVCRuntime::MultiThreaded:
Arguments.push_back("libcmt");
break;

case OutputInfo::MSVCRuntime::MultiThreadedDebug:
Arguments.push_back("libcmtd");
break;

case OutputInfo::MSVCRuntime::MultiThreadedDLL:
Arguments.push_back("msvcrt");
break;

case OutputInfo::MSVCRuntime::MultiThreadedDebugDLL:
Arguments.push_back("msvcrtd");
break;
}

// NOTE(compnerd) we do not support /ML and /MLd
Arguments.push_back("-Xcc");
Arguments.push_back("-D_MT");

if (RT == OutputInfo::MSVCRuntime::MultiThreadedDLL ||
RT == OutputInfo::MSVCRuntime::MultiThreadedDebugDLL) {
Arguments.push_back("-Xcc");
Arguments.push_back("-D_DLL");
}
}

ToolChain::InvocationInfo
ToolChain::constructInvocation(const CompileJobAction &job,
const JobContext &context) const {
Expand Down Expand Up @@ -301,6 +342,7 @@ ToolChain::constructInvocation(const CompileJobAction &job,

addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
Arguments);
addRuntimeLibraryFlags(context.OI, Arguments);

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

addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
Arguments);
addRuntimeLibraryFlags(context.OI, Arguments);

context.Args.AddLastArg(Arguments, options::OPT_import_objc_header);

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

addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
Arguments);
addRuntimeLibraryFlags(context.OI, Arguments);

addOutputsOfType(Arguments, context.Output, context.Args,
file_types::TY_SwiftModuleDocFile, "-emit-module-doc-path");
addOutputsOfType(Arguments, context.Output, context.Args,
Expand Down Expand Up @@ -908,8 +954,11 @@ ToolChain::constructInvocation(const REPLJobAction &job,
ArgStringList FrontendArgs;
for (auto &s : getDriver().getSwiftProgramArgs())
FrontendArgs.push_back(s.c_str());

addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
FrontendArgs);
addRuntimeLibraryFlags(context.OI, FrontendArgs);

context.Args.AddLastArg(FrontendArgs, options::OPT_import_objc_header);
context.Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework,
options::OPT_L);
Expand Down Expand Up @@ -994,6 +1043,8 @@ ToolChain::constructInvocation(const GeneratePCHJobAction &job,

addCommonFrontendArgs(*this, context.OI, context.Output, context.Args,
Arguments);
addRuntimeLibraryFlags(context.OI, Arguments);

addOutputsOfType(Arguments, context.Output, context.Args,
file_types::TY_SerializedDiagnostics,
"-serialize-diagnostics-path");
Expand Down
6 changes: 6 additions & 0 deletions lib/Driver/WindowsToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
Arguments.push_back(context.Args.MakeArgString(Target));
}

// Rely on `-libc` to correctly identify the MSVC Runtime Library. We use
// `-nostartfiles` as that limits the difference to just the
// `-defaultlib:libcmt` which is passed unconditionally with the `clang++`
// driver rather than the `clang-cl` driver.
Arguments.push_back("-nostartfiles");

SmallString<128> SharedRuntimeLibPath;
getRuntimeLibraryPath(SharedRuntimeLibPath, context.Args,
/*Shared=*/true);
Expand Down
2 changes: 1 addition & 1 deletion test/DebugInfo/debug_prefix_map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ func square(_ n: Int) -> Int {
}

// CHECK: !DIFile(filename: "/var/empty/debug_prefix_map.swift"
// CHECK: !DIModule(scope: null, name: "Globals", includePath: "/var/empty{{(/|\\5C)}}Globals.swiftmodule"
// CHECK: !DIModule(scope: null, name: "Globals", {{.*}}includePath: "/var/empty{{(/|\\5C)}}Globals.swiftmodule"
25 changes: 25 additions & 0 deletions test/Driver/windows-libc-options.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// -- check that invalid values are flagged
// RUN: not %swiftc_driver -target x86_64-unknown-windows-msvc -libc MLd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-INVALID
// CHECK-INVALID: error: invalid value 'MLd' in '-libc'

// -- check that cross-compilation still succeeds
// RUN: %swiftc_driver -target x86_64-unknown-linux-gnu -c %s -###

// -- check flags for /MD
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MD -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MD
// CHECK-MD: -autolink-library oldnames -autolink-library msvcrt -Xcc -D_MT -Xcc -D_DLL

// -- check flags for /MDd
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MDd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MDd
// CHECK-MDd: -autolink-library oldnames -autolink-library msvcrtd -Xcc -D_MT -Xcc -D_DLL

// -- check flags for /MT
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MT -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MT
// CHECK-MT: -autolink-library oldnames -autolink-library libcmt -Xcc -D_MT
// CHECK-MT-NOT: -D_DLL

// -- check flags for /MTd
// RUN: %swiftc_driver -target x86_64-unknown-windows-msvc -libc MTd -c %s -### 2>&1 | %FileCheck %s -check-prefix CHECK-MTd
// CHECK-MTd: -autolink-library oldnames -autolink-library libcmtd -Xcc -D_MT
// CHECK-MTd-NOT: -D_DLL

16 changes: 12 additions & 4 deletions test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,15 @@ config.substitutions.append( ('%mcp_opt', mcp_opt) )
config.substitutions.append( ('%swift_driver_plain', "%r" % config.swift) )
config.substitutions.append( ('%swiftc_driver_plain', "%r" % config.swiftc) )
if kIsWindows:
config.substitutions.append( ('%swift_driver', "%r %s %s %s" % (config.swift, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
config.substitutions.append( ('%swiftc_driver', "%r %s %s %s" % (config.swiftc, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
config.substitutions.append( ('%swift_driver',
"%r %s %s %s -libc %s" % (config.swift, mcp_opt,
config.swift_test_options,
config.swift_driver_test_options,
config.swift_stdlib_msvc_runtime)) )
config.substitutions.append( ('%swiftc_driver',
"%r %s %s %s" % (config.swiftc, mcp_opt,
config.swift_test_options,
config.swift_driver_test_options)) )
else:
config.substitutions.append( ('%swift_driver', "env SDKROOT= %r %s %s %s" % (config.swift, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
config.substitutions.append( ('%swiftc_driver', "env SDKROOT= %r %s %s %s" % (config.swiftc, mcp_opt, config.swift_test_options, config.swift_driver_test_options)) )
Expand Down Expand Up @@ -870,10 +877,11 @@ elif run_os in ['windows-msvc']:
config.target_runtime = 'native'

config.target_build_swift = \
('%r -target %s %s %s %s %s -Xlinker -nodefaultlib:libcmt' % \
('%r -target %s %s %s %s %s -libc %s' % \
(config.swiftc, config.variant_triple, resource_dir_opt, \
config.swift_test_options, config.swift_driver_test_options,\
swift_execution_tests_extra_flags))
swift_execution_tests_extra_flags, \
config.swift_stdlib_msvc_runtime))

config.target_run = ''

Expand Down
12 changes: 12 additions & 0 deletions test/lit.site.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ config.variant_triple = "@VARIANT_TRIPLE@"
config.variant_sdk = "@VARIANT_SDK@"
config.variant_suffix = "@VARIANT_SUFFIX@"
config.swiftlib_dir = "@LIT_SWIFTLIB_DIR@"
config.swift_stdlib_msvc_runtime = None
if "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreaded":
config.swift_stdlib_msvc_runtime = 'MT'
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebug":
config.swift_stdlib_msvc_runtime = 'MTd'
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDLL":
config.swift_stdlib_msvc_runtime = 'MD'
elif "@SWIFT_STDLIB_MSVC_RUNTIME_LIBRARY@" == "MultiThreadedDebugDLL":
config.swift_stdlib_msvc_runtime = 'MDd'
else:
assert(False)

config.swift_test_results_dir = \
lit_config.params.get("swift_test_results_dir", "@SWIFT_TEST_RESULTS_DIR@")
config.darwin_xcrun_toolchain = "@SWIFT_DARWIN_XCRUN_TOOLCHAIN@"
Expand Down