Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions CMake/ystdlib-cpp-helpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,43 @@ function(check_if_header_only SOURCE_LIST IS_HEADER_ONLY NON_HEADER_FILE)
set(${NON_HEADER_FILE} "" PARENT_SCOPE)
endfunction()

# Defines a CMake interface target to expose the include path resolution directory of a third-party
# library.

# The created target can be linked against `ystdlib-cpp` libraries to ensure
# consistent header resolution across dependent projects.
#
# This is useful for third-party libraries that do not properly configure target-based include paths
# using `target_include_directories($<INSTALL_INTERFACE>)`.
#
# Call this function after using the `find_package()` call so that `<LIB_NAME>_ROOT` is defined.
#
# @param LIB_NAME The base name of the library (expects <LIB_NAME>_ROOT to be defined).
# @param [DEP_LIST] Optional list of interface dependencies (e.g., nested include targets).
function(add_lib_include_interface_target)
set(options "")
set(oneValueArgs LIB_NAME)
set(multiValueArgs DEP_LIST)
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

# Extract path to package library installation
set(_LIB_ROOT_PATH_VAR "${arg_LIB_NAME}_ROOT")
if(NOT DEFINED ${_LIB_ROOT_PATH_VAR})
message(FATAL_ERROR "${arg_LIB_NAME} install path `${_LIB_ROOT_PATH_VAR}` is not defined.")
endif()
set(_LIB_ROOT_PATH "${${_LIB_ROOT_PATH_VAR}}")

set(_TARGET_NAME "${arg_LIB_NAME}_include")
add_library(${_TARGET_NAME} INTERFACE)
add_library(${arg_LIB_NAME}::${_TARGET_NAME} ALIAS ${_TARGET_NAME})
target_include_directories(
${_TARGET_NAME}
INTERFACE
"$<BUILD_INTERFACE:${_LIB_ROOT_PATH}/include>"
)
target_link_libraries(${_TARGET_NAME} INTERFACE ${arg_DEP_LIST})
endfunction()

# Adds a c++20 interface library in the subdirectory NAME with the target NAME and alias
# NAMESPACE::NAME. Libraries with multiple levels of namespace nesting are currently not supported.
#
Expand Down Expand Up @@ -65,12 +102,19 @@ function(cpp_library)

check_if_header_only(arg_cpp_lib_PRIVATE_SOURCES _IS_INTERFACE_LIB _)
if(_IS_INTERFACE_LIB)
if(arg_cpp_lib_PRIVATE_LINK_LIBRARIES)
message(
FATAL_ERROR
"Private dependency specifications disabled for interface library target ${_ALIAS_TARGET_NAME}."
)
endif()
add_library(${arg_cpp_lib_NAME} INTERFACE)
target_include_directories(
${arg_cpp_lib_NAME}
INTERFACE
"$<BUILD_INTERFACE:${arg_cpp_lib_BUILD_INCLUDE_DIR}>"
)
target_link_libraries(${arg_cpp_lib_NAME} INTERFACE ${arg_cpp_lib_PUBLIC_LINK_LIBRARIES})
target_compile_features(${arg_cpp_lib_NAME} INTERFACE cxx_std_20)
else()
# The library type is specified by `BUILD_SHARED_LIBS` if it is defined. Otherwise, the type
Expand All @@ -87,16 +131,16 @@ function(cpp_library)
PUBLIC
"$<BUILD_INTERFACE:${arg_cpp_lib_BUILD_INCLUDE_DIR}>"
)
target_link_libraries(
${arg_cpp_lib_NAME}
PUBLIC
${arg_cpp_lib_PUBLIC_LINK_LIBRARIES}
PRIVATE
${arg_cpp_lib_PRIVATE_LINK_LIBRARIES}
)
target_compile_features(${arg_cpp_lib_NAME} PUBLIC cxx_std_20)
endif()

target_link_libraries(
${arg_cpp_lib_NAME}
PUBLIC
${arg_cpp_lib_PUBLIC_LINK_LIBRARIES}
PRIVATE
${arg_cpp_lib_PRIVATE_LINK_LIBRARIES}
)
add_library(${_ALIAS_TARGET_NAME} ALIAS ${arg_cpp_lib_NAME})

