Giter VIP home page Giter VIP logo

cpm.cmake's Introduction



Setup-free CMake dependency management

CPM.cmake is a cross-platform CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper around CMake's FetchContent module that adds version control, caching, a simple API and more.

Manage everything

Any downloadable project or resource can be added as a version-controlled dependency through CPM, it is not necessary to modify or package anything. Projects using modern CMake are automatically configured and their targets can be used immediately. For everything else, the targets can be created manually after the dependency has been downloaded (see the snippets below for examples).

Further reading

Full CMakeLists Example

cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

# create project
project(MyProject)

# add executable
add_executable(main main.cpp)

# add dependencies
include(cmake/CPM.cmake)

CPMAddPackage("gh:fmtlib/fmt#7.1.3")
CPMAddPackage("gh:nlohmann/[email protected]")
CPMAddPackage("gh:catchorg/[email protected]")

# link dependencies
target_link_libraries(main fmt::fmt nlohmann_json::nlohmann_json Catch2::Catch2WithMain)

See the examples directory for complete examples with source code and check below or in the wiki for example snippets.

Adding CPM

To add CPM to your current project, simply add the latest release of CPM.cmake or get_cpm.cmake to your project's cmake directory. The command below will perform this automatically.

mkdir -p cmake
wget -O cmake/CPM.cmake https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake

You can also download CPM.cmake directly from your project's CMakeLists.txt. See the wiki for more details.

Usage

After CPM.cmake has been added to your project, the function CPMAddPackage can be used to fetch and configure a dependency. Afterwards, any targets defined in the dependency can be used directly. CPMAddPackage takes the following named parameters.

CPMAddPackage(
  NAME          # The unique name of the dependency (should be the exported target's name)
  VERSION       # The minimum version of the dependency (optional, defaults to 0)
  PATCHES       # Patch files to be applied sequentially using patch and PATCH_OPTIONS (optional)
  OPTIONS       # Configuration options passed to the dependency (optional)
  DOWNLOAD_ONLY # If set, the project is downloaded, but not configured (optional)
  [...]         # Origin parameters forwarded to FetchContent_Declare, see below
)

The origin may be specified by a GIT_REPOSITORY, but other sources, such as direct URLs, are also supported. If GIT_TAG hasn't been explicitly specified it defaults to v(VERSION), a common convention for git projects. On the other hand, if VERSION hasn't been explicitly specified, CPM can automatically identify the version from the git tag in some common cases. GIT_TAG can also be set to a specific commit or a branch name such as master, however this isn't recommended, as such packages will only be updated when the cache is cleared.

PATCHES takes a list of patch files to apply sequentially. For a basic example, see Highway.

If an additional optional parameter EXCLUDE_FROM_ALL is set to a truthy value, then any targets defined inside the dependency won't be built by default. See the CMake docs for details.

If an additional optional parameter SYSTEM is set to a truthy value, the SYSTEM directory property of the subdirectory added will be set to true. See the add_subdirectory and SYSTEM target property for details.

A single-argument compact syntax is also supported:

# A git package from a given uri with a version
CPMAddPackage("uri@version")
# A git package from a given uri with a git tag or commit hash
CPMAddPackage("uri#tag")
# A git package with both version and tag provided
CPMAddPackage("uri@version#tag")

In the shorthand syntax if the URI is of the form gh:user/name, it is interpreted as GitHub URI and converted to https://github.com/user/name.git. If the URI is of the form gl:user/name, it is interpreted as a GitLab URI and converted to https://gitlab.com/user/name.git. If the URI is of the form bb:user/name, it is interpreted as a Bitbucket URI and converted to https://bitbucket.org/user/name.git. Otherwise the URI used verbatim as a git URL. All packages added using the shorthand syntax will be added using the EXCLUDE_FROM_ALL and SYSTEM flag.

The single-argument syntax also works for URLs:

# An archive package from a given url. The version is inferred
CPMAddPackage("https://example.com/my-package-1.2.3.zip")
# An archive package from a given url with an MD5 hash provided
CPMAddPackage("https://example.com/my-package-1.2.3.zip#MD5=68e20f674a48be38d60e129f600faf7d")
# An archive package from a given url. The version is explicitly given
CPMAddPackage("https://example.com/[email protected]")

After calling CPMAddPackage, the following variables are defined in the local scope, where <dependency> is the name of the dependency.

  • <dependency>_SOURCE_DIR is the path to the source of the dependency.
  • <dependency>_BINARY_DIR is the path to the build directory of the dependency.
  • <dependency>_ADDED is set to YES if the dependency has not been added before, otherwise it is set to NO.
  • CPM_LAST_PACKAGE_NAME is set to the determined name of the last added dependency (equivalent to <dependency>).

For using CPM.cmake projects with external package managers, such as conan or vcpkg, setting the variable CPM_USE_LOCAL_PACKAGES will make CPM.cmake try to add a package through find_package first, and add it from source if it doesn't succeed.

In rare cases, this behaviour may be desirable by default. The function CPMFindPackage will try to find a local dependency via CMake's find_package and fallback to CPMAddPackage, if the dependency is not found.

Updating CPM

To update CPM to the newest version, update the script in the project's root directory, for example by running the same command as for adding CPM. Dependencies using CPM will automatically use the updated script of the outermost project.

Advantages

  • Small and reusable projects CPM takes care of all project dependencies, allowing developers to focus on creating small, well-tested libraries.
  • Cross-Platform CPM adds projects directly at the configure stage and is compatible with all CMake toolchains and generators.
  • Reproducible builds By versioning dependencies via git commits or tags it is ensured that a project will always be buildable.
  • Recursive dependencies Ensures that no dependency is added twice and all are added in the minimum required version.
  • Plug-and-play No need to install anything. Just add the script to your project and you're good to go.
  • No packaging required Simply add all external sources as a dependency.
  • Simple source distribution CPM makes including projects with source files and dependencies easy, reducing the need for monolithic header files or git submodules.

