modern-cmake / cppfront

CMake wrapper around the cppfront repository
BSD 3-Clause "New" or "Revised" License
75 stars 21 forks source link

cppfront cmake wrapper

CI

This is a wrapper around Herb Sutter's cppfront compiler. Go there to learn more about that project.

This repository adds a CMake build with some "magic" helpers to make it easier to use cpp2. Requires CMake 3.30+.

Disclaimer: As cppfront is highly experimental, expect abrupt, backwards-incompatible changes to be made here, too. This isn't a production-ready ecosystem, and breaking changes will be made if they improve the overall project. We're on [major-version 0] for the foreseeable future.

Note: This work might one day be merged upstream. The open pull request is here: https://github.com/hsutter/cppfront/pull/15

PRs are welcome, but please know CMake well.

Getting started

See the example for a full example project.

Find package

This is the workflow I will personally support.

Build this repository:

$ git clone --recursive https://github.com/modern-cmake/cppfront
$ cmake -S cppfront -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/wherever
$ cmake --build build --target install

Now just write your project like normal:

cmake_minimum_required(VERSION 3.30)
project(example)

find_package(cppfront REQUIRED)

add_executable(main main.cpp2)

And that's literally it. Any targets with a .cpp2 source will automatically get custom commands added to them. They will also be scanned for modules by CMake; this requires you to use a compiler that supports this. See the cxx-modules documentation for more detail. As of CMake 3.29, this includes:

  • MSVC toolset 14.34 and newer (provided with Visual Studio 17.4 and newer)
  • LLVM/Clang 16.0 and newer
  • GCC 14 (for the in-development branch, after 2023-09-20) and newer

FetchContent

FetchContent is also supported, though as always with FetchContent, there's a chance it will be wonky.

Here's the code.

cmake_minimum_required(VERSION 3.30)
project(example)

include(FetchContent)

FetchContent_Declare(
    cppfront
    GIT_REPOSITORY https://github.com/modern-cmake/cppfront.git
    GIT_TAG main  # or an actual git SHA if you don't like to live dangerously
)

FetchContent_MakeAvailable(cppfront)

add_executable(main main.cpp2)

The same automatic configuration will happen here, too. Though since FetchContent_MakeAvailable will only run our CMakeLists.txt once, the magic can only happen in the first directory to include it. Thus, you should probably explicitly run cppfront_enable(TARGETS main) and add set(CPPFRONT_NO_MAGIC 1) if you want your project to be consumable via FetchContent. Blech.

You can, of course, use this repo as a submodule and call add_subdirectory rather than using FetchContent. It's basically the same except FetchContent can be overridden using FIND_PACKAGE_ARGS.

I won't personally address issues for FetchContent users.

CMake documentation

No matter how you use this CMake build, it exposes the following points of configuration:

Targets

Options

Universal:

FetchContent-only:

Variables

Functions

cppfront_generate_cpp(<OUTVAR> <cpp2 files>...)

Writes to the variable named by OUTVAR a list of absolute paths to the generated .cpp files associated with each .cpp2 file in the arguments list. A hashing scheme prevents cppfront from running on the same .cpp2 file multiple times.

cppfront_enable(
    TARGETS <targets>...
)

Scans the SOURCES properties for each target in <targets> for entries ending in .cpp2. These are passed to cppfront_generate_cpp and the results are added to the target automatically. When CPPFRONT_NO_MAGIC is unset (i.e. by default), this command runs on all targets in the directory that imported this package at the end of processing the directory.

Developers

The CMake project regression-tests/CMakeLists.txt runs the test suite of cppfront. Read test-all.sh to see how to set it up. To have the test results updated, configure with -DCPPFRONT_DEVELOPING=TRUE.