Use version from Git submodule¶
Hunter allows the creation of an archive with sources on the fly by getting it from a Git submodule.
Example:
> git clone https://github.com/hunter-test-cases/git-submodule-integration
> cd git-submodule-integration
[git-submodule-integration]> git submodule update --init .
To instruct Hunter to use the contents of the submodule, add a local config file
and set the GIT_SUBMODULE
flag:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
LOCAL # <----- load cmake/Hunter/config.cmake
)
# cmake/Hunter/config.cmake
hunter_config(fruits GIT_SUBMODULE "3rdParty/fruits")
The path set by the GIT_SUBMODULE
flag is the same as in the .gitmodules
file:
[git-submodule-integration]> cat .gitmodules
[submodule "3rdParty/fruits"]
path = 3rdParty/fruits
url = https://github.com/cgold-examples/fruits
At the configure step Hunter will run the command git archive
to pack sources:
[git-submodule-integration]> cmake -H. -B_builds -DHUNTER_STATUS_DEBUG=ON
...
-- [hunter *** DEBUG *** ...] Creating archive '/.../git-submodule-integration/_builds/_3rdParty/Hunter/git-archives/fruits.tar'
...
Let’s build the project and run tests:
[git-submodule-integration]> cmake --build _builds
[git-submodule-integration]> (cd _builds && ctest -VV)
...
1: Quick meal:
1: plum x 2
1: pear x 1
...
If you want to make changes to the dependent project (the one added as submodule) and test them, you have to commit patches first:
[git-submodule-integration]> cd 3rdParty/fruits
[fruits]> grep return lib/fruits/rosaceae/Plum.cpp
return "plum";
[fruits]> vim lib/fruits/rosaceae/Plum.cpp
[fruits]> grep return lib/fruits/rosaceae/Plum.cpp
return "plum-v2";
[fruits]> git add lib/fruits/rosaceae/Plum.cpp
[fruits]> git commit -m 'Update'
Go back to the parent directory and run build. There is no need to run configure again, corresponding Git files are watched by CMake hence the configure step will start automatically when the build step is invoked:
[fruits]> cd ../..
[git-submodule-integration]> cmake --build _builds
Run tests to see changes:
[git-submodule-integration]> (cd _builds && ctest -VV)
1: Quick meal:
1: plum-v2 x 2
1: pear x 1
Possible problems with GIT_SUBMODULE¶
When using a package via the GIT_SUBMODULE
option, the Hunter defined CMake
variable HUNTER_<package>_VERSION
is set to the commit hash of the Git
sub-module. If the hunter.cmake
file of the package contains logic that
depends on the value of the HUNTER_<package>_VERSION
variable,
using the GIT_SUBMODULE
option may break the package build. If that is
the case you can add explicit VERSION
value
to hunter_config.
Use subdirectory of submodule¶
To instruct hunter to archive a subdirectory of the Git submodule add the keyword HUNTER_SUBMODULE_SOURCE_SUBDIR
to the CMake arguments:
# cmake/Hunter/config.cmake
hunter_config(fruits GIT_SUBMODULE "3rdParty/fruits"
CMAKE_ARGS "HUNTER_SUBMODULE_SOURCE_SUBDIR=app")
The created archive will contain just the subfolder app
of the submodule.
GIT_SUBMODULE vs add_subdirectory¶
Note that we can achieve the same by adding sources with add_subdirectory
:
# top level CMakeLists.txt
# ...
add_subdirectory(3rdParty/fruits)
The only pros of add_subdirectory
approach is that build artifacts of the
fruits
will live in our _builds
directory. GIT_SUBMODULE
will add
new package in the same way as regular release-based packages added, meaning
that after installation all build artifacts will be removed. Every new version
start build from scratch.
Next cons of using add_subdirectory
:
- Dependent project
fruits
is not installed, hence CMake API usage may be different. If package has targetfruits_rosaceae
internally then after installation it can befruits::fruits_rosaceae
- For the same reason C++ API may be different, e.g.
#include
directives - It’s not two separate projects now - it’s one big project. Hence they will share same cache which may lead to options conflicts, targets name conflicts, targets from both projects will be installed, tests from both projects will be run
- Correctness. Note that
add_subdirectory
can be used only for dependencies which is not used by other packages in Hunter. If current project use packagezoo
which depends onfruits
we can’t doadd_subdirectory(fruits)
sincehunter_add_package(zoo)
will build and usefruits
from Hunter. See next chapter for details
Injection¶
GIT_SUBMODULE
allow you to correctly inject new version of package into
existent hierarchy of packages.
For example let’s take a look at the project which use TIFF, TIFF depends on ZLIB:
> git clone https://github.com/hunter-test-cases/git-submodule-integration-deps
> cd git-submodule-integration-deps
[git-submodule-integration-deps]> git submodule update --init .
First let’s remove LOCAL
config and build standard TIFF with standard ZLIB:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
)
project(foo)
hunter_add_package(TIFF)
find_package(TIFF CONFIG REQUIRED)
Config-ID is f743b0b
:
[git-submodule-integration-deps]> cmake -H. -B_builds -DHUNTER_STATUS_DEBUG=ON
...
-- Downloading...
dst='~/.hunter/_Base/Download/ZLIB/1.2.8-p3/573dc28/v1.2.8-p3.tar.gz'
timeout='none'
-- Using src='https://github.com/hunter-packages/zlib/archive/v1.2.8-p3.tar.gz'
...
/usr/bin/cc ... -isystem ~/.hunter/_Base/3b39eff/e1266bb/f743b0b/Install/include ... /.../tif_zip.c
Now let’s add LOCAL
back and run build again:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz"
SHA1 "3319fe6a3b08090df7df98dee75134d68e2ef5a3"
LOCAL
)
project(foo)
hunter_add_package(TIFF)
find_package(TIFF CONFIG REQUIRED)
# cmake/Hunter/config.cmake
hunter_config(ZLIB GIT_SUBMODULE "3rdparty/zlib")
[git-submodule-integration-deps]> cmake -H. -B_builds -DHUNTER_STATUS_DEBUG=ON
Now we are getting sources from locally created ZLIB.tar
archive:
...
-- verifying file...
file='/.../_builds/_3rdParty/Hunter/git-archives/ZLIB.tar'
...
And rebuilding TIFF with newly installed ZLIB, Config-ID changed from
f743b0b
to 817c9cb
:
/usr/bin/cc ... -isystem ~/.hunter/_Base/3b39eff/e1266bb/817c9cb/Install/include ... /.../tif_zip.c
To achieve the same with add_subdirectory
you have to clone TIFF package too.
Then you have to be sure that TIFF supports external ZLIB targets configuration,
call add_subdirectory(3rdparty/zlib)
first, then add_subdirectory(3rdparty/TIFF)
.
Note that if you don’t know that TIFF depends on ZLIB and you just call
add_subdirectory(3rdparty/zlib)
you will end up with incorrect configuration!