Limitations

  • No pre-built binaries For every new build directory, all dependencies are initially downloaded and built from scratch. To avoid extra downloads it is recommend to set the CPM_SOURCE_CACHE environmental variable. Using a caching compiler such as ccache can drastically reduce build time.
  • Dependent on good CMakeLists Many libraries do not have CMakeLists that work well for subprojects. Luckily this is slowly changing, however, until then, some manual configuration may be required (see the snippets below for examples). For best practices on preparing projects for CPM, see the wiki.
  • First version used In diamond-shaped dependency graphs (e.g. A depends on C@1.1 and B, which itself depends on C@1.2 the first added dependency will be used (in this case C@1.1). In this case, B requires a newer version of C than A, so CPM will emit a warning. This can be easily resolved by adding a new version of the dependency in the outermost project, or by introducing a package lock file.
  • Some CMake policies set to NEW Including CPM.cmake will lead to several CMake policies being set to NEW. Users which need the old behavior will need to manually modify their CMake code to ensure they're set to OLD at the appropriate places. The policies are:
    • CMP0077 and CMP0126. They make setting package options from CMPAddPackage possible.
    • CMP0135 It allows for proper package rebuilds of packages which are archives, source cache is not used, and the package URL is changed to an older version.
    • CMP0150 Relative paths provided to GIT_REPOSITORY are treated as relative to the parent project's remote.

For projects with more complex needs and where an extra setup step doesn't matter, it may be worth to check out an external C++ package manager such as vcpkg, conan or hunter. Dependencies added with CPMFindPackage should work with external package managers. Additionally, the option CPM_USE_LOCAL_PACKAGES will enable find_package for all CPM dependencies.

Comparison to FindPackage

The usual way to add libraries in CMake projects is to call find_package(<PackageName>) and to link against libraries defined in a <PackageName>_LIBRARIES variable. While simple, this may lead to unpredictable builds, as it requires the library to be installed on the system and it is unclear which version of the library has been added. Additionally, it is difficult to cross-compile projects (e.g. for mobile), as the dependencies will need to be rebuilt manually for each targeted architecture.

CPM.cmake allows dependencies to be unambiguously defined and builds them from source. Note that the behaviour differs from find_package, as variables exported to the parent scope (such as <PackageName>_LIBRARIES) will not be visible after adding a package using CPM.cmake. The behaviour can be achieved manually, if required.

Comparison to pure FetchContent / ExternalProject

CPM.cmake is a wrapper for CMake's FetchContent module and adds a number of features that turn it into a useful dependency manager. The most notable features are:

  • A simpler to use API
  • Version checking: CPM.cmake will check the version number of any added dependency and emit a warning if another dependency requires a more recent version.
  • Offline builds: CPM.cmake will override CMake's download and update commands, which allows new builds to be configured while offline if all dependencies are available locally.
  • Automatic shallow clone: if a version tag (e.g. v2.2.0) is provided and CPM_SOURCE_CACHE is used, CPM.cmake will perform a shallow clone of the dependency, which should be significantly faster while using less storage than a full clone.
  • Overridable: all CPMAddPackage can be configured to use find_package by setting a CMake flag, making it easy to integrate into projects that may require local versioning through the system's package manager.
  • Package lock files for easier transitive dependency management.
  • Dependencies can be overridden per-build using CMake CLI parameters.

ExternalProject works similarly as FetchContent, however waits with adding dependencies until build time. This has a quite a few disadvantages, especially as it makes using custom toolchains / cross-compiling very difficult and can lead to problems with nested dependencies.

Options

CPM_SOURCE_CACHE

To avoid re-downloading dependencies, CPM has an option CPM_SOURCE_CACHE that can be passed to CMake as -DCPM_SOURCE_CACHE=<path to an external download directory>. This will also allow projects to be configured offline, as long as the dependencies have been added to the cache before. It may also be defined system-wide as an environmental variable, e.g. by exporting CPM_SOURCE_CACHE in your .bashrc or .bash_profile.

export CPM_SOURCE_CACHE=$HOME/.cache/CPM

Note that passing the variable as a configure option to CMake will always override the value set by the environmental variable.

You can use CPM_SOURCE_CACHE on GitHub Actions workflows cache and combine it with ccache, to make your CI faster. See the wiki for more info.

The directory where the version for a project is stored is by default the hash of the arguments to CPMAddPackage(). If for instance the patch command uses external files, the directory name can be set with the argument CUSTOM_CACHE_KEY.

CPM_DOWNLOAD_ALL

If set, CPM will forward all calls to CPMFindPackage as CPMAddPackage. This is useful to create reproducible builds or to determine if the source parameters have all been set correctly. This can also be set as an environmental variable. This can be controlled on a per package basis with the CPM_DOWNLOAD_<dependency name> variable.

CPM_USE_LOCAL_PACKAGES

CPM can be configured to use find_package to search for locally installed dependencies first by setting the CMake option CPM_USE_LOCAL_PACKAGES.

If the option CPM_LOCAL_PACKAGES_ONLY is set, CPM will emit an error if the dependency is not found locally. These options can also be set as environmental variables.

In the case that find_package requires additional arguments, the parameter FIND_PACKAGE_ARGUMENTS may be specified in the CPMAddPackage call. The value of this parameter will be forwarded to find_package.

Note that this does not apply to dependencies that have been defined with a truthy FORCE parameter. These will be added as defined.

CPM_USE_NAMED_CACHE_DIRECTORIES

If set, CPM use additional directory level in cache to improve readability of packages names in IDEs like CLion. It changes cache structure, so all dependencies are downloaded again. There is no problem to mix both structures in one cache directory but then there may be 2 copies of some dependencies. This can also be set as an environmental variable.

Local package override

Library developers are often in the situation where they work on a locally checked out dependency at the same time as on a consumer project. It is possible to override the consumer's dependency with the version by supplying the CMake option CPM_<dependency name>_SOURCE set to the absolute path of the local library. For example, to use the local version of the dependency Dep at the path /path/to/dep, the consumer can be built with the following command.

cmake -Bbuild -DCPM_Dep_SOURCE=/path/to/dep

Package lock

In large projects with many transitive dependencies, it can be useful to introduce a package lock file. This will list all CPM.cmake dependencies and can be used to update dependencies without modifying the original CMakeLists.txt. To use a package lock, add the following line directly after including CPM.cmake.

CPMUsePackageLock(package-lock.cmake)

To create or update the package lock file, build the cpm-update-package-lock target.

cmake -Bbuild
cmake --build build --target cpm-update-package-lock

See the wiki for more info.

Private repositories and CI

When using CPM.cmake with private repositories, there may be a need to provide an access token to be able to clone other projects. Instead of providing the token in CMake, we recommend to provide the regular URL and use git-config to rewrite the URLs to include the token.

As an example, you could include one of the following in your CI script.

# Github
git config --global url."https://${USERNAME}:${TOKEN}@github.com".insteadOf "https://github.com"
# GitLab
git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com".insteadOf "https://gitlab.com"

Built with CPM.cmake

Some amazing projects that are built using the CPM.cmake package manager. If you know others, feel free to add them here through a PR.

otto-project

OTTO - The Open Source GrooveBox

maphi

Maphi - the Math App

modern-cpp-starter

ModernCppStarter

liblava

liblava - Modern Vulkan library

klogg

klogg - fast advanced log explorer

MethaneKit

Methane Kit - modern 3D graphics rendering framework

JNGL

JNGL - easy to use cross-platform 2D game library

aaltitoad

AALTITOAD - verifier and simulator for Tick Tock Automata

ZIMO-Elektronik

ZIMO-Elektronik

ada

ada - WHATWG-compliant and fast URL parser written in modern C++

codon

codon - A high-performance, zero-overhead, extensible Python compiler using LLVM

CRoaring

CRoaring - Roaring bitmaps in C (and C++), with SIMD (AVX2, AVX-512 and NEON) optimizations: used by Apache Doris, ClickHouse, and StarRocks

Snippets

These examples demonstrate how to include some well-known projects with CPM. See the wiki for more snippets.

CPMAddPackage("gh:catchorg/[email protected]")
CPMAddPackage("gh:ericniebler/range-v3#0.12.0")
# as the tag is in an unusual format, we need to explicitly specify the version
CPMAddPackage("gh:jbeder/yaml-cpp#[email protected]")
CPMAddPackage(
  NAME nlohmann_json
  VERSION 3.9.1
  GITHUB_REPOSITORY nlohmann/json
  OPTIONS
    "JSON_BuildTests OFF"
)

Boost is a large project and will take a while to download. Using CPM_SOURCE_CACHE is strongly recommended. Cloning moves much more data than a source archive, so this sample will use a compressed source archive (tar.xz) release from Boost's github page.

# boost is a huge project and directly downloading the 'alternate release'
# from github is much faster than recursively cloning the repo.
CPMAddPackage(
  NAME Boost
  VERSION 1.84.0
  URL https://github.com/boostorg/boost/releases/download/boost-1.84.0/boost-1.84.0.tar.xz
  URL_HASH SHA256=2e64e5d79a738d0fa6fb546c6e5c2bd28f88d268a2a080546f74e5ff98f29d0e
  OPTIONS "BOOST_ENABLE_CMAKE ON"
)

For a working example of using CPM to download and configure the Boost C++ Libraries see here.

# the install option has to be explicitly set to allow installation
CPMAddPackage(
  GITHUB_REPOSITORY jarro2783/cxxopts
  VERSION 2.2.1
  OPTIONS "CXXOPTS_BUILD_EXAMPLES NO" "CXXOPTS_BUILD_TESTS NO" "CXXOPTS_ENABLE_INSTALL YES"
)
CPMAddPackage(
  NAME benchmark
  GITHUB_REPOSITORY google/benchmark
  VERSION 1.5.2
  OPTIONS "BENCHMARK_ENABLE_TESTING Off"
)

if(benchmark_ADDED)
  # enable c++11 to avoid compilation errors
  set_target_properties(benchmark PROPERTIES CXX_STANDARD 11)
endif()
CPMAddPackage(
  NAME lua
  GIT_REPOSITORY https://github.com/lua/lua.git
  VERSION 5.3.5
  DOWNLOAD_ONLY YES
)

if (lua_ADDED)
  # lua has no CMake support, so we create our own target

  FILE(GLOB lua_sources ${lua_SOURCE_DIR}/*.c)
  list(REMOVE_ITEM lua_sources "${lua_SOURCE_DIR}/lua.c" "${lua_SOURCE_DIR}/luac.c")
  add_library(lua STATIC ${lua_sources})

  target_include_directories(lua
    PUBLIC
      $<BUILD_INTERFACE:${lua_SOURCE_DIR}>
  )
endif()

For a full example on using CPM to download and configure lua with sol2 see here.

Full Examples

See the examples directory for full examples with source code and check out the wiki for many more example snippets.

Source Archives from GitHub

Using a compressed source archive is usually much faster than a shallow clone. Optionally, you can verify the integrity using SHA256 or similar. Setting the hash is useful to ensure a specific source is imported, especially since tags, branches, and archives can change.

Let's look at adding spdlog to a project:

CPMAddPackage(
  NAME     spdlog
  URL      https://github.com/gabime/spdlog/archive/refs/tags/v1.12.0.zip
  URL_HASH SHA256=6174bf8885287422a6c6a0312eb8a30e8d22bcfcee7c48a6d02d1835d7769232
)

URL_HASH is optional, but it's a good idea for releases.

Identifying the URL

Information for determining the URL is found here.

Release

Not every software package provides releases, but for those that do, they can be found on the release page of the project. In a browser, the URL of the specific release is determined in a browser is determined by right clicking and selecting Copy link address (or similar) for the desired release. This is the value you will use in the URL section.

This is the URL for spdlog release 1.13.0 in zip format: https://github.com/gabime/spdlog/archive/refs/tags/v1.13.0.zip

Branch

The URL for branches is non-obvious from a browser. But it's still fairly easy to figure it out. The format is as follows:

https://github.com/<user>/<name>/archive/refs/heads/<branch-name>.<archive-type>

Archive type can be one of tar.gz or zip.

The URL for branch v2.x of spdlog is: https://github.com/gabime/spdlog/archive/refs/heads/v2.x.tar.gz

Tag

Tags are similar, but with this format:

https://github.com/<user>/<name>/archive/refs/tags/<tag-name>.<archive-type>

Tag v1.8.5 of spdlog is this:

https://github.com/gabime/spdlog/archive/refs/tags/v1.8.5.tar.gz

Exactly like the release.

Commit

If a specific commit contains the code you need, it's defined as follows:

https://github.com/<user>/<name>/archive/<commit-hash>.<archive-type>

Example: https://github.com/gabime/spdlog/archive/c1569a3d293a6b511ecb9c18b2298826c9578d9f.tar.gz

Determining the Hash

The following snippet illustrates determining the SHA256 hash on a linux machine using wget and sha256sum:

wget https://github.com/gabime/spdlog/archive/refs/tags/v1.13.0.zip -O - | sha256sum

cpm.cmake's People

Contributors

alessandrow avatar clausklein avatar craighutchinson avatar developerpaul123 avatar gitter-badger avatar hacker-cb avatar higaski avatar ibob avatar jhasse avatar johelegp avatar kingsamchen avatar lemire avatar leozz37 avatar nightlark avatar olivierldff avatar percentboat4164 avatar pgorgon-hem avatar prabirshrestha avatar robertmaynard avatar rozefound avatar schtobia avatar scottbailey avatar sgssgene avatar studoot avatar thelartians avatar thomas-mp avatar tobi823 avatar trxcllnt avatar vinpasso avatar xmuller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cpm.cmake's Issues

CMake ignores existing git sources

When setting CPM_SOURCE_ROOT to an external directory, CMake will initially erase existing repositories and try to re-download them. This breaks the purpose of the feature.

Internal github repository?

Has CPM been tested with internal GitHub repositories?

My company will be switching to GitHub soon and obviously the repos aren't public.

So I'm curious how CPM works with internal repositories.

How does one go about signing/securing things? IE security problems.

If this is already possible and I didn't realize perhaps an explicit entry in the Wiki would be greatly beneficial.

load fmt as external fail

the tag of fmt has no v prefix

6.1.0
6.1.1
6.1.2
qls
v0.11.0

default strategy will add v prefix to VERSION supplying by user.

148   if (NOT DEFINED CPM_ARGS_GIT_TAG) 
149     set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION}) 
150   endif()

should we give an option to handle this situation as well as VERSION equal master?

Failure on empty CPM_SOURCE_CACHE

If CPM_SOURCE_CACHE is set to an empty string, CPM fails with file DOWNLOAD error: cannot create directory '/cpm' - Specify file by full.

Is there anyway to speed-up "configure" step with CPM?

Because I inherited an old project and there's a lot of dependencies, I don't really have a say in whether to include them or not.

Right now when I make any chanegs to the CMakeLists file, reconfiguring the cmake project literally takes like 5 mins to finish. This is largely because of CPM calling "configure" on a few old projects that do a lot of testing of different headers / platforms.

Would it be possible to mark a project as "CACHED" to configure it only once at the first load and just skip it in subsequent configures?

i.e. this is an example output I have for one such "configure" step, majority of the dependencies are never changing, so i don't think there's any need to reconfigure them

"C:\Program Files\JetBrains\CLion 2020.1\bin\cmake\win\bin\cmake.exe" -j 8 -G "Visual Studio 16 2019" -A x64 -Wno-dev -DCPM_SOURCE_CACHE=C:/Users/justb/tmp C:\Users\justb\Repos\kintek-explorer
-- The CXX compiler identification is MSVC 19.24.28314.0
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- MSVC toolchain runtime library is set to: MultiThreaded$<$<CONFIG:Debug>:Debug>
-- -Building MSVC 64 bit, x64
-- Found Git: C:/Program Files/Git/cmd/git.exe (found version "2.24.0.windows.2") 
-- Version header directory: C:/Users/justb/Repos/kintek-explorer/cmake-build-debug/include
-- Version target: version
-- Getting version of Git failed (maybe not tagged?), using backup: v0.0.0-dev-4923cbb
-- CPM: adding package zbslib@0 (v0)
-- ----- Library zbslib-1.0 start -----
-- >>> Library configured options
--      ZBSLIB_USE_KINFIT:         ON
--      ZBSLIB_USE_GLFW2:          OFF
--      ZBSLIB_USE_MULTITHREAD:    ON
--      ZBSLIB_USE_TRACEMSG:       OFF
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/gsl/ae31971594955d23ea61f9e8584cbfb6d8092a02)
-- The C compiler identification is MSVC 19.24.28314.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Got VERSION=2.5 from configure.ac
-- Got GSL_CURRENT=24 from configure.ac
-- Got GSL_REVISION=0 from configure.ac
-- Got GSL_AGE=1 from configure.ac
-- Got CBLAS_CURRENT=0 from configure.ac
-- Got CBLAS_REVISION=0 from configure.ac
-- Got CBLAS_AGE=0 from configure.ac
-- Looking for cos in m
-- Looking for cos in m - not found
-- Performing Test C_HAS_inline
-- Performing Test C_HAS_inline - Success
-- Performing Test C_EXTERN_INLINE
-- Performing Test C_EXTERN_INLINE - Failed
-- Performing Test C_C99INLINE
-- Performing Test C_C99INLINE - Success
-- Looking for include file ieeefp.h
-- Looking for include file ieeefp.h - not found
-- Looking for include file dlfcn.h
-- Looking for include file dlfcn.h - not found
-- Looking for include file inttypes.h
-- Looking for include file inttypes.h - found
-- Looking for include file memory.h
-- Looking for include file memory.h - found
-- Looking for include file stdint.h
-- Looking for include file stdint.h - found
-- Looking for include file stdlib.h
-- Looking for include file stdlib.h - found
-- Looking for include file strings.h
-- Looking for include file strings.h - not found
-- Looking for include file string.h
-- Looking for include file string.h - found
-- Looking for include file sys/stat.h
-- Looking for include file sys/stat.h - found
-- Looking for include file sys/types.h
-- Looking for include file sys/types.h - found
-- Looking for include file unistd.h
-- Looking for include file unistd.h - not found
-- Looking for include file stdio.h
-- Looking for include file stdio.h - found
-- Looking for EXIT_SUCCESS
-- Looking for EXIT_SUCCESS - found
-- Looking for EXIT_FAILURE
-- Looking for EXIT_FAILURE - found
-- Looking for feenableexcept
-- Looking for feenableexcept - not found
-- Looking for fesettrapenable
-- Looking for fesettrapenable - not found
-- Looking for hypot
-- Looking for hypot - found
-- Looking for expm1
-- Looking for expm1 - found
-- Looking for acosh
-- Looking for acosh - found
-- Looking for asinh
-- Looking for asinh - found
-- Looking for atanh
-- Looking for atanh - found
-- Looking for ldexp
-- Looking for ldexp - found
-- Looking for frexp
-- Looking for frexp - found
-- Looking for fprnd_t
-- Looking for fprnd_t - not found
-- Looking for isinf
-- Looking for isinf - found
-- Looking for isfinite
-- Looking for isfinite - found
-- Looking for finite
-- Looking for finite - not found
-- Looking for isnan
-- Looking for isnan - found
-- Looking for log1p
-- Looking for log1p - found
-- Looking for memcpy
-- Looking for memcpy - found
-- Looking for memmove
-- Looking for memmove - found
-- Looking for strdup
-- Looking for strdup - found
-- Looking for strtol
-- Looking for strtol - found
-- Looking for strtoul
-- Looking for strtoul - found
-- Looking for vprintf
-- Looking for vprintf - found
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/glfw/2f31e09fde64fd490349fe2a2cd52987d2adb363)
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE  
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE) 
-- Using Win32 for window creation
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/clapack/e5ae963fe2624cb05654378e04bfd231fae53345)
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/freetype/3b8bfc95faa8deb2b5a7aade44a3f8c019b61769)
DIST_NAME: freetype
DIST_VERSION: 1.3.1
DIST_LICENSE: FreeType License/GNU General Public License version 2
DIST_AUTHOR: David Turner, Robert Wilhelm, and Werner Lemberg
DIST_MAINTAINER: Bo Lu
DIST_URL: http://www.freetype.org
DIST_DESC: Freetype library.
DIST_DEPENDS: 
-- CPM: zbslib: adding package FreeImage@0 (C:/Users/justb/tmp/freeimage/d757ba79ca5586c0b5ce8f5ea2f02fe212273b4e)
-- CPM: zbslib: adding package nr3@0 (v0)
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/eigen/ce1fd8534701c94772980db1f9aede16d8fcc4fd)
-- Found OpenGL: opengl32   
-- OpenGL libs: opengl32;glu32
-- CPM: zbslib: adding package [email protected] (C:/Users/justb/tmp/pcre/8c5e4d9075a09a0b2efb979456ee100bf6f2c50a)
-- Could NOT find BZip2 (missing: BZIP2_LIBRARIES) (found version "1.0.6")
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY) (found version "1.2.11")
-- Could not find OPTIONAL package Readline
-- Could not find OPTIONAL package Editline
-- Looking for dirent.h
-- Looking for dirent.h - not found
-- Looking for windows.h
-- Looking for windows.h - found
-- Looking for C++ include type_traits.h
-- Looking for C++ include type_traits.h - not found
-- Looking for C++ include bits/type_traits.h
-- Looking for C++ include bits/type_traits.h - not found
-- Looking for bcopy
-- Looking for bcopy - not found
-- Looking for strerror
-- Looking for strerror - found
-- Looking for strtoll
-- Looking for strtoll - found
-- Looking for strtoq
-- Looking for strtoq - not found
-- Looking for _strtoi64
-- Looking for _strtoi64 - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of long long
-- Check size of long long - done
-- Check size of unsigned long long
-- Check size of unsigned long long - done
-- ** MSVC and PCRE_STATIC_RUNTIME: modifying compiler flags to use static runtime library
-- CPM: zbslib: adding package pthreads-win32@0 (v0)
-- Building pthreads-win32 with C setjmp/longjmp (default/recommended exception scheme).
-- Library name of pthreads-win32: pthreads-win32.
-- CPM: adding package plugin_kin@0 (v0)
-- ----- Library plugin_kin-1.0 start -----
-- >>> Library configured options
--      BUILD_STATIC_LIBS:       ON
-- CPM: plugin_kin: adding package common@0 (v0)
-- ----- Library common-1.0 start -----
-- CPM: plugin_kin: adding package [email protected] (C:/Users/justb/tmp/levmar/80e588f1a41525213cfa01a38e5f738b51f1bcba)
-- CPM: plugin_kin: adding package openssl-cmake@0 (C:/Users/justb/tmp/openssl-cmake/b00042477cdbbcd887e9aa71689f328cc34718ef)
-- OpenSSL version 1.1.1g
-- MSVC: using statically-linked runtime (/MT and /MTd).
-- Check size of long
-- Check size of long - done
-- Check size of long long
-- Check size of long long - done
-- Check size of int
-- Check size of int - done
-- Looking for fcntl.h
-- Looking for fcntl.h - found
-- CPM: plugin_kin: adding package [email protected] (C:/Users/justb/tmp/curl/dc5643b6537cf22e5b34400f19cea161a0629222)
CMake Warning at C:/Users/justb/tmp/curl/dc5643b6537cf22e5b34400f19cea161a0629222/CMakeLists.txt:50 (message):
  the curl cmake build system is poorly maintained.  Be aware


-- curl version=[7.67.0]
CMake Warning at C:/Users/justb/tmp/curl/dc5643b6537cf22e5b34400f19cea161a0629222/CMake/Macros.cmake:86 (message):
  Found no *nroff program
Call Stack (most recent call first):
  C:/Users/justb/tmp/curl/dc5643b6537cf22e5b34400f19cea161a0629222/CMakeLists.txt:202 (curl_nroff_check)


-- Found Perl: C:/Strawberry/perl/bin/perl.exe (found version "5.30.1") 
-- Looking for getch in ws2_32;
-- Looking for getch in ws2_32; - found
-- Looking for getch in winmm;ws2_32
-- Looking for getch in winmm;ws2_32 - found
-- Looking for cldap_open in wldap32;winmm;ws2_32;advapi32;crypt32
-- Looking for cldap_open in wldap32;winmm;ws2_32;advapi32;crypt32 - found
-- Looking for include file winldap.h
-- Looking for include file winldap.h - not found
-- Looking for include file winber.h
-- Looking for include file winber.h - not found
-- Looking for include file ldap_ssl.h
-- Looking for include file ldap_ssl.h - not found
-- Looking for include file ldapssl.h
-- Looking for include file ldapssl.h - not found
-- Looking for idn2_lookup_ul in idn2;wldap32;winmm;ws2_32;advapi32;crypt32
-- Looking for idn2_lookup_ul in idn2;wldap32;winmm;ws2_32;advapi32;crypt32 - not found
-- Performing Test USE_UNIX_SOCKETS
-- Performing Test USE_UNIX_SOCKETS - Failed
-- Looking for include files windows.h, winsock.h
-- Looking for include files windows.h, winsock.h - found
-- Looking for 3 include files windows.h, ..., ws2tcpip.h
-- Looking for 3 include files windows.h, ..., ws2tcpip.h - found
-- Looking for 4 include files windows.h, ..., winsock2.h
-- Looking for 4 include files windows.h, ..., winsock2.h - found
-- Looking for 5 include files windows.h, ..., stdio.h
-- Looking for 5 include files windows.h, ..., stdio.h - found
-- Looking for 6 include files windows.h, ..., sys/filio.h
-- Looking for 6 include files windows.h, ..., sys/filio.h - not found
-- Looking for 6 include files windows.h, ..., sys/ioctl.h
-- Looking for 6 include files windows.h, ..., sys/ioctl.h - not found
-- Looking for 6 include files windows.h, ..., sys/resource.h
-- Looking for 6 include files windows.h, ..., sys/resource.h - not found
-- Looking for 8 include files windows.h, ..., sys/uio.h
-- Looking for 8 include files windows.h, ..., sys/uio.h - not found
-- Looking for 8 include files windows.h, ..., sys/un.h
-- Looking for 8 include files windows.h, ..., sys/un.h - not found
-- Looking for 9 include files windows.h, ..., sys/xattr.h
-- Looking for 9 include files windows.h, ..., sys/xattr.h - not found
-- Looking for 9 include files windows.h, ..., arpa/tftp.h
-- Looking for 9 include files windows.h, ..., arpa/tftp.h - not found
-- Looking for 9 include files windows.h, ..., assert.h
-- Looking for 9 include files windows.h, ..., assert.h - found
-- Looking for 10 include files windows.h, ..., crypto.h
-- Looking for 10 include files windows.h, ..., crypto.h - not found
-- Looking for 10 include files windows.h, ..., des.h
-- Looking for 10 include files windows.h, ..., des.h - not found
-- Looking for 10 include files windows.h, ..., err.h
-- Looking for 10 include files windows.h, ..., err.h - not found
-- Looking for 10 include files windows.h, ..., errno.h
-- Looking for 10 include files windows.h, ..., errno.h - found
-- Looking for 12 include files windows.h, ..., idn2.h
-- Looking for 12 include files windows.h, ..., idn2.h - not found
-- Looking for 12 include files windows.h, ..., ifaddrs.h
-- Looking for 12 include files windows.h, ..., ifaddrs.h - not found
-- Looking for 13 include files windows.h, ..., krb.h
-- Looking for 13 include files windows.h, ..., krb.h - not found
-- Looking for 13 include files windows.h, ..., libgen.h
-- Looking for 13 include files windows.h, ..., libgen.h - not found
-- Looking for 13 include files windows.h, ..., locale.h
-- Looking for 13 include files windows.h, ..., locale.h - found
-- Looking for 14 include files windows.h, ..., netinet/tcp.h
-- Looking for 14 include files windows.h, ..., netinet/tcp.h - not found
-- Looking for 14 include files windows.h, ..., pem.h
-- Looking for 14 include files windows.h, ..., pem.h - not found
-- Looking for 14 include files windows.h, ..., poll.h
-- Looking for 14 include files windows.h, ..., poll.h - not found
-- Looking for 14 include files windows.h, ..., rsa.h
-- Looking for 14 include files windows.h, ..., rsa.h - not found
-- Looking for 16 include files windows.h, ..., ssl.h
-- Looking for 16 include files windows.h, ..., ssl.h - not found
-- Looking for 16 include files windows.h, ..., stdbool.h
-- Looking for 16 include files windows.h, ..., stdbool.h - found
-- Looking for 20 include files windows.h, ..., stropts.h
-- Looking for 20 include files windows.h, ..., stropts.h - not found
-- Looking for 25 include files windows.h, ..., sys/utsname.h
-- Looking for 25 include files windows.h, ..., sys/utsname.h - not found
-- Check size of size_t
-- Check size of size_t - done
-- Check size of ssize_t
-- Check size of ssize_t - failed
-- Check size of long long
-- Check size of long long - done
-- Check size of long
-- Check size of long - done
-- Check size of short
-- Check size of short - done
-- Check size of int
-- Check size of int - done
-- Check size of __int64
-- Check size of __int64 - done
-- Check size of time_t
-- Check size of time_t - done
-- Looking for basename
-- Looking for basename - not found
-- Looking for strncmpi
-- Looking for strncmpi - not found
-- Looking for alarm
-- Looking for alarm - not found
-- Looking for getpwuid_r
-- Looking for getpwuid_r - not found
-- Looking for usleep
-- Looking for usleep - not found
-- Looking for gethostbyname
-- Looking for gethostbyname - found
-- Looking for strerror_r
-- Looking for strerror_r - not found
-- Looking for siginterrupt
-- Looking for siginterrupt - not found
-- Looking for fork
-- Looking for fork - not found
-- Looking for freeaddrinfo
-- Looking for freeaddrinfo - found
-- Looking for freeifaddrs
-- Looking for freeifaddrs - not found
-- Looking for pipe
-- Looking for pipe - not found
-- Looking for ftruncate
-- Looking for ftruncate - not found
-- Looking for getprotobyname
-- Looking for getprotobyname - found
-- Looking for getpeername
-- Looking for getpeername - found
-- Looking for getsockname
-- Looking for getsockname - found
-- Looking for if_nametoindex
-- Looking for if_nametoindex - not found
-- Looking for getrlimit
-- Looking for getrlimit - not found
-- Looking for setlocale
-- Looking for setlocale - found
-- Looking for setmode
-- Looking for setmode - found
-- Looking for setrlimit
-- Looking for setrlimit - not found
-- Looking for fcntl
-- Looking for fcntl - not found
-- Looking for ioctl
-- Looking for ioctl - not found
-- Looking for setsockopt
-- Looking for setsockopt - found
-- Looking for mach_absolute_time
-- Looking for mach_absolute_time - not found
-- Looking for inet_pton
-- Looking for inet_pton - found
-- Looking for fsetxattr
-- Looking for fsetxattr - not found
-- Performing Curl Test HAVE_FCNTL_O_NONBLOCK
-- Performing Curl Test HAVE_FCNTL_O_NONBLOCK - Failed
-- Performing Curl Test HAVE_IOCTLSOCKET
-- Performing Curl Test HAVE_IOCTLSOCKET - Success
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL - Failed
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL_FIONBIO
-- Performing Curl Test HAVE_IOCTLSOCKET_CAMEL_FIONBIO - Success
-- Performing Curl Test HAVE_IOCTLSOCKET_FIONBIO
-- Performing Curl Test HAVE_IOCTLSOCKET_FIONBIO - Success
-- Performing Curl Test HAVE_IOCTL_FIONBIO
-- Performing Curl Test HAVE_IOCTL_FIONBIO - Failed
-- Performing Curl Test HAVE_IOCTL_SIOCGIFADDR
-- Performing Curl Test HAVE_IOCTL_SIOCGIFADDR - Failed
-- Performing Curl Test HAVE_SETSOCKOPT_SO_NONBLOCK
-- Performing Curl Test HAVE_SETSOCKOPT_SO_NONBLOCK - Failed
-- Performing Curl Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
-- Performing Curl Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID - Failed
-- Performing Curl Test HAVE_BOOL_T
-- Performing Curl Test HAVE_BOOL_T - Success
-- Performing Curl Test HAVE_FILE_OFFSET_BITS
-- Performing Curl Test HAVE_FILE_OFFSET_BITS - Failed
-- Performing Curl Test HAVE_VARIADIC_MACROS_C99
-- Performing Curl Test HAVE_VARIADIC_MACROS_C99 - Success
-- Performing Curl Test HAVE_VARIADIC_MACROS_GCC
-- Performing Curl Test HAVE_VARIADIC_MACROS_GCC - Failed
-- Check size of off_t
-- Check size of off_t - done
-- Check size of curl_off_t
-- Check size of curl_off_t - done
-- Performing Curl Test HAVE_GLIBC_STRERROR_R
-- Performing Curl Test HAVE_GLIBC_STRERROR_R - Failed
-- Performing Curl Test HAVE_POSIX_STRERROR_R
-- Performing Curl Test HAVE_POSIX_STRERROR_R - Failed
-- Performing Curl Test HAVE_CLOCK_GETTIME_MONOTONIC
-- Performing Curl Test HAVE_CLOCK_GETTIME_MONOTONIC - Failed
-- Performing Curl Test HAVE_BUILTIN_AVAILABLE
-- Performing Curl Test HAVE_BUILTIN_AVAILABLE - Failed
-- Performing Test curl_cv_recv
-- Performing Test curl_cv_recv - Success
-- Performing Test curl_cv_func_recv_test
-- Performing Test curl_cv_func_recv_test - Success
-- Tested: int recv(SOCKET, char *, int, int)
-- Performing Test curl_cv_send
-- Performing Test curl_cv_send - Success
-- Performing Test curl_cv_func_send_test
-- Performing Test curl_cv_func_send_test - Success
-- Tested: int send(SOCKET, const char *, int, int)
-- Performing Test HAVE_MSG_NOSIGNAL
-- Performing Test HAVE_MSG_NOSIGNAL - Failed
-- Performing Test HAVE_STRUCT_TIMEVAL
-- Performing Test HAVE_STRUCT_TIMEVAL - Success
-- Check size of sig_atomic_t
-- Check size of sig_atomic_t - done
-- Performing Test HAVE_SIG_ATOMIC_T_NOT_VOLATILE
-- Performing Test HAVE_SIG_ATOMIC_T_NOT_VOLATILE - Success
-- Check size of struct sockaddr_storage
-- Check size of struct sockaddr_storage - done
-- Performing Test HAVE_POLL_FINE
-- Performing Test HAVE_POLL_FINE - Failed
-- Enabled features: SSL IPv6 AsynchDNS SSPI SPNEGO Kerberos NTLM
-- Enabled protocols: DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP POP3 POP3S RTSP SMTP SMTPS TELNET TFTP
-- Enabled SSL backends: WinSSL
CMake Error at bin/CMakeLists.txt:10 (include):
  include could not find load file:

    ECMAddAppIcon.cmake


-- ---------------------------Configure done----------------------
-- Project source dir: C:/Users/justb/Repos/kintek-explorer
-- Project binary dir: C:/Users/justb/Repos/kintek-explorer/cmake-build-debug
-- Project build type: Release
-- CMAKE_C_FLAGS: /DWIN32 /D_WINDOWS /W2
-- CMAKE_CXX_FLAGS: /DWIN32 /D_WINDOWS /W2 /GR /EHsc
-- Configuring incomplete, errors occurred!
See also "C:/Users/justb/Repos/kintek-explorer/cmake-build-debug/CMakeFiles/CMakeOutput.log".
See also "C:/Users/justb/Repos/kintek-explorer/cmake-build-debug/CMakeFiles/CMakeError.log".

[

CPM hangs when downloading files with invalid URL_HASH

URL_HASH mismaches cause the download to be retried a few times in a row, with fixed sleep intervals in between. The lack of output during this time makes CMake look like its hanging. After about 2 minutes CMake terminates the configuration and prints all the download errors. These errors should ideally be printed while they happen so it doesn't look like its hanging.

Here is the example package with an invalid hash to reproduce my issue.

CPMAddPackage(
  NAME SDL2
  VERSION 2.0.12
  URL https://www.libsdl.org/release/SDL2-2.0.12.zip
  URL_HASH SHA256=f
)

Here is the output at which CMake seems to hang:

-- CPM: adding package [email protected] (2.0.12)

CPM.cmake vs. FetchContent

Hello, I was wondering what the differences really are between using CPM.cmake and just native CMake FetchContent functions? For me it seems that the benefits of CPM.cmake, those that are listed on the README, are actually benefits of FetchContent for the most parts. It seems that the "versioning" talked in documentation is the same as provided by FetchContent --- basically just referencing to particular commit hash or version tag.

set(PACKAGE_NAME cxxopts)

FetchContent_Declare(${PACKAGE_NAME}
    # Compared to release tag or branch, commit hash avoids network connection
    # if the local clone already has that particular commit.
    GIT_REPOSITORY          https://github.com/jarro2783/cxxopts.git
    GIT_TAG                 e6858d3429e0ba5fe6f42ce2018069ce992f3d26 # tag v2.2.0 
    )
FetchContent_MakeAvailable(${PACKAGE_NAME})

# What are the differences to CPMAddPackage here? (Aside from `OPTIONS`)

CPMAddPackage(
    NAME ${PACKAGE_NAME}
    GITHUB_REPOSITORY jarro2783/cxxopts
    VERSION 2.2.0
    OPTIONS
        "CXXOPTS_BUILD_EXAMPLES Off"
        "CXXOPTS_BUILD_TESTS Off"
    )

We can set cache path for both methods: FETCHCONTENT_BASE_DIR for FetchContent and CPM_SOURCE_CACHE for CPM. It seems that setting FETCHCONTENT-variables will also effect behaviour of CPM.cmake script. Setting FETCHCONTENT_FULLY_DISCONNECTED will also disable CPM packages and result configuration step working significantly faster.
Also notice the comment about using commit hash compared to version tag. I read somewhere that commit hash will perform faster check (probably on Professional CMake book).

Second thing. I tried to understand how the OPTIONS are passed to FetchContent internally in CPM.cmake script. May you enlighten me how can you do that actually? There is no mention about passing variables in CMake documentation like that. I will show example of how I have understood how "passing" the options works for FetchContent. The downside is that if those variables would effect other dependencies, then you need to unset them after adding the dependency.

set(PACKAGE nemtrif_utfcpp)
FetchContent_Declare(${PACKAGE}
    GIT_REPOSITORY          https://github.com/nemtrif/utfcpp.git
    GIT_TAG                 944ef0561ddcd33eb4fd94934538458b2b2de252 # v3.1.1
    GIT_PROGRESS            ON
    )
# We set additional options and compile definitions for target.
FetchContent_GetProperties(${PACKAGE})
if(NOT ${PACKAGE}_POPULATED)
    # Set options. (Descriptions will be set by package.)
    set(UTF8_TESTS OFF CACHE BOOL "")
    set(UTF8_INSTALL OFF CACHE BOOL "")
    set(UTF8_SAMPLES OFF CACHE BOOL "")
    
    message(STATUS "Downloading external dependency: ${PACKAGE}")
    FetchContent_Populate(${PACKAGE})
    add_subdirectory(
        ${${PACKAGE}_SOURCE_DIR}
        ${${PACKAGE}_BINARY_DIR}
        EXCLUDE_FROM_ALL
        )
    set(TARGET utf8cpp)
    target_compile_definitions(${TARGET}
        INTERFACE
            UTF_CPP_CPLUSPLUS=201103L # __cplusplus macro is erroneously used, this fixes that.
        )
    add_library("${PACKAGE}::${PACKAGE}" ALIAS ${TARGET})
endif()
# *****************************************************************************/

In above, rather complex example, we need to use add_subdirectory combined with add_library call made by the actual dependency's CMakeLists.txt, which names the main target as utf8cpp. This is due we want to pass CMake options and C++ compile definitions for the target.

DOWNLOAD_ONLY not parsed?

I have the following setup, with NEWLIB and its dependency jegp both depending on range-v3.
Having translated directly from a sequence of FetchContents and accompanying FetchContent_MakeAvailable to a sequence of CPMFindPackage, jegp is first found and finds range-v3, but when NEWLIB does it, DOWNLOAD_ONLY is "", as seen in the error below, for which I used cmake_print_variables.

Running /usr/bin/cmake -GNinja <source-root>/newlib in <source-root>/newlib/build.
-- Found SFML 2.5.1 in /usr/lib64/cmake/SFML
-- CPM: adding package jegp_cmake_modules@0 (master)
-- CPM: adding package jegp@0 (master)
-- CMAKE_CURRENT_LIST_FILE="<source-root>/newlib/build/_deps/jegp-src/cmake/JEGPFindDependencies.cmake" ; CPM_ARGS_NAME="jegp_cmake_modules" ; DOWNLOAD_ONLY="NO"
-- CPM: jegp: adding package range-v3@0 (master)
-- CMAKE_CURRENT_LIST_FILE="<source-root>/newlib/tools/cmake/NEWLIBFindDependencies.cmake" ; CPM_ARGS_NAME="range-v3" ; DOWNLOAD_ONLY=""
CMake Error at tools/cmake/CPM.cmake:167 (cpm_fetch_package):
  cpm_fetch_package Function invoked with incorrect arguments for function
  named: cpm_fetch_package
Call Stack (most recent call first):
  tools/cmake/CPM.cmake:135 (CPMCheckIfPackageAlreadyAdded)
  tools/cmake/NEWLIBFindDependencies.cmake:21 (CPMFindPackage)
  CMakeLists.txt:11 (include)


-- CPM: using local package fmt@0
-- CPM: adding package mp-units@0 (master)
-- Configuring incomplete, errors occurred!
See also "<source-root>/newlib/build/CMakeFiles/CMakeOutput.log".
CMake process exited with exit code 1.
Elapsed time: 00:03.

I have circumvented this by first declaring my direct dependencies for which I know my other direct dependencies depend upon, which is necessary since the content is immediately made available, but it could become a nightmare in more complex scenarios.

Examples to create a minimalistic CPM compliant library

Hi, for us at the more beginner state that wants to contribute or make our projects more compliant with CPM you have the wiki that states what needs to be added. However, I still struggle a little with it. So I was curious if you were interested in adding a minimalistic library example?

Automatic versioning convention detection

Currently GIT_TAG defaults to v(VERSION), which is the versioning convention many Git projects use, but not all. Is there a portable and efficient way to detect or find git-tag based versioning schemes?

hunter / conan / vcpkg compatibility

Libraries using CPM should already work in a hunter / conan / vcpkg package without modification, however they will always re-build dependencies even if they are already installed by the package manager. It should be possible to detect when the library is being installed by a package manager. In that case CPM should try to fetch the package with the package manager before downloading and building from source.
Perhaps additional arguments like CONAN_NAME etc. to CPMAddPackage can be used to specify the package manager parameters.

How to only include public headers?

Module in question
https://github.com/martell/pthreads-win32.cmake/blob/master/CMakeLists.txt

This is a cmake adaptation on top of the original pthreads-win32 library. The original library has header/source file in a single directory.

The cmake adaptation makes proper install targets and move the header/complied libs into the proper location (see below)

install(TARGETS ${PTHREADS_LIBRARY}
	RUNTIME DESTINATION ${PTHREADS_BINDIR} COMPONENT ${PTHREADS_BINCOMPONENT}
	LIBRARY DESTINATION ${PTHREADS_LIBDIR} COMPONENT ${PTHREADS_LIBCOMPONENT}
	ARCHIVE DESTINATION ${PTHREADS_LIBDIR} COMPONENT ${PTHREADS_LIBCOMPONENT}
	PUBLIC_HEADER DESTINATION ${PTHREADS_INCLUDEDIR} COMPONENT ${PTHREADS_INCLUDECOMPONENT})

When adding this library using CPMAddPackage(), I needed to do something like
target_include_libraries(TARGET INTERFACE <PATH_TO_SOURCE_DIR>)
This adds all .h files as include headers, not just the public header.

My understanding is that CPM does not trigger the "install" step, but just the "configure/build" steps when adding a package.

Is there anyway to only include the public header?

Thank you!

Here's how I am adding that library via CPM

# ---- pthreads for MSVC-----------
if(MSVC)
  CPMAddPackage(
          NAME pthreads-win32
          SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../external/pthreads-win32
  )
  print_target_properties(pthreadsVC2)
endif()

The print_target_properties is a debug function to dump all target properties, its output is:

Library name of pthreads-win32: pthreadsVC2.
pthreadsVC2 AUTOGEN_ORIGIN_DEPENDS = ON
pthreadsVC2 AUTOMOC_COMPILER_PREDEFINES = ON
pthreadsVC2 AUTOMOC_MACRO_NAMES = Q_OBJECT;Q_GADGET;Q_NAMESPACE
pthreadsVC2 AUTOMOC_PATH_PREFIX = ON
pthreadsVC2 BINARY_DIR = C:/Users/justb/Repos/kintek-explorer/cmake-build-debug/_deps/pthreads-win32-build
pthreadsVC2 BUILD_WITH_INSTALL_RPATH = FALSE
pthreadsVC2 DEBUG_POSTFIX = d
pthreadsVC2 IMPORTED = FALSE
pthreadsVC2 IMPORTED_GLOBAL = FALSE
pthreadsVC2 INCLUDE_DIRECTORIES = C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32
pthreadsVC2 INSTALL_NAME_DIR = @executable_path/../lib
pthreadsVC2 INSTALL_RPATH = $ORIGIN/../lib
pthreadsVC2 INSTALL_RPATH_USE_LINK_PATH = TRUE
pthreadsVC2 NAME = pthreadsVC2
pthreadsVC2 POSITION_INDEPENDENT_CODE = True
pthreadsVC2 PUBLIC_HEADER = C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/pthread.h;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/sched.h;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/semaphore.h
pthreadsVC2 SKIP_BUILD_RPATH = FALSE
pthreadsVC2 SOURCES = C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/attr.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/barrier.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/cancel.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/cleanup.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/condvar.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/create.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/dll.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/autostatic.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/errno.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/exit.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/fork.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/global.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/misc.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/mutex.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/nonportable.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/private.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/rwlock.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/sched.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/semaphore.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/signal.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/spin.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/sync.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/tsd.c;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/pthread.h;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/sched.h;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/semaphore.h;C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32/pthreads-win32/version.rc
pthreadsVC2 SOURCE_DIR = C:/Users/justb/Repos/kintek-explorer/external/pthreads-win32
pthreadsVC2 TYPE = SHARED_LIBRARY
pthreadsVC2 UNITY_BUILD_BATCH_SIZE = 8 

CPM pollutes project hierarchy

Hey there!
I successfully adopted CPM in my project, helping me to avoid 4 GB big repos being checked out everytime I change configuration or clear the cache. Which, by itself is pretty neat.

However, I recognized, that CPM pollutes my targets with files from other projects. See the following screenshot:
Capture

Yes, I had to censor the target and project names in order to avoid trouble at my work place. The two folders I marked with the red arrows contain files exclusively from other targets.

Interestingly, this happens only for targets that either:

  • are not imported/interface libraries.
  • are not retrieved via GitHub short links (i.e. GITHUB_REPOSITORY option)

Is there a way to prevent this?


Looks like I completely misunderstood the semantics of target_sources in combination with PUBLIC.

Better error message handling

I'm using glfw in my project (https://github.com/glfw/glfw)

Here is how I was invoking it.

    # The specific commit I chose is pretty arbitrary. The main point being that the current
    # tag just isn't suitable due to cmake usage.
    # Future releases will probably fix the major issues.
    CPMAddPackage(
        NAME glfw
        GITHUB_REPOSITORY "glfw/glfw"
        # 3.3 cmake isn't acceptable.
        VERSION "3.4"
        # 3.4 is not released yet, so use a recent commit
        GIT_TAG "3327050ca66ad34426a82c217c2d60ced61526b7"
        GIT_SHALLOW ON
    )

However I would receive this error message during configuration:

...
--  adding package [email protected] (3327050ca66ad34426a82c217c2d60ced61526b7 -> D:/Git/cpm_source_cache/glfw/a3795e0fea65df80bf394caa233dc04c95ecd068)
Microsoft (R) Build Engine version 16.8.1+bd2ea1e3c for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

  Checking Build System
  Creating directories for 'glfw-populate'
  Performing download step (git clone) for 'glfw-populate'
  Cloning into 'a3795e0fea65df80bf394caa233dc04c95ecd068'...
  fatal: reference is not a tree: 3327050ca66ad34426a82c217c2d60ced61526b7
  CMake Error at D:/Git/PitoGraphics/build/_deps/glfw-subbuild/glfw-populate-prefix/tmp/glfw-populate-gitclone.cmake:40 (message):
    Failed to checkout tag: '3327050ca66ad34426a82c217c2d60ced61526b7'


C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(238,5): error MSB8066: Custom build for 'D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-mkdir.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-download.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-update.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-patch.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-configure.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-build.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-install.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\b364269e99ee257291eb37ed22577959\glfw-populate-test.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\30ba90f333ff7f523cc3181fa49c2c56\glfw-populate-complete.rule;D:\Git\PitoGraphics\build\_deps\glfw-subbuild\CMakeFiles\1995fd9cb872cd1e32f0bcbf52fed4bd\glfw-populate.rule' exited with code 1. [D:\Git\PitoGraphics\build\_deps\glfw-subbuild\glfw-populate.vcxproj]

CMake Error at C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:989 (message):
  Build step for glfw failed: 1
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1111:EVAL:2 (__FetchContent_directPopulate)
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1111 (cmake_language)
  C:/Program Files/CMake/share/cmake-3.19/Modules/FetchContent.cmake:1154 (FetchContent_Populate)
  D:/Git/cpm_source_cache/cpm/CPM_0.27.5.cmake:461 (FetchContent_MakeAvailable)
  D:/Git/cpm_source_cache/cpm/CPM_0.27.5.cmake:347 (cpm_fetch_package)
  cmake/PitoGraphics.cmake:52 (CPMAddPackage)
  CMakeLists.txt:26 (SetupGlfw)


-- Configuring incomplete, errors occurred!
See also "D:/Git/PitoGraphics/build/CMakeFiles/CMakeOutput.log".

However doing this causes configuration to fail.

The only thing I found to fix this was to get rid of the GIT_SHALLOW command.

    # The specific commit I chose is pretty arbitrary. The main point being that the current
    # tag just isn't suitable due to cmake usage.
    # Future releases will probably fix the major issues.
    CPMAddPackage(
        NAME glfw
        GITHUB_REPOSITORY "glfw/glfw"
        # 3.3 cmake isn't acceptable.
        VERSION "3.4"
        # 3.4 is not released yet, so use a recent commit
        GIT_TAG "3327050ca66ad34426a82c217c2d60ced61526b7"
    )

Was I doing something wrong by specifying shallow?

Can we give users a better error message?

Thoughts?

[Feature] extract version from target

Dont know if I need to create an issue link with the pr #164 .

The issue is when you work with cmake and never install package on host, i.e when developing for embeded device.
This is a fix extract the version from the target itself if possible,
I use that since we work with multiple lib for embedded prog.
In each lib we just had to set the Properties Version

I just put that at the end of all package I made:

get_target_property(_TARGET_TYPE ${PROJECT_NAME} TYPE)
if(_TARGET_TYPE STREQUAL "INTERFACE_LIBRARY")
    set_target_properties(${PROJECT_NAME} PROPERTIES INTERFACE_VERSION ${PROJECT_VERSION} )
else()
    set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} )
