Skip to content

anonymouspc/cppmake

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cppmake: A C++20 Modules Build System

Cppmake is a modern, fast, and accurate C++ build system focusing on C++20 Modules.

Cppmake aims to

  • Make everything modular.
  • Easily modularize third-party libraries.
  • Be fast, parallel, and fully cached.

Cppmake is written in pure Python with no additional pip dependencies.

Show

vedio

Install

Use pip to install cppmake:

pip install cppmake

Or install from source:

git clone https://github.com/anonymouspc/cppmake
cd cppmake
python install.py

Getting Started

In a cppmake project:

  • module aaa.bbb should be placed at module/aaa/bbb.cpp
  • module aaa:ccc should be placed at module/aaa/ccc.cpp
  • source main should be placed at source/main.cpp
  • std module will be auto-installed.

For example:

├── module
│   ├── aaa.cpp
│   ├── aaa
│   │   ├── bbb.cpp // aaa.bbb
│   │   └── ccc.cpp // aaa:ccc
│   └── ddd.cpp
├── source
│   └── main.cpp
└── cppmake.py

Then, run

cppmake

The output will be generated in the binary/ directory.

Advanced

Cppmake provides various configurable options, such as:

cppmake --compiler=clang++ --std=c++23
cppmake --compiler=/opt/gcc/bin/g++ --linker=lld --std=c++26 --type=release --target=make --parallel=$(nproc)

System/compiler support:

clang emcc gcc msvc
Linux N/A
Macos N/A
Windows
  • ✓: Supported and tested.
  • ✗: Not implemented yet; planned for future releases.
  • (The author does not own a Windows PC. Contributions for Windows support are welcome!)

Configure

Cppmake uses a cppmake.py file (pure Python) to describe the C++ project. The configuration is entirely standard Python syntax.

For example:

from cppmakelib import *
def make():
    Source("main").compile()

This cppmake.py defines a single source source/main.cpp, which will be built into a binary.

  • (Imported modules and packages will be built automatically before compiling the source. For example, if source/main.cpp imports module my_module and module boost.asio, then Cppmake will precompile module my_module, cmake build boost, and precompile module boost.asio before finally compiling source/main.cpp.)
  • (By default, the imported modules and packages form a directed acyclic graph and will be executed with maximum possible parallelism, depending on your cpu thread count. You can control the level of parallelism using cppmake --parallel=N, or force serial compilation through cppmake --parallel=1.)

Another example:

from cppmakelib import *

if type(compiler) == Gcc:
    compiler.compile_flags += ["-fno-inline"] # global
    compiler.define_macros |= {"NDEBUG": '1'} # global

package.define_macros = {"MY_MACRO": "42"} # package-local

def build(): # select a source file to compile
    if type(system) == Linux:
        Source("linux").compile()

def test(): # compile and test all units
    for file in iterate_dir("source/test", recursive=True):
        Source(file=file).compile()
        Executable(file=file).run()

This cppmake.py defines 2 targets (switchable via cppmake --target=build|test) and several configuration rules. You can easily extend it with any other Python code.

Integrating third-party packages

Third-party packages should be located in package/, for example

├── module
│   ├── aaa.cpp
│   ├── aaa
│   │   ├── bbb.cpp // aaa.bbb
│   │   └── ccc.cpp // aaa:ccc
│   └── ddd.cpp
├── source
│   └── main.cpp
├── package
│   ├── boost
│   │   ├── git
│   │   │   └── [git clone]
│   │   ├── module
│   │   │   ├── boost.cpp // boost
│   │   │   └── boost
│   │   │       ├── asio.cpp // boost.asio
│   │   │       ├── beast.cpp // boost.beast
│   │   │       └── numeric.cpp // boost.numeric
│   │   │           ├── interval.cpp // boost.numeric.interval
│   │   │           └── ublas.cpp // boost.numeric.ublas
│   │   └── cppmake.py
│   └── eigen
│       ├── git
│       │   └── [git clone]
│       ├── module
│       │   └── eigen.cpp // eigen
│       └── cppmake.py
└── cppmake.py

In package/boost/cppmake.py we can define a build() function to describe how this package should be built. For example:

# package/boost/cppmake.py
from cppmakelib import *

def build():
    cmake.build(
        package=package,
        args=[
            "-DBUILD_SHARED_LIBS=OFF"
        ]
    )

Then:

// package/boost/module/boost/asio.cpp
module;
#include <boost/asio.hpp>
export module boost.asio;
export namespace boost::asio
{
    using boost::asio::io_context;
    //...
}

will modularize boost.asio into a module.

Builder support:

cmake include* makefile meson msbuild
(soon)
  • ✓: Supported and tested.
  • ✗: Not implemented yet; planned for future releases.
  • (include: means header-only libraries.)

Thank you!

About

A modern C++ builder based on C++20 Modules.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published