Skip to content

Commit

Permalink
GHI #18 Fix and polish CMake (#19)
Browse files Browse the repository at this point in the history
The few visible changes made:
- renamed `create_test(...)` to `_create_test(...)`
- added `create_bt(...)` and `create_ut(...)`
- BTs are skipped if `patomic::patomic` isn't available and can't be
found
- UTs are skipped if `patomic_test` isn't build as a sub-project of
`patomic` (because `patomic` sets `PATOMIC_{BINARY, SOURCE}_DIR`
variables for the UTs to find the required files)
- `gmock` currently not linked because it breaks automatic test lookup
(might add later once there's a pipeline)

---------

Signed-off-by: doodspav <[email protected]>
  • Loading branch information
doodspav authored Oct 21, 2023
1 parent 547b2ef commit e15fe7e
Show file tree
Hide file tree
Showing 16 changed files with 511 additions and 268 deletions.
70 changes: 48 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
cmake_minimum_required(VERSION 3.14)

include(cmake/util/PreventInSourceBuilds.cmake)
include(cmake/PreventInSourceBuilds.cmake)


# ---- Initialize Project ----

# used to support find_package
set(package_name "patomic")

# create base project
project(
patomic
VERSION 0.5.1
Expand All @@ -11,80 +18,99 @@ project(
)

# don't change include order, OptionVariables checks if project is top level
include(cmake/util/ProjectIsTopLevel.cmake)
include(cmake/util/OptionVariables.cmake)
include(cmake/ProjectIsTopLevel.cmake)
include(cmake/OptionVariables.cmake)


# ---- Declare Library ----

add_library(
patomic_patomic
${build_type}
# target that we can modify (can't modify ALIAS targets)
# target name should not be the same as ${PROJECT_NAME}, causes add_subdirectory issues
set(target_name "patomic-patomic")
add_library(${target_name} ${build_type})

# alias to cause error at configuration time instead of link time if target is missing
add_library(patomic::patomic ALIAS ${target_name})

# add /include files to target
# unfortunately can't have CML file in /include
target_sources(
${target_name} PRIVATE
# include
include/patomic/patomic.h
# src
src/patomic.c
)

# alias to cause error at configuration time instead of link time if target is missing
add_library(patomic::patomic ALIAS patomic_patomic)
# add /src files to target
add_subdirectory(src)


# ---- Generate Build Info Headers ----

# used in export header generated below
if(NOT PATOMIC_BUILD_SHARED)
target_compile_definitions(patomic_patomic PUBLIC PATOMIC_STATIC_DEFINE)
target_compile_definitions(${target_name} PUBLIC PATOMIC_STATIC_DEFINE)
endif()

# generate header file with export macros prefixed with BASE_NAME
include(GenerateExportHeader)
generate_export_header(
patomic_patomic
${target_name}
BASE_NAME patomic
EXPORT_FILE_NAME include/patomic/patomic_export.h
)


# ---- Library Properties ----

# hide all symbols by default
# use SameMajorVersion versioning for shared library lookup
set_target_properties(
patomic_patomic PROPERTIES
${target_name} PROPERTIES
C_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN YES
VERSION "${PROJECT_VERSION}"
SOVERSION "${PROJECT_VERSION_MAJOR}"
EXPORT_NAME patomic
OUTPUT_NAME patomic
EXPORT_NAME "patomic"
OUTPUT_NAME "patomic"
)

# header files generated by CMake
target_include_directories(
patomic_patomic SYSTEM
PUBLIC
${target_name} SYSTEM PUBLIC
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>"
)

# header files from /include
target_include_directories(
patomic_patomic ${warning_guard}
PUBLIC
${target_name} ${warning_guard} PUBLIC
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
)

target_compile_features(patomic_patomic PUBLIC c_std_90)
# require C90 compiler support
target_compile_features(${target_name} PUBLIC c_std_90)


# ---- Install Rules ----

if(NOT CMAKE_SKIP_INSTALL_RULES)
include(cmake/util/InstallRules.cmake)
include(cmake/InstallRules.cmake)
endif()


# ---- Setup Tests ----

if(PATOMIC_BUILD_TESTING)

# need to enable testing in case BUILD_TESTING is disabled
enable_testing()
if(PROJECT_IS_TOP_LEVEL)
enable_testing()
endif()

# tell unit tests where our files are
set(PATOMIC_BINARY_DIR "${PROJECT_BINARY_DIR}")
set(PATOMIC_SOURCE_DIR "${PROJECT_SOURCE_DIR}")

# include test project
add_subdirectory(test)

endif()
66 changes: 66 additions & 0 deletions cmake/InstallRules.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
include(CMakePackageConfigHelpers)

# copy header files to CMAKE_INSTALL_INCLUDEDIR
install(
DIRECTORY
"${PROJECT_SOURCE_DIR}/include/" # our header files
"${PROJECT_BINARY_DIR}/include/" # generated header files
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT ${package_name}-development
)

# copy target build output artifacts to OS dependent locations
# (except includes, that just sets a compiler flag with the path)
install(
TARGETS ${target_name}
EXPORT ${package_name}-targets
RUNTIME #
COMPONENT ${package_name}-runtime
LIBRARY #
COMPONENT ${package_name}-runtime
NAMELINK_COMPONENT ${package_name}-development
ARCHIVE #
COMPONENT ${package_name}-development
INCLUDES #
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

# create config file that points to targets file
configure_file(
"${PROJECT_SOURCE_DIR}/cmake/in/patomic-config.cmake.in"
"${PROJECT_BINARY_DIR}/cmake/${package_name}-config.cmake"
@ONLY
)

# copy config file for find_package to find
install(
FILES "${PROJECT_BINARY_DIR}/cmake/${package_name}-config.cmake"
DESTINATION "${PATOMIC_INSTALL_CMAKEDIR}"
COMPONENT ${package_name}-development
)

# create version file for consumer to check version in CMake
write_basic_package_version_file(
"${package_name}-config-version.cmake"
COMPATIBILITY SameMajorVersion # a.k.a. SemVer
)

# copy version file for find_package to find for version check
install(
FILES "${PROJECT_BINARY_DIR}/${package_name}-config-version.cmake"
DESTINATION "${PATOMIC_INSTALL_CMAKEDIR}"
COMPONENT ${package_name}-development
)

# create targets file included by config file with targets for consumers
install(
EXPORT ${package_name}-targets
NAMESPACE patomic::
DESTINATION "${PATOMIC_INSTALL_CMAKEDIR}"
COMPONENT ${package_name}-development
)

# support packaging library
if(PROJECT_IS_TOP_LEVEL)
include(CPack)
endif()
116 changes: 116 additions & 0 deletions cmake/OptionVariables.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# included further down to avoid interfering with our cache variables
# include(GNUInstallDirs)


# ---- Options Summary ----

# ------------------------------------------------------------------------------------------------
# | Option | Availability | Default |
# |==============================|===============|===============================================|
# | BUILD_SHARED_LIBS | Top-Level | OFF |
# | BUILD_TESTING | Top-Level | OFF |
# | CMAKE_INSTALL_INCLUDEDIR | Top-Level | include/${package_name}-${PROJECT_VERSION} |
# |------------------------------|---------------|-----------------------------------------------|
# | PATOMIC_BUILD_SHARED | Always | ${BUILD_SHARED_LIBS} |
# | PATOMIC_BUILD_TESTING | Always | ${BUILD_TESTING} |
# | PATOMIC_INCLUDES_WITH_SYSTEM | Not Top-Level | ON |
# | PATOMIC_INSTALL_CMAKEDIR | Always | ${CMAKE_INSTALL_LIBDIR}/cmake/${package_name} |
# ------------------------------------------------------------------------------------------------


# ---- Build Shared ----

# Sometimes it's useful to be able to single out a dependency to be built as
# static or shared, even if obtained from source.
if(PROJECT_IS_TOP_LEVEL)
option(BUILD_SHARED_LIBS "Build shared libs" OFF)
endif()
option(
PATOMIC_BUILD_SHARED
"Override BUILD_SHARED_LIBS for ${package_name} library"
${BUILD_SHARED_LIBS}
)
mark_as_advanced(PATOMIC_BUILD_SHARED)
set(build_type STATIC)
if(PATOMIC_BUILD_SHARED)
set(build_type SHARED)
endif()


# ---- Warning Guard ----

# target_include_directories with 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(warning_guard "")
if(NOT PROJECT_IS_TOP_LEVEL)
option(
PATOMIC_INCLUDES_WITH_SYSTEM
"Use SYSTEM modifier for ${package_name}'s includes, disabling warnings"
ON
)
mark_as_advanced(PATOMIC_INCLUDES_WITH_SYSTEM)
if(PATOMIC_INCLUDES_WITH_SYSTEM)
set(warning_guard SYSTEM)
endif()
endif()


# ---- Enable Testing ----

# By default tests aren't enabled even with BUILD_TESTING unless the library is
# built as a top level project.
# This is in order to cut down on unnecessary compile times, since it's unlikely
# for users to want to run the tests of their dependencies.
if(PROJECT_IS_TOP_LEVEL)
option(BUILD_TESTING "Build tests" OFF)
endif()
option(
PATOMIC_BUILD_TESTING
"Override BUILD_TESTING for ${package_name} library"
${BUILD_TESTING}
)
mark_as_advanced(PATOMIC_BUILD_TESTING)


# ---- Install Include Directory ----

# Adds an extra directory to the include path by default, so that when you link
# against the target, you get `<prefix>/include/<package>-X.Y.Z` added to your
# include paths rather than `<prefix/include`.
# This doesn't affect include paths used by consumers of this project.
# The variable type is STRING rather than PATH, because otherwise passing
# -DCMAKE_INSTALL_INCLUDEDIR=include on the command line would expand to an
# absolute path with the base being the current CMake directory, leading to
# unexpected errors.
if(PROJECT_IS_TOP_LEVEL)
set(
CMAKE_INSTALL_INCLUDEDIR "include/${package_name}-${PROJECT_VERSION}"
CACHE STRING ""
)
# marked as advanced in GNUInstallDirs version, so we follow their lead
mark_as_advanced(CMAKE_INSTALL_INCLUDEDIR)
endif()


# do not include earlier or we can't set CMAKE_INSTALL_INCLUDEDIR above
# required for CMAKE_INSTALL_LIBDIR below
include(GNUInstallDirs)


# ---- Install CMake Directory ----

# This allows package maintainers to freely override the installation path for
# the CMake configs.
# This doesn't affect include paths used by consumers of this project.
# The variable type is STRING rather than PATH, because otherwise passing
# -DPATOMIC_INSTALL_CMAKEDIR=lib/cmake on the command line would expand to an
# absolute path with the base being the current CMake directory, leading to
# unexpected errors.
set(
PATOMIC_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${package_name}"
CACHE STRING "CMake package config location relative to the install prefix"
)
# depends on CMAKE_INSTALL_LIBDIR which is marked as advanced in GNUInstallDirs
mark_as_advanced(PATOMIC_INSTALL_CMAKEDIR)
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions cmake/in/patomic-config.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# init @ variables before doing anything else
@PACKAGE_INIT@

# no dependencies or special setup

# we cannot modify an existing IMPORT target
if(NOT TARGET patomic::patomic)

# import targets
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")

endif()
1 change: 0 additions & 1 deletion cmake/util/InstallConfig.cmake

This file was deleted.

63 changes: 0 additions & 63 deletions cmake/util/InstallRules.cmake

This file was deleted.

Loading

0 comments on commit e15fe7e

Please sign in to comment.