endif()

with that the PROJECT_VERSION is the version selected by CPM.

[Feature Request] Use shallow clone for git repositories

CPM currently clones full history for git-repository dependencies, which takes more time than necessary (in most cases) on downloading, and consumes more disk space.

Maybe use git shallow clone by default for those dependencies?

There is a GIT_SHALLOW option to enable --depth=1 with clone, which does what we exactly desire.

If I may, I would like to make a PR on it, :-)

Help passing HTTP_PASSWORD value as a variable

I need to pass HTTP_USERNAME and HTTP_PASSWORD parameters as variables like this:

CPMAddPackage(
	NAME headers
	URL https://<my URL here>file.zip
	HTTP_PASSWORD ${NEXUS_PASSWORD}
	HTTP_USERNAME ${NEXUS_USER}
)

It works fine when I hardcode username and password but doesn't work when I use variables. Please help.

[Minor feature request] Manifest for download dependencies

Hello, first thanks for your work, it is very good and helps me a lot in my projects.

I think that including a manifest as a way to download dependencies would be an incredible resource for this project, as it will improve the organization and readability of the projects that use it as a package manager.

CI testing for Mac + Windows

Currently CI tests are done by running all example script on a Linux system. It would be great to extend tests to the the Windows and Mac platform as well. The main issue here is supporting C++17 on travis builds, as the examples depend on it.

Some projects don't prepend the tag with 'v' for the version

Some projects don't use the 'v' when tagging. CPM.cmake assumes/adds a 'v' in front on the tag for VERSION. Perhaps it should just use what it is given?

<+>UTF-8
===================================================================
--- cmake/CPM.cmake	(revision 42a2615a11b234c89fbbfb687bfabcfff35848d7)
+++ cmake/CPM.cmake	(date 1606469749260)
@@ -226,7 +226,7 @@
     if (DEFINED CPM_ARGS_GIT_REPOSITORY)
         list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY})
         if (NOT DEFINED CPM_ARGS_GIT_TAG)
-            set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
+            set(CPM_ARGS_GIT_TAG ${CPM_ARGS_VERSION})
         endif()
     endif()

CPM Option Parse Error if Option Doesn't Have Key/Value Syntax

The cpm_parse_option function fails if the list of options don't follow the key/value format. I discovered this with the following code:

CPMAddPackage(
    NAME googletest
    GITHUB_REPOSITORY google/googletest
    GIT_TAG release-1.8.1
    VERSION 1.8.1
    OPTIONS
       "INSTALL_GTEST OFF"
       "gtest_force_shared_crt ON"
       "GTEST_HAS_STD_TUPLE"
)

Error message: string begin index: 20 is out of range 0 - 19 on line 196 of CPM.cmake.
The issue goes away if you do the following instead:

CPMAddPackage(
    NAME googletest
    GITHUB_REPOSITORY google/googletest
    GIT_TAG release-1.8.1
    VERSION 1.8.1
    OPTIONS
       "INSTALL_GTEST OFF"
       "gtest_force_shared_crt ON"
       "GTEST_HAS_STD_TUPLE ON"
)

DOWNLOAD_ONLY doing more than downloading

Specifying DOWNLOAD_ONLY in CPMAddPackage or CPMFindPackage seems to be configuring the package.

Not sure if this is a CPM bug, or if I've misunderstood the behavior when DOWNLOAD_ONLY is present.

For example, this starts configuring the libcu++ LLVM tests:

cmake_minimum_required(VERSION 3.18 FATAL_ERROR)

project(LIBCUDACXX_CPM_TEST)

# Uses CPM v0.27.5
include(get_cpm.cmake)

CPMAddPackage(NAME  libcudacxx
    VERSION         1.4.0
    GIT_TAG         1.4.0
    GIT_REPOSITORY  https://github.com/NVIDIA/libcudacxx.git
    GIT_SHALLOW     TRUE
    DONWLOAD_ONLY   TRUE
)

CPM: IODash not found via find_package(IODash )

I'm tryiing to build ydotool which is a package using CPM.make. This is for fedora and they do not allow builds using in-build downloads - I have to provide a versioned tarball including all the dependencies.

ydotool has several dependencies including IODash

I'm trying to use -DCPM_IODash_SOURCE=/path/to/source but I always get the error:

  CPM: IODash not found via find_package(IODash )
Call Stack (most recent call first):
  CPM.cmake-0.27.5/cmake/CPM.cmake:252 (CPMAddPackage)
  CMakeLists.txt:16 (CPMAddPackage)

-- CPM: adding package IODash@ (/home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/x86_64-redhat-linux-gnu/IODash-0.1.0)

I've tried dropping a plain source tarball as well as a git repo at that location but neither work.

The full cmake invocation is:

cmake -S . -B x86_64-redhat-linux-gnu -DCMAKE_C_FLAGS_RELEASE:STRING=-DNDEBUG \
-DCMAKE_CXX_FLAGS_RELEASE:STRING=-DNDEBUG -DCMAKE_Fortran_FLAGS_RELEASE:STRING=-DNDEBUG \
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr -DINCLUDE_INSTALL_DIR:PATH=/usr \
/include -DLIB_INSTALL_DIR:PATH=/usr/lib64 -DSYSCONF_INSTALL_DIR:PATH=/etc \
-DSHARE_INSTALL_PREFIX:PATH=/usr/share -DLIB_SUFFIX=64 -DBUILD_SHARED_LIBS:BOOL=ON \
-DCPM_USE_LOCAL_PACKAGES:BOOL=TRUE -DCPM_LOCAL_PACKAGES_ONLY:BOOL=TRUE \
-DCPM_IODash_SOURCE=/home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/x86_64-redhat-linux-gnu/IODash-0.1.0 \
-DCPM_libevdevPlus_SOURCE=/home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/libevdevPlus-0.2.1 \
-DCPM_libuInputPlus_SOURCE=/home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/libuInputPlus-0.2.1 \
-DCPM_cxxopts_SOURCE=/home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/cxxopts-2d8e17c4f88efce80e274cb03eeb902e055a91d3

