Skip to content

Commit e7fb272

Browse files
authored
Merge pull request #116
Add Dependency Build Instruction File Handling
2 parents aca8e57 + 428e817 commit e7fb272

File tree

2 files changed

+176
-80
lines changed

2 files changed

+176
-80
lines changed

share/c/cmake/DependencyUtil.cmake

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,29 @@ include(FetchContent)
2626
# either Git repositories or source archive files. It is a thin wrapper
2727
# around the FetchContent machinery provided by CMake. By using this function,
2828
# a dependency becomes available to the underlying project in a
29-
# declarative way. There are three steps involved in processing a dependency:
29+
# declarative way. There are four steps involved in processing a dependency:
3030
# First, the specified dependency is passed to the CMake FetchContent_Declare()
3131
# function. The caller does not need to take care of the different arguments
3232
# as used by FetchContent_Declare(), as they are handled entirely by
3333
# this function. Secondly, an additional configuration file is potentially
3434
# included by this function. The purpose of such a file is to configure the
3535
# dependency to be made available to the underlying project. The configuration
36-
# file can contain arbitrary CMake code. Lastly, the dependency is made
36+
# file can contain arbitrary CMake code. Thirdly, the dependency is made
3737
# available by means of the CMake FetchContent_MakeAvailable() function.
38+
# This steps makes the declared targets of the dependency available to
39+
# the underlying project. Lastly, an additional build file is potentially
40+
# included by this function. This is similar to the configuration step, but
41+
# it allows a project to potentially manipulate the dependency target and its
42+
# build directly.
3843
#
39-
# The configuration file for a dependency is an ordinary CMake file, i.e. it
40-
# must contain syntactically valid CMake code. Each dependency configuration
41-
# file is included by this function. It can be used to set variables or do any
42-
# other kind of processing in order to properly configure the dependency to
43-
# be used by the underlying project. If no concrete config file is
44-
# specified by the DEPENDENCY_CONFIG_FILE argument, then this function will
45-
# look for a dependency config file in the "cmake" directory relative
44+
# The configuration and build files for a dependency are ordinary CMake files,
45+
# i.e. it must contain syntactically valid CMake code. Each dependency
46+
# configuration and build file included by this function if found.
47+
# The configuration file can be used to set variables or do any other kind of
48+
# processing in order to properly configure the dependency to be used by the
49+
# underlying project. If no concrete config file is specified by
50+
# the DEPENDENCY_CONFIG_FILE argument, then this function will look for a
51+
# dependency config file in the "cmake" directory relative
4652
# to CMAKE_CURRENT_SOURCE_DIR. The corresponding config file must be
4753
# named "Config${DEPENDENCY_NAME}.cmake", where ${DEPENDENCY_NAME} is the
4854
# value of the mandatory dependency name argument. Please note that the
@@ -51,6 +57,9 @@ include(FetchContent)
5157
# concrete dependency is named "mydep", then the conventional config file
5258
# has to be named "ConfigMydep.cmake". The inclusion of any dependency config
5359
# file can be disabled by using the DEPENDENCY_NO_CONFIG option.
60+
# The same convention applies to the build file, with a varying file prefix
61+
# of "Build*" instead of "Config*". For example, a conventional build file
62+
# might be named "BuildMydep.cmake".
5463
#
5564
# Every dependency has a scope. A dependency is only used if its scope
5665
# is active. The following scopes are available: "ANY", "RELEASE", "TEST"
@@ -134,6 +143,11 @@ include(FetchContent)
134143
# to configure the dependency. This argument can optionally be used to
135144
# specify a file which deviates from the convention.
136145
#
146+
# DEPENDENCY_BUILD_FILE:
147+
# The relative path to the file containing CMake instructions to be used
148+
# to build the dependency. This argument can optionally be used to
149+
# specify a file which deviates from the convention.
150+
#
137151
# [options]
138152
#
139153
# DEPENDENCY_QUIET:
@@ -181,6 +195,7 @@ function(dependency)
181195
DEPENDENCY_SCOPE
182196
DEPENDENCY_FILE_HASH
183197
DEPENDENCY_CONFIG_FILE
198+
DEPENDENCY_BUILD_FILE
184199
)
185200
set(multiValueArgs "")
186201

@@ -283,6 +298,46 @@ function(dependency)
283298
set(DEP_ARGS_DEPENDENCY_RESOURCE "${_DEP_BASE_URL}/${_DEP_SRC_RES}")
284299
endif()
285300

