Compare commits

...

8 Commits

Author SHA1 Message Date
Lars Melchior
c3c7e2d9a3 add on-demand download script to release (#146) 2020-08-20 09:32:03 +02:00
Lars Melchior
30b98af416 Add link to tutorial (#143) 2020-08-12 13:41:40 +02:00
Lars Melchior
5063c7d992 Add built with CPM.cmake section (#142)
* add built with cpm.cmake section

* update text

* explicitly set width
2020-08-11 14:49:21 +02:00
Lars Melchior
3cfb309f3c add comparisons to other approaches (#141) 2020-08-11 12:49:37 +02:00
Lars Melchior
25603ac4ad Update publish script to set CPM.cmake version automatically (#139)
* update publish script to set CPM.cmake version automatically

* set a minimum development version to avoid deprecated error handler call
2020-08-04 13:12:35 +02:00
Lars Melchior
ac872f6908 Bump version and add gitlab source to examples (#138)
* use gitlab as source for example library

* bump CPM.cmake version
2020-08-04 12:24:06 +02:00
jecassis
bd14ccbd5a Fix indeterminate command for GitLab argument (#137) 2020-08-04 11:40:58 +02:00
Kingsley Chen
f8afae6eb3 Add asio standalone example (#133)
* Add asio standalone example

* Mark VERSION explicitly

Without this version information, CPM's versioning mechanism may break
in some cases.

Also add comments for compile definition on Windows.

* Use aync-tcp-echo-server as the example

* Add boost software license to the demo source

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>

Co-authored-by: Lars Melchior <TheLartians@users.noreply.github.com>
2020-06-24 12:40:12 +02:00
10 changed files with 297 additions and 10 deletions

View File

@@ -11,11 +11,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set CPM version by tag
run: |
mkdir dist
sed "s/0.27.2-development-version/${GITHUB_REF/refs\/tags\/v}/g" cmake/CPM.cmake > dist/CPM.cmake
sed "s/0.27.2-development-version/${GITHUB_REF/refs\/tags\/v}/g" cmake/get_cpm.cmake > dist/get_cpm.cmake
- name: Upload CPM.cmake to release
uses: svenstaro/upload-release-action@v1-release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: cmake/CPM.cmake
asset_name: CPM.cmake
tag: ${{ github.ref }}
file: dist/*.cmake
file_glob: true
overwrite: true

View File

@@ -10,7 +10,7 @@
# Setup-free CMake dependency management
CPM.cmake is a CMake script that adds dependency management capabilities to CMake.
It's built as a thin wrapper around CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module that adds version control, caching and a simple API.
It's built as a thin wrapper around CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module that adds version control, caching, a simple API [and more](#comparison-to-pure-fetchcontent--externalproject).
## Manage everything
@@ -49,6 +49,8 @@ After calling `CPMAddPackage` or `CPMFindPackage`, the following variables are d
The difference between `CPMFindPackage` and `CPMAddPackage` is that `CPMFindPackage` will try to find a local dependency via CMake's `find_package` and fallback to `CPMAddPackage` if the dependency is not found.
This behaviour can be also modified globally via [CPM options](#options).
See [this medium article](https://medium.com/swlh/cpm-an-awesome-dependency-manager-for-c-with-cmake-3c53f4376766) for a short tutorial on using CPM.cmake.
## Full CMakeLists Example
```cmake
@@ -73,7 +75,7 @@ CPMAddPackage(
target_link_libraries(tests Catch2)
```
See the [examples directory](https://github.com/TheLartians/CPM.cmake/tree/master/examples) for complete examples with source code or the [wiki](https://github.com/TheLartians/CPM.cmake/wiki/More-Snippets) for example snippets.
See the [examples directory](https://github.com/TheLartians/CPM.cmake/tree/master/examples) for complete examples with source code and check [below](#snippets) or in the [wiki](https://github.com/TheLartians/CPM.cmake/wiki/More-Snippets) for example snippets.
## Adding CPM
@@ -111,6 +113,33 @@ For projects with more complex needs and where an extra setup step doesn't matte
Dependencies added with `CPMFindPackage` should work with external package managers.
Additionally, the option [`CPM_USE_LOCAL_PACKAGES`](#cpmuselocalpackages) 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](https://github.com/TheLartians/CPM.cmake/issues/132#issuecomment-644955140), 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 omit a warning if another dependency requires a more recent version.
- Options: any Options passed to a dependency are stored and compared on later use, so if another dependency tries to add an existing dependency with incompatible options a warning will be emitted to the user.
- 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](#cpm_source_cache).
- 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](#cpm_use_local_packages), making it easy to integrate into projects that may require local versioning through the system's package manager.
- [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.
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
@@ -166,6 +195,41 @@ cmake --build build --target cpm-update-package-lock
See the [wiki](https://github.com/TheLartians/CPM.cmake/wiki/Package-lock) for more info.
## 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.
<table>
<tr>
<td>
<a href="https://otto-project.github.io">
<p align="center">
<img src="https://avatars2.githubusercontent.com/u/40357059?s=200&v=4" alt="otto-project" height=100pt width=100pt />
</p>
<p align="center"><b>OTTO - The Open Source GrooveBox</b></p>
</a>
</td>
<td>
<a href="https://maphi.app">
<p align="center">
<img src="https://user-images.githubusercontent.com/4437447/89892751-71af8000-dbd7-11ea-9d87-4fe107845069.png" alt="maphi" height=100pt width=100pt />
</p>
<p align="center"><b>Maphi - the Math App</b></p>
</a>
</td>
<td>
<a href="https://github.com/TheLartians/ModernCppStarter">
<p align="center">
<img src="https://repository-images.githubusercontent.com/254842585/4dfa7580-7ffb-11ea-99d0-46b8fe2f4170" alt="modern-cpp-starter" height=100pt width=200pt />
</p>
<p align="center"><b>ModernCppStarter</b></p>
</a>
</td>
</tr>
</table>
## Snippets
These examples demonstrate how to include some well-known projects with CPM.

View File

@@ -28,7 +28,7 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
set(CURRENT_CPM_VERSION 0.27.1)
set(CURRENT_CPM_VERSION 0.27.2-development-version)
if(CPM_DIRECTORY)
if(NOT CPM_DIRECTORY STREQUAL CMAKE_CURRENT_LIST_DIR)
@@ -219,7 +219,7 @@ function(CPMAddPackage)
endif()
if (DEFINED CPM_ARGS_GITLAB_REPOSITORY)
list(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git")
set(CPM_ARGS_GIT_REPOSITORY "https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git")
endif()
if (DEFINED CPM_ARGS_GIT_REPOSITORY)

19
cmake/get_cpm.cmake Normal file
View File

@@ -0,0 +1,19 @@
set(CPM_DOWNLOAD_VERSION 0.27.2-development-version)
if(CPM_SOURCE_CACHE)
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/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 to ${CPM_DOWNLOAD_LOCATION}")
file(DOWNLOAD
https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
${CPM_DOWNLOAD_LOCATION}
)
endif()
include(${CPM_DOWNLOAD_LOCATION})

View File

@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(CPMExampleASIOStandalone)
# ---- Dependencies ----
include(../../cmake/CPM.cmake)
find_package(Threads REQUIRED)
CPMAddPackage(
NAME asio
VERSION 1.16.1
GITHUB_REPOSITORY chriskohlhoff/asio
GIT_TAG asio-1-16-1 # asio uses non-standard version tag, we must specify GIT_TAG
)
# ASIO doesn't use CMake, we have to configure it manually.
# Extra notes for using on Windows:
# 1) If _WIN32_WINNT is not set, ASIO assumes _WIN32_WINNT=0x0501, i.e. Windows XP target,
# which is definitely not the platform which most users target.
# 2) WIN32_LEAN_AND_MEAN is defined to make Winsock2 work.
if(asio_ADDED)
add_library(asio INTERFACE)
target_include_directories(asio
INTERFACE ${asio_SOURCE_DIR}/asio/include
)
target_compile_definitions(asio
INTERFACE
ASIO_STANDALONE
ASIO_NO_DEPRECATED
)
target_link_libraries(asio
INTERFACE
Threads::Threads
)
if(WIN32)
# macro see @ https://stackoverflow.com/a/40217291/1746503
macro(get_win32_winnt version)
if (CMAKE_SYSTEM_VERSION)
set(ver ${CMAKE_SYSTEM_VERSION})
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
if ("${verMajor}" MATCHES "10")
set(verMajor "A")
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
endif ("${verMajor}" MATCHES "10")
# Remove all remaining '.' characters.
string(REPLACE "." "" ver ${ver})
# Prepend each digit with a zero.
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
set(${version} "0x${ver}")
endif()
endmacro()
if(NOT DEFINED _WIN32_WINNT)
get_win32_winnt(ver)
set(_WIN32_WINNT ${ver})
endif()
message(STATUS "Set _WIN32_WINNET=${_WIN32_WINNT}")
target_compile_definitions(asio
INTERFACE
_WIN32_WINNT=${_WIN32_WINNT}
WIN32_LEAN_AND_MEAN
)
endif()
endif()
# ---- Executable ----
add_executable(CPMExampleASIOStandalone main.cpp)
target_link_libraries(CPMExampleASIOStandalone asio)

View File

@@ -0,0 +1,118 @@
//
// async_tcp_echo_server.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
//
#include <cstdlib>
#include <iostream>
#include <memory>
#include <utility>
#include "asio.hpp"
// An asynchronous tcp echo server.
// See https://think-async.com/Asio/asio-1.16.1/src/examples/cpp11/echo/async_tcp_echo_server.cpp
using asio::ip::tcp;
class session
: public std::enable_shared_from_this<session>
{
public:
session(tcp::socket socket)
: socket_(std::move(socket))
{
}
void start()
{
do_read();
}
private:
void do_read()
{
auto self(shared_from_this());
socket_.async_read_some(asio::buffer(data_, max_length),
[this, self](std::error_code ec, std::size_t length)
{
if (!ec)
{
do_write(length);
}
});
}
void do_write(std::size_t length)
{
auto self(shared_from_this());
asio::async_write(socket_, asio::buffer(data_, length),
[this, self](std::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
do_read();
}
});
}
tcp::socket socket_;
enum { max_length = 1024 };
char data_[max_length];
};
class server
{
public:
server(asio::io_context& io_context, short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}
private:
void do_accept()
{
acceptor_.async_accept(
[this](std::error_code ec, tcp::socket socket)
{
if (!ec)
{
std::make_shared<session>(std::move(socket))->start();
}
do_accept();
});
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 2)
{
std::cerr << "Usage: async_tcp_echo_server <port>\n";
return 1;
}
asio::io_context io_context;
server s(io_context, std::atoi(argv[1]));
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}

View File

@@ -8,7 +8,7 @@ include(../../cmake/CPM.cmake)
CPMAddPackage(
NAME fibonacci
GIT_REPOSITORY https://github.com/TheLartians/Fibonacci.git
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)

View File

@@ -8,7 +8,7 @@ include(../../cmake/CPM.cmake)
CPMAddPackage(
NAME fibonacci
GIT_REPOSITORY https://github.com/TheLartians/Fibonacci.git
GITHUB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)

View File

@@ -8,7 +8,7 @@ include(../../cmake/CPM.cmake)
CPMAddPackage(
NAME fibonacci
GIT_REPOSITORY https://github.com/TheLartians/Fibonacci.git
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)

View File

@@ -8,7 +8,7 @@ include(../../cmake/CPM.cmake)
CPMAddPackage(
NAME fibonacci
GIT_REPOSITORY https://github.com/TheLartians/Fibonacci.git
GITLAB_REPOSITORY TheLartians/Fibonacci
VERSION 2.0
)