the directory /home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/x86_64-redhat-linux-gnu/IODash-0.1.0 definitely contains the source tarball from IODash...

$ ls /home/bhepple/rpmbuild/BUILD/ydotool-0.2.0/x86_64-redhat-linux-gnu/IODash-0.1.0 
Benchmarks  CMakeLists.txt  cpp_modules  IODash  IODash.cpp  IODash.hpp  LICENSE  README.md  test.cpp

I've also tried putting the full git repo there but I get the same error.

Any ideas for me?

PS the top level CMakeLists.txt file for ydotool has been patched to:

cmake_minimum_required(VERSION 3.14)
project(ydotool)

set(CMAKE_CXX_STANDARD 17)

set(CPM_DOWNLOAD_VERSION 0.27.5)
set(CPM_DOWNLOAD_LOCATION "CPM.cmake-${CPM_DOWNLOAD_VERSION}/cmake/CPM.cmake")

if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
    message(STATUS "Downloading CPM.cmake")
    file(DOWNLOAD https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake ${CPM_DOWNLOAD_LOCATION})
endif()

include(${CPM_DOWNLOAD_LOCATION})

CPMAddPackage(
        NAME IODash
        GITHUB_REPOSITORY YukiWorkshop/IODash
        VERSION 0.1.0
)
...

SSH private gitlab

suppose I have a private gitlab repo that I can clone with this command (SSH):

git clone [email protected]:my-team/my-project.git

how do i do it with cpm?

it seems that cpm.cmake GITLAB_REPOSITORY want a https clone command

How to make a project CPM-ready?

I understand the usage but documentation is missing on how to make my projects useable with CPM:

  • Where to store the version number?
  • Where to place public include headers?
  • How to create header only projects?
  • How to define static or dynamic libs?

GitLab repo is not cloneable

I get the following error:

-- CPM: adding package CliArguments@0 (v0)
[ 11%] Performing download step (git clone) for 'cliarguments-populate'
fatal: could not create work tree dir '': No such file or directory
fatal: could not create work tree dir '': No such file or directory
fatal: could not create work tree dir '': No such file or directory
-- Had to git clone more than once:
          3 times.
CMake Error at cliarguments-subbuild/cliarguments-populate-prefix/tmp/cliarguments-populate-gitclone.cmake:66 (message):
  Failed to clone repository:
  'https://gitlab.com/aggsol/cliarguments-cpp.git'

I add the package like this:

CPMAddPackage(
  NAME CliArguments
  GIT_REPOSITORY https://gitlab.com/aggsol/cliarguments-cpp.git
  TAG 1.0.0
)

The tag has been created as you can see here: https://gitlab.com/aggsol/cliarguments-cpp/-/tags

Did I miss something else to setup?

Is it possible to use CPM to include boost

Hi, is it possible to use CPM to include and build Boost, or do packages need to follow good CMake practices? Can you use something like:

CPMAddPackage(
NAME boost
GITHUB_REPOSITORY boostorg/boost
VERSION 1.70.0
GIT_TAG boost-1.70.0
)

if (boost_ADDED)
add_library(boost INTERFACE IMPORTED)
target_include_directories(boost INTERFACE "${boost_SOURCE_DIR}/include")
endif()

target_link_libraries(asio-test PRIVATE boost)

no default CPM_ARGS_VERSION

Hello,
In commit ab7000d the set(CPM_ARGS_VERSION 0) was removed.
So when cpm cant find the version from a package there will be no default version number.
Was there any issue with this setup?

It was useful to compare between two cpm of the same package.

Any problem with downloading and caching CPM.cmake in CMake?

Hi, thanks for developing the very nice tool. I like the snippet in the Wiki page, Downloading CPM.cmake in CMake, which makes it easy to set up CPM in my project just by adding a few lines.

But I was wondering that the downloaded CPM could be also stored in the cache specified by CPM_SOURCE_CACHE. Indeed, the following seems to work:

set(CPM_DOWNLOAD_VERSION 0.27.2)
if(DEFINED ENV{CPM_SOURCE_CACHE})
  # If CPM_SOURCE_CACHE is given, then use the cache directory also for CPM.
  set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
else()
  set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
endif()

if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
  message(STATUS "Downloading CPM.cmake")
  file(DOWNLOAD https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake ${CPM_DOWNLOAD_LOCATION})
endif()

This gives a benefit that repeating downloads of CPM.cmake can be also avoided, and one can create new builds offline if CPM and all dependencies are cached. The disadvantage I can see is only that one needs the 4 additional lines in CMakeLists.txt.

Do you see any problem with using a cached CPM.cmake in the above way? I just checked with a small test, so maybe I missed something.

If the above has no problem, then perhaps putting it in the Wiki page would be a good idea, maybe in addition to the original simpler one, if you like.

Use macros instead of functions

I want to affect the scope from which CPMFindPackage is called to append the package's source directory to CMAKE_MODULE_PATH, as they contain my project's CMake modules. With FetchContent it is possible, as FetchContent_MakeAvailable (apparently a macro) eventually calls add_subdirectory.

The CMake modules repository CMakeLists.txt is

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} PARENT_SCOPE)

Before realizing this was possible, I just included its first line after the FetchContent_MakeAvailable call.

Setting CPM_SOURCE_ROOT from the environment

I use similar dependencies for various project, so that new feature would help me a lot. Is there a way to setup an environment variable for it? I would set CPM_SOURCE_ROOT per machine/user not per project. I would point in to $HOME/.cache/CPM or similar

duplicate target name causing collision in parent project

Hi,