301+
# Set default conventional config and build files
302+
string(
303+
TOLOWER
304+
${DEP_ARGS_DEPENDENCY_NAME}
305+
DEPENDENCY_NAME_LOWER
306+
)
307+
string(
308+
SUBSTRING
309+
${DEPENDENCY_NAME_LOWER} 1 -1
310+
DEPENDENCY_NAME_LOWER
311+
)
312+
string(
313+
SUBSTRING
314+
${DEP_ARGS_DEPENDENCY_NAME} 0 1
315+
DEPENDENCY_NAME_FIRST
316+
)
317+
string(
318+
TOUPPER
319+
${DEPENDENCY_NAME_FIRST}
320+
DEPENDENCY_NAME_FIRST
321+
)
322+
set(DEPENDENCY_DEFAULT_CONFIG_FILE "cmake/Config")
323+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ${DEPENDENCY_NAME_FIRST})
324+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ${DEPENDENCY_NAME_LOWER})
325+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ".cmake")
326+
string(
327+
PREPEND
328+
DEPENDENCY_DEFAULT_CONFIG_FILE
329+
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
330+
)
331+
set(DEPENDENCY_DEFAULT_BUILD_FILE "cmake/Build")
332+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ${DEPENDENCY_NAME_FIRST})
333+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ${DEPENDENCY_NAME_LOWER})
334+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ".cmake")
335+
string(
336+
PREPEND
337+
DEPENDENCY_DEFAULT_BUILD_FILE
338+
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
339+
)
340+
286341
set(OPT_DEP_CACHE_SRC_PATH "")
287342
set(OPT_DEP_GIT_SHALLOW "GIT_SHALLOW")
288343
set(DEP_USE_GIT_SHALLOW ON)
@@ -397,41 +452,34 @@ function(dependency)
397452
endif()
398453
else()
399454
# Use the conventional file
400-
string(
401-
TOLOWER
402-
${DEP_ARGS_DEPENDENCY_NAME}
403-
DEPENDENCY_NAME_LOWER
404-
)
405-
string(
406-
SUBSTRING
407-
${DEPENDENCY_NAME_LOWER} 1 -1
408-
DEPENDENCY_NAME_LOWER
409-
)
410-
string(
411-
SUBSTRING
412-
${DEP_ARGS_DEPENDENCY_NAME} 0 1
413-
DEPENDENCY_NAME_FIRST
414-
)
415-
string(
416-
TOUPPER
417-
${DEPENDENCY_NAME_FIRST}
418-
DEPENDENCY_NAME_FIRST
419-
)
420-
set(DEPENDENCY_CONFIG_FILE "cmake/Config")
421-
string(APPEND DEPENDENCY_CONFIG_FILE ${DEPENDENCY_NAME_FIRST})
422-
string(APPEND DEPENDENCY_CONFIG_FILE ${DEPENDENCY_NAME_LOWER})
423-
string(APPEND DEPENDENCY_CONFIG_FILE ".cmake")
424-
string(
425-
PREPEND
426-
DEPENDENCY_CONFIG_FILE
427-
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
428-
)
429-
if(EXISTS "${DEPENDENCY_CONFIG_FILE}")
430-
include("${DEPENDENCY_CONFIG_FILE}")
455+
if(EXISTS "${DEPENDENCY_DEFAULT_CONFIG_FILE}")
456+
include("${DEPENDENCY_DEFAULT_CONFIG_FILE}")
431457
endif()
432458
endif()
433459
endif()
434460

435461
FetchContent_MakeAvailable(${DEP_ARGS_DEPENDENCY_NAME})
436462

463+
# Check if a build file needs to be included
464+
if(DEFINED DEP_ARGS_DEPENDENCY_BUILD_FILE)
465+
set(
466+
DEPENDENCY_BUILD_FILE
467+
"${CMAKE_CURRENT_SOURCE_DIR}/${DEP_ARGS_DEPENDENCY_BUILD_FILE}"
468+
)
469+
if(EXISTS "${DEPENDENCY_BUILD_FILE}")
470+
include("${DEPENDENCY_BUILD_FILE}")
471+
else()
472+
message(
473+
WARNING
474+
"The specified build file for "
475+
"dependency ${DEP_ARGS_DEPENDENCY_NAME} "
476+
"was not found: '${DEPENDENCY_BUILD_FILE}'"
477+
)
478+
endif()
479+
else()
480+
# Use the conventional file
481+
if(EXISTS "${DEPENDENCY_DEFAULT_BUILD_FILE}")
482+
include("${DEPENDENCY_DEFAULT_BUILD_FILE}")
483+
endif()
484+
endif()
437485
endfunction()

