Skip to content

Commit

Permalink
Improve the quality of the CMake build scripts
Browse files Browse the repository at this point in the history
This commit does a couple changes:

* Actually adheres to the declared CMake 3.8 requirement
  * HOMEPAGE_URL in project() was added in 3.12
  * install(TARGETS) requires the DESTINATION argument
  * Tests' CML uses CONFIGURE_DEPENDS from CMake 3.12
* Removes unnecessary things
  * Looking for RPM and DEB packagers is pointless
  * Misc arguments to CMake commands
* Improves correctness
  * Includes CPack and CTest modules only if top level
  * Assigns install rules to a project specific component to not clobber
    the global, `Unspecified` one
  * Adds a warning guard for projects that vendor ctre
  * CMAKE_INSTALL_PREFIX may change at install time, so .pc file is
    generated at that time to ensure the prefix is always right
  * Enables the install rules to be opt-out using the CMake built-in
    variable
  * Emulates ARCH_INDEPENDENT for the version config
  * Installs headers to their own directory (fixes hanickadot#207)
* Small optimization
  * LANGUAGES can be set to NONE, because this is a header only library
  • Loading branch information
friendlyanon committed Nov 8, 2021
1 parent 2d31ccc commit a8920de
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 97 deletions.
194 changes: 106 additions & 88 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,105 +1,123 @@
cmake_minimum_required(VERSION 3.8.0)
# When updating to a newer version of CMake, see if we can use the following
project(ctre
HOMEPAGE_URL "https://compile-time.re"
VERSION 3.0
LANGUAGES CXX)
cmake_minimum_required(VERSION 3.8)

project(ctre VERSION 3.0 LANGUAGES NONE)

# ---- project() variable shims ----

# Added in CMake 3.9
set(PROJECT_DESCRIPTION "Fast compile-time regular expressions with support for matching/searching/capturing during compile-time or runtime.")

include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(CTest)

find_program(CTRE_DPKG_BUILDPACKAGE_FOUND dpkg-buildpackage)
find_program(CTRE_RPMBUILD_FOUND rpmbuild)

cmake_dependent_option(CTRE_BUILD_TESTS "Build ctre Tests" ON
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(CTRE_BUILD_PACKAGE "Build ctre Packages" ON
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
cmake_dependent_option(CTRE_BUILD_PACKAGE_DEB
"Create DEB Package (${PROJECT_NAME})" ON
"CTRE_BUILD_PACKAGE;CTRE_DPKG_BUILDPACKAGE_FOUND" OFF)
cmake_dependent_option(CTRE_BUILD_PACKAGE_RPM
"Create RPM Package (${PROJECT_NAME})" ON
"CTRE_BUILD_PACKAGE;CTRE_RPMBUILD_FOUND" OFF)

add_library(${PROJECT_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_compile_features(ctre INTERFACE cxx_std_17)

install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets)

if (NOT EXISTS "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in")
file(WRITE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in [[
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
]])
# Added in CMake 3.12
set(PROJECT_HOMEPAGE_URL "https://compile-time.re")

# Added in CMake 3.21
set(PROJECT_IS_TOP_LEVEL NO)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(PROJECT_IS_TOP_LEVEL YES)
endif()

configure_package_config_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO)

write_basic_package_version_file(ctre-config-version.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)

install(EXPORT ${PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
NAMESPACE ${PROJECT_NAME}::)
install(
FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME})
install(DIRECTORY include/ DESTINATION include
FILES_MATCHING PATTERN *.hpp)
# ---- Warning guard for vendoring projects ----

if(CTRE_BUILD_TESTS)
add_subdirectory(tests)
set(warning_guard "")
if(NOT PROJECT_IS_TOP_LEVEL)
option(ctre_INCLUDES_WITH_SYSTEM
"Use SYSTEM modifier for ctre's includes, disabling warnings" ON)
mark_as_advanced(ctre_INCLUDES_WITH_SYSTEM)
if(ctre_INCLUDES_WITH_SYSTEM)
set(warning_guard SYSTEM)
endif()
endif()

if (NOT CTRE_BUILD_PACKAGE)
return()
endif()
# ---- Declare library ----

list(APPEND source-generators TBZ2 TGZ TXZ ZIP)
add_library(ctre_ctre INTERFACE)
add_library(ctre::ctre ALIAS ctre_ctre)

if (CTRE_BUILD_PACKAGE_DEB)
list(APPEND binary-generators "DEB")
endif()
set_property(TARGET ctre_ctre PROPERTY EXPORT_NAME ctre)

if (CTRE_BUILD_PACKAGE_RPM)
list(APPEND binary-generators "RPM")
endif()
target_include_directories(ctre_ctre ${warning_guard} INTERFACE
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>")
target_compile_features(ctre_ctre INTERFACE cxx_std_17)

# ---- Install rules ----

if(NOT CMAKE_SKIP_INSTALL_RULES)
# For hygienic reasons, install headers to their own directory (issue #207)
if(PROJECT_IS_TOP_LEVEL)
set(CMAKE_INSTALL_INCLUDEDIR include/ctre CACHE PATH "")
endif()

set(CPACK_SOURCE_GENERATOR ${source-generators})
set(CPACK_GENERATOR ${binary-generators})
# The project is configured without a language, so this needs to be set
set(CMAKE_INSTALL_LIBDIR lib CACHE PATH "")

set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Hanicka Dusíková")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${PROJECT_DESCRIPTION}")
set(CPACK_DEBIAN_PACKAGE_NAME "lib${PROJECT_NAME}-dev")
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME ctre_Development)

set(CPACK_RPM_PACKAGE_NAME "lib${PROJECT_NAME}-devel")
install(DIRECTORY include/
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
FILES_MATCHING PATTERN *.hpp)

set(PKG_CONFIG_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/packaging/pkgconfig.pc.in" "${PKG_CONFIG_FILE_NAME}" @ONLY)
install(FILES "${PKG_CONFIG_FILE_NAME}"
DESTINATION "${CMAKE_INSTALL_DATADIR}/pkgconfig"
)
install(TARGETS ctre_ctre
EXPORT ctre-targets
DESTINATION dummy # required until 3.14
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")

# Replace with ARCH_INDEPENDENT once updated to CMake 3.14
set(tmp_CMAKE_SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P}")
set(CMAKE_SIZEOF_VOID_P "")

write_basic_package_version_file(ctre-config-version.cmake
COMPATIBILITY SameMajorVersion)

set(CMAKE_SIZEOF_VOID_P "${tmp_CMAKE_SIZEOF_VOID_P}")

# Allow package maintainers to freely override the path for the configs
set(ctre_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/cmake/ctre"
CACHE PATH "CMake package config location relative to the install prefix")
mark_as_advanced(ctre_INSTALL_CMAKEDIR)

install(FILES "${PROJECT_BINARY_DIR}/ctre-config-version.cmake"
DESTINATION "${ctre_INSTALL_CMAKEDIR}")

install(EXPORT ctre-targets
FILE ctre-config.cmake
DESTINATION "${ctre_INSTALL_CMAKEDIR}"
NAMESPACE ctre::)

option(ctre_ENABLE_PKGCONFIG "Install a .pc file for the project" ON)
if(ctre_ENABLE_PKGCONFIG)
set(ctre_INSTALL_PKGCONFIG "${CMAKE_INSTALL_DATADIR}/pkgconfig/ctre.pc"
CACHE FILEPATH "pkgconfig file location relative to the install prefix")
mark_as_advanced(ctre_INSTALL_PKGCONFIG)

# Export variables for pkgconfig.cmake to use in the install script
install(CODE "set(pc_path [==[${ctre_INSTALL_PKGCONFIG}]==])")
install(CODE "set(include_dir [==[${CMAKE_INSTALL_INCLUDEDIR}]==])")
foreach(var IN ITEMS NAME DESCRIPTION VERSION)
install(CODE "set(PROJECT_${var} [==[${PROJECT_${var}}]==])")
endforeach()
install(SCRIPT packaging/pkgconfig.cmake)
endif()

if(PROJECT_IS_TOP_LEVEL)
# This variable is normally used by set_property(INSTALL), but there aren't
# any in this project, so it makes this a convenient place to provide some
# defaults
set(CPACK_PROPERTIES_FILE
"${PROJECT_SOURCE_DIR}/packaging/CPackDefaults.cmake")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}")
set(CPACK_PACKAGE_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
include(CPack)
endif()
endif()

list(APPEND CPACK_SOURCE_IGNORE_FILES /.git/ /build/ .gitignore .DS_Store)
# ---- Testing ----

include(CPack)
if(PROJECT_IS_TOP_LEVEL)
include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
endif()
13 changes: 13 additions & 0 deletions packaging/CPackDefaults.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This file is loaded at the end of the generated CPackConfig.cmake

set(CPACK_PACKAGE_FILE_NAME "ctre-${CPACK_PACKAGE_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")

set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Hanicka Dusíková")
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
set(CPACK_DEBIAN_PACKAGE_NAME libctre-dev)

set(CPACK_RPM_PACKAGE_NAME libctre-devel)

list(APPEND CPACK_SOURCE_IGNORE_FILES
"/\\.git/" /build/ "\\.gitignore" "\\.DS_Store")
12 changes: 12 additions & 0 deletions packaging/pkgconfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This script is run at CMake install time

get_filename_component(prefix "${CMAKE_INSTALL_PREFIX}" ABSOLUTE)
file(WRITE "${CMAKE_INSTALL_PREFIX}/${pc_path}" "\
prefix=${prefix}
includedir=\${prefix}/${include_dir}
Name: ${PROJECT_NAME}
Description: ${PROJECT_DESCRIPTION}
Version: ${PROJECT_VERSION}
Cflags: -I\${includedir}
")
7 changes: 0 additions & 7 deletions packaging/pkgconfig.pc.in

This file was deleted.

9 changes: 7 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
cmake_minimum_required(VERSION 3.12)

enable_language(CXX)

# CONFIGURE_DEPENDS was added in 3.12, so tests require at least that version
file(GLOB test-sources CONFIGURE_DEPENDS *.cpp)

add_custom_target(ctre-test)

foreach (source IN LISTS test-sources)
foreach(source IN LISTS test-sources)
get_filename_component(test "${source}" NAME_WE)
add_library(ctre-test-${test} STATIC EXCLUDE_FROM_ALL ${source})
target_link_libraries(ctre-test-${test} PRIVATE ctre)
target_link_libraries(ctre-test-${test} PRIVATE ctre::ctre)
add_dependencies(ctre-test ctre-test-${test})
endforeach()

0 comments on commit a8920de

Please sign in to comment.