在Visual Studio 2019中用Clang前端构建C++98项目的问题求助
解决VS2019中Clang+CMake编译C++98项目的标准库冲突问题
首先咱们得搞清楚你遇到的问题根源:当用Clang-cl(Windows下的Clang前端)配合MSVC的标准库时,强制指定C++98标准会触发MSVC STL内部的兼容性冲突。VS2019附带的MSVC 14.20版本的标准库,其实已经是基于C11及以后特性实现的——哪怕你指定了C98编译,STL内部还是会用到static_assert、type_traits这些C11才有的特性,而Clang在严格C98模式下会把这些当成非法语法,所以才会报出vadefs.h里的那些错误。
下面给你几个不用换旧版MSVC的解决办法,还有Windows下非MinGW的C++98构建方案:
方案一:改用Clang的libc++标准库(推荐)
MSVC的STL对C98的兼容性已经很差了,而Clang自带的libc对C98有更好的支持。你只需要调整CMake配置,让项目使用libc替代MSVC的STL:
修改后的CMakeLists.txt
cmake_minimum_required(VERSION 3.11 FATAL_ERROR) project(sink) # 用CMake标准变量指定C++98标准,比手动传-Xclang更可靠 set(CMAKE_CXX_STANDARD 98) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # 添加编译选项,指定使用libc++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -stdlib=libc++") # 链接时指定libc++相关库 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi") set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") set(BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIR}/bin") file(GLOB SOURCES "${SRC_DIR}/*.cpp" "${SRC_DIR}/*.cc" "${SRC_DIR}/*.c") file(GLOB HEADERS "${INCLUDE_DIR}/*.h" "${INCLUDE_DIR}/*.hpp") add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
修改CMakeSettings.json
注意不要让命令行参数覆盖CMakeLists里的CMAKE_CXX_FLAGS,去掉原来的CMAKE_CXX_FLAGS设置:
{ "configurations": [ { "name": "Debug", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_x64" ], "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", "cmakeCommandArgs": "-DCMAKE_CXX_COMPILER:PATH=\"C:\\Program Files\\LLVM\\bin\\clang-cl.exe\" -DCMAKE_CXX_FLAGS_DEBUG:STRING=\"/MDd /Zi /Ob0 /Od /RTC1\"", "buildCommandArgs": "-v", "ctestCommandArgs": "", "variables": [] } ] }
方案二:保留MSVC STL,添加兼容宏
如果你一定要用MSVC的标准库,可以通过定义宏来禁用STL内部的C11特性,让它尽量兼容C98:
修改CMakeLists.txt
在原来的基础上添加兼容宏,同时改用CMake标准变量指定C++98:
cmake_minimum_required(VERSION 3.11 FATAL_ERROR) project(sink) # 指定C++98标准 set(CMAKE_CXX_STANDARD 98) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # 添加编译选项和兼容宏,禁用MSVC STL的C++11特性 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic") add_definitions(-_HAS_CXX11=0 -_HAS_CXX0X=0) set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include") set(BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/build") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIR}/bin") file(GLOB SOURCES "${SRC_DIR}/*.cpp" "${SRC_DIR}/*.cc" "${SRC_DIR}/*.c") file(GLOB HEADERS "${INCLUDE_DIR}/*.h" "${INCLUDE_DIR}/*.hpp") add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
这个方案的局限性在于:MSVC STL的旧兼容模式并不完美,可能还是会有一些隐藏的兼容性问题,但对于简单项目应该能正常工作。
Windows下非MinGW的C++98构建其他选项
如果你不想用Clang,还可以直接用MSVC编译器本身构建C++98项目:
- 在CMake里设置
CMAKE_CXX_COMPILER为MSVC的cl.exe,然后指定标准:set(CMAKE_CXX_STANDARD 98),或者添加编译选项/std:c++98 /Za(/Za禁用微软扩展)。 - 不过MSVC对C++98的支持也有一些细节差异,比如某些模板特性的实现,但胜在和自身STL完全兼容。
内容的提问来源于stack exchange,提问作者adziri
相关产品推荐
相关产品推荐

