Modernize the CMake build files (#102)

List of things that this commit brings:
* Makes the project `FetchContent` ready
  This is achieved by conditionally executing code that is only useful
  for a consumer of the project, such as examples.
* Componentize the install rules
  Because this is a header-only library, its install rules should be
  categorized in a dev component (think foo-dev packages in apt). By
  assigning all install rules to a component, the project no longer
  clobbers the global component when vendored (see the previous point).
* Provide an interface similar to the install interface when vendored
  This is achieved by adding SYSTEM to the include directories
  conditionally and only providing targets that are actually needed.
* Make the project architecture independant
  This is achieved by setting the ARCH_INDEPENDENT argument when
  generating the version config file, which is available since CMake
  3.14. This feature is intended to be used for header-only libraries.
* Misc changes for trivial packaging
  The install rules are written in a way that allows package maintainers
  to trivially package the project.

Co-authored-by: friendlyanon <friendlyanon@users.noreply.github.com>
This commit is contained in:
friendlyanon 2021-05-20 21:03:35 +02:00 committed by GitHub
parent 9c59810084
commit a9262c672f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 71 deletions

View File

@ -1,54 +1,44 @@
cmake_minimum_required(VERSION 3.13...3.19)
cmake_minimum_required(VERSION 3.14)
project(tomlplusplus LANGUAGES CXX VERSION 2.4.0)
# Determine if this project is built as a subproject (using
# add_subdirectory) or if it is the master project.
set(MASTER_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
message(STATUS "CMake version: ${CMAKE_VERSION}")
endif()
add_library(tomlplusplus INTERFACE)
add_library(tomlplusplus::tomlplusplus ALIAS tomlplusplus)
target_compile_features(tomlplusplus INTERFACE cxx_std_17)
target_include_directories(tomlplusplus INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
project(
tomlplusplus
VERSION 2.4.0
DESCRIPTION "Header-only TOML config file parser and serializer for C++17 (and later!)"
HOMEPAGE_URL "https://marzer.github.io/tomlplusplus/"
LANGUAGES CXX
)
include(cmake/project-is-top-level.cmake)
include(cmake/variables.cmake)
option(TOMLPP_BUILD_EXAMPLES "Build examples." ${MASTER_PROJECT})
if(TOMLPP_BUILD_EXAMPLES)
# ---- Declare library ----
add_library(tomlplusplus_tomlplusplus INTERFACE)
add_library(tomlplusplus::tomlplusplus ALIAS tomlplusplus_tomlplusplus)
set_property(
TARGET tomlplusplus_tomlplusplus PROPERTY
EXPORT_NAME tomlplusplus
)
target_include_directories(
tomlplusplus_tomlplusplus
${tomlplusplus_warning_guard} # unquoted for list expansion
INTERFACE
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
)
target_compile_features(tomlplusplus_tomlplusplus INTERFACE cxx_std_17)
# ---- Install rules ----
include(cmake/install-rules.cmake)
# ---- Examples ----
if(PROJECT_IS_TOP_LEVEL)
option(BUILD_EXAMPLES "Build examples tree." OFF)
if(BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
option(TOMLPP_INSTALL "Generate the install target" ${MASTER_PROJECT})
if(TOMLPP_INSTALL)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
install(TARGETS tomlplusplus EXPORT ${PROJECT_NAME}Targets)
install(DIRECTORY include/toml++ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
write_basic_package_version_file(
${PROJECT_NAME}ConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
install(
FILES cmake/tomlplusplusConfig.cmake # ---------->
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(
EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
FILE ${PROJECT_NAME}Targets.cmake # <----------
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
endif()
endif()

46
cmake/install-rules.cmake Normal file
View File

@ -0,0 +1,46 @@
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
install(
DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT tomlplusplus_Development
)
install(
TARGETS tomlplusplus_tomlplusplus
EXPORT tomlplusplusTargets
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
write_basic_package_version_file(
tomlplusplusConfigVersion.cmake
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT
)
set(
tomlplusplus_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/tomlplusplus"
CACHE STRING "CMake package config location relative to the install prefix"
)
mark_as_advanced(tomlplusplus_INSTALL_CMAKEDIR)
install(
FILES
"${PROJECT_SOURCE_DIR}/cmake/tomlplusplusConfig.cmake"
"${PROJECT_BINARY_DIR}/tomlplusplusConfigVersion.cmake"
DESTINATION "${tomlplusplus_INSTALL_CMAKEDIR}"
COMPONENT tomlplusplus_Development
)
install(
EXPORT tomlplusplusTargets
NAMESPACE tomlplusplus::
DESTINATION "${tomlplusplus_INSTALL_CMAKEDIR}"
COMPONENT tomlplusplus_Development
)
if(PROJECT_IS_TOP_LEVEL)
include(CPack)
endif()

View File

@ -0,0 +1,6 @@
# This variable is set by project() in CMake 3.21+
string(
COMPARE EQUAL
"${CMAKE_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}"
PROJECT_IS_TOP_LEVEL
)

View File

@ -1,14 +0,0 @@
@PACKAGE_INIT@
# If tomlplusplus::tomlplusplus target is not defined it will be included
if(NOT TARGET tomlplusplus::tomlplusplus)
# Import tomlplusplus interface library
add_library(tomlplusplus::tomlplusplus INTERFACE IMPORTED)
set_target_properties(tomlplusplus::tomlplusplus PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${PACKAGE_PREFIX_DIR}/include")
# Require C++17
target_compile_features(tomlplusplus::tomlplusplus INTERFACE cxx_std_17)
endif()

18
cmake/variables.cmake Normal file
View File

@ -0,0 +1,18 @@
# ---- Warning guard ----
# target_include_directories with the SYSTEM modifier will request the compiler
# to omit warnings from the provided paths, if the compiler supports that
# This is to provide a user experience similar to find_package when
# add_subdirectory or FetchContent is used to consume this project
set(tomlplusplus_warning_guard "")
if(NOT PROJECT_IS_TOP_LEVEL)
option(
tomlplusplus_INCLUDES_WITH_SYSTEM
"Use SYSTEM modifier for tomlplusplus's includes, disabling warnings"
ON
)
mark_as_advanced(tomlplusplus_INCLUDES_WITH_SYSTEM)
if(tomlplusplus_INCLUDES_WITH_SYSTEM)
set(tomlplusplus_warning_guard SYSTEM)
endif()
endif()

View File

@ -1,15 +1,25 @@
cmake_minimum_required(VERSION 3.13...3.19)
cmake_minimum_required(VERSION 3.14)
project(Examples LANGUAGES CXX)
if(NOT TARGET tomlplusplus::tomlplusplus)
find_package(tomlplusplus REQUIRED)
include(../cmake/project-is-top-level.cmake)
if(PROJECT_IS_TOP_LEVEL)
find_package(tomlplusplus REQUIRED)
endif()
add_executable(toml_to_json_transcoder toml_to_json_transcoder.cpp)
target_link_libraries(toml_to_json_transcoder PRIVATE tomlplusplus::tomlplusplus)
add_custom_target(run_examples COMMENT "Running all examples")
enable_testing()
add_test(NAME toml_to_json_transcoder
COMMAND toml_to_json_transcoder ${CMAKE_CURRENT_LIST_DIR}/example.toml
)
function(add_example name)
cmake_parse_arguments(PARSE_ARGV 1 "" "" "" ARGS)
add_executable("${name}" "${name}.cpp")
target_link_libraries("${name}" PRIVATE tomlplusplus::tomlplusplus)
target_compile_features("${name}" PRIVATE cxx_std_17)
add_custom_target("run_${name}" COMMAND "${name}" ${_ARGS} VERBATIM)
add_dependencies(run_examples "run_${name}")
endfunction()
add_example(error_printer)
add_example(simple_parser ARGS "${PROJECT_SOURCE_DIR}/example.toml")
add_example(toml_generator ARGS 100)
add_example(toml_to_json_transcoder ARGS "${PROJECT_SOURCE_DIR}/example.toml")