Documentation is in process of migrating from
GitHub wiki.
Some information may be missing: blank pages, broken links, etc.
See issue #667
for details.

Welcome to the Hunter package manager documentation!

Hunter is a CMake driven cross-platform package manager for C/C++ [1] projects.
With the help of Hunter you can organize builds for Linux, Windows,
macOS, iOS, Android, Raspberry Pi and other platforms.
Third-party external projects are highly customizable, effectively allowing you
to have myriad variants of directories with them based on combinations of
version to build, static/shared, CMake -D options, Release/Debug, etc.

Separate root directories will be created for each variant, so they all
can be used simultaneously on one machine without conflicts
(just like virtualenv but automatically).
Going further: each such root directory can be shared between several
local projects if configuration of externals matches.
So when you are starting another project from scratch and use the same external
packages, there will be no additional copy or build triggered; the only
overhead is checking the existence of a DONE stamp file for each package.
In case your local environment is similar enough to the continuous integration
environment of Travis/AppVeyor service, then build will not be triggered at all
- cached binaries will be downloaded from GitHub server instead.

Mainly Hunter is designed to manage packages with CMake build system under the
hood and existing CMake packages can be quite easily integrated into system,
but non-CMake packages are also supported too using custom templates
(build schemes) with ExternalProject_Add command(s).

The Hunter client is a collection of CMake-only modules
(i.e. it‚Äôs not a binary like apt-get or script like brew)
so it supports out-of-the-box all platforms/generators/IDEs which CMake can
handle, like Visual Studio, Xcode, Android Studio,
QtCreator, NMake, Ninja, Cygwin or MinGW. It works fine with CMake-GUI too.

The prime directive used for adding package to the current root is
hunter_add_package which companioning CMake‚Äôs find_package. For
example:

This is a brief overview of big picture. It takes about 5 minutes of reading
but will show you the main features/aspects of using Hunter. Please don‚Äôt make
any assumptions about how Hunter works without reading this part. Also avoid
running real code for now, it will be covered in next
Quick start section.

Every Hunter release (Atom feed) archive is a meta-package with build
instructions and URLs of real packages. The archive will be downloaded and
unpacked automatically by the HunterGate CMake module. You only need to set
the URL and SHA1:

Note that Hunter‚Äôs approach differs from a
requirements.txt-like approach
(i.e. when external packages are specified in a separate file). This allows Hunter to avoid
duplication of logic in many cases, even if the requirements.txt style approach also automatically downloads
dependencies too.

Imagine that we have to specify dependencies in some kind of requirements.cmake
file and there is a user option BUILD_WITH_BAR:

Later, when you need to change this dependency in CMakeLists.txt, you‚Äôd better not forget to also modify requirements.cmake
accordingly. Remember real world libraries can have nontrivial chain of conditions, e.g.
OpenCV components.

If you are already familiar with ExternalProject_Add and have written some
super-build projects before, you are probably already aware that writing a complete
solution with toolchains, build types, build options, parallel jobs,
forwarding of compiler flags, and making it work correctly for all generators
is not a trivial task.

Hunter stores ExternalProject_Add recipes as a set of templates. Once
written, formula (build scheme) can be reused by other projects without
copying the collection of super-build files (DRY principle).
When a new package with a new scheme is introduced, all you need to do is just update
the SHA1/URL of HunterGate command.

Hunter-ID is the first 7 digits of SHA1
of Hunter archive. This level defines list of available packages and mapping
version->URL/SHA1. Several Hunter-ID can coexist in the same
HUNTER_ROOT directory. HunterGate command will control your choice:

Each build can be run with different toolchains. In general the result is
a completely different root directory (containing (lib/include). For example on
Windows you can simultaneously build Visual Studio (32/64), NMake, Cygwin and
MinGW projects, on Linux GCC/Clang, on Mac Xcode, Makefile, iOS. Or choose
various clang tools like static analyzer/sanitizers and other platforms like
Android/Raspberry Pi. Each toolchain file will be forwarded to external project.
This means, if you create a toolchain with compiler g++ and flag -std=c++11 all
dependent projects will be built by g++-std=c++11. Information about
toolchain has some internal representation (toolchain.info). As identifier
(ID) the first 7 digits of the SHA1 hash of this file are used.

The toolchain file is the only way to apply global settings for 3rd party
projects in Hunter.

Only CMAKE_TOOLCHAIN_FILE will be forwarded for all packages,
neither standard CMAKE_CXX_COMPILER/CMAKE_CXX_FLAGS nor custom variables
like ANDROID_FOO=boo will be applied globally. First reason is the simplicity
of forwarding logic, second reason is about distinguishing local and global
settings. E.g. if a user wants to set -Wall only for the local project he can use
CMAKE_CXX_FLAGS. If user wants to set -Wall globally then he can use
CMAKE_TOOLCHAIN_FILE.

Third level of customization. Set version of package to build and
its build options.

Config-ID is the first 7 digits of SHA1 of the file with
hunter_config commands (internal unified representation). This level can
be customized with HunterGate options: GLOBAL, LOCAL and
FILEPATH. Packages from Hunter-ID1eae623 can be built using different
versions and different CMake arguments:

A root directory with installed packages can be shared between several local
projects. If one local project triggers installation of a new third
party package, then the root directory will be locked against modifications until the install
has either finished or interrupted (i.e. Ctrl-C). Other local projects that try to run
hunter_add_package for the same root at the same time will automatically wait for the root
to be unlocked. Note that different root directories have independent locks,
e.g. triggering a build of OpenSSL for iOS will not delay building of
GTest for Android. Internally this is done using the file(LOCK...) CMake
command (available since 3.2).

Similar synchronization is done when initializing Hunter using the HunterGate command.
This is a very handy feature for CI systems where an environment is shared
between several jobs, e.g. Jenkins.

Hunter has an internal mechanism that saves the binaries of installed packages along
with meta-data about the toolchain, build options, and dependencies.
This allows Hunter to avoid triggering the same build when a new root directory is created.
For example, when a user changes the version of OpenSSL from 1.0.1 to 1.0.2
it will affect Config-ID, so a new root will be created. However, it will not affect
how GTest builds (if it‚Äôs not a dependency), so the GTest archive can be
unpacked from the local cache. The cache can be kept local or uploaded to a Hunter cache server.

The default server with cached binaries is
ingenue/hunter-cache.
Archives are saved as GitHub release assets
and each is associated with a git tag.
Available packages can be queried using an upload.* HTTP query from the GitHub branches URL:

Note that some toolchains may not work for specific packages. Check the
status in the Travis CI job details. For example, Qt is broken for the iOS armv7s architecture, so
we have to use the ios-*-wo-armv7s toolchains:

Binaries/headers are stored in archives and archives are the result of packing the
CMAKE_INSTALL_PREFIX directory produced by the
cmake--build_builds--targetinstall command. The idea is similar to CPack
functionality but is extended for non-CMake packages too.

So this makes it easy to use Hunter as experimental feature. All information
that users need to know about new commands is that hunter_add_package and
HunterGate will do nothing as long as HUNTER_ENABLED is NO.

Note that Hunter itself add HUNTER_ENABLED=YES while building third party
package. It means that if package released with HUNTER_ENABLED=NO by default
it still can be used in Hunter, no extra modifications needed.

Not all packages have the same CMake usage API. E.g. for CURL in Hunter
there is imported target CURL::libcurl but there are only
CURL_INCLUDE_DIRS and CURL_LIBRARIES defined in standard FindCURL
module.

Module CURLConfig from ‚Äúdisabled-mode‚ÄĚ modules will be added to CMake
search path, loaded, call standard FindCURL and create imported target
CURL::libcurl. This will allow to use same API with and without Hunter:

Short description of main commands. First part is about choosing CMake version
to use, then example of commands for downloading Boost components. At the end
take a look at GitHub repository with tiny project that use GTest and try it
yourself.

Set HUNTER_ROOT environment variable to an empty directory. This
directory will be used by HunterGate module for storing packages and
utility files. Using environment variable is recommended but not mandatory,
see other options.

How does Hunter affect end users which do usually run *.msi or *.dmg
installers? The answer - it does not at all. Hunter in fact do quite the same
stuff that developer do with packages: download, build, install, reuse in other
projects. There will be no new functionality introduced by package - it will
be installed in the same way as system package manager or custom build script do.
But giving you much more control and allow you experimenting seamlessly. From
some point of view Hunter is like adding unit-testing to your project. It‚Äôs
the tool that will not extend final behavior of application directly.
However just like with unit-testing users will probably notice result effect
such as stability/quality in overall.

This kind of developer can read CMake code that was written by more
experienced CMake developer. He understand some simple features like that
executable added by add_executable command and this command contains list
of sources files. But probably will not be able to tell why in some cases
include_directories command called but target_include_directories in
other cases. The main target of modifications is C++ code.

Such developers can do:

Add more targets to project

Add more sources to targets

Add C++ flags that does not break compatibility (e.g. warnings/optimization)

Using hunter_private_data
module user can download files that are private for the current project, i.e.
some data that will not be shared with other projects. Unlike regular
packages such data is not injectable, i.e. user will not be able to add his own
code just by changing version of private data (well there even no such essence
as private data version). This feature is quite orthogonal to main Hunter
functionality and just use Hunter root directory and tools like stamps and
locks.

They both will share same myfile.txt file. If for example you switch to
different Git branch with different version of myfile.txt file Hunter will
download this version and create separate directory basing on new hash.
Same variable myfile_path will point to new location.

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:

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.

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 target fruits_rosaceae internally then after
installation it can be fruits::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 package
zoo which depends on fruits we can‚Äôt do add_subdirectory(fruits)
since hunter_add_package(zoo) will build and use fruits from Hunter.
See next chapter for details

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!

It can be useful for testing find_package(fruits...) functionality and
that generated fruitsConfig.cmake file is correct.

Note

Under the hood gitarchive command is used to pack the project, hence
if you want to test modifications you have to commit them. This is similar
to GIT_SUBMODULE feature. But unlike GIT_SUBMODULE feature not all
the dirty files will be checked. While using GIT_SELF the dirty files
inside fruits/example directory will be ignored (check log messages).
Also if you want to ignore any untracked file, you can use the
HUNTER_GIT_SELF_IGNORE_UNTRACKED
option.

It is possible to upload Hunter binary cache to the server.
Next shown an example of using GitHub as a hosting. All big raw *.tar.bz2 archives
uploaded as assets to release with names cache-* (directory layout does not
matter) and all small text files with meta information uploaded directly to
branch master (directory layout matters) (see
hunter-cache as example).

Note

If you have shared folder in your network there is no need to use
any scripts, you can just set HUNTER_ROOT variable to location of this
directory.

Note

Currently upload procedure is implemented using Python script with
requests and gitpython modules, check that you have Python installed
in your system. This limitation will be removed in future. Downloading from
server done by file(DOWNLOAD...) CMake commands, so client is still
CMake-only based. Module gitpython expects Git executable installed in
system. You can use environment variable
HUNTER_GIT_EXECUTABLE
to specify custom path.

If you have problems with installing travis try to install
ruby from brew:

> brew install ruby

Login with account with which you have registered repository for CI.
In my case it‚Äôs my personal account ruslo:

Login with ruslo (add --pro if repository is private):

> travis login
We need your GitHub login to identify you.
This information will not be sent to Travis CI, only to api.github.com.
The password will not be displayed.
Try running with --github-token or --auto if you don't want to enter your password anyway.
Username: ruslo
Password for ruslo: xxxxxx
Two-factor authentication code for ruslo: xxxxxx
Successfully logged in as ruslo!
> travis whoami
You are ruslo (Ruslan Baratov)

Artifactory treats URLs like
https://my.server.com/.../file.txt.sha1 as a special URL to get SHA1 hash
of file https://my.server.com/.../file.txt. Use SUB_SHA1_SUFFIX
to download all internal Hunter cache meta files of form abc.sha1
by using abc_sha1 URL.

Note

http://localhost:8081 repeated 3 times, that may looks redundant
but in general HUNTER_CACHE_SERVERS is a list, hence there may be
several different servers used. For each server there may be one
hunter_cache_server_password(SERVER...) command. Server
from hunter_upload_password may not be in HUNTER_CACHE_SERVERS list
at all, though it might not make a lot of sense.

Run CMake build. After build finished update page and check the state of
hunter repository:

Global settings for all packages, no package specific information saved here.
Created by analyzing an output of compilation of C++ file
ShowPredefined.cpp
(created from
list).
We get unified information about compiler, compiler version, compiler
flags, etc. (everything from user‚Äôs CMAKE_TOOLCHAIN_FILE).

When using Boost Math you will need to link in the libraries, however these are not named math but
rather are individual based on what you need to link it, the easiest of which is to link in all parts:

For package versions 1.8.0-hunter-p1 and higher the package also
includes GMock. When finding the GMock package GTest is automatically
included. Note that package version 1.8.0-hunter-p1 does not support
the MinGW and Visual Studio 2005 toolchains, so GMock is not
available in these cases.

hunter_add_package(GTest)find_package(GMockCONFIGREQUIRED)# GMock::gmock and GTest::main will be linked automaticallytarget_link_libraries(fooGMock::main)

# Imported target can be used as-is# in "build time" commands like 'add_custom_target'add_custom_target(show_lua_versionLua::lua-vCOMMENT"Show version of Lua executable")

# Full path to executable 'LUA_EXECUTABLE' should be used# for "generate time" commands like 'execute_process'execute_process(COMMAND${LUA_EXECUTABLE}-vRESULT_VARIABLEresultOUTPUT_VARIABLEoutputERROR_VARIABLEerrorOUTPUT_STRIP_TRAILING_WHITESPACEERROR_STRIP_TRAILING_WHITESPACE)

since hunter
v0.18.44
OpenCV can‚Äôt find system libraries to link against on Linux. If you
need those dependencies (FFMPEG, GTK, GStreamer, V4L2, etc.) you need
to fork hunter and revert commit
f6f0965
in your fork. Try this
fork for some already
patched releases.

Error: You are creating QApplication before calling UIApplicationMain.
If you are writing a native iOS application, and only want to use Qt for
parts of the application, a good place to create QApplication is from
within 'applicationDidFinishLaunching' inside your UIApplication
delegate.

Errors when compiling on Linux Debian without manually installing
some Qt dependencies first. See Qt Issue
2. The Problem
can be fixed by installing the necessary libraries before calling
CMake with the command:

To use this package the vulkan headers (not part of Hunter at the time of writing) must be installed.
On debian variants use ‚Äúapt-get install libvulkan-dev‚ÄĚ. On Mac, Windows, and iOS download and
install the Vulkan SDK from here.
Recent versions of the android NDK supports Vulkan out of the box.

WebP codec: library to encode and decode images in WebP format. This package contains the library that can be used in other programs to add WebP support, as well as the command line tools cwebp and dwebp.

Ceres Solver is an open source C++ library for modeling and solving
large, complicated optimization problems. It can be used to solve
Non-linear Least Squares problems with bounds constraints and general
unconstrained optimization problems. It is a mature, feature rich, and
performant library that has been used in production at Google since
2010. For more, see official website.

Cross compilation to iOS and Android might fail since the build require to find corrade-rc (native executable)
in your path. In order to build an iOS or Android package, first compile corrade-rc natively, and add it to your path.

Next custom dependencies should be set in local config.cmake file explicitly:

hunter_config(xgboostVERSION0.40-p10CMAKE_ARGSXGBOOST_USE_HALF=ONXGBOOST_USE_CEREAL=ONXGBOOST_DO_LEAN=ON)hunter_config(acfVERSION${HUNTER_acf_VERSION}CMAKE_ARGSACF_BUILD_OGLES_GPGPU=ON)if(ANDROID)# https://travis-ci.org/ingenue/hunter/jobs/287844545# Will be fixed in Android NDK 17set(drishti_dlib_version19.2-p2)# error: 'struct lconv' has no member named 'decimal_point' -/-hunter_config(nlohmann_jsonVERSION2.1.1-p1)else()set(drishti_dlib_version19.6-p2)endif()hunter_config(dlibVERSION${drishti_dlib_version}CMAKE_ARGSDLIB_USE_BLAS=OFFDLIB_USE_LAPACK=OFFDLIB_USE_MKL_FFT=OFF)

This package does not compile the Thrift compiler by default. Nor does it
compile the thriftz and thrifnb libraries. It just builds the basic thrift
library, without SSL support. To compile the Thrift compiler, you must pass in
custom CMake arguments in your toolchain, namely BUILD_COMPILER=ON.
Similarly, to build thriftz, pass WITH_ZLIB=ON. To build thriftnb,
pass WITH_LIBEVENT=ON. To compile with SSL support, pass WITH_OPENSSL=ON.

ArrayFire - general-purpose library that simplifies the process of developing software that targets parallel and massively-parallel architectures including CPUs, GPUs, and other hardware acceleration devices.

This is a guide for adding new package to Hunter. We start with the simple
one (CMake based, no dependencies), then cover ‚Äúhunterization‚ÄĚ (CMake based,
depends on other packages). Final is a most complex one (non-CMake packages,
creating custom build scheme).

If your CMake code is correctly written and has no dependencies then release
with sources can be used as is in Hunter. There is no need to have
HunterGate/hunter_add_package calls and no need to have a maintenance fork.

Note that this is kind of a natural limitation because otherwise Hunter have
to save the whole outside environment like default paths, environment
variables, etc. This is not doable on practice.

Exception is the variables related to compiler/toolchain like compiler version,
compiler id, platforms, generators, architectures: WIN32, IOS,
ANDROID, etc. Number of such traits is limited and forms
toolchain-id.

The easiest way to integrate installed libraries into other project is to use
find_package
command. Project should generate and install *Config.cmake files instead
of using Find*.cmake modules. It‚Äôs the one of the painless ways to support
relocation - imported targets can be cached and downloaded as prebuilt binary
archive from build servers. Plus only imported targets works nicely with non
standard build types like MinSizeRel or RelWithDebInfo.

To check this feature you can try to install files to local directory.
If result of installation looks like this:

Add this information to cmake/projects/hunter_box_1/hunter.cmake file:

# !!! DO NOT PLACE HEADER GUARDS HERE !!!include(hunter_add_version)include(hunter_cacheable)include(hunter_download)include(hunter_pick_scheme)hunter_add_version(PACKAGE_NAMEhunter_box_1VERSION1.0.0URL"https://github.com/hunterbox/hunter_box_1/archive/v1.0.0.tar.gz"SHA1c724e0f8a4ebc95cf7ba628b89b998b3b3c2697d)hunter_pick_scheme(DEFAULTurl_sha1_cmake)hunter_cacheable(hunter_box_1)hunter_download(PACKAGE_NAMEhunter_box_1)

Note that it does not make sense to build and install stuff like examples,
tests or documentation. Please check that your package has CMake options to
disable those. If such an option is not disabled by default use
hunter_cmake_args:

...: error MSB3491: Could not write lines to file "...".
The specified path, file name, or both are too long. The fully qualified file
name must be less than 260 characters, and the directory name must be less than
248 characters

If some toolchains are working and some toolchains failed it means the project
has platform-specific problems. Note that you don‚Äôt have to have all
toolchains working and there is no need to fix all issues you see.
If at least something is working then you can exclude broken
toolchains and you or somebody else can apply fixes later.

Please follow these guidelines when disabling toolchains:

Do not remove toolchains from .travis.yml/appveyor.yml configs.
Comment it out instead to simplify enabling it back.

Note that now the main project Bar and the hunter dependency Roo contain
a HunterGate command. The URL and SHA1 of the HunterGate command my not match.
In this case the URL and SHA1 of the main project Bar are used for both
HunterGate commands. The user does not need to manage them manually.
The same is true for sub-projects added by add_subdirectory calls.

Very often, you will come across a package that uses autotools as its build
system and does not support CMake builds. Although Hunter prefers CMake builds
when possible, it does support autotools projects when no CMake build is
available. Here is how to do it.

When following this pkg-config practice and attempting to keep foo
cacheable, you must add this piece of code to your package‚Äôs hunter.cmake:

hunter_download(PACKAGE_NAMEfooPACKAGE_INTERNAL_DEPS_ID"1"# Increment for each new pull requestPACKAGE_UNRELOCATABLE_TEXT_FILESlib/pkgconfig/foo.pc)

The pkg-config files will probably need to be patched so that they do not point
to the directory they are initially installed into.
PACKAGE_UNRELOCATABLE_TEXT_FILES identifies these files for Hunter to patch.

If the autotools build does not produce a pkg-config output file, you must
add Findfoo.cmake place it in the cmake/find directory so Hunter can
find the package. This script should also provide import targets for dependent
builds, such that linking against foo::foo pulls in the foo includes and
libraries. In this case, dependent projects will use code similar to the following:

Non-CMake projects can be added too. But sometimes it‚Äôs not a trivial task
(for example there are a 3 custom schemes for OpenSSL. In general it‚Äôs better to
apply a patch to an existing CMake build and use CMake (no dependencies) add
instruction. Anyway here is a guide how to add a project with custom build:

If the package has not been updated in some time, the CI toolchains
may have fallen out of date. It is preferable to keep the CI
configuration in sync with the working defaults from pkg.template
to make sure the package will build with recent compilers and to help
ensure cache hits for any required Hunter managed dependencies.

Once the tests are passing, and all required toolchain modifications have been applied to the ci fork in pkg.hunter_box_1 via pull requests (see above), the original package update in pr.hunter_box_1 should then be pushed to your Hunter fork (origin in above discussions):

[hunter]> git push -u origin pr.hunter_box_1

Finally, a pull request should be opened to send the package update to the main Hunter repository, as illustrated in the previous section pull request screen shot.

If you want to create new fork let me know about it in a corresponding issue
with ‚Äúnew package‚ÄĚ label, I will create a new team and add you so you can
push changes.

Please follow next rules:

Instead of pushing changes directly to branch, open pull request so other
developers can review your changes.

Rebase your changes, check that history has not merge commits. In this
case it will be easier to do review and reuse your work in future.

Start working on patches from latest stable upstream tag. I.e. if latest
release is v1.3.15 then create branch hunter-1.3.15 and add
patches there. If you want to have version that is not released yet, say
da39a3e, then create branch hunter-1.3.15-da39a3e. If there are not
tags in upstream then start with dummy v0.0.0 version to avoid conflict
with future releases, i.e. create branch hunter-0.0.0-da39a3e.

Keep other branches in a clean state so we can always do
gitmerge--ff-only from upstream.

Please do push commits only related to hunterization. Do not push general
fixes and improvements, do push them upstream instead. Perfect
hunterization should contain only:

Test your changes. Add temporary release to Hunter system and
check that hunter_add_package(foo) is actually working. Do it at least
for one toolchain locally but of course it will be
better if you test all of them remotely.

Note that I‚Äôm not willing and can‚Äôt maintain all packages in practice. Therefore
I do add all developers to the team if they ask to. If you want to be
a maintainer, keep eye on changes, pull requests, be responsible for review
and releases - let me know.

Also note that Hunter is designed to have zero maintenance for such tasks,
since you can add HUNTER_ENABLED=OFF option at the top of the project
to skip all package management stuff (see Backward compatibility). It
means you can push branch hunter to upstream without affecting
functionality of the project. As a summary it may sounds strange, but the final
goal of this organization is to have no forks of packages at all.

Since local.properties contains information about local machine
you should add it to
.gitignore.

Please check that cmake.dir has such value that <cmake.dir>/bin/cmake
executable exists.

At this moment you can launch Android Studio and open your project but
note that Gradle will start configuring, it will trigger CMake configuration
which will trigger Hunter builds for 3 architectures:

Not all CMake files necessary for build will be created if initial
configure step will fail. In this case you can add return() command
right after first hunter_add_package call (this is where initialization
is happening and all *-ID calculated) to mimic successful CMake
configure step:

It means that debugger can be used to step into md5 package source code.
Open hello-jni.cpp file and set breakpoint to md5_append call:

Click Debug'app'(Shift+F9) to run application in Debug mode.
After application started click CALCULATE button on device.
When debugger will reach md5_append call click StepInto(F7).
As you can see debugger stepped into md5.c source code of third party
md5 package and ‚Äúdata‚ÄĚ with value ‚ÄúSome string‚ÄĚ passed to ‚Äúmd5_append‚ÄĚ function:

CMake toolchain file used to
customize third party packages builds in Hunter. And since Android Studio
provide it‚Äôs own toolchain for build such action do introduce a little quirk.
Some of the variables like ANDROID_ABI was read from command line and is
not part of the toolchain, hence Hunter will not forward them to third parties.
User also may want to add extra settings to toolchain. And one more problem is
that variables provided by Android Studio toolchain little bit differs from
ones expected by project that relies on CMAKE_ANDROID_* conventions
(introduced in CMake 3.7).

As a workaround for all the issues above we can inject our own toolchain with
FORCE.

GitHub creates release archives on-the-fly and they are not guaranteed to be
stable. This fact was discovered after few years of relying on the assumption
of stability of such archives :)

In most cases the problem can be solved just by updating Hunter to latest
version and using latest packages version in case you have saved non-default
versions in LOCAL.

There will be no automatic update of hashes introduced since it affects binary
cache, hence all the packages should be re-uploaded. And upload procedure is not
automatic yet. Instead update will be introduced on demand.

The best solution is to find archive with old SHA1 in local
Download directory. Then upload it as asset
attached to the same release tag and add new URL to Hunter. In this case it
will fix new builds and keep old cache binaries, feel free to open new issue
and provide the link to old archive.

Mixing package managers in general is a bad idea (see for example
Macports and Homebrew). Such approach
may lead to conflicts, violates
automatic downloads principle and making impossible
the usage of central server with binaries because it‚Äôs hard to obtain an
information about dependency. Also it does break reproducibility feature of
Hunter since version of system package may differs for different OS, e.g.
default version of Boost on Ubuntu14.04 is 1.54.0 and for Ubuntu16.04 it‚Äôs 1.58.0. Secondly if current version of installed system
package fit your needs it may not be true after you perform an upgrade. Hunter
has a ‚Äústatic‚ÄĚ nature: for good or for bad nothing will change until you
substitute arguments of HunterGate module.

Note that Hunter can install packages in the same way as regular package
managers do: you can set all build types to Release, BUILD_SHARED_LIBS=ON
and upload binaries to public. So the question
HowtomakeHunterinteractwithsystemlibraries? should really be
HowtoimproveHuntersoitbehaveslikesystempackagemanager?, e.g.
add new packages that are currently missing.

If settings and environment of your local project does not match environment
of Travis/AppVeyor services (this is where binaries usually uploaded from)
you will see Cachemiss message and package will be build locally:

Forks put the burden of pushing new
branches/releases from upstream, merging and resolving conflicts by maintainers
and at the first view look like a bad, aggressively intrusive choice. But in
practice it‚Äôs the clearest, robust and universal solution for all the issues
related to integration of package into Hunter.

Note

Forks are not requirement. Hunterization changes can be pushed upstream
without affecting main functionality, see
compatibility for details. And if package
has no dependencies it can be used as is in Hunter,
see examples.

Note

As already noted here all the issues that are
not related to hunterization should be pushed upstream. Including most of
the issues described in this section.

Assuming that we can‚Äôt change the order of include paths (local includes
should have higher priority than external because different version of same
package itself can be installed in system) there is no ‚Äúsoft‚ÄĚ solution here
and the only way to integrate package is to removedmlc folder from
sources. In practice it means forking the project and applying ‚Äúremove folder‚ÄĚ
patch. Note that it really doesn‚Äôt depend on the package manager, build system
or C++ compiler. All C++ compilers works similar to

> c++ -I/path/to/local -I/path/to/external ...

Meaning #include<dmlc/timer.h> will always fall to the choice of picking
local files.

Another way to avoid forks is to keep needed *.patch files in Hunter and
apply them to upstream releases before running build instructions. Such approach
used by Homebrew and Gentoo
for example. In practice such set of patches can be quite big, e.g. 19 commits
for package OpenCV (add HunterGate module, lock version in
HunterGate, adding hunter_add_package calls, applying ANDROID_*
variables introduced by new CMake version and general improvements):

At this moment there are 29 versions of OpenCV available for users, hence
it will be 19 x 29 = 551 *.patch files to maintain. Some of them can be
shared between versions, some of them can be fused with each other, etc.
If such approach will be chosen we will end up with system for maintaining
patches, but there is no need to reinvent the wheel, such system already
exist and called Git. Assuming the fact that Hunter project hosted on
GitHub and GitHub offer free unlimited repositories for public projects there
are no real reasons to choose *.patch approach over forks. The use of
the forks allow us to rebase, merge, cherry-pick, discuss and review the patches
easily.

High cohesion means that you should keep parts of a code base that are related
to each other in a single place [1]. The fact that version v1.0 of package
Foo works fine with Hunter archive v0.10 is perfectly expressed by
adding child commit AddHunterv0.10 to parent commit Foov1.0. Change
of dependencies from version to version is another example.

Having CMake build instructions in package is the easiest way to integrate
package into Hunter (but not the only one) however
not all developers of the upstream projects are ready to accept CMake code
because it may put burden
on maintaining another build system (if CMake added as extra build system),
learning new build system (if you want to substitute existing system with CMake)
or increase CMake minimum version to introduce new code.
https://github.com/hunter-packages is a central place where CMake friendly code
can leave and shared with others.

Overwhelming majority of projects use FindXXX.cmake (or even something like
find_library) instead of recommended XXXConfig.cmake approach,
effectively making project non-relocatable. It‚Äôs not a problem for the package
managers that are using single-root directory (e.g. /usr/lib for
apt-get on Ubuntu and /usr/local/lib for brew on OSX) but since
Hunter allow to have
multiple custom configurations
it will not work.

Usually hunter_add_package(foo) call placed right before similar
find_package(foo...) call, hence it raise the question: ‚ÄúIf most of the
information is inside find_package already will it be possible to get rid
of the hunter_add_package?‚ÄĚ.

TL;DR It is possible but implementation will be tricky and usefulness of such
feature in practice is quite questionable.

Not all type of packages does found by find_package. For example extra
sources or data for testing use *_ROOT variables which added to the
current scope by hunter_add_package:

Meaning that hunter_add_package will still exist and user will have to
remember that sometimes magical download hook is inside find_package and
sometimes hunter_add_package have to be called explicitly.

Mixing unrelated functionality. hunter_add_package(foo) will download
and install foo package while find_package(foo) should only look up
for files in read-only mode. When user see the code like this:

hunter_add_package(foo)find_package(foo1.22CONFIGREQUIRED)

It‚Äôs clear here that version 1.22 will not be used while downloading
package since it goes afterhunter_add_package call and result of
hunter_add_package call is an installed package. If package will be
installed by hook in find_package:

find_package(foo1.22CONFIGREQUIRED)

User might got a feeling that version 1.22 is installed, which is not
guaranteed.

The change of find_package behavior will have fragile implementation. As
an example: you can introduce custom macro find_package and call standard
CMake instructions by using _find_package. It‚Äôs undocumented CMake
feature of saving previous function under underscore starting name.
Overwriting standard CMake calls simply look like a hack in my opinion. I
think if you have an idea that can be solved this way, then it make sense to
either design and implement it in CMake itself or don‚Äôt touch original code
and wrap your extra functionality in separate function. As you understand
Hunter pick the latter. Also this approach will not work if user will
introduce his own custom find_package hook, or will use
include(FindXXX)/find_library. All this are errors that should be
fixed anyway but it just show an example that you will have to patch the
original code effectively nullifying the benefits of this hook.

As showed in F.A.Q.: Why do we need forks?
the adding of hunter_add_package is a relatively quite small amount of
code comparing to the rest of the patch needed in practice. Such optimization
is only look useful at the first glance. If you try to do few practical
examples you will see that it‚Äôs not a big deal and not worth optimization at
all, at least for now.

So the choice here is between a clean, simple and universal solution introduced
by hunter_add_package and tricky, undocumented, surprising for user
implementation that will still not cover all the scenarios.

If package is already installed then overhead for each hunter_add_package
call is a check of one DONE stamp file,
e.g. is equal to if(EXISTS"/path/to/DONE"). Penalty for such action is
hardly measurable.

If package is not installed then an archive with binaries can be
downloaded from server. There will be no source
download step performed for package or dependencies, and of course there will be
no configure/build/install steps.

If binaries for the package are not available on server then we have to build
package from sources. Archive with sources will be downloaded once,
configure/build/install steps will be performed once too. Results will be
shared between several local projects.

By default HUNTER_STATUS_DEBUG option is OFF
and you may not see some Hunter activity. If you think that Hunter hangs at
some point then this option is probably need to be set to ON.

Variable HUNTER_CONFIGURATION_TYPES by
default set to Release + Debug, meaning that build time is longer about
twice compared to a single Release build. Final size of the package usually
will be more than twice.

Prefer latest Hunter version and default package version. E.g. Windows platform
is known to have performance issues while unpacking big archives. On Windows
with default anti-virus turned on Boost 1.66.0 archive took more than 4 minutes
to unpack, if anti-virus turned off it‚Äôs about 30 (!) seconds (on Linux machine
with the weaker hardware it took less than 10 seconds). Hunter by default used
1.66.0-p0 patched archive with removed examples, tests and documentation. This
reduce the size from 70.7 MB to 17.7 MB, the unpack time dropped to 8 seconds.
As usual downloading from cache is the best option, e.g. Boost.system Release
+ Debug archive has 154 KB size:

Each CMake configure step will trigger calculation of
Hunter-ID/Config-ID/Toolchain-ID triple. While Hunter-ID and
Config-ID have small overhead, the calculation of Toolchain-ID for
some generators can be noticeable. To calculate Toolchain-ID Hunter will
create isolated project with one C++ file, and for example with Xcode generator
it may take much longer then with Makefile generator:

When this option is ON user is responsible for correctness of
Toolchain-ID value on updates of compiler and compiler flags. E.g. you have
to set this option to OFF explicitly for every local project when you do
change CXX environment variable, upgrade compiler, update or switch Xcode
version, when you change CMAKE_TOOLCHAIN_FILE path or content of CMake
toolchain. Violation of this rule can lead to invalid unrecoverable cache state.
Because of this it‚Äôs highly recommended not to use this option on machine
which can be used to build and upload binaries. Note that Hunter will upload
all archives from Cache directory, not only packages build by current
local project.

As an example here are actions that can lead to incorrect cache state: