Skip to content

Commit 7eaaf7f

Browse files
committed
Improved handling of FIND_PACKAGE_ARGS in declarations
Allow the user to completely specify the additional find package arguments by implementing a "default to 'REQUIRED'" strategy: if nothing is specified a find_package(<content_name> REQUIRED) is run, otherwise the user has to specify the FULL argument set except <content_name>. For good measure a bit of validation is done. Updated the documentation accordingly. CHANGELOG - improved the handling of HFC's FIND_PACKAGE_ARGS in library declarations to allow more arguments to be passed (now search <version> can be specified among other things) Change-Id: I213ae84308423de275bd701258b36ea7efcf0074
1 parent 7d0e6e5 commit 7eaaf7f

File tree

7 files changed

+161
-8
lines changed

7 files changed

+161
-8
lines changed

cmake/HermeticFetchContent.cmake

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,36 @@ Commands
327327
328328
Set the base directory for all the hermetic dependency build directory and related folders
329329
330+
Fallback to system provided dependencies
331+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
332+
333+
For use-cases in which you want to have the option to revert to a system provided library but still have the ability
334+
to build your own, you may set ``FORCE_SYSTEM_<content-name>`` to ``ON``. In this case Hermetic FetchContent will
335+
execute a CMake ``find_package(<content-name> REQUIRED)`` call during targets discovery.
336+
337+
If you need to specify arguments to ``find_package()`` you may add the ``FIND_PACKAGE_ARGS`` to the content declaration.
338+
339+
.. code-block:: cmake
340+
set(FORCE_SYSTEM_boost ON) # <- take boost from the system, toggle this to OFF to have Boost built by your project
341+
FetchContent_Declare(
342+
boost
343+
GIT_REPOSITORY https://github.com/boostorg/boost.git
344+
GIT_TAG ad09f667e61e18f5c31590941e748ac38e5a81bf # that's v1.84
345+
)
346+
347+
FetchContent_MakeHermetic(
348+
boost
349+
HERMETIC_BUILD_SYSTEM cmake
350+
FIND_PACKAGE_ARGS "1.84 EXACT REQUIRED" # <- makes sure we take a 1.84 only from the system!
351+
)
352+
353+
HermeticFetchContent_MakeAvailableAtBuildTime(boost)
354+
355+
Note that in the special case of ``FORCE_SYSTEM_<content-name>=ON`` the context in which the find_package() will be
356+
run, will be slightly different from the normal context for hermetic builds. One major difference is that the Hermetic
357+
FetchContent will inject the project's ``CMAKE_MODULE_PATH`` into the toolchain extension in addition to forcing
358+
``find_package()`` to search exclusively on the system through setting ``CMAKE_FIND_ROOT_PATH_MODE_*`` appropriately.
359+
330360
Build introspection
331361
^^^^^^^^^^^^^^^^^^^
332362

cmake/modules/hfc_make_available_single.cmake

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,22 @@ function(hfc_make_available_single content_name build_at_configure_time)
194194
HERMETIC_FIND_PACKAGES "${__PARAMS_HERMETIC_FIND_PACKAGES}"
195195
PROJECT_TOOLCHAIN_EXTENSION "${__PARAMS_HERMETIC_TOOLCHAIN_EXTENSION}"
196196
DESTINATION_TOOLCHAIN_PATH "${proxy_toolchain_path}"
197-
)
197+
)
198+
199+
if(__PARAMS_FIND_PACKAGE_ARGS)
200+
set(findpackage_args "${__PARAMS_FIND_PACKAGE_ARGS}")
201+
else()
202+
set(findpackage_args "REQUIRED")
203+
endif()
204+
205+
if(NOT findpackage_args MATCHES "REQUIRED")
206+
hfc_log(WARNING "The FIND_PACKAGE_ARGS provided in the content declaration of ${content_name} do not contain the REQUIRED flag. This might cause the resulting targets to be empty if the dependency cannot be resolve. (Valud of FIND_PACKAGE_ARGS='${__PARAMS_FIND_PACKAGE_ARGS}')")
207+
endif()
198208

