Description
Note: Poac is still under development and may contain a bunch of bugs.
Poac (pronounced as /pəʊək/
) is a package manager and build system for C++ users, inspired by Cargo for Rust.
Poac can download project's dependencies and compile a project. Please visit poac.dev and The Poac Book for more details.
Demo
By using Poac, you can create a C++ project, build sources, and execute an application:
Hello World
You can get started with just a few commands as the demo shows. Let's create a new Poac project as follows:
you:~$ poac create hello_world
Created binary (application) `hello_world` package
Then, you can use the poac run
command to run your application:
you:~$ cd hello_world
you:~/hello_world$ poac run
Compiling 1/1: hello_world v0.1.0 (/Users/you/hello_world)
Finished debug target(s) in 0.90s
Running `/Users/you/hello_world/poac-out/debug/hello_world`
Hello, world!
Supported Operating Systems
Linux | macOS |
---|---|
Installation
3rd Party Installation (recommended)
Since packages through these providers may not be maintained by Poac owners, install them at your own risk.
It is important to verify the package name and copy it accurately to prevent typosquatting attacks. You can check the correct name by following the link in Packaging status
(Repology).
Homebrew (macOS & Linux)
brew install poac
MacPorts (macOS)
sudo port install poac
Build from source
If your environment is not included in the released packages, you have to construct Poac from the source. To build Poac, you will require the following compilers, tools, and libraries:
compilers
- Compilers which support C++20 and modules
Clang
:16
or later
tools
libraries
boost
:1.70.0
or later- algorithm
- asio
- beast
- container_hash
- dynamic_bitset
- graph
- predef
- preprocessor
- property_tree
- range
- regex
- scope_exit
- uuid
openssl
:3.0.0
or later- some
SHA256
functions are marked as deprecated since3.0.0
- some
Note:
When configuring with CMake, the following libraries will be installed automatically. Therefore, there is usually no need to be concerned about them. (click here to view additional dependencies.)
Note: When configuring with CMake, the following libraries will be installed automatically. Therefore, there is usually no need to be concerned about them. (click here to view additional dependencies.)
dependencies
fmt
:9.0.0
or latergit2-cpp
:0.1.1
or laterglob
:v0.0.1
or laterlibarchive
:v3.6.1
or later- requires this commit
libgit2
:v1.4.3
or later- requires security updates
mitama-cpp-result
:v9.3.0
or later- requires this commit
ninja
:57b8fee
or later- requires this commit
v1.11.1
does not include the commit
spdlog
:1.9.0
or laterstructopt
:b1e1e16
or later- requires this commit
- awaiting the next release above
v0.1.3
toml11
:9086b11
or later- requires this commit
- awaiting the next release above
v3.7.1
dev-dependencies
Once you have all the necessary requirements in place, you can proceed to build Poac by executing the following commands:
git clone https://github.com/poac-dev/poac.git
cd poac
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DPOAC_BUILD_TESTING=OFF
cd build
ninja
ninja install
Poac attempts to utilize locally installed dependencies by default. To bypass the use of local packages, you can specify -DCPM_USE_LOCAL_PACKAGES=OFF
as an option for the cmake
command.
Usage
Start a new project with Poac
The poac create
command lets you start a new Poac project:
you:~$ poac create hello_world
Created binary (application) `hello_world` package
Note: If you want to integrate your existing project with Poac, use the
init
command:you:~/your-pj$ poac init Created binary (application) `your-pj` packageThis command just creates a
poac.toml
file not to break your project.
Build the project
In most cases, you will want to execute a binary as well as build the project—of course, you can.
you:~/hello_world$ poac run
Compiling 1/1: hello_world v0.1.0 (/Users/you/hello_world)
Finished debug target(s) in 0.90s
Running `/Users/you/hello_world/poac-out/debug/hello_world`
Hello, world!
Should you just build it, run the build
command:
you:~/hello_world$ poac build
Finished debug target(s) in 0.21s
Poac uses a cache since we executed the command with no changes.
Install dependencies
Like Cargo for Rust does, Poac installs dependencies at build time.
However, Poac does not support weired version specifiers, such as ~
and ^
.
You can specify dependencies like:
poac.toml
[dependencies]
"boost/bind" = ">=1.64.0 and <2.0.0"
We regularly avoid auto updating packages to major versions which bring breaking changes, but minor and patch are acceptable.
Note: If you would use a specific version, you can write the version as following:
[dependencies] "boost/bind" = "1.66.0"
Conan V1 Registry
Poac also supports Conan V1 Registry. To use it:
poac.toml
[dependencies]
fmt = { version = "9.1.0", registry = "conan-v1" }
spdlog = { version = "1.10.0", registry = "conan-v1" }
leveldb = { version = "1.23", registry = "conan-v1" }
The demo is publised on wx257osn2/poac-conan-demo
After editing poac.toml
, executing the build
command will install the package and its dependencies.
you:~/hello_world$ poac build
Resolving dependencies ...
Downloading packages ...
Downloaded boost/bind v1.66.0
Downloaded boost/core v1.66.0
Downloaded boost/assert v1.66.0
Downloaded boost/config v1.66.0
Compiling 1/1: hello_world v0.1.0 (/Users/you/hello_world)
Finished debug target(s) in 0.70s
To use this dependency, update the main.cpp
file.
src/main.cpp
#include <iostream>
#include <boost/bind.hpp>
int f(int a, int b) {
return a + b;
}
int main(int argc, char** argv) {
std::cout << boost::bind(f, 5, _1)(10) << std::endl;
}
You can now run this source code:
you:~/hello_world$ poac run
Compiling 1/1: hello_world v0.1.0 (/Users/you/hello_world)
Finished debug target(s) in 0.50s
Running `/Users/you/hello_world/poac-out/debug/hello_world`
15
Warning: We currently support building a project with header-only dependencies. Building with build-required dependencies will be soon supported.
Create a dependency graph
You can create a dependency graph by using the graph
command:
you:~/hello_world$ poac graph -o out.png
Generated out.png
Or you can export the graph as a .dot
file:
you:~/hello_world$ poac graph -o out.dot
Generated out.dot
digraph G {
0[label="boost/bind: 1.66.0"];
1[label="boost/config: 1.66.0"];
2[label="boost/core: 1.66.0"];
3[label="boost/assert: 1.66.0"];
0->2 ;
0->1 ;
2->3 ;
2->1 ;
3->1 ;
}
Note: When you want to export the graph as a
.png
file, please ensuregraphviz
is installed.
If you omit specifying the output path, then Poac emits the graph to standard output:
you:~/hello_world$ poac graph
boost/bind -> boost/core
boost/bind -> boost/config
boost/core -> boost/assert
boost/core -> boost/config
boost/assert -> boost/config
Run linter
Linting source code is essential to protect its quality.
Poac supports linting it by a simple command with cpplint
:
you:~/hello_world$ poac lint
Linting hello_world
src/main.cpp:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]
Done processing src/main.cpp
Total errors found: 1
Error: `cpplint` completed with exit code 1
Note: If you do not have
cpplint
, install it with the following command:pip install cpplint
The lint
command works without configurations, and Poac would automatically opt out of unwanted lints by adjusting to each project.
To customize the lint settings, try adding the [lint.cpplint]
key in your poac.toml
like this
or creating a CPPLINT.cfg
file to the repository root.
Run formatter
Poac also supports formatting your source code with clang-format
.
Ensure having installed clang-format
before running this command.
you:~/hello_world$ poac fmt
Formatting hello_world
Note: This command automatically detects what files we need to format to avoid bothering commands like:
$ # We need to avoid the `build` dir and such dirs ... $ clang-format ./src/*.cpp -i $ clang-format ./include/**/*.hpp -i $ clang-format ./tests/**/*.cpp -i $ ...
To customize the format settings, try creating a .clang-format
file to the repository root.
Search packages
In case you would find what packages are provided, you can use the search
command or visit poac.dev.
$ poac search func
boost/function = "1.66.0" # Boost.org function module
boost/function_types = "1.66.0" # Boost.org function_types module
boost/functional = "1.66.0" # Boost.org functional module
Publish packages
WIP
Roadmap
Feature | Status |
---|---|
Install dependencies | ✅ |
Build a project with header-only dependencies | ✅ |
Support dev-dependencies | ✅ |
Build a project including separated headers & impls | |
Publish packages | WIP |
Build a project with build-required dependencies | |
Build a project with CMake |
Why Poac?
C++ is often considered a complex language and unconsciously avoided by many. The absence of a definitive package manager and the unfamiliar syntax of build systems like CMake make it seem difficult to set up a C++ environment, leaving people hesitant.
To simplify the process and allow users to develop applications and libraries without worrying about CMake, I created a package manager and build system with an intuitive interface, similar to Cargo. This allows developers to focus on learning C++ without any hindrances. Additionally, I aim to integrate with other build systems and package managers, providing a seamless transition between development environments.
Naming Background
Poac is originated from cpp
but designed to prioritize ease of typing and reduce strain on one hand as it will be frequently used as a command. Its name is ergonomically optimized to prevent the development of tenosynovitis.
Despite C++ often being overlooked for product development, I believe that Poac can help to promote it as a fun language. Amemiya and Mizutani argue that the sound of /p/
is associated with a bright and soft impression among Japanese consonants (157)1. In the same way, I believe that Poac's name can convey a similarly positive impression.
Contributing
Source Code Documentation
A source code documentation for Poac is generated by Doxygen every commit to the main
branch:
Before submitting your PR
Please make sure to follow these steps:
Note: I expect you to use the latest
clang-tidy
andclang-format
.
cpplint
)
Run linter (poac lint
clang-format
)
Run formatter (poac fmt
clang-tidy
Build with Follow the instruction at Build from source.
These are also done when pre-push as specified in .githooks/pre-push
.
In case you would skip these hooks, use the --no-verify
option.
This project exists thanks to all the people who contribute.
License
Poac is licensed under the terms of the Apache License version 2.0.
Please see LICENSE for details.
Third-party software
- boost - https://github.com/boostorg/boost/blob/master/LICENSE_1_0.txt
- fmt - https://github.com/fmtlib/fmt/blob/master/LICENSE.rst
- git2-cpp - https://github.com/ken-matsui/git2-cpp/blob/main/LICENSE
- glob - https://github.com/p-ranav/glob/blob/master/LICENSE
- libarchive - https://github.com/libarchive/libarchive/blob/master/COPYING
- libgit2 - https://github.com/libgit2/libgit2/blob/master/COPYING
- mitama-cpp-result - https://github.com/LoliGothick/mitama-cpp-result/blob/master/LICENSE
- ninja - https://github.com/ninja-build/ninja/blob/master/COPYING
- openssl - https://github.com/openssl/openssl/blob/master/LICENSE.txt
- spdlog - https://github.com/gabime/spdlog/blob/v1.x/LICENSE
- structopt - https://github.com/p-ranav/structopt/blob/master/LICENSE
- toml11 - https://github.com/ToruNiina/toml11/blob/master/LICENSE
- μt - https://github.com/boost-ext/ut/blob/master/LICENSE.md
Footnotes
-
Amemiya, T., & Mizutani, S. (2006). On the Basic Affective Dimensions of Japanese Onomatopoeia and the Basic Level of Japanese Phonesthemes. 関西大学社会学部紀要, 37(2), 139–166. https://hdl.handle.net/10112/12311 ↩