Let me preface this issue report with a huge congratulations. I love cpm.cmake, it solved a lot of dependency management I had with using cmake. and I am working on porting over my build system to use cpm.cmake exclusively.

I ran into an issue while using cpm.cmake with duplicate target names by trying to add two child cmake packages.

To reproduce:

CPMAddPackage(
        NAME CLAPACK
        VERSION 3.2.1
        URL http://www.netlib.org/clapack/clapack-3.2.1-CMAKE.tgz
)

if(CLAPACK_ADDED)
  # Set include directories for the targets
  target_include_directories(f2c INTERFACE "${CLAPACK_SOURCE_DIR}/INCLUDE")
  target_include_directories(lapack INTERFACE "${CLAPACK_SOURCE_DIR}/INCLUDE")
endif()


CPMAddPackage(
        NAME Eigen
        VERSION 3.2.8
        URL https://gitlab.com/libeigen/eigen/-/archive/3.2.8/eigen-3.2.8.tar.gz
        OPTIONS
        "EIGEN_LEAVE_TEST_IN_ALL_TARGET 0"
)

The error I get when I run cmake:

CMake Error at cmake-build-debug/_deps/eigen-src/blas/CMakeLists.txt:15 (add_custom_target):
  add_custom_target cannot create target "blas" because another target with
  the same name already exists.  The existing target is a static library
  created in source directory
  "/Users/blu/Repos/kintek-explorer/cmake-build-debug/_deps/clapack-src/BLAS/SRC".
  See documentation for policy CMP0002 for more details.

CMake Error at cmake-build-debug/_deps/eigen-src/lapack/CMakeLists.txt:15 (add_custom_target):
  add_custom_target cannot create target "lapack" because another target with
  the same name already exists.  The existing target is a static library
  created in source directory
  "/Users/blu/Repos/kintek-explorer/cmake-build-debug/_deps/clapack-src/SRC".
  See documentation for policy CMP0002 for more details.

I can work around this issue by setting a CMake option to pick one or the other, but was wondering if there's a way to add "namespace" to target names to avoid this from the package manager itself?

find_package and CPMFindPackage have different behaviors

Hello,

I'm using CPMFindPackage() to check for a dependency on CMocka and noticing some strange behavior with the find_package portion. Do you know what I might be doing wrong here?

CPMFindPackage(
  NAME CMOCKA
  GIT_REPOSITORY https://git.cryptomilk.org/projects/cmocka.git/
  VERSION 1.1.5
  GIT_TAG cmocka-1.1.5
  OPTIONS
    "WITH_EXAMPLES OFF"
)

message("CMOCKA_FOUND: ${CMOCKA_FOUND}")
message("CMOCKA_ADDED: ${CMOCKA_ADDED}")
message("CMOCKA_INCLUDES: ${CMOCKA_INCLUDE_DIR}")
message("CMOCKA_LIBRARIES: ${CMOCKA_LIBRARIES}")

The library is installed on my system with a CMake config file. I see this output from CPM, but the FOUND/ADDED variables are not set, and the other variables defined by the config file aren't used.

-- CPM: using local package [email protected]
CMOCKA_FOUND:
CMOCKA_ADDED:
CMOCKA_INCLUDES:
CMOCKA_LIBRARIES:

If I remove CPMFindPackage and add find_package:

find_package(CMOCKA)

This time, CMOCKA_FOUND will be defined, and the values defined by the config file are used.

CMOCKA_FOUND: 1
CMOCKA_ADDED:
CMOCKA_INCLUDES: /usr/local/include
CMOCKA_LIBRARIES: /usr/local/lib/libcmocka.dylib

[Help] SDL2 addon libraries

I'm having a hard time using CPM with the SDL2 libraries.
I've used the ModerCppStarter repository to start this project.

Adding SDL2 works fine:

CPMAddPackage(
  NAME SDL2
  VERSION 2.0.12
  URL https://libsdl.org/release/SDL2-2.0.12.zip
)

But I can't make TTF and Mixer libraries to work as intended:


CPMAddPackage(
  NAME SDL2_ttf
  VERSION 2.0.15
  URL https://libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.15.zip
  DOWNLOAD_ONLY TRUE
)

CPMAddPackage(
  NAME SDL2_mixer
  VERSION 2.0.15
  URL https://libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.4.zip
  DOWNLOAD_ONLY TRUE
)

...

add_library(PacMan ${headers} ${sources})

target_include_directories(PacMan
  PUBLIC
    $<BUILD_INTERFACE:${SDL2_ttf_SOURCE_DIR}>
)

target_include_directories(PacMan
  PUBLIC
    $<BUILD_INTERFACE:${SDL2_mixer_SOURCE_DIR}>
)

...

target_link_libraries(PacManStandalone PacMan cxxopts SDL2 SDL2_ttf SDL2_mixer glm)

When linking the SDL2_ttf and SDL2_mixer libraries to the project, in the CMakeLists.txt file of the standalone source, I've get the following error:

[ 47%] Built target SDL2
[ 51%] Built target PacMan
[ 51%] Linking CXX executable PacMan
/usr/bin/ld: cannot find -lSDL2_ttf
/usr/bin/ld: cannot find -lSDL2_mixer
/usr/bin/ld: cannot find -lSDL2::SDL2
/usr/bin/ld: cannot find -lFreetype::Freetype

Apparently, I need to build the SDL2_ttf and SDL2_mixer linking to the SDL2 target, but I have no clue of how to do that.
Thanks in advance.

Not compiling SDL2 when set to use a static library

CPMAddPackage(
  NAME SDL2
  VERSION 2.0.12
  URL https://libsdl.org/release/SDL2-2.0.12.zip
  OPTIONS
    "SDL_SHARED Off"
)

add_executable (test "main.cpp" )
set_target_properties(test PROPERTIES CXX_STANDARD 20)
target_link_libraries(test SDL2)

I get an Error LNK1104 cannot open file 'SDL2.lib', SDL2.lib does not exist, it was not compiled.
Building with the shared library compiles fine.

How to use Howard Hinnant's date library with CPM?

I'm trying to use Howard Hinnant's date library with CPM.

This works:

CPMAddPackage(
        NAME HowardHinnant_date
        GITHUB_REPOSITORY HowardHinnant/date
        VERSION 3.0.0
)

But I have to use #include "include/date/date.h" to include the header. I want to get rid of the include part in the #include path (#include "date/date.h").

I tried

if(HowardHinnant_date_ADDED)
    target_include_directories( HowardHinnant_date INTERFACE
            ${HowardHinnant_date_SOURCE_DIR}/include )
endif()

But cmake complains that target HowardHinnant_date is not build in my cmake project. So I changed this into (using the actual target's name (e.g., myproject))

if(HowardHinnant_date_ADDED)
    target_include_directories( myproject INTERFACE
            ${HowardHinnant_date_SOURCE_DIR}/include )
endif()

But still the pre-processor cannot find date/date.h in #include "date/date.h".

Allowing EXCLUDE_FROM_ALL

Hi @TheLartians ,

Thanks for the library.

When I include a CMake library with CPM.cmake it runs all the install commands in that library even when I don't need these installers with my own library.

When adding the library as a subdirectory, it's possible to use add_subdirectory(libname EXCLUDE_FROM_ALL) to avoid that behavior.

Is it possible to use EXCLUDE_FROM_ALL when downloading a CMake library?

I don't know if that's a question or an enhancement.

Best,

Old CMake support

Currently CPM.cmake requires CMake 3.14, as specific used FetchContent features are only available in recent versions of CMake. Theoretically, it should be possible to support older Versions of CMake by downloading the FetchContent.cmake script on-demand for old CMake versions.

Create a Gitter chat room

Create a chat room on Gitter would be a great way of asking and answering questions, and discuss in general!

subcommand failing when using CPM_SOURCE_CACHE on Windows

When I active the CPM_SOURCE_CACHE, I get a subcommand failed error. It appears to be originating from this line.

executing:
cmake -B_build -GNinja -DCMAKE_TOOLCHAIN_FILE="../../cmake/arm-gcc-cortex-m4.cmake" -DCPM_SOURCE_CACHE="C:\Users\ryanw/.cpm"

results in:
[1/9] Performing download step for 'threadx-populate'
':' is not recognized as an internal or external command,
operable program or batch file.
FAILED: threadx-populate-prefix/src/threadx-populate-stamp/threadx-populate-download
cmd.exe /C "cd /D D:\projects\iot\getting-started\Renesas\AE-CLOUD2_build_deps\threadx-subbuild\threadx-populate-prefix\src && : && "C:\Program Files\CMake\bin\cmake.exe" -E touch D:/projects/iot/getting-started/Renesas/AE-CLOUD2/_bu
ild/_deps/threadx-subbuild/threadx-populate-prefix/src/threadx-populate-stamp/threadx-populate-download"
ninja: build stopped: subcommand failed.

Clarification on "offline" builds

As I understood the documentation, I should be able to configure a cmake project with CPM packages without internet access as long as the I am using a local cache and it contains the package in the version needed.

One question I have about this: when I specify GIT_TAG master how does it know if the cache is still valid without checking online?

When I try to use it that way without internet access, it actually fails somewhere in the FetchContent module while trying to access the online repository. (I checked the cache is active, populated and CPM shows it is finding a cache entry).

So the "offline" mode only works if you specify a commit hash? Would be good to add this to the documentation I think.

[Feature Request] npm-like version managment

Hello, firstly thanks for the awesome package manager you made. I had a great time using this in some of my projects.

But I think a more advanced versioning feature like npm is essential for a package manager.

I think having this would be a great improvement for CPM. Would you like to have a look into it?

Thanks a lot in advance!

Multiple versions of CPM?

I want to use CPM at my company but I'm concerned about the following types of scenarios. That could easily occur if every project is individually downloading CPM.

Project A uses CPM 0.27.5
Project B uses CPM 1.01.0
Project C uses CPM 0.10.0

What happens if project A uses project B?

What happens if project B uses project A?

What happens if project B uses project C?

What happens if project C uses project B?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.