199209
get_hermetic_target_cache_file_path(${content_name} target_cache_file)
200210
hfc_targets_cache_create_isolated(
201211
${content_name}
202-
LOAD_TARGETS_CMAKE "[==[find_package(${content_name} REQUIRED ${__PARAMS_FIND_PACKAGE_ARGS} ) \n]==]"
212+
LOAD_TARGETS_CMAKE "[==[find_package(${content_name} ${findpackage_args}) \n]==]"
203213
CACHE_DESTINATION_FILE "${target_cache_file}"
204214
TEMP_DIR "${HERMETIC_FETCHCONTENT_INSTALL_DIR}/targets_dump_tmp"
205215
TOOLCHAIN_FILE ${proxy_toolchain_path}

docs/modules/HermeticFetchContent.html

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ <h3>Navigation</h3>
6969
<ul>
7070
<li><p><a class="reference internal" href="#overview" id="id2">Overview</a></p></li>
7171
<li><p><a class="reference internal" href="#commands" id="id3">Commands</a></p></li>
72-
<li><p><a class="reference internal" href="#build-introspection" id="id4">Build introspection</a></p></li>
73-
<li><p><a class="reference internal" href="#rationale" id="id5">Rationale</a></p></li>
72+
<li><p><a class="reference internal" href="#fallback-to-system-provided-dependencies" id="id4">Fallback to system provided dependencies</a></p></li>
73+
<li><p><a class="reference internal" href="#build-introspection" id="id5">Build introspection</a></p></li>
74+
<li><p><a class="reference internal" href="#rationale" id="id6">Rationale</a></p></li>
7475
</ul>
7576
</li>
7677
</ul>
@@ -360,9 +361,22 @@ <h2><a class="toc-backref" href="#id3" role="doc-backlink">Commands</a><a class=
360361
<p>Set the base directory for all the hermetic dependency build directory and related folders</p>
361362
</dd></dl>
362363

364+
</section>
365+
<section id="fallback-to-system-provided-dependencies">
366+
<h2><a class="toc-backref" href="#id4" role="doc-backlink">Fallback to system provided dependencies</a><a class="headerlink" href="#fallback-to-system-provided-dependencies" title="Permalink to this heading"></a></h2>
367+
<p>For use-cases in which you want to have the option to revert to a system provided library but still have the ability
368+
to build your own, you may set <code class="docutils literal notranslate"><span class="pre">FORCE_SYSTEM_&lt;content-name&gt;</span></code> to <code class="docutils literal notranslate"><span class="pre">ON</span></code>. In this case Hermetic FetchContent will
369+
execute a CMake <code class="docutils literal notranslate"><span class="pre">find_package(&lt;content-name&gt;</span> <span class="pre">REQUIRED)</span></code> call during targets discovery.</p>
370+
<p>If you need to specify arguments to <code class="docutils literal notranslate"><span class="pre">find_package()</span></code> you may add the <code class="docutils literal notranslate"><span class="pre">FIND_PACKAGE_ARGS</span></code> to the content declaration.</p>
371+
<blockquote>
372+
<div></div></blockquote>
373+
<p>Note that in the special case of <code class="docutils literal notranslate"><span class="pre">FORCE_SYSTEM_&lt;content-name&gt;=ON</span></code> the context in which the find_package() will be
374+
run, will be slightly different from the normal context for hermetic builds. One major difference is that the Hermetic
375+
FetchContent will inject the project's <code class="docutils literal notranslate"><span class="pre">CMAKE_MODULE_PATH</span></code> into the toolchain extension in addition to forcing
376+
<code class="docutils literal notranslate"><span class="pre">find_package()</span></code> to search exclusively on the system through setting <code class="docutils literal notranslate"><span class="pre">CMAKE_FIND_ROOT_PATH_MODE_*</span></code> appropriately.</p>
363377
</section>
364378
<section id="build-introspection">
365-
<h2><a class="toc-backref" href="#id4" role="doc-backlink">Build introspection</a><a class="headerlink" href="#build-introspection" title="Permalink to this heading"></a></h2>
379+
<h2><a class="toc-backref" href="#id5" role="doc-backlink">Build introspection</a><a class="headerlink" href="#build-introspection" title="Permalink to this heading"></a></h2>
366380
<p>HermeticFetchContent adds a number of cmake build targets to the build system that can be executed after the project configuration to enable
367381
some build introspection:</p>
368382
<dl class="cmake command">
@@ -417,7 +431,7 @@ <h2><a class="toc-backref" href="#id4" role="doc-backlink">Build introspection</
417431
<p>Prints the list of executables of <code class="docutils literal notranslate"><span class="pre">${content_name}</span></code> on the console.</p>
418432
</section>
419433
<section id="rationale">
420-
<h2><a class="toc-backref" href="#id5" role="doc-backlink">Rationale</a><a class="headerlink" href="#rationale" title="Permalink to this heading"></a></h2>
434+
<h2><a class="toc-backref" href="#id6" role="doc-backlink">Rationale</a><a class="headerlink" href="#rationale" title="Permalink to this heading"></a></h2>
421435
<dl class="simple">
422436
<dt>Ressembling add_subdirectory through external cmake execution is key to providing reusable install trees :</dt><dd><ul class="simple">
423437
<li><p>One project depending on a library can reuse the library built by another project</p></li>
@@ -450,6 +464,7 @@ <h3><a href="../index.html">Table of Contents</a></h3>
450464
<li><a class="reference internal" href="#">FetchContent_MakeHermetic</a><ul>
451465
<li><a class="reference internal" href="#overview">Overview</a></li>
452466
<li><a class="reference internal" href="#commands">Commands</a></li>
467+
<li><a class="reference internal" href="#fallback-to-system-provided-dependencies">Fallback to system provided dependencies</a></li>
453468
<li><a class="reference internal" href="#build-introspection">Build introspection</a></li>
454469
<li><a class="reference internal" href="#rationale">Rationale</a></li>
455470
</ul>

docs/searchindex.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/targets_cache_test.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,15 @@ namespace hfc::test {
5656
targets_cache_test_data_set{ "hfc_targets_cache/autotools_export_declaration", "Iconv.cmake", true },
5757
targets_cache_test_data_set{ "hfc_targets_cache/cmake_no_install", "mathslib.cmake", false },
5858
targets_cache_test_data_set{ "hfc_targets_cache/alternate_exports_naming", "mathslib.cmake", true },
59-
targets_cache_test_data_set{ "hfc_targets_cache/alternate_exports_naming", "mathslib.cmake", false, false /* expect configure failure */, false, "-DHFCTEST_NEGATIVE_CASE=ON" /* enable the negative test in the project */ }
59+
targets_cache_test_data_set{ "hfc_targets_cache/alternate_exports_naming", "mathslib.cmake", false, false /* expect configure failure */, false, "-DHFCTEST_NEGATIVE_CASE=ON" /* enable the negative test in the project */ },
60+
61+
// check that FIND_PACKAGE_ARGS are correctly forwarded to the underlying find_package() call
62+
// > the cases below are just FORCE_SYSTEM_Iconv[ON;OFF] * TEST_INJECT_FIND_PACKAGE_ARGS[ON;OFF]
63+
// > to have the neg cases to validate the test code behavior IRT to expected outcomes
64+
targets_cache_test_data_set{ "hfc_targets_cache/FORCE_SYSTEM_find_pagacke_args", "Iconv.cmake", false, false, false, "-DFORCE_SYSTEM_Iconv=OFF -DTEST_INJECT_FIND_PACKAGE_ARGS=ON" }, // neg test
65+
targets_cache_test_data_set{ "hfc_targets_cache/FORCE_SYSTEM_find_pagacke_args", "Iconv.cmake", false, false, false, "-DFORCE_SYSTEM_Iconv=ON -DTEST_INJECT_FIND_PACKAGE_ARGS=OFF" }, // neg test
66+
targets_cache_test_data_set{ "hfc_targets_cache/FORCE_SYSTEM_find_pagacke_args", "Iconv.cmake", false, false, false, "-DFORCE_SYSTEM_Iconv=OFF -DTEST_INJECT_FIND_PACKAGE_ARGS=OFF" }, // neg test
67+
targets_cache_test_data_set{ "hfc_targets_cache/FORCE_SYSTEM_find_pagacke_args", "Iconv.cmake", true, true, true, "-DFORCE_SYSTEM_Iconv=ON -DTEST_INJECT_FIND_PACKAGE_ARGS=ON" }
6068
};
6169

6270
static auto TEST_DATA_hfc_makeAvailableAt_type = {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#
2+
# Check if arguments injected through HFC's FIND_PACKAGE_ARGS make it
3+
# to the underlying find_package() call
4+
#
5+
# WORD OF CAUTION:
6+
# ================
7+
# we're overriding the find_package() function in the toolchain extension to this end.
8+
# The whole execution is fundamentally broken for any other purpose than checking the
9+
# arguments being forwarded!
10+
#
11+
12+
cmake_minimum_required(VERSION 3.27.6)
13+
project(
14+
ModernCMakeExample
15+
VERSION 1.0
16+
LANGUAGES CXX)
17+
18+
19+
set(CMAKE_MODULE_PATH
20+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
21+
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
22+
${CMAKE_MODULE_PATH}
23+
)
24+
25+
include(FetchContent)
26+
include(HermeticFetchContent)
27+
28+
29+
# this is set by the test program, just making sure we have a value
30+
# when set to ON this should ensure we get to use the FindIconv.cmake module found under ./projectCmakeModules/
31+
if(NOT DEFINED FORCE_SYSTEM_Iconv)
32+
message(FATAL_ERROR "FORCE_SYSTEM_Iconv not defined")
33+
endif()
34+
35+
36+
if(NOT DEFINED TEST_INJECT_FIND_PACKAGE_ARGS)
37+
message(FATAL_ERROR "TEST_INJECT_FIND_PACKAGE_ARGS not defined")
38+
endif()
39+
40+
if(TEST_INJECT_FIND_PACKAGE_ARGS)
41+
set(find_package_args_value "REQUIRED HFC_TEST_FLAG")
42+
else()
43+
set(find_package_args_value "REQUIRED")
44+
endif()
45+
46+
47+
FetchContent_Declare(
48+
Iconv
49+
GIT_REPOSITORY "https://github.com/tipi-build/unittest-autotools-sample.git"
50+
GIT_TAG "ad80b024eeda8f4c0a96eedf669dc453ed33a094"
51+
)
52+
53+
FetchContent_MakeHermetic(
54+
Iconv
55+
FIND_PACKAGE_ARGS "${find_package_args_value}"
56+
HERMETIC_TOOLCHAIN_EXTENSION
57+
[=[
58+
59+
# override find_package with one that can check if HFC_TEST_FLAG was set
60+
function(find_package)
61+
# check if HFC_TEST_FLAG was set
62+
if(NOT "HFC_TEST_FLAG" IN_LIST ARGN)
63+
message(FATAL_ERROR "Flag HFC_TEST_FLAG was not passed...")
64+
endif()
65+
66+
include(FindIconv) # yeah...
67+
68+
#_find_package(${ARGN})
69+
endfunction()
70+
71+
]=]
72+
HERMETIC_CMAKE_EXPORT_LIBRARY_DECLARATION
73+
[=[
74+
message(FATAL_ERROR "This should never be run in this test")
75+
]=]
76+
HERMETIC_BUILD_SYSTEM autotools
77+
)
78+
79+
HermeticFetchContent_MakeAvailableAtConfigureTime("Iconv")
80+
81+
82+
if(NOT TARGET Iconv::Iconv)
83+
message(FATAL_ERROR "Could not find target Iconv::Iconv")
84+
endif()
85+
86+
add_executable(MyExample simple_example.cpp)
87+
target_link_libraries(MyExample PRIVATE Iconv::Iconv)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
int main() {
2+
return 0;
3+
}

0 commit comments

Comments
 (0)