Skip to content

Commit 4cbf443

Browse files
authored
If a name isn't provided, try to infer it from the git repo (#202)
* Added assert_not_defined check * Function to get package name form git uri and tests * Autofix format * If name is not provided, try to infer it from the git repo * Unset result of cpm_package_name_from_git_uri if there is no match - Also reordered tests to ensure that the result is actually unset when needed * Removed trailing spaces in README * Updated the main example with the new minimal syntax * Well... autofix format again * Update error message for missing name to reflect the possible auto-infer step * Autofix format... yet again :)
1 parent 2744b87 commit 4cbf443

File tree

4 files changed

+71
-15
lines changed

4 files changed

+71
-15
lines changed

README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ CPMAddPackage(
4343

4444
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).
4545
If `GIT_TAG` hasn't been explicitly specified it defaults to `v(VERSION)`, a common convention for git projects.
46-
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.
46+
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.
4747
`GIT_TAG` can also be set to a specific commit or a branch name such as `master` to always download the most recent version.
4848
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).
4949

@@ -71,7 +71,6 @@ add_executable(tests tests.cpp)
7171
include(cmake/CPM.cmake)
7272
7373
CPMAddPackage(
74-
NAME Catch2
7574
GITHUB_REPOSITORY catchorg/Catch2
7675
VERSION 2.5.0
7776
)
@@ -112,7 +111,7 @@ Dependencies using CPM will automatically use the updated script of the outermos
112111
## Limitations
113112

114113
- **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.
115-
- **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).
114+
- **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).
116115
- **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).
117116

