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

Adds find_optional_dependency #149

Merged
merged 7 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions cmake/cmaize/user_api/dependencies/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@
include_guard()

include(cmaize/user_api/dependencies/find_dependency)
include(cmaize/user_api/dependencies/find_optional_dependency)
include(cmaize/user_api/dependencies/find_or_build_dependency)
64 changes: 64 additions & 0 deletions cmake/cmaize/user_api/dependencies/find_optional_dependency.cmake
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()
51 changes: 51 additions & 0 deletions cmake/cmaize/user_api/dependencies/impl_/check_optional_flag.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 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
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
# the error-checking logic for ensuring that users passsed the value.
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
#
# :param flag: Should be the name of a variable.
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
# :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, recived an empty string"

)
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
elseif("${_cof_type}" STREQUAL "bool")
cpp_raise(
RUNTIME_ERROR
"Expected variable serving as the flag, recieved boolean value."
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
)
endif()

endfunction()
1 change: 0 additions & 1 deletion cmake/cmaize/user_api/user_api.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ include(cmaize/user_api/add_tests)
include(cmaize/user_api/cmaize_option)
include(cmaize/user_api/cmaize_project)
include(cmaize/user_api/dependencies/dependencies)
include(cmaize/user_api/find_or_build_dependency)
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(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()


ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved
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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# 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}" "${find_optional_dependency}"
)
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved

# 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)
ryanmrichard marked this conversation as resolved.
Show resolved Hide resolved

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()
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

include(cmake_test/cmake_test)
include(cmaize/user_api/cmaize_project)
include(cmaize/user_api/find_or_build_dependency)
include(cmaize/user_api/dependencies/find_or_build_dependency)
include(cmaize/utilities/python)

#[[[
Expand Down
Loading