share/cpp/cmake/DependencyUtil.cmake

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,29 @@ include(FetchContent)
2626
# either Git repositories or source archive files. It is a thin wrapper
2727
# around the FetchContent machinery provided by CMake. By using this function,
2828
# a dependency becomes available to the underlying project in a
29-
# declarative way. There are three steps involved in processing a dependency:
29+
# declarative way. There are four steps involved in processing a dependency:
3030
# First, the specified dependency is passed to the CMake FetchContent_Declare()
3131
# function. The caller does not need to take care of the different arguments
3232
# as used by FetchContent_Declare(), as they are handled entirely by
3333
# this function. Secondly, an additional configuration file is potentially
3434
# included by this function. The purpose of such a file is to configure the
3535
# dependency to be made available to the underlying project. The configuration
36-
# file can contain arbitrary CMake code. Lastly, the dependency is made
36+
# file can contain arbitrary CMake code. Thirdly, the dependency is made
3737
# available by means of the CMake FetchContent_MakeAvailable() function.
38+
# This steps makes the declared targets of the dependency available to
39+
# the underlying project. Lastly, an additional build file is potentially
40+
# included by this function. This is similar to the configuration step, but
41+
# it allows a project to potentially manipulate the dependency target and its
42+
# build directly.
3843
#
39-
# The configuration file for a dependency is an ordinary CMake file, i.e. it
40-
# must contain syntactically valid CMake code. Each dependency configuration
41-
# file is included by this function. It can be used to set variables or do any
42-
# other kind of processing in order to properly configure the dependency to
43-
# be used by the underlying project. If no concrete config file is
44-
# specified by the DEPENDENCY_CONFIG_FILE argument, then this function will
45-
# look for a dependency config file in the "cmake" directory relative
44+
# The configuration and build files for a dependency are ordinary CMake files,
45+
# i.e. it must contain syntactically valid CMake code. Each dependency
46+
# configuration and build file included by this function if found.
47+
# The configuration file can be used to set variables or do any other kind of
48+
# processing in order to properly configure the dependency to be used by the
49+
# underlying project. If no concrete config file is specified by
50+
# the DEPENDENCY_CONFIG_FILE argument, then this function will look for a
51+
# dependency config file in the "cmake" directory relative
4652
# to CMAKE_CURRENT_SOURCE_DIR. The corresponding config file must be
4753
# named "Config${DEPENDENCY_NAME}.cmake", where ${DEPENDENCY_NAME} is the
4854
# value of the mandatory dependency name argument. Please note that the
@@ -51,6 +57,9 @@ include(FetchContent)
5157
# concrete dependency is named "mydep", then the conventional config file
5258
# has to be named "ConfigMydep.cmake". The inclusion of any dependency config
5359
# file can be disabled by using the DEPENDENCY_NO_CONFIG option.
60+
# The same convention applies to the build file, with a varying file prefix
61+
# of "Build*" instead of "Config*". For example, a conventional build file
62+
# might be named "BuildMydep.cmake".
5463
#
5564
# Every dependency has a scope. A dependency is only used if its scope
5665
# is active. The following scopes are available: "ANY", "RELEASE", "TEST"
@@ -134,6 +143,11 @@ include(FetchContent)
134143
# to configure the dependency. This argument can optionally be used to
135144
# specify a file which deviates from the convention.
136145
#
146+
# DEPENDENCY_BUILD_FILE:
147+
# The relative path to the file containing CMake instructions to be used
148+
# to build the dependency. This argument can optionally be used to
149+
# specify a file which deviates from the convention.
150+
#
137151
# [options]
138152
#
139153
# DEPENDENCY_QUIET:
@@ -181,6 +195,7 @@ function(dependency)
181195
DEPENDENCY_SCOPE
182196
DEPENDENCY_FILE_HASH
183197
DEPENDENCY_CONFIG_FILE
198+
DEPENDENCY_BUILD_FILE
184199
)
185200
set(multiValueArgs "")
186201

@@ -283,6 +298,46 @@ function(dependency)
283298
set(DEP_ARGS_DEPENDENCY_RESOURCE "${_DEP_BASE_URL}/${_DEP_SRC_RES}")
284299
endif()
285300

