The Cppm Book (BETA)
Cppm is BETA Project Please Give Feedback
Cppm is CMake based Cross Platform C++ package manager
Manage and Downloads C++ dependencies, easy project build, install,
upload to cppkg
Features
- Easy to use CMake
- Easy Config file than CMakeList.txt
- Generate Cross Platform CMake base C++ Project
- Dependencies auto install in build step
- can use cmake uninstall target
- CMake base project can build with cppm (cppm build) (Use CMake's toolchain feature)
- Manage Depdendency with cppkg and Hunter Package Manage
- Dependency install only use CMake
Getting Started
To get started with Cppm, Install this Dependency
- C++ Compiler (c++17) # can use filesystem.h and optional.h
- CMake (3.12)
- ccache (optional) # Build cache
Installation
Install Cppm
cppm install command install defualt prefix is $HOME/.cppm/bin
Require
- C++17 Compiler (AppleClang can't build)
- CMake (Minumum 3.12)
- git
- ccache (optional)
Linux and MacOS
git clone --recurse-submodules https://github.com/injae/cppm.git
cd cppm
cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DUSE_CPPM_PATH=ON .
cd build
cmake --build . --config Release
cd Release
./cppm build install
# Add to cppm path
export PATH=$PATH:$HOME/.cppm/bin
Windows
# need visual studio , git , cmake
# scoop install git cmake
git clone --recurse-submodules https://github.com/injae/cppm.git
cd cppm
cmake -Bbuild -DCMAKE_BUILD_TYPE=Release -DUSE_CPPM_PATH=ON .
cd build
cmake --build . --config Release --target install --target cppm_link
# Add System Path %USERPROFILE%\.cppm\bin
First Steps with Cppm
To start a new package with Cppm, use cppm init
$ cppm init -h
Usage:
cppm init [--verbose]
Option:
--bin [-b] {name} :initialize new c++ binary project
--help [-h] :show cppm commands and options
--lib [-l] {name} :initialize new c++ library project
New Binary Project
$ cppm init --bin hello_world
Generated project
$ cd hello_world
$ tree .
.
|-- build # Build directory
| |-- Debug # Debug mode target directory
| `-- Release # Release mode target directory
|-- cmake # cmake module path
| |-- Modules # cmake Find*.cmake path
| `-- cppm_tool.cmake # cppm_tool load tool
|-- cppm.toml
|-- include # public header
|-- src # private header and sources
| `-- main.cpp
`-- thirdparty # cppkg config and file path
`-- ${cppkg_name}/${cppkg_version}/cppkg.toml # cppkg config file
Cppm project config file
# cppm.toml
[package]
name = "hello_world"
version = "0.0.1"
description = ""
[[bin]]
name = "hello_world"
source = ["src/.*"]
Generated defualt cpp file
// src/main.cpp
#include <iostream>
int main(int argc, char* argv[]) {
std::cout<<"hello world"<<std::endl;
return 0;
}
Compile "hello_world" project with cppm build
, this command generate CMakeLists.txt
$ cppm build
[cppm] Generate CMakeLists.txt
From https://github.com/injae/cppm_tools
1c79dca..00fb374 0.0.9 -> origin/0.0.9
-- [cppm] cppm_tools-0.0.9 download to /home-path/.cppm/src/cppm_tools/0.0.9
-- The C compiler identification is Clang 9.0.0
-- The CXX compiler identification is Clang 9.0.0
-- Check for working C compiler: /usr/local/opt/llvm/bin/clang
-- Check for working C compiler: /usr/local/opt/llvm/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/local/opt/llvm/bin/clang++
-- Check for working CXX compiler: /usr/local/opt/llvm/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- [cppm] Target: hello_world [Type:debug, Cppm:0.0.9, CMake:3.16.2]
-- [cppm] System: x86_64-Darwin-19.3.0
-- [cppm] Compiler: Clang-9.0.0
-- [cppm] Generator: Unix Makefiles
-- [cppm] Build Cache: ccache
-- [cppm] cppm_root: /path/to/.cppm
-- [cppm] c++ version: 17
-- [cppm] Compiler Option: -std=c++17 -Wall -fPIC -O0 -g
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/hello_world/build
Scanning dependencies of target hello_world
[ 50%] Building CXX object CMakeFiles/hello_world.dir/src/main.cpp.o
[100%] Linking CXX executable hello_world
[100%] Built target hello_world
And the run it.
$ cd build/Debug
$ ./hello_world
hello world
Easy run command cppm run
, default binary name ${[package.name]}
$ cppm run
hello world
Generated CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
include(cmake/cppm_tool.cmake)
cppm_project()
project(hello_world VERSION 0.0.1 LANGUAGES C CXX)
cppm_setting()
cppm_cxx_standard(17)
cppm_compiler_option(DEFAULT)
cppm_target_define(hello_world BINARY
SOURCES
src/main.cpp
)
cppm_target_dependencies(hello_world)
cppm_target_install(hello_world)
Changed project Directory
$ tree .
.
├── CMakeLists.txt
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 3.17.1
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── CMakeCCompilerId.c
│ │ │ │ ├── a.out
│ │ │ │ └── tmp
│ │ │ └── CompilerIdCXX
│ │ │ ├── CMakeCXXCompilerId.cpp
│ │ │ ├── a.out
│ │ │ └── tmp
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── Makefile.cmake
│ │ ├── Makefile2
│ │ ├── TargetDirectories.txt
│ │ ├── cmake.check_cache
│ │ ├── progress.marks
│ │ ├── hello_world.dir
│ │ │ ├── CXX.includecache
│ │ │ ├── DependInfo.cmake
│ │ │ ├── build.make
│ │ │ ├── cmake_clean.cmake
│ │ │ ├── depend.internal
│ │ │ ├── depend.make
│ │ │ ├── flags.make
│ │ │ ├── link.txt
│ │ │ ├── progress.make
│ │ │ └── src
│ │ │ └── main.cpp.o
│ │ └── hello_world_info.dir
│ │ ├── DependInfo.cmake
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ └── progress.make
│ ├── Debug
│ │ └── hello_world # Binary or Library export Directory
│ ├── Makefile
│ ├── cmake_install.cmake
│ └── compile_commands.json
├── cmake
│ ├── Modules
│ └── cppm_tool.cmake
├── cppm.toml
├── include
├── src
│ └── main.cpp
└── thirdparty
Cppm Guide
Cppm Base Project Layout
.
|-- cppm.toml # cppm config file
|-- CMakeLists.txt # <-- generated from cppm.toml
|-- build # Build directory
| |-- Debug # Debug mode target directory
| `-- Release # Release mode target directory
|-- cmake # cmake module path
| |-- Modules # cmake Find*.cmake path
| `-- cppm_tool.cmake # cppm_tool load script (require)
|-- include # public header (export header)
|-- src # private header and sources
| `-- main.cpp
|-- test # test src directory
| `-- test01.cpp
|-- examples # example src directory
| `-- example01.cpp
`-- thirdparty # cppkg config and file path
`-- ${cppkg_name}/${cppkg_version}/cppkg.toml # cppkg config file
Cppm Structure
cppm use cmake toolchain feature cppm build command use CMakeCache.txt
cppm build command search cppm.toml or CMakeLists.txt
$ cppm build --detail
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/.cppm/cppkg/cppm-tools-0.0.11/toolchain.cmake -DUSE_CPPM_PATH=ON -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . --config Debug -- -j{your cpu core}
~/.cppm/
├── bin # cppm installed binary path (symbolic links)
│ └── cppm # -> ../share/cppm-0.0.10/bin/cppm
├── cache ... # cmake build cache
├── cmake # cppm module path
│ ├── HunterGate.cmake # if you use hunter package this file copy your package cmake/HunterGate.cmake
│ └── cppm_tool.cmake
├── repo # cppkg regiested package installer path
│ └── cppkg
│ ├── Catch2
│ │ ├── 2.9.1
│ │ │ ├── Catch2.cmake.in
│ │ │ └── cppkg.toml
│ │ └── git
│ │ ├── Catch2.cmake.in
│ │ └── cppkg.toml
│ ├── cppm
│ │ └── git
│ . ├── cppkg.toml
│ . └── cppm.cmake.in
└── cppkg # cppkg install path
├── cppm-0.0.11
. ├── bin ...
. ├── include ...
. └── lib ...
cppkg.toml
[package]
name = "..." # (require)
version = "..." # (require)
desciprtion = "..." # (require)
standard = "{11|14|17(default)|20}"
git = "..." # this option use to cppm build --export
vcpkg= "false(default)|true" # cppm auto detect vcpkg option
[hunter] # (optional) hunter package manager setting option
use = true|false(default) # if you use hunter package this option is default is true
url = "..." # custom hunter version url setting option, [ url, sha1 ] is pair
sha1 = "..." # custom hunter version sha1 setting option, [ url, sha1 ] is pair
[cmake] # (optional) cmake setting option
include = ["xxx.cmake", ...] # this option is include cmake file
version = "..." # minimum cmake version setting option default is 3.12
option = "..." # cmake build option use to command 'cppm build'
toolchains = "..." # (incomplete) cmake toolchains option
Profiles Prfiles provide a way alter the compiler settings, Profile settings can be overridden for specific packages
[profile.dev] # this is only debug or test or example mode compiler option
[profile.release] # this is only release mode compiler option
[profile.test] # (incomplete) this is only test mode compiler option
[profile.release.compiler] # this is only release mode compiler option
clang = "..." # compiler option
gcc = "..." # compiler option
msvc = "..." # compiler option
[profile.release.package.{package.name}] # (incomplete) override for specific packages
[profile.release.package.{package_name}.compiler] # (incomplete) this is only release mode compiler option
[[bin]]
name = "..." # target name (require)
sources = ["src/ss/.*", src/xx.cpp, ...] # (require), source files, you can use regex
install = true(default)|false # disable install setting
[lib]
name = "..." # target name, export cmake package name
type = "static(default)|shared|hearder-only"
namespace = "... " (default: [package.name]) # cmake export namespace
sources = ["src/xxx.cpp", ...] # type = "header_only" this option not working
install = true(default)|false # disable install setting
[[test]]
name = "..." # target name, export cmake package name
type = "binary(default)|static|shared|hearder-only"
sources = ["src/xxx.cpp", ...] # use source files, type = "header_only" no nessasery this optio
install = true|false(default) # disable install setting
[[example]]
name = "..." # target name, export cmake package name
type = "binary(default)|static|shared|hearder-only"
sources = ["src/xxx.cpp", ...] # use source files, type = "header_only" no nessasery this option
install = true|false(default) # disable install setting
# sub project setting
[workspace]
member = ["path/", "path"]
[dev-dependency] # this dependency only work debug mode
[dependencies]
# cppkg package add dependency
# name version(require)
... = "x.x.x|git|latest" # this config find cppkg.toml in ${package root}/thirdparty/${name}/${version}/cppkg.toml
# inline dependency setting
# name (require) (optional) (optional) default is public (optional) package type
... = {module = "..." , version ="...", components="... ...", link = "public|private|interface", type="lib(default)|bin|cmake(incomplete)", repo="cppkg(default)|hunter" }
# hunter package add dependency
# name (require) (optional) (optional) default is public (require) load hunter package
... = {module = "..." , version ="latest", components="... ...", link = "public|private|interface" , repo="hunter" }
# none cmake package add dependency
# name (require) (optional) (optional) default is public (require) none cmake package
... = {module = "...", components="... ...", lnk_type = "public|private|interface", no_module= true }
# module is name that cmake find_package
# matched cmake scirpt
# find_package(${name} ${version} COMPONENTS ${components})
# target_link_libraries(${target} ${lnk_type} ${module})
#link.public => this library use header and source , dependency foward
#link.private => this library use source only, dependency not forward
#link.interface => this library use header only, dependency forward
[target.{triplet}.dependencies]
[target.{triplet}.dev-dependencies]
# triplet types
# {arch}-{platform}-{compiler}
# arch
# x86 or x64 or arm or arm64 or arm64s or arm7s or all(default)
# platform
# ( unix ) ( windows )
# linux or osx or freebsd or android or uwp or windows
# compiler
# ( clang )
# clang or clang_cl apple_clang or gnu(gcc) or msvc(cl) or intel or cuda(nvidia)
## example
[target.x64-windows-msvc.dependencies]
[target.all-windows-msvc.dependencies]
[target.windows.dependencies]
[target.unix.dependencies]
[target.x64-macos-apple_clang.dependencies]
[target.x64-macos-clang.dependencies]
[target.macos.dependencies]
[target.linux.dependencies]
# (incomplete)
[exclude]
# (incomplete)
[ci.github_action]
[ci.appveyer]
[ci.azure]
[ci.travis]
Dependencies
cppkg is cppm central package repository
cppm use it by default to find requested packages
if you want to use Hunter Package Manager manager set repo="hunter"
cppm auto detect vcpkg (with package.vcpkg config)
you can find package with cppm cppkg search
$ cppm cppkg search -h
Usage:
cppm cppkg search [--verbose]
Option:
--all [-a] :show all package
--help [-h] :show cppm commands and options
--repo [-r] {repo name} :show {repo_name}'s packages # cppkg or hunter
Adding a Dependency
add [dependencies] in your cppm.tomlfile
[dependencies]
fmt = "6.2.0"
Re-run cppm build, and Cppm Search yout package thirdparty directory thirdparty/fmt/6.2.0/cppkg.toml
if can't find it cppm search from cppkg repository and copy to thirdparty/fmt/6.2.0/cppkg.toml
You can easily add unregistered packages
If you want to add unregistered package need to make cppkg.toml file cmake base unregistered package is only need 3 config version git or url *** module *** no cmake base package need to custom downloader cppm provides commands to create cppkg.toml
cppkg file generate command
$ cppm run cppkg init -h
Usage:
cppm cppkg init [--verbose]
Option:
--des [-d] {description} :add description
--flags [-f] {arg} :add cmake build flags
--git [-g] {repo} :add git repo
--git_tag [-t] {tag} :add git tag
--help [-h] :show cppm commands and options
--module [-m] {module} :add module name
--type [-t] {arg} :add type default is lib
--uri [-U] {arg} :auto detect uri or git and version
--url [-u] {url} :add url repo Require --version
--version [-v] {version} :add library version Require --version
Example fmt library
6.2.0 version config
# thirdparty/fmt/6.2.0/cppkg.toml
[fmt]
version = "6.2.0"
description = "A modern formatting library"
module = "fmt::fmt"
url="https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip"
flags="-DFMT_DOC=OFF -DFMT_TEST=OFF -DFMT_FUZZ=OFF" # (optional) for cmake build fast flags
git repository version
git version dependency always version check in CMake build step
# thirdparty/fmt/git/cppkg.toml
[fmt]
version = "git"
description = "A modern formatting library"
module = "fmt::fmt"
git="https://github.com/fmtlib/fmt.git"
flags="-DFMT_DOC=OFF -DFMT_TEST=OFF -DFMT_FUZZ=OFF" # (optional) for cmake build fast flags
Easy Way to use cppkg init command
# fmt 6.2.0
$ cppm cppkg init -u "https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip" -v "6.2.0" -m "fmt::fmt" fmt
# or (auto detect version)
$ cppm cppkg init -U "https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip" fmt
# fmt git
$ cppm cppkg init -U "https://github.com/fmtlib/fmt.git" fmt
# or (auto detect version)
$ cppm cppkg init -g "https://github.com/fmtlib/fmt.git" -m "fmt::fmt" fmt
# fmt 6.2.0 with cmake flags
$ cppm cppkg init -U "https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip" --flags "-DFMT_DOC=OFF -DFMT_TEST=OFF -DFMT_FUZZ=OFF" fmt
Hunter package manager version
# cppm.toml
[dependencies]
fmt = {version="latest", module="fmt::fmt", repo="hunter"}
Custom Downloader
#thirdparty/fmt/6.2.0/cppkg.toml
[fmt]
version = "6.2.0"
description = "A modern formatting library"
module = "fmt::fmt"
url="https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip"
custom=true
#helper=""(incomplete)
# Cppkg Base Dependency Downloader
# Almost same cmake ExternalProject_Add
# Other Options:
# - Linux Configures:
# L_CONFIGURE {...}, L_BUILD {...}, L_INSTALL {...}
# - Windows Configures:
# W_CONFIGURE {...}, W_BUILD {...}, W_INSTALL {...}
# - Install Path Options:
# LOCAL(default) GLOBAL
cmake_minimum_required(VERSION 3.6)
project(fmt-6.2.0-install C CXX)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cppm_tool.cmake)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
download_package(fmt 6.2.0 URL https://github.com/fmtlib/fmt/releases/download/6.2.0/fmt-6.2.0.zip CMAKE_ARGS ${CMAKE_ARGS} -DFMT_DOC=OFF -DFMT_TEST=OFF -DFMT_FUZZ=OFF)
Dependency Format
[${name}]
version = "x.x.x|git|latest(hunter only)"
type = "lib(default)|bin|cmake(incomplete)"
git = "..." # if git version
url = "..." # if x.x.x version
module = "..." # (require)
link = "public(default)|private|interface"
custom = "false(default)|true" # cppm build time cppkg.toml translate ${name}.cmake.in in
# if you want to custom installer(${name}.cmake.in) set true
repo = "cppkg(default)|hunter"
flags="${cmake build flags}"
helper="Find...cmake" (optional) cmake/Modules/Find${package_name}.cmake
components = "..."
Cppm Commands
- ***cppm build ***
- ***cppm cppkg ***
- ***cppm init ***
- ***cppm test ***
- ***cppm update ***