mirror of
https://github.com/cpm-cmake/CPM.cmake.git
synced 2025-11-23 20:57:38 -05:00
Compare commits
3 Commits
v0.29.0-pr
...
v0.30.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cbf443363 | ||
|
|
2744b87f07 | ||
|
|
fd539b8ff3 |
@@ -33,6 +33,7 @@ parse:
|
||||
DOWNLOAD_NO_EXTRACT: 1
|
||||
HTTP_USERNAME: 1
|
||||
HTTP_PASSWORD: 1
|
||||
EXCLUDE_FROM_ALL: 1
|
||||
OPTIONS: +
|
||||
cpmfindpackage:
|
||||
pargs:
|
||||
|
||||
17
README.md
17
README.md
@@ -43,7 +43,7 @@ CPMAddPackage(
|
||||
|
||||
The origin may be specified by a `GIT_REPOSITORY`, but other sources, such as direct URLs, are [also supported](https://cmake.org/cmake/help/v3.11/module/ExternalProject.html#external-project-definition).
|
||||
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.
|
||||
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` to always download the most recent version.
|
||||
The optional argument `FIND_PACKAGE_ARGUMENTS` can be specified to a string of parameters that will be passed to `find_package` if enabled (see below).
|
||||
|
||||
@@ -71,7 +71,6 @@ add_executable(tests tests.cpp)
|
||||
include(cmake/CPM.cmake)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME Catch2
|
||||
GITHUB_REPOSITORY catchorg/Catch2
|
||||
VERSION 2.5.0
|
||||
)
|
||||
@@ -112,7 +111,7 @@ Dependencies using CPM will automatically use the updated script of the outermos
|
||||
## 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`](#CPM_SOURCE_CACHE) environmental variable. Using a caching compiler such as [ccache](https://github.com/TheLartians/Ccache.cmake) 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](#snippets) for examples). For best practices on preparing projects for CPM, see the [wiki](https://github.com/cpm-cmake/CPM.cmake/wiki/Preparing-projects-for-CPM.cmake).
|
||||
- **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](#snippets) for examples). For best practices on preparing projects for CPM, see the [wiki](https://github.com/cpm-cmake/CPM.cmake/wiki/Preparing-projects-for-CPM.cmake).
|
||||
- **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](#package-lock).
|
||||
|
||||
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](https://github.com/microsoft/vcpkg), [conan](https://conan.io) or [hunter](https://github.com/ruslo/hunter).
|
||||
@@ -143,7 +142,7 @@ The most notable features are:
|
||||
- [Package lock files](#package-lock) for easier transitive dependency management.
|
||||
- Dependencies can be overridden [per-build](#local-package-override) using CMake CLI parameters.
|
||||
|
||||
ExternalProject works similarly as FetchContent, however waits with adding dependencies until build time.
|
||||
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
|
||||
@@ -178,7 +177,7 @@ These options can also be set as environmental variables.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```bash
|
||||
cmake -Bbuild -DCPM_Dep_SOURCE=/path/to/dep
|
||||
@@ -205,7 +204,7 @@ See the [wiki](https://github.com/cpm-cmake/CPM.cmake/wiki/Package-lock) for mor
|
||||
|
||||
## Built with CPM.cmake
|
||||
|
||||
Some amazing projects that are built using the CPM.cmake package manager.
|
||||
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.
|
||||
|
||||
<table>
|
||||
@@ -284,7 +283,7 @@ CPMAddPackage(
|
||||
# 0.6.2 uses deprecated CMake syntax
|
||||
VERSION 0.6.3
|
||||
# 0.6.3 is not released yet, so use a recent commit
|
||||
GIT_TAG 012269756149ae99745b6dafefd415843d7420bb
|
||||
GIT_TAG 012269756149ae99745b6dafefd415843d7420bb
|
||||
OPTIONS
|
||||
"YAML_CPP_BUILD_TESTS Off"
|
||||
"YAML_CPP_BUILD_CONTRIB Off"
|
||||
@@ -314,7 +313,7 @@ endif()
|
||||
```cmake
|
||||
CPMAddPackage(
|
||||
NAME nlohmann_json
|
||||
VERSION 3.6.1
|
||||
VERSION 3.6.1
|
||||
# the git repo is incredibly large, so we download the archived include directory
|
||||
URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip
|
||||
URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf
|
||||
@@ -337,7 +336,7 @@ CPMAddPackage(
|
||||
DOWNLOAD_ONLY True
|
||||
)
|
||||
|
||||
if(range-v3_ADDED)
|
||||
if(range-v3_ADDED)
|
||||
add_library(range-v3 INTERFACE IMPORTED)
|
||||
target_include_directories(range-v3 INTERFACE "${range-v3_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
@@ -134,6 +134,19 @@ endif()
|
||||
include(FetchContent)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Infer package name from git repository uri (path or url)
|
||||
function(cpm_package_name_from_git_uri URI RESULT)
|
||||
string(REGEX MATCH "([^/:]+)/?.git/?$" cpmGitUriMatch "${URI}")
|
||||
if(DEFINED cpmGitUriMatch)
|
||||
set(${RESULT}
|
||||
${CMAKE_MATCH_1}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
else()
|
||||
unset(${RESULT} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Initialize logging prefix
|
||||
if(NOT CPM_INDENT)
|
||||
set(CPM_INDENT
|
||||
@@ -243,8 +256,6 @@ endfunction()
|
||||
# Download and add a package from source
|
||||
function(CPMAddPackage)
|
||||
|
||||
set(flagArgs EXCLUDE_FROM_ALL)
|
||||
|
||||
set(oneValueArgs
|
||||
NAME
|
||||
FORCE
|
||||
@@ -259,11 +270,12 @@ function(CPMAddPackage)
|
||||
FIND_PACKAGE_ARGUMENTS
|
||||
NO_CACHE
|
||||
GIT_SHALLOW
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
set(multiValueArgs OPTIONS)
|
||||
|
||||
cmake_parse_arguments(CPM_ARGS "${flagArgs}" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
|
||||
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
|
||||
|
||||
# Set default values for arguments
|
||||
|
||||
@@ -292,6 +304,11 @@ function(CPMAddPackage)
|
||||
if(NOT DEFINED CPM_ARGS_GIT_TAG)
|
||||
set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
|
||||
endif()
|
||||
|
||||
# If a name wasn't provided, try to infer it from the git repo
|
||||
if(NOT DEFINED CPM_ARGS_NAME)
|
||||
cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPM_SKIP_FETCH FALSE)
|
||||
@@ -304,6 +321,15 @@ function(CPMAddPackage)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for required arguments
|
||||
|
||||
if(NOT DEFINED CPM_ARGS_NAME)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"CPM: 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Check if package has been added before
|
||||
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}")
|
||||
if(CPM_PACKAGE_ALREADY_ADDED)
|
||||
@@ -579,7 +605,7 @@ function(cpm_fetch_package PACKAGE DOWNLOAD_ONLY EXCLUDE)
|
||||
set(CPM_OLD_INDENT "${CPM_INDENT}")
|
||||
set(CPM_INDENT "${CPM_INDENT} ${PACKAGE}:")
|
||||
cpm_add_subdirectory(
|
||||
${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} ${EXCLUDE}
|
||||
${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR} "${EXCLUDE}"
|
||||
)
|
||||
set(CPM_INDENT "${CPM_OLD_INDENT}")
|
||||
endif()
|
||||
|
||||
@@ -10,6 +10,18 @@ function(ASSERT_EQUAL)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ASSERT_NOT_EQUAL)
|
||||
if(NOT ARGC EQUAL 2)
|
||||
message(FATAL_ERROR "assertion failed: invalid argument count: ${ARGC}")
|
||||
endif()
|
||||
|
||||
if(${ARGV0} STREQUAL ${ARGV1})
|
||||
message(FATAL_ERROR "assertion failed: '${ARGV0}' == '${ARGV1}'")
|
||||
else()
|
||||
message(STATUS "test passed: '${ARGV0}' != '${ARGV1}'")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ASSERT_EMPTY)
|
||||
if(NOT ARGC EQUAL 0)
|
||||
message(FATAL_ERROR "assertion failed: input ${ARGC} not empty: '${ARGV}'")
|
||||
@@ -24,6 +36,14 @@ function(ASSERT_DEFINED KEY)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ASSERT_NOT_DEFINED KEY)
|
||||
if(DEFINED ${KEY})
|
||||
message(FATAL_ERROR "assertion failed: '${KEY}' is defiend")
|
||||
else()
|
||||
message(STATUS "test passed: '${KEY}' is not defined")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(ASSERT_TRUTHY KEY)
|
||||
if(${${KEY}})
|
||||
message(STATUS "test passed: '${KEY}' is set truthy")
|
||||
|
||||
2
test/unit/broken_dependency/.gitignore
vendored
Normal file
2
test/unit/broken_dependency/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/CMakeLists.txt
|
||||
/package-lock.cmake
|
||||
13
test/unit/broken_dependency/CMakeLists.txt.in
Normal file
13
test/unit/broken_dependency/CMakeLists.txt.in
Normal file
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
|
||||
project(CPMTest)
|
||||
|
||||
# ---- Dependencies ----
|
||||
|
||||
include(@CPM_PATH@/CPM.cmake)
|
||||
|
||||
CPMAddPackage(
|
||||
NAME BrokenDependency
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/dependency
|
||||
EXCLUDE_FROM_ALL @EXCLUDE_FROM_ALL@
|
||||
)
|
||||
3
test/unit/broken_dependency/dependency/CMakeLists.txt
Normal file
3
test/unit/broken_dependency/dependency/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
project(BrokenDependency)
|
||||
|
||||
add_custom_target(error ALL ${CMAKE_COMMAND} -E false)
|
||||
35
test/unit/exclude_from_all.cmake
Normal file
35
test/unit/exclude_from_all.cmake
Normal file
@@ -0,0 +1,35 @@
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(${CPM_PATH}/testing.cmake)
|
||||
|
||||
set(TEST_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/exclude_from_all)
|
||||
|
||||
function(init_project EXCLUDE_FROM_ALL)
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_LIST_DIR}/broken_dependency/CMakeLists.txt.in"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/broken_dependency/CMakeLists.txt"
|
||||
INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/junk
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} "-H${CMAKE_CURRENT_LIST_DIR}/broken_dependency" "-B${TEST_BUILD_DIR}"
|
||||
RESULT_VARIABLE ret
|
||||
)
|
||||
|
||||
assert_equal(${ret} "0")
|
||||
endfunction()
|
||||
|
||||
function(build_project expected_success)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} "--build" "${TEST_BUILD_DIR}" RESULT_VARIABLE ret)
|
||||
|
||||
if(expected_success)
|
||||
assert_equal(${ret} 0)
|
||||
else()
|
||||
assert_not_equal(${ret} 0)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
init_project(FALSE)
|
||||
build_project(FALSE)
|
||||
|
||||
init_project(TRUE)
|
||||
build_project(TRUE)
|
||||
28
test/unit/package_name_from_git_uri.cmake
Normal file
28
test/unit/package_name_from_git_uri.cmake
Normal file
@@ -0,0 +1,28 @@
|
||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
||||
|
||||
include(${CPM_PATH}/CPM.cmake)
|
||||
include(${CPM_PATH}/testing.cmake)
|
||||
|
||||
cpm_package_name_from_git_uri("https://github.com/cpm-cmake/CPM.cmake.git" name)
|
||||
assert_equal("CPM.cmake" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("ssh://user@host.xz:123/path/to/pkg.git/" name)
|
||||
assert_equal("pkg" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("git://host.xz/path/to/pkg.git" name)
|
||||
assert_equal("pkg" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("git@host.xz:cool-pkg.git" name)
|
||||
assert_equal("cool-pkg" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("file:///path/to/pkg33.git" name)
|
||||
assert_equal("pkg33" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("../local-repo/.git" name)
|
||||
assert_equal("local-repo" ${name})
|
||||
|
||||
cpm_package_name_from_git_uri("asdf" name)
|
||||
assert_not_defined(name)
|
||||
|
||||
cpm_package_name_from_git_uri("/something.git/stuff" name)
|
||||
assert_not_defined(name)
|
||||
Reference in New Issue
Block a user