Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for conditional dependencies via INCLUDE_IF keyword. #394

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ CPMAddPackage(
VERSION # The minimum version of the dependency (optional, defaults to 0)
OPTIONS # Configuration options passed to the dependency (optional)
DOWNLOAD_ONLY # If set, the project is downloaded, but not configured (optional)
INCLUDE_IF # If set, the value has to evaluate to true for the dependency to be added (optional)
[...] # Origin parameters forwarded to FetchContent_Declare, see below
)
```
Expand Down
76 changes: 75 additions & 1 deletion cmake/CPM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ endfunction()

# Find a package locally or fallback to CPMAddPackage
function(CPMFindPackage)
set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS)
set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS INCLUDE_IF)

cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "" ${ARGN})

Expand All @@ -272,6 +272,33 @@ function(CPMFindPackage)
endif()
endif()

if(DEFINED CPM_ARGS_INCLUDE_IF)

# Filter out INCLUDE_IF from arguments
cpm_remove_one_value_arg(INCLUDE_IF ARGN ${ARGN})
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function currently assumes that the user has always supplied a value for INCLUDE_IF.
That might be okay, but for CMake 3.15 and newer, we could also check if INCLUDE_IF is not in CPM_ARGS_KEYWORDS_MISSING_VALUES and otherwise inform this function about the fact that there is no value to be removed (see cmake_parse_arguments docs.


# If INCLUDE_IF evaluates to false, do not add the package, but do add it to the package lock
# and register it.
if(NOT CPM_ARGS_INCLUDE_IF)
CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")
if(CPM_PACKAGE_LOCK_ENABLED)
if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)
cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
elseif(CPM_ARGS_SOURCE_DIR)
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory")
else()
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
endif()
endif()

message(
STATUS
"${CPM_INDENT} skipping package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (INCLUDE_IF: ${CPM_ARGS_INCLUDE_IF})"
)
return()
endif()
endif()

set(downloadPackage ${CPM_DOWNLOAD_ALL})
if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME})
set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}})
Expand Down Expand Up @@ -495,6 +522,25 @@ function(cpm_override_fetchcontent contentName)
set_property(GLOBAL PROPERTY ${propertyName} TRUE)
endfunction()

# filter out a one value keyword and its value from a list of arguments
function(cpm_remove_one_value_arg KEYWORD OUTPUT_VAR)
# Always start with a copy of the data
set(RESULT ${ARGN})

# Find the keyword location
list(FIND RESULT ${KEYWORD} KEYWORD_INDEX)
if(KEYWORD_INDEX GREATER_EQUAL 0)
# Keyword found; remove data at the same index twice to get rid of the keyword and its value
list(REMOVE_AT RESULT ${KEYWORD_INDEX})
list(REMOVE_AT RESULT ${KEYWORD_INDEX})
endif()

set(${OUTPUT_VAR}
${RESULT}
PARENT_SCOPE
)
endfunction()

# Download and add a package from source
function(CPMAddPackage)
cpm_set_policies()
Expand Down Expand Up @@ -524,6 +570,7 @@ function(CPMAddPackage)
GIT_SHALLOW
EXCLUDE_FROM_ALL
SOURCE_SUBDIR
INCLUDE_IF
)

set(multiValueArgs URL OPTIONS)
Expand All @@ -538,6 +585,33 @@ function(CPMAddPackage)
endif()
endif()

if(DEFINED CPM_ARGS_INCLUDE_IF)

# Filter out INCLUDE_IF from arguments
cpm_remove_one_value_arg(INCLUDE_IF ARGN ${ARGN})

# If INCLUDE_IF evaluates to false, do not add the package, but do add it to the package lock
# and register it.
if(NOT CPM_ARGS_INCLUDE_IF)
CPMRegisterPackage("${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}")
if(CPM_PACKAGE_LOCK_ENABLED)
if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)
cpm_add_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
elseif(CPM_ARGS_SOURCE_DIR)
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "local directory")
else()
cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} "${ARGN}")
endif()
endif()

message(
STATUS
"${CPM_INDENT} skipping package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (INCLUDE_IF: ${CPM_ARGS_INCLUDE_IF})"
)
return()
endif()
endif()

if(CPM_ARGS_DOWNLOAD_ONLY)
set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})
else()
Expand Down