3.18/3.19: Cannot force C language source to compile as C++
Upgraded from 3.14 to 3.18 (and 3.19) via scoop
recently and broke my privately maintained version of the pthreads4w
library. This library uses a single source file, pthread.c
, with different compile-time constants to produce different versions of the library, depending on how thread cleanup is done. One of the versions should compile pthread.c
as C++ source, which used to be possible in the MSVC path by adding /TP
via target_compile_options
. However, it's now the case that /TC
is hardwired into the CMake
source and /TP
seems to be silently stripped (or ignored).
I've tried setting the target's linker language, as this seems to be a default suggested by the source. (The symlink
suggestion posed on Stackoverflow is unreliable on Windows.)
What's the preferred way to compile C and C++ source with 3.18/19? Is this a feature or bug?
Code snippet from the CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(pthreads4w VERSION ${PTHREADS4W_VERSION} LANGUAGES C CXX)
## ...
set(VCEFLAGS)
if(MSVC)
if(MSVC_VERSION EQUAL 1200)
set(VCEFLAGS "/EHa" "/TP")
else()
set(VCEFLAGS "/EHs" "/TP")
endif()
set(build_defines ${build_defines} HAVE_CONFIG_H __PTW32_RC_MSC)
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
set(build_defines ${build_defines} HAVE_CONFIG_H)
endif()
## ...
function(shared_lib type def)
set(targ pthread${type}${PTW32_VER})
add_library(${targ} SHARED pthread.c ${CMAKE_BINARY_DIR}/version.rc)
message(STATUS ${targ})
target_compile_definitions(${targ} PRIVATE ${def} ${build_defines} __PTW32_BUILD_INLINED)
set_target_properties(${targ} PROPERTIES DEBUG_POSTFIX "d")
if (MSVC)
# Set resource compiler definition...
target_compile_definitions(${targ} PRIVATE __PTW32_RC_MSC)
endif ()
if (${type} STREQUAL "VCE")
## Should set "/TP" here, but it's either silently stripped or ignored
set_target_properties(${targ} PROPERTIES LINKER_LANGUAGE CXX)
target_compile_options(${targ} PUBLIC "${VCEFLAGS}")
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "GNU")
target_compile_options(${targ} PRIVATE "-mthreads")
if (${type} STREQUAL "GCE")
set_target_properties(${targ} PROPERTIES LINKER_LANGUAGE CXX)
target_compile_options(${targ} PRIVATE "-xc++")
target_link_libraries(${targ} stdc++)
target_link_options(${targ} PRIVATE "-shared-libgcc")
endif (${type} STREQUAL "GCE")
endif (${type} STREQUAL "VCE")
install(
TARGETS ${targ}
ARCHIVE # DESTINATION ${TARGET_ARCH}/${CONFIG}/lib
LIBRARY # DESTINATION ${TARGET_ARCH}/${CONFIG}/lib
RUNTIME # DESTINATION ${TARGET_ARCH}/${CONFIG}/bin
)
install(
FILES $<TARGET_PDB_FILE:${targ}>
CONFIGURATION Debug
DESTINATION lib
OPTIONAL
)
endfunction()
if (MSVC)
shared_lib ( VCE __PTW32_CLEANUP_CXX )
shared_lib ( VSE __PTW32_CLEANUP_SEH )
shared_lib ( VC __PTW32_CLEANUP_C )
elseif (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
## NOTE: MinGW64 does support SEH exception handling, BUT it does not yet
## have the MSVC keywords "__try", "__except" and "__finally".
shared_lib ( GCE __PTW32_CLEANUP_CXX )
shared_lib ( GC __PTW32_CLEANUP_C )
endif (MSVC)