Skip to content

Instantly share code, notes, and snippets.

@anordal
Last active July 26, 2023 08:06
Show Gist options
  • Save anordal/c73be8a8fc922bef6088105f9cbfe802 to your computer and use it in GitHub Desktop.
Save anordal/c73be8a8fc922bef6088105f9cbfe802 to your computer and use it in GitHub Desktop.
Lessons from Meson to CMake

Lessons from Meson to CMake

If you are using CMake, you can have some of the niceties of Meson by reimplementing them yourself.

Dependency download fallback

This is in my opinion the killer feature of Meson: Be nice, both to users who just want to build the thing, who may have a hard time satisfying your dependencies, and to packagers, your CI and others, who want to assert that only installed dependencies are used.

option(DOWNLOAD_FALLBACK "Download dependencies if not found" ON)

find_package(PkgConfig REQUIRED)
include(FetchContent)
 
pkg_check_modules(Catch2 IMPORTED_TARGET GLOBAL catch2>=2.0.0)
if(Catch2_FOUND)
    add_library(Catch2 ALIAS PkgConfig::Catch2)
elseif(DOWNLOAD_FALLBACK)
    FetchContent_Declare(Catch2
        GIT_REPOSITORY https://github.com/catchorg/Catch2
        GIT_TAG v2.0.0
    )
    FetchContent_GetProperties(Catch2)
    if(NOT catch2_POPULATED)
        FetchContent_Populate(Catch2)
        add_subdirectory(${catch2_SOURCE_DIR} ${catch2_BINARY_DIR})
    endif()
endif()

Use Ccache if available

find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif()

Making the "test" target depend on "all" (sort of)

When you ninja test, you expect any changed unittests to be rebuilt, right? Next, you try ninja all test, which tries to run and build concurrently. 🤦

# It is impossible to make target "test" depend on "all":
# https://gitlab.kitware.com/cmake/cmake/-/issues/8774
# Set a magic variable in a magic file that tells ctest
# to invoke the generator once before running the tests:
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake"
    "set(CTEST_CUSTOM_PRE_TEST ${CMAKE_MAKE_PROGRAM})\n"
)

Test coverage

Meson supports both Lcov and Gcovr, presumably on multiple platforms. This covers Gcovr and Gcc:

option(COVERAGE "Build with test coverage" ON)
if(COVERAGE)
    find_program(GCOVR_FOUND gcovr)
    if(NOT GCOVR_FOUND)
        message(FATAL_ERROR "Coverage enabled, but Gcovr not found")
    endif()
    add_compile_options(--coverage)
    add_link_options(--coverage)
endif()
 
add_custom_target(coverage-html
    COMMAND gcovr -r ${CMAKE_CURRENT_SOURCE_DIR} . --exclude _deps --print-summary --html-details --html-title "Unittest coverage" -o coverage.html
)

More

There are more, but these are my tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment