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

Add automatic Hunter package release / easy setup with FetchContent #2

Merged
merged 1 commit into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
168 changes: 146 additions & 22 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,33 +1,157 @@
# Copyright (c) 2013-2014, Ruslan Baratov
# Copyright (c) 2019 Cristian Adam
# All rights reserved.

cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.2)

include("cmake/HunterGate.cmake")

# 1. Try to detect hunter by:
# * cmake variable
# * environment variable
# * in HOME (`.hunter` directory)
# * in SYSTEMDRIVE (`.hunter` directory, windows only)
# * in USERPROFILE (`.hunter` directory, windows only)
# 2. if failed, download it
# 3. set HUNTER_GATE_* variables
# 4. include master file: 'include(${HUNTER_SELF}/cmake/Hunter)
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.18.12.tar.gz"
SHA1 "7e8c74787e08c476484d3e5106524fe7a5a0cc56"
if (NOT HUNTER_URL AND NOT HUNTER_SHA1)
file(
DOWNLOAD https://api.github.com/repos/cpp-pm/hunter/releases/latest
${CMAKE_BINARY_DIR}/LatestGate.json)

file(READ ${CMAKE_BINARY_DIR}/LatestGate.json latestGateJson)
string(REGEX MATCH "tag_name\": \"([a-z0-9.]+)\"" tagName "${latestGateJson}")

set(hunterUrlTarball "https://github.com/cpp-pm/hunter/archive/${CMAKE_MATCH_1}.tar.gz")
set(hunterLocalTarballName "${CMAKE_BINARY_DIR}/hunter-${CMAKE_MATCH_1}.tar.gz")

file(DOWNLOAD ${hunterUrlTarball} "${hunterLocalTarballName}")

file(SHA1 "${hunterLocalTarballName}" HUNTER_SHA1)
set(HUNTER_URL "file://${hunterLocalTarballName}")
endif()

if (NOT HUNTER_LOCAL_CONFIG OR
NOT HUNTER_GLOBAL_CONFIG OR
NOT HUNTER_FILEPATH_CONFIG OR
HUNTER_PACKAGES)
# Write the Hunter Configuration file
file(WRITE ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in "")
foreach(package IN LISTS HUNTER_PACKAGES)
file(APPEND ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in
"hunter_config(${package}
VERSION ")
if (HUNTER_${package}_VERSION)
file(APPEND ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in
"${HUNTER_${package}_VERSION}")
else()
file(APPEND ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in
"\${HUNTER_${package}_VERSION}")
endif()

if (HUNTER_${package}_CMAKE_ARGS)
file(APPEND ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in "
CMAKE_ARGS \${HUNTER_${package}_CMAKE_ARGS}")
endif()

file(APPEND ${CMAKE_BINARY_DIR}/HunterConfig.cmake.in ")\n\n")
endforeach()
configure_file(
${CMAKE_BINARY_DIR}/HunterConfig.cmake.in
${CMAKE_BINARY_DIR}/HunterConfig.cmake @ONLY)
endif()

unset(HUNTER_GATE_CONFIG)
if (HUNTER_LOCAL_CONFIG)
set(HUNTER_GATE_CONFIG LOCAL)
elseif (HUNTER_GLOBAL_CONFIG)
set(HUNTER_GATE_CONFIG GLOBAL ${HUNTER_GLOBAL_CONFIG})
elseif (HUNTER_FILEPATH_CONFIG)
set(HUNTER_GATE_CONFIG FILEPATH ${HUNTER_FILEPATH_CONFIG})
elseif (HUNTER_PACKAGES)
set(HUNTER_GATE_CONFIG FILEPATH ${CMAKE_BINARY_DIR}/HunterConfig.cmake)
endif()

file(WRITE
${CMAKE_BINARY_DIR}/HunterSetup.cmake.in
"include(${CMAKE_BINARY_DIR}/HunterGate.cmake)\n"
"HunterGate(
URL ${HUNTER_URL}
SHA1 ${HUNTER_SHA1}
${HUNTER_GATE_CONFIG}
)\n"
)

project(gate-usage-example)
configure_file(
${CMAKE_BINARY_DIR}/HunterSetup.cmake.in
${CMAKE_BINARY_DIR}/HunterSetup.cmake @ONLY)

# Build only the current CMAKE_BUILD_TYPE
if (NOT HUNTER_CONFIGURATION_TYPES)
set(HUNTER_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE STRING "Configurations HUNTER will build")
endif()

include(${CMAKE_BINARY_DIR}/HunterSetup.cmake)

#
# Create a toolchain file
#

file(WRITE ${CMAKE_BINARY_DIR}/HunterToolchain.cmake.in
[=[
# Add hunter install directory to the find_package variables
if (EXISTS "${CMAKE_BINARY_DIR}/_3rdParty/Hunter/install-root-dir")
file(READ ${CMAKE_BINARY_DIR}/_3rdParty/Hunter/install-root-dir HunterInstall)
list(APPEND CMAKE_FIND_ROOT_PATH \"${HunterInstall}\")
list(APPEND CMAKE_PREFIX_PATH \"${HunterInstall}\")
endif()
]=])

if(ANDROID_ABI AND ANDROID_NATIVE_API_LEVEL)
file(APPEND ${CMAKE_BINARY_DIR}/HunterToolchain.cmake.in
"set(ANDROID_ABI ${ANDROID_ABI})\n"
"set(ANDROID_NATIVE_API_LEVEL ${ANDROID_NATIVE_API_LEVEL})\n"
# Android has RPATH, and we dont' have to relink when installed\n"
"set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)\n")
endif()

foreach(lang IN ITEMS C CXX)
if(CMAKE_${lang}_COMPILER_LAUNCHER)
file(APPEND ${CMAKE_BINARY_DIR}/HunterToolchain.cmake.in
"set(CMAKE_${lang}_COMPILER_LAUNCHER ${CMAKE_${lang}_COMPILER_LAUNCHER})\n")
endif()
endforeach()

if (CMAKE_TOOLCHAIN_FILE)
file(APPEND ${CMAKE_BINARY_DIR}/HunterToolchain.cmake.in
"include(\"${CMAKE_TOOLCHAIN_FILE}\")\n")
endif()

configure_file(
${CMAKE_BINARY_DIR}/HunterToolchain.cmake.in
${CMAKE_BINARY_DIR}/HunterToolchain.cmake @ONLY)

# Setup a project, and add the packages
project(HunterSetup)

#
# Building the packages
#

# Build the hunter packages with the configured toolchain
if (CMAKE_TOOLCHAIN_FILE)
set(ORIGINAL_TOOLCHAIN_FILE ${CMAKE_TOOLCHAIN_FILE})
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/HunterToolchain.cmake)
endif()

foreach(package IN LISTS HUNTER_PACKAGES)
unset(_package_components)
if (HUNTER_${package}_COMPONENTS)
set(_package_components COMPONENTS ${HUNTER_${package}_COMPONENTS})
endif()
hunter_add_package(${package} ${_package_components})
endforeach()

# now hunter can be used, like
hunter_add_package(Sugar)
# Restore the original TOOLCHAIN_FILE
if (ORIGINAL_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "${ORIGINAL_TOOLCHAIN_FILE}")
endif()

# add downloaded package to project
include("${SUGAR_ROOT}/cmake/Sugar")
include(sugar_status_print)
#
# Make sure the parent find_package calls work as expected
#

# use downloaded package
set(SUGAR_STATUS_PRINT ON CACHE BOOL "")
sugar_status_print("Hello!")
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} PARENT_SCOPE)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
150 changes: 139 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,145 @@
[appveyor_status]: https://ci.appveyor.com/api/projects/status/nmkbcuoxwre7w2jp/branch/master?svg=true
[appveyor_builds]: https://ci.appveyor.com/project/ruslo/gate/branch/master

This is a gate file to [Hunter](https://github.com/ruslo/hunter) package manager.
This is a gate file to [Hunter](https://github.com/cpp-pm/hunter) package manager.

The gate project will download the latest [packages archive release](https://github.com/cpp-pm/hunter/releases/), unless `HUNTER_URL` and `HUNTER_SHA1` are configured.

The gate project will issue `hunter_add_package` to all packages specified in `HUNTER_PACKAGES` list. For every package it will create a `hunter_config`
in which `VERSION` and `CMAKE_ARGS` variables will be set.

For manual configuration of `hunter_config` file you can set the `HUNTER_LOCAL_CONFIG`, `HUNTER_GLOBAL_CONFIG`, or `HUNTER_FILEPATH_CONFIG` variables.

The gate project will set `CMAKE_BUILD_TYPE` as `HUNTER_CONFIGURATION_TYPES`, so that if you're building `Release` you won't be getting a `Debug` build of the packages.

The gate project will create a `HunterToolchain.cmake` file which will set up the `CMAKE_PREFIX_PATH` and `CMAKE_FIND_ROOT_PATH` variables with the installed path of the Hunter packages.
If a `CMAKE_TOOLCHAIN_FILE` was used during compilation, it will be included in the `HunterToolchain.cmake` file.

## Usage

Setting up Hunter, and adding a package list is as easy as:

```cmake
# FetchContent is available since CMake version 3.11
cmake_minimum_required(VERSION 3.11)

# Setting up dlib as an external package
set(HUNTER_PACKAGES dlib)

include(FetchContent)
FetchContent_Declare(SetupHunter GIT_REPOSITORY https://github.com/cpp-pm/gate)
FetchContent_MakeAvailable(SetupHunter)

# Using the dlib package
find_package(dlib REQUIRED)
target_link_libraries(myapp PRIVATE dlib::dlib)
```

## Usage with custom CMake variables per package
```cmake
set(HUNTER_pcre2_CMAKE_ARGS
PCRE2_BUILD_PCRE2_8=OFF
PCRE2_BUILD_PCRE2_16=ON
PCRE2_BUILD_PCRE2_32=OFF
PCRE2_SUPPORT_JIT=ON)

set(HUNTER_PACKAGES pcre2)
```

## Usage with package components
```cmake
set(HUNTER_Boost_COMPONENTS Filesystem Python)
set(HUNTER_PACKAGES Boost)
```

## Usage with specific package version
```cmake
set(HUNTER_fmt_VERSION 5.3.0)
set(HUNTER_PACKAGES fmt)
```

## Usage with specific Hunter Gate
```cmake
set(HUNTER_URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz")
set(HUNTER_SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be")

set(HUNTER_PACKAGES fmt ZLIB)

include(FetchContent)
FetchContent_Declare(SetupHunter GIT_REPOSITORY https://github.com/cpp-pm/gate)
FetchContent_MakeAvailable(SetupHunter)
```

## Usage with HunterToolchain.cmake

This allows building the 3rd party packages separate than the user projects, and simply use CMake's
`find_package` with no usage of Hunter at all.

```cmake
cmake_minimum_required(VERSION 3.11)

set(HUNTER_PACKAGES freetype ZLIB PNG double-conversion pcre2)

set(HUNTER_pcre2_CMAKE_ARGS
PCRE2_BUILD_PCRE2_8=OFF
PCRE2_BUILD_PCRE2_16=ON
PCRE2_BUILD_PCRE2_32=OFF
PCRE2_SUPPORT_JIT=ON)

include(FetchContent)
FetchContent_Declare(SetupHunter GIT_REPOSITORY https://github.com/cpp-pm/gate)
FetchContent_MakeAvailable(SetupHunter)

project(3rdparty)
```

Then compile your project with:
```
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/your/3rdparty/build/HunterToolchain.cmake
```

## Usage with explicit config
```cmake
file(WRITE ${CMAKE_BUILD_DIR}/HunterConfig.cmake [=[
hunter_config(zlib VERSION 1.2.8)

hunter_config(pcre2
VERSION ${HUNTER_pcre2_VERSION}
CMAKE_ARGS
PCRE2_BUILD_PCRE2_8=OFF
PCRE2_BUILD_PCRE2_16=ON
PCRE2_BUILD_PCRE2_32=OFF
PCRE2_SUPPORT_JIT=ON
)
]=])

set(HUNTER_URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz")
set(HUNTER_SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be")
set(HUNTER_FILEPATH_CONFIG ${CMAKE_BUILD_DIR}/HunterConfig.cmake)

include(FetchContent)
FetchContent_Declare(SetupHunter GIT_REPOSITORY https://github.com/cpp-pm/gate)
FetchContent_MakeAvailable(SetupHunter)

hunter_add_package(ZLIB)
hunter_add_package(pcre2)

find_package(ZLIB CONFIG REQUIRED)
find_package(pcre2 CONFIG REQUIRED)

add_executable(boo main.c)
target_link_libraries(boo PRIVATE ZLIB::zlib PCRE2::PCRE2)
```

## Usage (manual)

* Copy file `HunterGate.cmake` to project
* Include gate file: `include("cmake/HunterGate.cmake")`
* Put any valid [Hunter](https://github.com/ruslo/hunter/releases) archive with `SHA1` hash:
* Put any valid [Hunter](https://github.com/cpp-pm/hunter/releases) archive with `SHA1` hash:
```cmake
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.7.0.tar.gz"
SHA1 "e730118c7ec65126398f8d4f09daf9366791ede0"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz"
SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be"
)
```

Expand All @@ -29,8 +157,8 @@ Optionally custom [config.cmake][1] file can be specified. File may has differen
* `GLOBAL`. The one from Hunter archive:
```cmake
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.7.0.tar.gz"
SHA1 "e730118c7ec65126398f8d4f09daf9366791ede0"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz"
SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be"
GLOBAL myconfig
# load `${HUNTER_SELF}/cmake/configs/myconfig.cmake` instead of
# default `${HUNTER_SELF}/cmake/configs/default.cmake`
Expand All @@ -39,16 +167,16 @@ HunterGate(
* `LOCAL`. Default local config.
```cmake
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.7.0.tar.gz"
SHA1 "e730118c7ec65126398f8d4f09daf9366791ede0"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz"
SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be"
LOCAL # load `${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/config.cmake`
)
```
* `FILEPATH`. Any location.
```cmake
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.7.0.tar.gz"
SHA1 "e730118c7ec65126398f8d4f09daf9366791ede0"
URL "https://github.com/cpp-pm/hunter/archive/v0.23.224.tar.gz"
SHA1 "18e57a43efc435f2e1dae1291e82e42afbf940be"
FILEPATH "/any/path/to/config.cmake"
)
```
Expand Down Expand Up @@ -80,7 +208,7 @@ HunterGate(
* [Weather](https://github.com/ruslo/weather)

## Links
* [Hunter](https://github.com/ruslo/hunter)
* [Hunter](https://github.com/cpp-pm/hunter)
* [Some packages](https://github.com/ruslo/hunter/wiki/Packages)

[1]: https://github.com/ruslo/hunter/blob/master/cmake/configs/default.cmake
Expand Down