[libc++][CMake] Use debug MSVC runtimes when libc++ is built in debug mode
Summary: This patch allows libc++ to be built against the debug MSVC runtimes instead of just the release ones.
Reviewers: rnk, majnemer, compnerd, smeenai
Subscribers: mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D28725
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@292006 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b12910f..652e945 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -369,6 +369,11 @@
endif()
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
+if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
+ set(LIBCXX_DEBUG_BUILD ON)
+else()
+ set(LIBCXX_DEBUG_BUILD OFF)
+endif()
#===============================================================================
# Setup Compiler Flags
@@ -386,7 +391,7 @@
# 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" "/RTC1")
+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
@@ -485,7 +490,8 @@
# Assertion flags =============================================================
define_if(LIBCXX_ENABLE_ASSERTIONS -UNDEBUG)
define_if_not(LIBCXX_ENABLE_ASSERTIONS -DNDEBUG)
-if (LIBCXX_ENABLE_ASSERTIONS)
+define_if(LIBCXX_DEBUG_BUILD -D_DEBUG)
+if (LIBCXX_ENABLE_ASSERTIONS AND NOT LIBCXX_DEBUG_BUILD)
# MSVC doesn't like _DEBUG on release builds. See PR 4379.
define_if_not(LIBCXX_TARGETING_MSVC -D_DEBUG)
endif()
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index f83051f..23a17dd 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -102,14 +102,21 @@
if (NOT WIN32)
add_flags_if_supported(-fPIC)
endif()
+
add_link_flags_if_supported(-nodefaultlibs)
if (LIBCXX_TARGETING_MSVC)
+ if (LIBCXX_DEBUG_BUILD)
+ set(LIB_SUFFIX "d")
+ else()
+ set(LIB_SUFFIX "")
+ endif()
add_compile_flags(/Zl)
add_link_flags(/nodefaultlib)
- add_library_flags(ucrt) # Universal C runtime
- add_library_flags(vcruntime) # C++ runtime
- add_library_flags(msvcrt) # C runtime startup files
+
+ add_library_flags(ucrt${LIB_SUFFIX}) # Universal C runtime
+ add_library_flags(vcruntime${LIB_SUFFIX}) # C++ runtime
+ add_library_flags(msvcrt${LIB_SUFFIX}) # C runtime startup files
# Required for standards-complaint wide character formatting functions
# (e.g. `printfw`/`scanfw`)
add_library_flags(iso_stdio_wide_specifiers)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index ad110fb..b9d5f91 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -35,6 +35,7 @@
pythonize_bool(LIBCXX_HAS_ATOMIC_LIB)
pythonize_bool(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB)
pythonize_bool(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
+pythonize_bool(LIBCXX_DEBUG_BUILD)
# By default, for non-standalone builds, libcxx and libcxxabi share a library
# directory.
diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py
index 448700f..49347df 100644
--- a/test/libcxx/test/config.py
+++ b/test/libcxx/test/config.py
@@ -68,6 +68,7 @@
self.cxx_runtime_root = None
self.abi_library_root = None
self.link_shared = self.get_lit_bool('enable_shared', default=True)
+ self.debug_build = self.get_lit_bool('debug_build', default=False)
self.exec_env = {}
self.use_target = False
self.use_system_cxx_lib = False
@@ -148,6 +149,7 @@
self.lit_config.note('Using available_features: %s' %
list(self.config.available_features))
self.lit_config.note('Using environment: %r' % self.exec_env)
+ sys.stderr.flush() # Force flushing to avoid broken output on Windows
def get_test_format(self):
return LibcxxTestFormat(
@@ -438,13 +440,20 @@
['-target', self.config.target_triple]):
self.lit_config.warning('use_target is true but -target is '\
'not supported by the compiler')
+ if self.is_windows and self.debug_build:
+ self.cxx.compile_flags += ['-D_DEBUG']
def configure_compile_flags_header_includes(self):
- support_path = os.path.join(self.libcxx_src_root, 'test/support')
+ support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
if self.cxx_stdlib_under_test != 'libstdc++' and \
not self.is_windows:
self.cxx.compile_flags += [
'-include', os.path.join(support_path, 'nasty_macros.hpp')]
+ if self.is_windows and self.debug_build:
+ self.cxx.compile_flags += [
+ '-include', os.path.join(support_path,
+ 'set_windows_crt_report_mode.h')
+ ]
self.configure_config_site_header()
cxx_headers = self.get_lit_conf('cxx_headers')
if cxx_headers == '' or (cxx_headers is None
@@ -667,7 +676,8 @@
self.cxx.link_flags += ['-lcxxrt']
elif cxx_abi == 'none' or cxx_abi == 'default':
if self.is_windows:
- self.cxx.link_flags += ['-lmsvcrt']
+ debug_suffix = 'd' if self.debug_build else ''
+ self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
else:
self.lit_config.fatal(
'C++ ABI setting %s unsupported for tests' % cxx_abi)
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 0cccffc..72dcc3a 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -26,7 +26,7 @@
config.llvm_unwinder = "@LIBCXXABI_USE_LLVM_UNWINDER@"
config.has_libatomic = "@LIBCXX_HAS_ATOMIC_LIB@"
config.use_libatomic = "@LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB@"
-
+config.debug_build = "@LIBCXX_DEBUG_BUILD@"
config.libcxxabi_shared = "@LIBCXXABI_ENABLE_SHARED@"
config.cxx_ext_threads = "@LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY@"
diff --git a/test/support/set_windows_crt_report_mode.h b/test/support/set_windows_crt_report_mode.h
new file mode 100644
index 0000000..5fc1698
--- /dev/null
+++ b/test/support/set_windows_crt_report_mode.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SUPPORT_SET_WINDOWS_CRT_REPORT_MODE_H
+#define SUPPORT_SET_WINDOWS_CRT_REPORT_MODE_H
+
+#ifndef _DEBUG
+#error _DEBUG must be defined when using this header
+#endif
+
+#ifndef _WIN32
+#error This header can only be used when targeting Windows
+#endif
+
+#include <crtdbg.h>
+
+// On Windows in debug builds the default assertion handler opens a new dialog
+// window which must be dismissed manually by the user. This function overrides
+// that setting and instead changes the assertion handler to log to stderr
+// instead.
+inline int init_crt_report_mode() {
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
+ return 0;
+}
+
+static int init_crt_anchor = init_crt_report_mode();
+
+#endif // SUPPORT_SET_WINDOWS_CRT_REPORT_MODE_H