Skip to content

Commit

Permalink
Make header_only_library() function (#262)
Browse files Browse the repository at this point in the history
Au is overwhelmingly built from header-only libraries.  We can make this
a lot easier to maintain with a CMake function, `header_only_library()`,
that presents an Au-centric interface.  Specifically, the function will
automatically:

- Make the target an `INTERFACE`
- Set `FILE_SET HEADERS`
- Set `BASE_DIRS` to the base Au directory

Users must provide the `HEADERS` option, and we will use those to set
the `FILES` option.  Users can optionall provide the `DEPS` option, and
we'll use it if present to populate a `target_link_libraries` call.

We also add an optional `GTEST_SRCS` argument.  If this is provided,
then we will automatically create a `_test`-suffixed target, link to the
library and to `gtest_main`, and run `gtest_discover_tests()`.  If the
test has any dependencies apart from the tested target, and GTest, they
can be supplied via an optional `GTEST_EXTRA_DEPS` argument.

Finally, we provide the option to mark a library as `INTERNAL_ONLY`. For
now, we borrow the `EXPORT_NAME` manipulation from the original CMake
branch, but we could choose to do other things later --- the important
part is marking the intent that the library is internal-only.

Helps #215.
  • Loading branch information
chiphogg authored Jul 10, 2024
1 parent eb128a9 commit 34c201b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .github/license-check/license-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"**/*.sh",
"**/*.yml",
"**/BUILD.bazel",
"**/CMakeLists.txt",
"tools/bin/au-docs-serve",
"tools/bin/buildifier",
"tools/bin/clang-format",
Expand All @@ -16,6 +17,7 @@
".envrc",
".github/**/*.yml",
"requirements.in",
"cmake/*.cmake",
"WORKSPACE"
],
"exclude": [
Expand Down Expand Up @@ -58,6 +60,9 @@
"third_party/**/*",
"tools/bazel",
"tools/bin/bazel"
],
"exclude": [
"**/CMakeLists.txt"
]
}
]
24 changes: 6 additions & 18 deletions au/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH AU_BASE_DIRECTORY)
include(../cmake/HeaderOnlyLibrary.cmake)

#
# Private implementation detail targets
#

add_library(stdx INTERFACE)
target_sources(stdx
INTERFACE
FILE_SET HEADERS
BASE_DIRS ${AU_BASE_DIRECTORY}
FILES
header_only_library(
NAME stdx
INTERNAL_ONLY
HEADERS
stdx/experimental/is_detected.hh
stdx/functional.hh
stdx/type_traits.hh
stdx/utility.hh
)

add_executable(stdx_test)
target_sources(stdx_test
PRIVATE
GTEST_SRCS
stdx/test/utility_test.cc
)
target_link_libraries(stdx_test
PRIVATE
stdx
GTest::gtest_main
)
gtest_discover_tests(stdx_test)
74 changes: 74 additions & 0 deletions cmake/HeaderOnlyLibrary.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright 2024 Aurora Operations, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

function(header_only_library)
#
# Handle argument parsing
#

set(prefix ARG)
set(noValueVars INTERNAL_ONLY)
set(singleValueVars NAME)
set(multiValueVars
HEADERS
DEPS
GTEST_SRCS
GTEST_EXTRA_DEPS
)

cmake_parse_arguments(
PARSE_ARGV 0
"${prefix}"
"${noValueVars}"
"${singleValueVars}"
"${multiValueVars}"
)

#
# Function body
#

# Add the main target.
add_library(${ARG_NAME} INTERFACE)
target_sources(
${ARG_NAME}
INTERFACE
FILE_SET HEADERS
BASE_DIRS ${CMAKE_SOURCE_DIR}
FILES ${ARG_HEADERS}
)
if (DEFINED ARG_DEPS)
target_link_libraries(${ARG_NAME} INTERFACE ${ARG_DEPS})
endif()

# If it's internal-only, change its export name accordingly.
# See: https://stackoverflow.com/a/68321274
if (ARG_INTERNAL_ONLY)
set_target_properties(${ARG_NAME} PROPERTIES EXPORT_NAME "_Au_private_${ARG_NAME}")
endif()

# Add the test, if requested.
if (DEFINED ARG_GTEST_SRCS)
add_executable("${ARG_NAME}_test")
target_sources("${ARG_NAME}_test" PRIVATE ${ARG_GTEST_SRCS})
target_link_libraries(
"${ARG_NAME}_test"
PRIVATE
${ARG_NAME}
${ARG_GTEST_EXTRA_DEPS}
GTest::gmock_main
)
gtest_discover_tests("${ARG_NAME}_test")
endif()
endfunction()

0 comments on commit 34c201b

Please sign in to comment.