-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds find_optional_dependency (#149)
* backup [skip ci] * fixes failing unit test/refactors CMaizeProject * backup [skip ci] * adds_optional_dependency * Apply suggestions from code review Co-authored-by: Zachery Crandall <[email protected]> * checks target type --------- Co-authored-by: Zachery Crandall <[email protected]>
- Loading branch information
1 parent
5d0bacd
commit 2acab9a
Showing
8 changed files
with
279 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
cmake/cmaize/user_api/dependencies/find_optional_dependency.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Copyright 2023 CMakePP | ||
# | ||
# 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. | ||
|
||
include_guard() | ||
|
||
include(cmaize/user_api/dependencies/impl_/check_optional_flag) | ||
include(cmaize/user_api/dependencies/find_dependency) | ||
|
||
#[[[ | ||
# Wraps the process of finding an optional dependency. | ||
# | ||
# Many build systems have optional dependencies. The inclusion of the dependency | ||
# is usually controlled with a flag (e.g., a variable like ``ENABLE_XXX`` for | ||
# an optional dependency ``XXX``). Because of CMake's verbose nature the logic | ||
# for whether or not the dependency is enabled is usually needed in a few | ||
# places. CMaize is capable of automatically propagating the logic for the | ||
# user, as long as the user tells CMaize the flag that controls the inclusion of | ||
# of the dependency. | ||
# | ||
# When the dependency is enabled this function essentially wraps | ||
# ``cmaize_find_dependency`` and the user should consult the documentation for | ||
# ``cmaize_find_dependency`` to understand the full set of options. When enabled | ||
# CMaize will add a compile definition to the target with the same name as the | ||
# flag (common practice for optional dependencies is to use such a definition | ||
# for enabling/disabling sections of source code). | ||
# | ||
# When the dependency is disabled this function simply creates an interface | ||
# target to serve as a placedholder for the dependency. The interface target | ||
# has no state and linking to/installing the target does nothing. | ||
# | ||
# :param name: The name of the dependency. | ||
# :type name: desc | ||
# :param flag: The variable to use as a flag. Used to name the compile | ||
# definition. | ||
# :type flag: desc | ||
# :param kwargs: Keyword arguments to forward to ``cmaize_find_dependency``. | ||
# See the documentation for ``cmaize_find_dependency`` for the full list. | ||
#]] | ||
function(cmaize_find_optional_dependency _cfod_name _cfod_flag) | ||
|
||
# N.B. ${_cfod_flag} is the variable serving as the flag and | ||
# ${${_cfod_flag}} is its value | ||
|
||
_check_optional_flag("${_cfod_flag}") | ||
|
||
if("${${_cfod_flag}}") | ||
cmaize_find_dependency("${_cfod_name}" ${ARGN}) | ||
target_compile_definitions("${_cfod_name}" INTERFACE "${_cfod_flag}") | ||
elseif(NOT TARGET "${_cfod_name}") | ||
add_library("${_cfod_name}" INTERFACE) | ||
endif() | ||
|
||
endfunction() |
File renamed without changes.
50 changes: 50 additions & 0 deletions
50
cmake/cmaize/user_api/dependencies/impl_/check_optional_flag.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Copyright 2023 CMakePP | ||
# | ||
# 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. | ||
|
||
include_guard() | ||
|
||
include(cmakepp_lang/cmakepp_lang) | ||
|
||
#[[[ | ||
# Code factorization for checking that a user passed the name of a flag. | ||
# | ||
# The various ``optional_dependency`` functions are tied to a configuration flag | ||
# which determines whether the option is enabled or not. Users need to provide | ||
# those functions with the name of the flag, NOT its value. This function wraps | ||
# the error-checking logic for ensuring that users passed the value. | ||
# | ||
# :param flag: Name of the option variable. | ||
# :type flag: desc | ||
# | ||
# :raises RUNTIME_ERROR: If ``flag`` is not the name of a variable. In | ||
# particular we check for empty strings and truth-y/false-y values. | ||
# | ||
#]] | ||
function(_check_optional_flag _cof_flag) | ||
|
||
cpp_type_of(_cof_type "${_cof_flag}") | ||
|
||
if("${_cof_flag}" STREQUAL "") | ||
cpp_raise( | ||
RUNTIME_ERROR | ||
"Expected variable serving as the flag, received an empty string" | ||
) | ||
elseif("${_cof_type}" STREQUAL "bool") | ||
cpp_raise( | ||
RUNTIME_ERROR | ||
"Expected variable serving as the flag, received boolean value." | ||
) | ||
endif() | ||
|
||
endfunction() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
tests/cmaize/user_api/dependencies/impl_/test_check_optional_flag.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Copyright 2023 CMakePP | ||
# | ||
# 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. | ||
|
||
include(cmake_test/cmake_test) | ||
include(cmaize/user_api/dependencies/impl_/check_optional_flag) | ||
|
||
ct_add_test(NAME "test_check_optional_flag") | ||
function("${test_check_optional_flag}") | ||
|
||
ct_add_section(NAME "empty_string" EXPECTFAIL) | ||
function("${empty_string}") | ||
|
||
_check_optional_flag("") | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "value_is_true" EXPECTFAIL) | ||
function("${value_is_true}") | ||
|
||
_check_optional_flag(TRUE) | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "value_is_on" EXPECTFAIL) | ||
function("${value_is_on}") | ||
|
||
_check_optional_flag(ON) | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "value_is_false" EXPECTFAIL) | ||
function("${value_is_false}") | ||
|
||
_check_optional_flag(FALSE) | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "value_is_off" EXPECTFAIL) | ||
function("${value_is_off}") | ||
|
||
_check_optional_flag(OFF) | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "flag_value" EXPECTFAIL) | ||
function("${flag_value}") | ||
|
||
set(ENABLE_DEPENDENCY ON) | ||
_check_optional_flag("${ENABLE_DEPENDENCY}") | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "valid_flag") | ||
function("${valid_flag}") | ||
include(cmaize/user_api/dependencies/impl_/check_optional_flag) | ||
_check_optional_flag(ENABLE_DEPENDENCY) | ||
|
||
endfunction() | ||
|
||
endfunction() |
91 changes: 91 additions & 0 deletions
91
tests/cmaize/user_api/dependencies/test_find_optional_dependency.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Copyright 2023 CMakePP | ||
# | ||
# 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. | ||
|
||
include(cmake_test/cmake_test) | ||
include(cmaize/user_api/cmaize_project) | ||
include(cmaize/user_api/dependencies/find_optional_dependency) | ||
include(cmaize/user_api/dependencies/impl_/get_package_manager) | ||
include(cmaize/utilities/python) | ||
|
||
ct_add_test(NAME "test_find_optional_dependency") | ||
function("${test_find_optional_dependency}") | ||
|
||
find_python(py_exe py_version) | ||
create_virtual_env( | ||
venv_dir | ||
"${py_exe}" | ||
"${CMAKE_BINARY_DIR}" | ||
"${test_find_optional_dependency}" | ||
) | ||
|
||
# Make sure everything is using the venv Python | ||
set(Python3_EXECUTABLE "${venv_dir}/bin/python3") | ||
|
||
ct_add_section(NAME "is_disabled_empty") | ||
function("${is_disabled_empty}") | ||
|
||
ct_assert_target_does_not_exist(not_real_empty) | ||
|
||
set(ENABLE_NOT_REAL "") | ||
cmaize_find_optional_dependency(not_real_empty ENABLE_NOT_REAL) | ||
|
||
ct_assert_target_exists(not_real_empty) | ||
get_target_property(target_type not_real_empty TYPE) | ||
ct_assert_equal(target_type "INTERFACE_LIBRARY") | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "is_disabled_false") | ||
function("${is_disabled_false}") | ||
|
||
ct_assert_target_does_not_exist(not_real_false) | ||
|
||
set(ENABLE_NOT_REAL FALSE) | ||
cmaize_find_optional_dependency(not_real_false ENABLE_NOT_REAL) | ||
|
||
ct_assert_target_exists(not_real_false) | ||
|
||
# Verify we can call the function multiple times w/o error | ||
cmaize_find_optional_dependency(not_real_false ENABLE_NOT_REAL) | ||
|
||
endfunction() | ||
|
||
ct_add_section(NAME "is_enabled") | ||
function("${is_enabled}") | ||
|
||
# Create a project | ||
set(proj_name "test_find_optional_dependency_is_enabled") | ||
project("${proj_name}") | ||
cmaize_project("${proj_name}") | ||
cpp_get_global(proj_obj CMAIZE_TOP_PROJECT) | ||
|
||
# Create the specification for CMinx | ||
PackageSpecification(CTOR cminx_corr) | ||
PackageSpecification(SET "${cminx_corr}" name "cminx") | ||
|
||
# Install CMinx | ||
_fob_get_package_manager(pm "${proj_obj}" "pip") | ||
PackageManager(install_package "${pm}" "${cminx_corr}") | ||
|
||
set(ENABLE_CMINX TRUE) | ||
|
||
ct_assert_target_does_not_exist(cminx) | ||
|
||
cmaize_find_optional_dependency(cminx ENABLE_CMINX PACKAGE_MANAGER pip) | ||
|
||
ct_assert_target_exists(cminx) | ||
|
||
endfunction() | ||
|
||
endfunction() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters