diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -389,6 +389,11 @@ message(FATAL_ERROR "Only one of LIBCXX_ABI_FORCE_ITANIUM and LIBCXX_ABI_FORCE_MICROSOFT can be specified.") endif () +if (LIBCXX_ENABLE_SHARED AND CMAKE_MSVC_RUNTIME_LIBRARY AND + (NOT CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$")) + message(WARNING "A static CRT linked into a shared libc++ doesn't work correctly.") +endif() + #=============================================================================== # Configure System #=============================================================================== @@ -482,11 +487,6 @@ include(HandleLibCXXABI) # Setup the ABI library flags -# FIXME: Remove all debug flags and flags that change which Windows -# default libraries are linked. Currently we only support linking the -# non-debug DLLs -remove_flags("/D_DEBUG" "/MTd" "/MDd" "/MT" "/Md") - # FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC. # Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors # so they don't get transformed into -Wno and -errors respectively. @@ -711,8 +711,16 @@ set(LIB_SUFFIX "") endif() - target_link_libraries(${target} PRIVATE msvcrt${LIB_SUFFIX}) # C runtime startup files - target_link_libraries(${target} PRIVATE msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals. + if (NOT CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$") + set(CRT_LIB "msvcrt") + set(CXX_LIB "msvcprt") + else() + set(CRT_LIB "libcmt") + set(CXX_LIB "libcpmt") + endif() + + target_link_libraries(${target} PRIVATE ${CRT_LIB}${LIB_SUFFIX}) # C runtime startup files + target_link_libraries(${target} PRIVATE ${CXX_LIB}${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals. # Required for standards-complaint wide character formatting functions # (e.g. `printfw`/`scanfw`) target_link_libraries(${target} PRIVATE iso_stdio_wide_specifiers) diff --git a/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in --- a/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in +++ b/libcxx/test/configs/llvm-libc++-shared-clangcl.cfg.in @@ -4,18 +4,26 @@ lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') dbg_include = '' -lib_suffix = '' +runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@' + +if runtime_library == '' or runtime_library.endswith('DLL'): + crt_lib = 'msvcrt' + cxx_lib = 'msvcprt' +else: + crt_lib = 'libcmt' + cxx_lib = 'libcpmt' if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG': dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h' - lib_suffix = 'd' + crt_lib += 'd' + cxx_lib += 'd' config.substitutions.append(('%{flags}', '--driver-mode=g++')) config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX' + dbg_include )) config.substitutions.append(('%{link_flags}', - '-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix) + '-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T --prepend_env PATH=%{lib} -- ' diff --git a/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in --- a/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in +++ b/libcxx/test/configs/llvm-libc++-shared-no-vcruntime-clangcl.cfg.in @@ -5,18 +5,26 @@ lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') dbg_include = '' -lib_suffix = '' +runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@' + +if runtime_library == '' or runtime_library.endswith('DLL'): + crt_lib = 'msvcrt' + cxx_lib = 'msvcprt' +else: + crt_lib = 'libcmt' + cxx_lib = 'libcpmt' if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG': dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h' - lib_suffix = 'd' + crt_lib += 'd' + cxx_lib += 'd' config.substitutions.append(('%{flags}', '--driver-mode=g++')) config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX -D_HAS_EXCEPTIONS=0' + dbg_include )) config.substitutions.append(('%{link_flags}', - '-nostdlib -L %%{lib} -lc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix) + '-nostdlib -L %%{lib} -lc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T --prepend_env PATH=%{lib} -- ' diff --git a/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in b/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in --- a/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in +++ b/libcxx/test/configs/llvm-libc++-static-clangcl.cfg.in @@ -4,18 +4,26 @@ lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg') dbg_include = '' -lib_suffix = '' +runtime_library = '@CMAKE_MSVC_RUNTIME_LIBRARY@' + +if runtime_library == '' or runtime_library.endswith('DLL'): + crt_lib = 'msvcrt' + cxx_lib = 'msvcprt' +else: + crt_lib = 'libcmt' + cxx_lib = 'libcpmt' if '@uppercase_CMAKE_BUILD_TYPE@' == 'DEBUG': dbg_include = ' -D_DEBUG -include set_windows_crt_report_mode.h' - lib_suffix = 'd' + crt_lib += 'd' + cxx_lib += 'd' config.substitutions.append(('%{flags}', '--driver-mode=g++')) config.substitutions.append(('%{compile_flags}', '-nostdinc++ -I %{include} -I %{target-include} -I %{libcxx}/test/support -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_STDIO_ISO_WIDE_SPECIFIERS -DNOMINMAX' + dbg_include )) config.substitutions.append(('%{link_flags}', - '-nostdlib -L %%{lib} -llibc++ -lmsvcrt%s -lmsvcprt%s -loldnames' % (lib_suffix, lib_suffix) + '-nostdlib -L %%{lib} -llibc++ -l%s -l%s -loldnames' % (crt_lib, cxx_lib) )) config.substitutions.append(('%{exec}', '%{executor} --execdir %T -- ' diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -777,6 +777,19 @@ limit: 2 timeout_in_minutes: 120 + - label: "Clang-cl (Static CRT)" + command: "bash libcxx/utils/ci/run-buildbot clang-cl-static-crt" + artifact_paths: + - "**/test-results.xml" + - "**/*.abilist" + agents: + queue: "windows" + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + timeout_in_minutes: 120 + - label: "MinGW (DLL, x86_64)" command: "bash libcxx/utils/ci/run-buildbot mingw-dll" artifact_paths: diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot --- a/libcxx/utils/ci/run-buildbot +++ b/libcxx/utils/ci/run-buildbot @@ -646,6 +646,15 @@ echo "+++ Running the libc++ tests" ${NINJA} -vC "${BUILD_DIR}" check-cxx ;; +clang-cl-static-crt) + clean + # Test linking a static libc++ with the static CRT ("MultiThreaded" denotes + # the static CRT, as opposed to "MultiThreadedDLL" which is the default). + generate-cmake-libcxx-win -DLIBCXX_ENABLE_SHARED=OFF \ + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded + echo "+++ Running the libc++ tests" + ${NINJA} -vC "${BUILD_DIR}" check-cxx +;; mingw-dll) clean # Explicitly specify the compiler with a triple prefix. The CI