✨ Update CMake to modern approach
New Features: pugixml-shared and pugixml-static are "always" available, but not always built. This allows downstream projects to still use them, and to make sure our configurations are correct regardless of if they are being built. They are not always installed however. pugixml-shared and pugixml-static have ALIAS libraries of pugixml::shared and pugixml::static respectively. These names are also respected in the `find_package(pugixml CONFIG)` generated files, so its safe to use pugixml in a CMake project regardless of whether it is installed locally, or if its a subproject via `add_subdirectory`. pugixml will automatically select the correct library type based on BUILD_SHARED_LIBS. A pugixml::pugixml ALIAS is also available. CMAKE_MSVC_RUNTIME_LIBRARY from CMake 3.15 has been backported. CMake will now rely on generator expressions (a powerful abstraction in large projects with many subdirectories) for most work. This offloads work from the single-threaded configure stage to the multithreaded generation stage. pugixml now uses CTest as the runner. Some settings are automatically disabled if pugixml is used as a subdirectory. These are still able to be manually set, but are hidden from folks who choose to use CMake GUI.
This commit is contained in:
parent
195dfe1d8d
commit
1c5a0bb325
2 changed files with 173 additions and 72 deletions
242
CMakeLists.txt
242
CMakeLists.txt
|
@ -19,96 +19,194 @@ cmake_dependent_option(STATIC_CRT
|
|||
"Use static MSVC RT libraries" OFF
|
||||
"MSVC" OFF)
|
||||
|
||||
cmake_dependent_option(BUILD_TESTS
|
||||
"Build pugixml tests" OFF
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
|
||||
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" OFF)
|
||||
# Technically not needed for this file. This is builtin.
|
||||
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
|
||||
|
||||
set(BUILD_DEFINES CACHE STRING "Build defines")
|
||||
|
||||
# This is used to backport a CMake 3.15 feature
|
||||
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
MultiThreaded$<$<CONFIG:Debug>:Debug>$<$<NOT:$<BOOL:${STATIC_CRT}>>:DLL>)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
|
||||
option(BUILD_TESTS "Build tests" OFF)
|
||||
|
||||
set(BUILD_DEFINES "" CACHE STRING "Build defines")
|
||||
|
||||
# Pre-defines standard install locations on *nix systems.
|
||||
mark_as_advanced(CLEAR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR)
|
||||
|
||||
set(HEADERS src/pugixml.hpp src/pugiconfig.hpp)
|
||||
set(SOURCES src/pugixml.cpp)
|
||||
|
||||
if(BUILD_SHARED_LIBS AND MSVC)
|
||||
set(PUGIXML_WINDLL_SRCS scripts/pugixml_dll.rc)
|
||||
if (USE_POSTFIX)
|
||||
set(CMAKE_RELWITHDEBINFO_POSTFIX _r)
|
||||
set(CMAKE_MINSIZEREL_POSTFIX _m)
|
||||
set(CMAKE_DEBUG_POSTFIX _d)
|
||||
endif()
|
||||
|
||||
if(DEFINED BUILD_DEFINES)
|
||||
foreach(DEFINE ${BUILD_DEFINES})
|
||||
add_definitions("-D" ${DEFINE})
|
||||
endforeach()
|
||||
endif()
|
||||
# Generator expressions to make backporting more readable
|
||||
set(should-backport-msvc-rt $<VERSION_LESS:${CMAKE_VERSION},3.15>)
|
||||
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
|
||||
set(msvc-rt-mtd-shared $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
|
||||
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
|
||||
set(msvc-rt-mt-shared $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
|
||||
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
|
||||
|
||||
if(BUILD_SHARED_AND_STATIC_LIBS)
|
||||
set(LIBRARY pugixml-static pugixml-shared)
|
||||
set(msvc-rt-mtd-shared $<AND:${should-backport-msvc-rt},${msvc-rt-mtd-shared}>)
|
||||
set(msvc-rt-mtd-static $<AND:${should-backport-msvc-rt},${msvc-rt-mtd-static}>)
|
||||
set(msvc-rt-mt-shared $<AND:${should-backport-msvc-rt},${msvc-rt-mt-shared}>)
|
||||
set(msvc-rt-mt-static $<AND:${should-backport-msvc-rt},${msvc-rt-mt-static}>)
|
||||
|
||||
set(build-shared $<BOOL:${BUILD_SHARED_LIBS}>)
|
||||
set(build-both $<BOOL:${BUILD_SHARED_AND_STATIC_LIBS}>)
|
||||
set(versioned-dir $<$<BOOL:${USE_VERSIONED_LIBDIR}>:/pugixml-${PROJECT_VERSION}>)
|
||||
|
||||
add_library(pugixml) # Auto selects static or shared based on BUILD_SHARED_LIBS
|
||||
add_library(pugixml-shared SHARED)
|
||||
add_library(pugixml-static STATIC)
|
||||
|
||||
add_library(pugixml::pugixml ALIAS pugixml)
|
||||
add_library(pugixml::shared ALIAS pugixml-shared)
|
||||
add_library(pugixml::static ALIAS pugixml-static)
|
||||
|
||||
# This means you can use pugixml::shared when a `find_package(pugixml CONFIG)`
|
||||
# is called. This keeps it consistent with the aliases we provide.
|
||||
set_property(TARGET pugixml-shared PROPERTY EXPORT_NAME shared)
|
||||
set_property(TARGET pugixml-static PROPERTY EXPORT_NAME static)
|
||||
|
||||
set_target_properties(pugixml-shared pugixml-static pugixml
|
||||
PROPERTIES
|
||||
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY}
|
||||
EXCLUDE_FROM_ALL ON
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
VERSION ${PROJECT_VERSION})
|
||||
|
||||
# XXX: EXCLUDE_FROM_ALL cannot be set via a generator expression! :(
|
||||
if (BUILD_SHARED_AND_STATIC_LIBS)
|
||||
set_target_properties(pugixml-shared pugixml-static
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL OFF)
|
||||
set(install-targets pugixml-shared pugixml-static)
|
||||
else()
|
||||
set(LIBRARY pugixml)
|
||||
set_target_properties(pugixml
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL OFF)
|
||||
set(install-targets pugixml)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_AND_STATIC_LIBS)
|
||||
add_library(pugixml-static STATIC ${HEADERS} ${SOURCES})
|
||||
add_library(pugixml-shared SHARED ${HEADERS} ${SOURCES} ${PUGIXML_WINDLL_SRCS})
|
||||
else()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_library(pugixml SHARED ${HEADERS} ${SOURCES} ${PUGIXML_WINDLL_SRCS})
|
||||
else()
|
||||
add_library(pugixml STATIC ${HEADERS} ${SOURCES})
|
||||
target_sources(pugixml-shared
|
||||
PRIVATE
|
||||
$<${build-shared}:${PROJECT_SOURCE_DIR}/scripts/pugixml_dll.rc>
|
||||
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
|
||||
target_sources(pugixml-static
|
||||
PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
|
||||
target_sources(pugixml
|
||||
PRIVATE
|
||||
$<${build-shared}:${PROJECT_SOURCE_DIR}/scripts/pugixml_dll.rc>
|
||||
${PROJECT_SOURCE_DIR}/src/pugixml.cpp)
|
||||
|
||||
# XXX: INSTALL_INTERFACE is not used here so that INCLUDES DESTINATION can work
|
||||
# correctly if USE_VERSIONED_LIBDIR is set. $<INSTALL_INTERFACE> can't expand
|
||||
# generator expressions otherwise.
|
||||
target_include_directories(pugixml-shared
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_include_directories(pugixml-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_include_directories(pugixml
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
|
||||
target_compile_definitions(pugixml-shared
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:PUGIXML_API=__declspec\(dllexport\)>)
|
||||
target_compile_definitions(pugixml
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:PUGIXML_API=__declspec\(dllexport\)>)
|
||||
|
||||
target_compile_options(pugixml-shared
|
||||
PRIVATE
|
||||
$<${msvc-rt-mtd-shared}:-MDd>
|
||||
$<${msvc-rt-mtd-static}:-MTd>
|
||||
$<${msvc-rt-mt-shared}:-MD>
|
||||
$<${msvc-rt-mt-static}:-MT>)
|
||||
target_compile_options(pugixml
|
||||
PRIVATE
|
||||
$<${msvc-rt-mtd-shared}:-MDd>
|
||||
$<${msvc-rt-mtd-static}:-MTd>
|
||||
$<${msvc-rt-mt-shared}:-MD>
|
||||
$<${msvc-rt-mt-static}:-MT>)
|
||||
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/pugixml-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
NO_SET_AND_CHECK_MACRO)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
|
||||
configure_file(scripts/pugixml.pc.in pugixml.pc @ONLY)
|
||||
|
||||
install(TARGETS ${install-targets}
|
||||
EXPORT pugixml-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir})
|
||||
|
||||
install(EXPORT pugixml-targets
|
||||
NAMESPACE pugixml::
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/pugixml)
|
||||
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config-version.cmake"
|
||||
"${PROJECT_BINARY_DIR}/pugixml-config.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/pugixml)
|
||||
|
||||
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
|
||||
|
||||
install(
|
||||
FILES
|
||||
"${PROJECT_SOURCE_DIR}/src/pugiconfig.hpp"
|
||||
"${PROJECT_SOURCE_DIR}/src/pugixml.hpp"
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_INCLUDEDIR}${versioned-dir})
|
||||
|
||||
if (BUILD_TESTS)
|
||||
set(fuzz-pattern "tests/fuzz_*.cpp")
|
||||
set(test-pattern "tests/*.cpp")
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.11)
|
||||
list(INSERT fuzz-pattern 0 CONFIGURE_DEPENDS)
|
||||
list(INSERT test-pattern 0 CONFIGURE_DEPENDS)
|
||||
endif()
|
||||
file(GLOB test-sources ${test-pattern})
|
||||
file(GLOB fuzz-sources ${fuzz-pattern})
|
||||
list(REMOVE_ITEM test-sources ${fuzz-sources})
|
||||
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
|
||||
add_executable(pugixml-check ${test-sources})
|
||||
add_test(NAME pugixml::test
|
||||
COMMAND pugixml-check
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
add_dependencies(check pugixml-check)
|
||||
target_link_libraries(pugixml-check
|
||||
PRIVATE
|
||||
$<IF:${build-both},pugixml::static,pugixml::pugixml>)
|
||||
endif()
|
||||
|
||||
# Export symbols for shared library builds
|
||||
if(BUILD_SHARED_AND_STATIC_LIBS AND MSVC)
|
||||
target_compile_definitions(pugixml-shared PRIVATE "PUGIXML_API=__declspec(dllexport)")
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS AND MSVC)
|
||||
target_compile_definitions(pugixml PRIVATE "PUGIXML_API=__declspec(dllexport)")
|
||||
endif()
|
||||
|
||||
if(USE_VERSIONED_LIBDIR)
|
||||
# Install library into its own directory under LIBDIR
|
||||
set(INSTALL_SUFFIX /pugixml-${pugixml_VERSION})
|
||||
endif()
|
||||
|
||||
foreach(TARGET ${LIBRARY})
|
||||
# Enable C++11 long long for compilers that are capable of it
|
||||
if(NOT ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} STRLESS 3.1 AND ";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_long_long_type;")
|
||||
target_compile_features(${TARGET} PUBLIC cxx_long_long_type)
|
||||
endif()
|
||||
|
||||
set_target_properties(${TARGET} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}${INSTALL_SUFFIX}>)
|
||||
|
||||
if(USE_POSTFIX)
|
||||
set_target_properties(${TARGET} PROPERTIES DEBUG_POSTFIX "_d" MINSIZEREL_POSTFIX "_m" RELWITHDEBINFO_POSTFIX "_r")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
install(TARGETS ${LIBRARY} EXPORT pugixml-config
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}${INSTALL_SUFFIX}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}${INSTALL_SUFFIX}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}${INSTALL_SUFFIX})
|
||||
install(EXPORT pugixml-config DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pugixml)
|
||||
|
||||
configure_file(scripts/pugixml.pc.in ${PROJECT_BINARY_DIR}/pugixml.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/pugixml.pc DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig)
|
||||
#[[
|
||||
|
||||
if(BUILD_TESTS)
|
||||
file(GLOB TEST_SOURCES tests/*.cpp)
|
||||
|
@ -122,4 +220,4 @@ if(BUILD_TESTS)
|
|||
target_link_libraries(check pugixml)
|
||||
endif()
|
||||
add_custom_command(TARGET check POST_BUILD COMMAND check WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
endif()]]
|
||||
|
|
3
pugixml-config.cmake.in
Normal file
3
pugixml-config.cmake.in
Normal file
|
@ -0,0 +1,3 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/pugixml-targets.cmake")
|
Loading…
Add table
Reference in a new issue