301+
# Set default conventional config and build files
302+
string(
303+
TOLOWER
304+
${DEP_ARGS_DEPENDENCY_NAME}
305+
DEPENDENCY_NAME_LOWER
306+
)
307+
string(
308+
SUBSTRING
309+
${DEPENDENCY_NAME_LOWER} 1 -1
310+
DEPENDENCY_NAME_LOWER
311+
)
312+
string(
313+
SUBSTRING
314+
${DEP_ARGS_DEPENDENCY_NAME} 0 1
315+
DEPENDENCY_NAME_FIRST
316+
)
317+
string(
318+
TOUPPER
319+
${DEPENDENCY_NAME_FIRST}
320+
DEPENDENCY_NAME_FIRST
321+
)
322+
set(DEPENDENCY_DEFAULT_CONFIG_FILE "cmake/Config")
323+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ${DEPENDENCY_NAME_FIRST})
324+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ${DEPENDENCY_NAME_LOWER})
325+
string(APPEND DEPENDENCY_DEFAULT_CONFIG_FILE ".cmake")
326+
string(
327+
PREPEND
328+
DEPENDENCY_DEFAULT_CONFIG_FILE
329+
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
330+
)
331+
set(DEPENDENCY_DEFAULT_BUILD_FILE "cmake/Build")
332+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ${DEPENDENCY_NAME_FIRST})
333+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ${DEPENDENCY_NAME_LOWER})
334+
string(APPEND DEPENDENCY_DEFAULT_BUILD_FILE ".cmake")
335+
string(
336+
PREPEND
337+
DEPENDENCY_DEFAULT_BUILD_FILE
338+
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
339+
)
340+
286341
set(OPT_DEP_CACHE_SRC_PATH "")
287342
set(OPT_DEP_GIT_SHALLOW "GIT_SHALLOW")
288343
set(DEP_USE_GIT_SHALLOW ON)
@@ -397,41 +452,34 @@ function(dependency)
397452
endif()
398453
else()
399454
# Use the conventional file
400-
string(
401-
TOLOWER
402-
${DEP_ARGS_DEPENDENCY_NAME}
403-
DEPENDENCY_NAME_LOWER
404-
)
405-
string(
406-
SUBSTRING
407-
${DEPENDENCY_NAME_LOWER} 1 -1
408-
DEPENDENCY_NAME_LOWER
409-
)
410-
string(
411-
SUBSTRING
412-
${DEP_ARGS_DEPENDENCY_NAME} 0 1
413-
DEPENDENCY_NAME_FIRST
414-
)
415-
string(
416-
TOUPPER
417-
${DEPENDENCY_NAME_FIRST}
418-
DEPENDENCY_NAME_FIRST
419-
)
420-
set(DEPENDENCY_CONFIG_FILE "cmake/Config")
421-
string(APPEND DEPENDENCY_CONFIG_FILE ${DEPENDENCY_NAME_FIRST})
422-
string(APPEND DEPENDENCY_CONFIG_FILE ${DEPENDENCY_NAME_LOWER})
423-
string(APPEND DEPENDENCY_CONFIG_FILE ".cmake")
424-
string(
425-
PREPEND
426-
DEPENDENCY_CONFIG_FILE
427-
"${CMAKE_CURRENT_SOURCE_DIR}" "/"
428-
)
429-
if(EXISTS "${DEPENDENCY_CONFIG_FILE}")
430-
include("${DEPENDENCY_CONFIG_FILE}")
455+
if(EXISTS "${DEPENDENCY_DEFAULT_CONFIG_FILE}")
456+
include("${DEPENDENCY_DEFAULT_CONFIG_FILE}")
431457
endif()
432458
endif()
433459
endif()
434460

435461
FetchContent_MakeAvailable(${DEP_ARGS_DEPENDENCY_NAME})
436462

463+
# Check if a build file needs to be included
464+
if(DEFINED DEP_ARGS_DEPENDENCY_BUILD_FILE)
465+
set(
466+
DEPENDENCY_BUILD_FILE
467+
"${CMAKE_CURRENT_SOURCE_DIR}/${DEP_ARGS_DEPENDENCY_BUILD_FILE}"
468+
)
469+
if(EXISTS "${DEPENDENCY_BUILD_FILE}")
470+
include("${DEPENDENCY_BUILD_FILE}")
471+
else()
472+
message(
473+
WARNING
474+
"The specified build file for "
475+
"dependency ${DEP_ARGS_DEPENDENCY_NAME} "
476+
"was not found: '${DEPENDENCY_BUILD_FILE}'"
477+
)
478+
endif()
479+
else()
480+
# Use the conventional file
481+
if(EXISTS "${DEPENDENCY_DEFAULT_BUILD_FILE}")
482+
include("${DEPENDENCY_DEFAULT_BUILD_FILE}")
483+
endif()
484+
endif()
437485
endfunction()

0 commit comments

Comments
 (0)