118117
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:
143142
- [Package lock files](#package-lock) for easier transitive dependency management.
144143
- Dependencies can be overridden [per-build](#local-package-override) using CMake CLI parameters.
145144

146-
ExternalProject works similarly as FetchContent, however waits with adding dependencies until build time.
145+
ExternalProject works similarly as FetchContent, however waits with adding dependencies until build time.
147146
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.
148147

149148
## Options
@@ -178,7 +177,7 @@ These options can also be set as environmental variables.
178177

179178
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.
180179
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.
181-
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.
180+
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.
182181

183182
```bash
184183
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
205204

206205
## Built with CPM.cmake
207206

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

211210
<table>
@@ -284,7 +283,7 @@ CPMAddPackage(
284283
# 0.6.2 uses deprecated CMake syntax
285284
VERSION 0.6.3
286285
# 0.6.3 is not released yet, so use a recent commit
287-
GIT_TAG 012269756149ae99745b6dafefd415843d7420bb
286+
GIT_TAG 012269756149ae99745b6dafefd415843d7420bb
288287
OPTIONS
289288
"YAML_CPP_BUILD_TESTS Off"
290289
"YAML_CPP_BUILD_CONTRIB Off"
@@ -314,7 +313,7 @@ endif()
314313
```cmake
315314
CPMAddPackage(
316315
NAME nlohmann_json
317-
VERSION 3.6.1
316+
VERSION 3.6.1
318317
# the git repo is incredibly large, so we download the archived include directory
319318
URL https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip
320319
URL_HASH SHA256=69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf
@@ -337,7 +336,7 @@ CPMAddPackage(
337336
DOWNLOAD_ONLY True
338337
)
339338
340-
if(range-v3_ADDED)
339+
if(range-v3_ADDED)
341340
add_library(range-v3 INTERFACE IMPORTED)
342341
target_include_directories(range-v3 INTERFACE "${range-v3_SOURCE_DIR}/include")
343342
endif()

cmake/CPM.cmake

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ endif()
134134
include(FetchContent)
135135
include(CMakeParseArguments)
136136

137+
# Infer package name from git repository uri (path or url)
138+
function(cpm_package_name_from_git_uri URI RESULT)
139+
string(REGEX MATCH "([^/:]+)/?.git/?$" cpmGitUriMatch "${URI}")
140+
if(DEFINED cpmGitUriMatch)
141+
set(${RESULT}
142+
${CMAKE_MATCH_1}
143+
PARENT_SCOPE
144+
)
145+
else()
146+
unset(${RESULT} PARENT_SCOPE)
147+
endif()
148+
endfunction()
149+
137150
# Initialize logging prefix
138151
if(NOT CPM_INDENT)
139152
set(CPM_INDENT
@@ -264,12 +277,6 @@ function(CPMAddPackage)
264277

265278
cmake_parse_arguments(CPM_ARGS "" "${oneValueArgs}" "${multiValueArgs}" "${ARGN}")
266279

267-
# Check for required arguments
268-
269-
if(NOT DEFINED CPM_ARGS_NAME)
270-
message(FATAL_ERROR "CPM: 'NAME' was not provided for package added with arguments: '${ARGN}'")
271-
endif()
272-
273280
# Set default values for arguments
274281

275282
if(NOT DEFINED CPM_ARGS_VERSION)
@@ -297,6 +304,11 @@ function(CPMAddPackage)
297304
if(NOT DEFINED CPM_ARGS_GIT_TAG)
298305
set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})
299306
endif()
307+
308+
# If a name wasn't provided, try to infer it from the git repo
309+
if(NOT DEFINED CPM_ARGS_NAME)
310+
cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)
311+
endif()
300312
endif()
301313

302314
set(CPM_SKIP_FETCH FALSE)
@@ -309,6 +321,15 @@ function(CPMAddPackage)
309321
endif()
310322
endif()
311323

324+
# Check for required arguments
325+
326+
if(NOT DEFINED CPM_ARGS_NAME)
327+
message(
328+
FATAL_ERROR
329+
"CPM: 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'"
330+
)
331+
endif()
332+
312333
# Check if package has been added before
313334
cpm_check_if_package_already_added(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" "${CPM_ARGS_OPTIONS}")
314335
if(CPM_PACKAGE_ALREADY_ADDED)

cmake/testing.cmake

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ function(ASSERT_DEFINED KEY)
3636
endif()
3737
endfunction()
3838

39+
function(ASSERT_NOT_DEFINED KEY)
40+
if(DEFINED ${KEY})
41+
message(FATAL_ERROR "assertion failed: '${KEY}' is defiend")
42+
else()
43+
message(STATUS "test passed: '${KEY}' is not defined")
44+
endif()
45+
endfunction()
46+
3947
function(ASSERT_TRUTHY KEY)
4048
if(${${KEY}})
4149
message(STATUS "test passed: '${KEY}' is set truthy")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
2+
3+
include(${CPM_PATH}/CPM.cmake)
4+
include(${CPM_PATH}/testing.cmake)
5+
6+
cpm_package_name_from_git_uri("https://github.com/cpm-cmake/CPM.cmake.git" name)
7+
assert_equal("CPM.cmake" ${name})
8+
9+
cpm_package_name_from_git_uri("ssh://user@host.xz:123/path/to/pkg.git/" name)
10+
assert_equal("pkg" ${name})
11+
12+
cpm_package_name_from_git_uri("git://host.xz/path/to/pkg.git" name)
13+
assert_equal("pkg" ${name})
14+
15+
cpm_package_name_from_git_uri("git@host.xz:cool-pkg.git" name)
16+
assert_equal("cool-pkg" ${name})
17+
18+
cpm_package_name_from_git_uri("file:///path/to/pkg33.git" name)
19+
assert_equal("pkg33" ${name})
20+
21+
cpm_package_name_from_git_uri("../local-repo/.git" name)
22+
assert_equal("local-repo" ${name})
23+
24+
cpm_package_name_from_git_uri("asdf" name)
25+
assert_not_defined(name)
26+
27+
cpm_package_name_from_git_uri("/something.git/stuff" name)
28+
assert_not_defined(name)

0 commit comments

Comments
 (0)