if(YSTDLIB_CPP_ENABLE_TESTS)
Expand Down
17 changes: 12 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.22.1)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake)
include(ystdlib-cpp-helpers)

project(YSTDLIB_CPP LANGUAGES CXX)

set(YSTDLIB_CPP_VERSION "0.0.1" CACHE STRING "Project version.")
Expand Down Expand Up @@ -40,7 +43,7 @@ if(YSTDLIB_CPP_IS_TOP_LEVEL)
# Include dependency settings if the project isn't being included as a subproject.
# NOTE: We mark the file optional because if the user happens to have the dependencies
# installed, this file is not necessary.
include(build/deps/settings.cmake OPTIONAL)
include(build/deps/CMake/settings.cmake OPTIONAL)

# If previously undefined, `BUILD_TESTING` will be set to ON.
include(CTest)
Expand All @@ -50,8 +53,14 @@ if(BUILD_TESTING AND YSTDLIB_CPP_BUILD_TESTING)
set(YSTDLIB_CPP_ENABLE_TESTS ON)
endif()

# Import CMake helper functions
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake)
find_package(outcome REQUIRED)
if(outcome_FOUND)
message(STATUS "Found outcome.")
add_lib_include_interface_target(LIB_NAME quickcpplib)
add_lib_include_interface_target(LIB_NAME outcome DEP_LIST quickcpplib::quickcpplib_include)
else()
message(FATAL_ERROR "Could not find libraries for outcome.")
endif()

if(YSTDLIB_CPP_ENABLE_TESTS)
find_package(Catch2 3.8.0 REQUIRED)
Expand All @@ -77,6 +86,4 @@ if(YSTDLIB_CPP_ENABLE_TESTS)
catch_discover_tests(${UNIFIED_UNIT_TEST_TARGET} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/testbin)
endif()

include(ystdlib-cpp-helpers)

add_subdirectory(src/ystdlib)
5 changes: 3 additions & 2 deletions taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ vars:
G_CPP_SRC_DIR: "{{.ROOT_DIR}}/src"
G_DEPS_DIR: "{{.G_BUILD_DIR}}/deps"

# This should be kept in-sync with its usage in CMakeLists.txt
G_DEPS_CMAKE_SETTINGS_FILE: "{{.G_DEPS_DIR}}/settings.cmake"
# These should be kept in-sync with its usage in CMakeLists.txt
G_DEPS_CMAKE_SETTINGS_DIR: "{{.G_DEPS_DIR}}/CMake"
G_DEPS_CMAKE_SETTINGS_FILE: "{{.G_DEPS_CMAKE_SETTINGS_DIR}}/settings.cmake"

G_TEST_BIN_DIR: "{{.G_BUILD_DIR}}/testbin"
G_TEST_TARGET_SUFFIXES:
Expand Down
90 changes: 87 additions & 3 deletions taskfiles/deps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,56 @@ version: "3"
vars:
G_CATCH2_LIB_NAME: "Catch2"
G_CATCH2_WORK_DIR: "{{.G_DEPS_DIR}}/{{.G_CATCH2_LIB_NAME}}"
G_OUTCOME_LIB_NAME: "outcome"
G_OUTCOME_WORK_DIR: "{{.G_DEPS_DIR}}/{{.G_OUTCOME_LIB_NAME}}"
G_QUICKCPPLIB_LIB_NAME: "quickcpplib"
G_QUICKCPPLIB_WORK_DIR: "{{.G_DEPS_DIR}}/{{.G_QUICKCPPLIB_LIB_NAME}}"

tasks:
install-all:
desc: "Install all dependencies required by ystdlib-cpp."
run: "once"
cmds:
- task: "install-all-init"
- task: "install-all-run"
- task: "install-all-finish"

install-all-init:
internal: true
cmds:
- "rm -rf {{.G_DEPS_CMAKE_SETTINGS_DIR}}"
- "mkdir -p {{.G_DEPS_CMAKE_SETTINGS_DIR}}"

install-all-run:
internal: true
deps:
- "install-Catch2"
- "install-outcome"

