1
+ # @param SOURCE_LIST The list of source files to check.
2
+ # @param IS_HEADER_ONLY Returns whether the list only contains header files.
3
+ # @param NON_HEADER_FILE Returns the name of the first, if any, non-header file.
4
+ function (check_if_header_only SOURCE_LIST IS_HEADER_ONLY NON_HEADER_FILE)
5
+ set (_LOCAL_SOURCE_LIST "${${SOURCE_LIST} }" )
6
+ foreach (src_file IN LISTS _LOCAL_SOURCE_LIST)
7
+ if (NOT ${src_file} MATCHES ".*\\ .(h|hpp)" )
8
+ set (${IS_HEADER_ONLY} FALSE PARENT_SCOPE)
9
+ set (${NON_HEADER_FILE} ${src_file} PARENT_SCOPE)
10
+ return ()
11
+ endif ()
12
+ endforeach ()
13
+ set (${IS_HEADER_ONLY} TRUE PARENT_SCOPE)
14
+ set (${NON_HEADER_FILE} "" PARENT_SCOPE)
15
+ endfunction ()
16
+
1
17
# Adds a c++20 interface library in the subdirectory NAME with the target NAME and alias
2
18
# NAMESPACE::NAME. Libraries with multiple levels of namespace nesting are currently not supported.
3
19
#
6
22
#
7
23
# @param NAME
8
24
# @param NAMESPACE
25
+ # @param PUBLIC_HEADERS
26
+ # @param PRIVATE_SOURCES
27
+ # @param PUBLIC_LINK_LIBRARIES
28
+ # @param PRIVATE_LINK_LIBRARIES
9
29
# @parms TESTS_SOURCES
10
- # @param [LIB_BUILD_INTERFACE="${PROJECT_SOURCE_DIR}/src"] The list of include paths for building
11
- # the library and for external projects that link against it via the add_subdirectory() function.
30
+ # @param [BUILD_INCLUDE_DIR="${PROJECT_SOURCE_DIR}/src"] The list of include paths for building the
31
+ # library and for external projects that builds `ystdlib-cpp` as a CMAKE subproject via the
32
+ # add_subdirectory() function.
12
33
function (cpp_library)
13
34
set (options "" )
14
35
set (oneValueArgs
15
36
NAME
16
37
NAMESPACE
17
38
)
18
39
set (multiValueArgs
40
+ PUBLIC_HEADERS
41
+ PRIVATE_SOURCES
42
+ PUBLIC_LINK_LIBRARIES
43
+ PRIVATE_LINK_LIBRARIES
19
44
TESTS_SOURCES
20
- LIB_BUILD_INTERFACE
45
+ BUILD_INCLUDE_DIR
21
46
)
22
47
cmake_parse_arguments (arg_cpp_lib "${options} " "${oneValueArgs} " "${multiValueArgs} " ${ARGN} )
23
48
49
+ set (_ALIAS_TARGET_NAME "${arg_cpp_lib_NAMESPACE} ::${arg_cpp_lib_NAME} " )
50
+
24
51
# TODO: Turn this into a function for handling other optional params that have default values.
25
- if ("LIB_BUILD_INTERFACE" IN_LIST arg_cpp_lib_KEYWORDS_MISSING_VALUES)
52
+ if ("BUILD_INCLUDE_DIR" IN_LIST arg_cpp_lib_KEYWORDS_MISSING_VALUES)
53
+ message (FATAL_ERROR "Missing build interface list for ${_ALIAS_TARGET_NAME} ." )
54
+ elseif (NOT DEFINED arg_cpp_lib_BUILD_INCLUDE_DIR)
55
+ set (arg_cpp_lib_BUILD_INCLUDE_DIR "${PROJECT_SOURCE_DIR} /src" )
56
+ endif ()
57
+
58
+ check_if_header_only(arg_cpp_lib_PUBLIC_HEADERS _IS_VALID_INTERFACE _INVALID_HEADER_FILE)
59
+ if (NOT _IS_VALID_INTERFACE)
26
60
message (
27
61
FATAL_ERROR
28
- "Missing build interface list for ${arg_cpp_lib_NAMESPACE} ::${arg_cpp_lib_NAME} ."
62
+ "Invalid interface header file ${_INVALID_HEADER_FILE} for ${_ALIAS_TARGET_NAME} ."
63
+ )
64
+ endif ()
65
+
66
+ check_if_header_only(arg_cpp_lib_PRIVATE_SOURCES _IS_INTERFACE_LIB _)
67
+ if (_IS_INTERFACE_LIB)
68
+ add_library (${arg_cpp_lib_NAME} INTERFACE )
69
+ target_include_directories (
70
+ ${arg_cpp_lib_NAME}
71
+ INTERFACE
72
+ "$<BUILD_INTERFACE:${arg_cpp_lib_BUILD_INCLUDE_DIR} >"
73
+ )
74
+ target_compile_features (${arg_cpp_lib_NAME} INTERFACE cxx_std_20)
75
+ else ()
76
+ # The library type is specified by `BUILD_SHARED_LIBS` if it is defined. Otherwise, the type
77
+ # defaults to static.
78
+ add_library (${arg_cpp_lib_NAME} )
79
+ target_sources (
80
+ ${arg_cpp_lib_NAME}
81
+ PRIVATE
82
+ ${arg_cpp_lib_PUBLIC_HEADERS}
83
+ ${arg_cpp_lib_PRIVATE_SOURCES}
84
+ )
85
+ target_include_directories (
86
+ ${arg_cpp_lib_NAME}
87
+ PUBLIC
88
+ "$<BUILD_INTERFACE:${arg_cpp_lib_BUILD_INCLUDE_DIR} >"
29
89
)
30
- elseif (NOT DEFINED arg_cpp_lib_LIB_BUILD_INTERFACE)
31
- set (arg_cpp_lib_LIB_BUILD_INTERFACE "${PROJECT_SOURCE_DIR} /src" )
90
+ target_compile_features (${arg_cpp_lib_NAME} PUBLIC cxx_std_20)
32
91
endif ()
33
92
34
- # Build interface library
35
- add_library (${arg_cpp_lib_NAME} INTERFACE )
36
- target_include_directories (
93
+ target_link_libraries (
37
94
${arg_cpp_lib_NAME}
38
- INTERFACE
39
- "$<BUILD_INTERFACE:${arg_cpp_lib_LIB_BUILD_INTERFACE} >"
95
+ PUBLIC
96
+ ${arg_cpp_lib_PUBLIC_LINK_LIBRARIES}
97
+ PRIVATE
98
+ ${arg_cpp_lib_PRIVATE_LINK_LIBRARIES}
40
99
)
41
- target_compile_features (${arg_cpp_lib_NAME} INTERFACE cxx_std_20)
42
- add_library (${arg_cpp_lib_NAMESPACE} ::${arg_cpp_lib_NAME} ALIAS ${arg_cpp_lib_NAME} )
100
+ add_library (${_ALIAS_TARGET_NAME} ALIAS ${arg_cpp_lib_NAME} )
43
101
44
102
if (YSTDLIB_CPP_ENABLE_TESTS)
45
103
# Build library-specific unit test target
@@ -50,7 +108,7 @@ function(cpp_library)
50
108
${_UNIT_TEST_TARGET}
51
109
PRIVATE
52
110
Catch2::Catch2WithMain
53
- ${arg_cpp_lib_NAMESPACE} :: ${arg_cpp_lib_NAME }
111
+ ${_ALIAS_TARGET_NAME }
54
112
)
55
113
target_compile_features (${_UNIT_TEST_TARGET} PRIVATE cxx_std_20)
56
114
set_property (
@@ -63,10 +121,6 @@ function(cpp_library)
63
121
64
122
# Link against unified unit test
65
123
target_sources (${UNIFIED_UNIT_TEST_TARGET} PRIVATE ${arg_cpp_lib_TESTS_SOURCES} )
66
- target_link_libraries (
67
- ${UNIFIED_UNIT_TEST_TARGET}
68
- PRIVATE
69
- ${arg_cpp_lib_NAMESPACE} ::${arg_cpp_lib_NAME}
70
- )
124
+ target_link_libraries (${UNIFIED_UNIT_TEST_TARGET} PRIVATE ${_ALIAS_TARGET_NAME} )
71
125
endif ()
72
126
endfunction ()
0 commit comments