@@ -225,3 +225,135 @@ Anything `H5Easy` related goes in files with the appropriate name.
225225What's left goes in ` tests/unit/test_high_five_base.cpp ` . This covers opening
226226files, groups, dataset or attributes; checking certain pathological edge cases;
227227etc.
228+
229+ ## CMake Integration
230+ In ` tests/cmake_integration ` we test that HighFive can be used in downstream projects;
231+ and that those project can, in turn, be used.
232+
233+ ### Overview
234+ #### Vendoring Strategies
235+ We'll refer to the process of embedding a copy of HighFive into a consuming
236+ library as * vendoring* . The * vendoring strategies* will include the strategy to
237+ not vendor.
238+
239+ There's two broad strategies for integrating HighFive into other code: * finding* or
240+ * vendoring* . When finding HighFive, the assumption by the consumer is that it's
241+ been installed somewhere and it can find it. When vendoring, the consumer
242+ brings their own copy of HighFive and uses it. The different vendoring
243+ strategies are:
244+
245+ - ** find_package** : the standard way for finding dependencies in CMake. Usually
246+ the assumption is that HighFive was install properly, either systemwide or in
247+ a specific subdirectory. HighFive is then found with ` find_package ` (or
248+ ` find_dependency ` when called from ` *Config.cmake ` ).
249+
250+ - ** add_subdirectory** : the consuming code contains a submodule or subdirectory
251+ with the HighFive code; and ` add_subdirectory ` is used to bring HighFive and
252+ all it's targets into the consumer.
253+
254+ - ** fetch_content** : the consuming code uses CMake's FetchContent to download
255+ and integrate HighFive.
256+
257+ - ** external_project** : similar to FetchContent; we don't current test if this
258+ works.
259+
260+ #### Integration Strategies
261+ These refer to downstream projects picking different HighFive targerts to
262+ "link" with HighFive. There's four: two regular targets, a target that only
263+ adds ` -I <dir> ` and one that skips all HighFive CMake code.
264+
265+ #### Location Hints
266+ There are serveral ways of indicating where to find a package:
267+
268+ - ** CMAKE_PREFIX_PATH** : which adds a list of directories to the list of
269+ directories that are used as prefixes when searching for ` HighFiveConfig. `
270+
271+ - ** HighFive_ROOT** : which specifies a guess for where to additionally look
272+ (but only when finding HighFive).
273+
274+ There's two types of directories where a dependency can be located:
275+
276+ - ** install** : the place it ends up after ` cmake --install build ` .
277+
278+ - ** build** : one can, if one wants to (and we have users that do), specify
279+ a build directory (not and install directory) as ` HighFive_ROOT ` .
280+
281+
282+ #### CMake's ` export() `
283+ Furthermore, there's ` export(...) ` . Documentation describes it as being useful
284+ for cross-compilation, when one wants to have a set of host tool along with a
285+ library compiled for the device. It seems we don't need it in HighFive and can
286+ make it and easily write test consumers work perfectly without.
287+
288+ However, if one of our consumers adds ` export(...) ` to their ` CMakeLists.txt `
289+ then their build breaks, complaining about missing HighFive targets (and it
290+ seems they can't "fix it up" on their end because then CMake complains that
291+ there's duplicate exported HighFive related targets).
292+
293+ The second way ommiting the missing ` export() ` can break downstream projects is
294+ if they attempt to use HighFive's build directory (not install directory) as
295+ ` HighFive_ROOT ` (or ` CMAKE_PREFIX_PATH ` ).
296+
297+ #### HighFive Visibility
298+ This is the idea that libraries behave differently depending on whether they
299+ use HighFive in their distributed headers; or not. If they don't they could
300+ attempt to hide the fact that they use HighFive from their users.
301+
302+ Currently, we don't check that libraries can hide the use of HighFive.
303+
304+ #### Applications vs Libraries
305+ In what follows application will refer to code that compiles into an
306+ executable. While libraries refer to code that compiles into a binary that
307+ other developers will link to in their library or application.
308+
309+ Libraries and applications that have dependencies that use HighFive must be
310+ able to agree on a common version of HighFive they want to use. Otherwise,
311+ during the final linking phase, multiple definitions of the same HighFive
312+ symbols will exist, and they linker will pick one (arbitrarily); which is only
313+ safe if all definitions are identical.
314+
315+ ### Test "Organization"
316+ The script to check everything is unwieldy. Here's a summary of what it attemps
317+ to do.
318+
319+ There's three downstream project in play: ` dependent_library ` is a library that
320+ uses HighFive in its public API, ` application ` is an executable that uses
321+ HighFive directly, ` test_dependent_library ` is an application that uses
322+ ` dependent_library ` its purpose is to check that our users can write CMake code
323+ that makes them integrate well with other projects.
324+
325+ The conceptually easy choices are:
326+
327+ - Application that don't have dependencies that use HighFive, can use any
328+ strategy to integrate HighFive; because they know they're the only ones using
329+ HighFive.
330+
331+ - Libraries and applications that have dependencies that use HighFive should
332+ use ` find_package ` since it's the easiest way of injecting a common version
333+ of HighFive everwhere.
334+
335+ Since we can't (and don't want to) force our consumers to use ` find_package `
336+ and ban vendoring, we have to test what happens when libraries vendor
337+ HighFive. (Many of these are likely sources of headache if you try to figure
338+ out which code is when using which of the multiple copies of HighFive
339+ involved; and how they decide to use that version.)
340+
341+ We'll assume that there's some way that all involved projects agree on a single
342+ version of HighFive (i.e. the exact same source code or git commit).
343+
344+ The ` dependent_library ` will integrate HighFive using any of the following
345+ strategies: ` external ` in two variations one from HighFive's install dir and
346+ the other from HighFive's build dir; ` submodule ` in two variations which uses
347+ ` add_subdirectory ` once with and once without ` EXCLUDE_FROM_ALL ` ,
348+ ` fetch_content ` in one variation.
349+
350+ The ` test_dependent_library ` itself always incorporates ` dependent_library `
351+ using ` find_package ` (Config mode). Since that layer might choose any of the
352+ strategies of integrating HighFive, we again check several. Additionally,
353+ ` test_dependent_library ` isn't (and probably shouldn't be) required to
354+ integrate HighFive directly: option ` none ` .
355+
356+ Imagine a script that tries all combinations of the above; and attempts to only
357+ provide hints for the HighFive package location when needed, e.g. for ` none `
358+ there's a ` find_dependency ` in ` Hi5DependentConfig ` that needs to be told where
359+ to look. This is what ` test_cmake_integration.sh ` attempts to do.
0 commit comments