install-all-finish:
internal: true
cmds:
- >-
for file in {{.G_DEPS_CMAKE_SETTINGS_DIR}}/*.cmake; do
if [ "$file" != "{{.G_DEPS_CMAKE_SETTINGS_FILE}}" ]; then
echo "include($file)" >> "{{.G_DEPS_CMAKE_SETTINGS_FILE}}";
fi
done

add-package-root-to-cmake-settings:
internal: true
requires:
vars:
- "NAME"
- "INSTALL_PREFIX"
cmds:
- "rm -f '{{.G_DEPS_CMAKE_SETTINGS_FILE}}'"
- >-
echo "set(
{{.G_CATCH2_LIB_NAME}}_ROOT \"{{.G_CATCH2_WORK_DIR}}/{{.G_CATCH2_LIB_NAME}}-install\"
)" >> "{{.G_DEPS_CMAKE_SETTINGS_FILE}}"
{{.NAME}}_ROOT
\"{{.INSTALL_PREFIX}}\"
CACHE PATH
\"Path to {{.NAME}} settings\"
)" >> "{{.G_DEPS_CMAKE_SETTINGS_DIR}}/{{.NAME}}.cmake"

install-Catch2:
internal: true
Expand All @@ -26,3 +64,49 @@ tasks:
WORK_DIR: "{{.G_CATCH2_WORK_DIR}}"
FILE_SHA256: "1ab2de20460d4641553addfdfe6acd4109d871d5531f8f519a52ea4926303087"
URL: "https://github.com/catchorg/Catch2/archive/refs/tags/v3.8.0.tar.gz"
- task: "add-package-root-to-cmake-settings"
vars:
NAME: "{{.G_CATCH2_LIB_NAME}}"
INSTALL_PREFIX: "{{.G_CATCH2_WORK_DIR}}/{{.G_CATCH2_LIB_NAME}}-install"

install-outcome:
internal: true
run: "once"
deps:
- "install-quickcpplib"
cmds:
- task: ":utils:cmake-install-remote-tar"
vars:
NAME: "{{.G_OUTCOME_LIB_NAME}}"
WORK_DIR: "{{.G_OUTCOME_WORK_DIR}}"
FILE_SHA256: "0382248cbb00806ce4b5f3ce6939797dc3b597c85fd3531614959e31ef488b39"
URL: "https://github.com/ned14/outcome/archive/refs/tags/v2.2.11.tar.gz"
GEN_ARGS:
- "-C {{.G_DEPS_CMAKE_SETTINGS_DIR}}/{{.G_QUICKCPPLIB_LIB_NAME}}.cmake"
- "-DBUILD_TESTING=OFF"
- "-DCMAKE_BUILD_TYPE=Release"
- "-DCMAKE_POLICY_DEFAULT_CMP0074=NEW"
- "-DCMAKE_POLICY_DEFAULT_CMP0148=OLD"
- task: "add-package-root-to-cmake-settings"
vars:
NAME: "{{.G_OUTCOME_LIB_NAME}}"
INSTALL_PREFIX: "{{.G_OUTCOME_WORK_DIR}}/{{.G_OUTCOME_LIB_NAME}}-install"

install-quickcpplib:
internal: true
run: "once"
cmds:
- task: ":utils:cmake-install-remote-tar"
vars:
NAME: "{{.G_QUICKCPPLIB_LIB_NAME}}"
WORK_DIR: "{{.G_QUICKCPPLIB_WORK_DIR}}"
FILE_SHA256: "cd1f4cd5e9580957bd9e9fabf5b9133ffe3594071a1eed6fe685d9143b961294"
URL: "https://github.com/ned14/quickcpplib/archive/master.tar.gz"
GEN_ARGS:
- "-DBUILD_TESTING=OFF"
- "-DCMAKE_BUILD_TYPE=Release"
- "-DCMAKE_POLICY_DEFAULT_CMP0148=OLD"
- task: "add-package-root-to-cmake-settings"
vars:
NAME: "{{.G_QUICKCPPLIB_LIB_NAME}}"
INSTALL_PREFIX: "{{.G_QUICKCPPLIB_WORK_DIR}}/{{.G_QUICKCPPLIB_LIB_NAME}}-install"