Introducing the new C++ plugins

This post introduces some new plugins for C++ that we’ve been working on. These plugins can build C++ libraries and applications. They work on macOS, Linux, and Windows with GCC, Clang and Visual C++/Visual Studio.

Building an application

The build script should look familiar to anyone who has used Gradle’s Java plugins:

plugins{id'cpp-application'}

This application has no dependencies, and the C++ source files and headers live in the default location: the src/main/cpp directory. Since this is Gradle, you can easily configure the source locations to match whatever layout your project has, including the common pattern of putting everything in one directory.

Here’s the result of running ./gradlew assemble on this sample:

Take a look at the build scan for this build to see what happened in more detail.

The plugins automatically find the compiler, linker and other tools to build the application. The result ends up installed in the build/install directory ready to run.

IDE support

Xcode is currently supported for C++ projects. You can just run ./gradlew xcode and open the generated workspace. Support for generating Visual Studio solutions will be added early this year and support for other IDEs will be gradually added after that.

Here is the result of running ./gradlew xcode on the sample:

This is how the workspace looks in Xcode:

Dependencies

The plugin uses Gradle’s dependency management features, just like other plugins such as the Java or Android plugins. This means, for example, transitive dependencies work just fine.

Let’s add a dependency on a library to the application. In this sample, the C++ library is downloaded from a Maven repository. You don’t have to install the library anywhere manually, and everyone who runs the build will use the version specified in the build script, rather than whatever version happens to be installed on their machine.

The build script defines a Maven repository and declares a dependency on another sample C++ library:

repositories{maven{// In this sample, we used a local Maven repository, // but Maven Central or Artifactory server can be used.url'http://localhost:8000/'}}dependencies{implementation'org.gradle.cpp-samples:math:1.5'}

Here is the result of running ./gradlew assemble. Gradle downloads the headers and shared library binary and compiles and links against these:

The build scan shows more detail, including the downloads.

Here is how this project looks in Xcode:

Tests

Basic unit testing is supported out of the box. Here is a sample that uses Google Test, downloaded from a Maven repository. We published the binaries using this fork of Google Test, which simply adds a Gradle build.

The build script declares a dependency on Google test and a Maven repository that can be used to locate the Google test binaries:

plugins{id'cpp-unit-test'}repositories{maven{url'https://repo.gradle.org/gradle/libs-snapshots-local/'}}dependencies{// Currently we have to encode the operating system and architecture in // the dependency name. This will disappear in later releasesunitTestImplementation'org.gradle.cpp-samples:googletest_macosx_x86-64_4.5:1.9.0-SNAPSHOT'}

Here is the result of running ./gradlew check. Gradle downloads the Google test library, compiles the C++ source and tests and then runs the tests:

Richer reporting, build scan support, parallel execution and filtering for Google Test will be added this year with support for other C++ testing frameworks after that.

Fast builds

The plugins can produce debug and release builds of the application or library using Gradle’s new variant-aware dependency management, so that debug builds are compiled and linked against debug library binaries, and release builds are compiled and linked against release library binaries. When you build the debug build, which is the default, Gradle builds only the debug builds of the libraries that you need, rather than building everything.

Developer and CI builds are fast. C++ compilation is a cacheable task, so you can avoid unnecessary and long compilation times when using the build cache. Gradle Enterprise comes with a build cache backend. You don’t need to use the --parallel option as Gradle does incremental and parallel compilation and linking by default.

Let’s run some clean builds that use the build cache:

You can see that the second build is faster, as the result is fetched from the build cache rather than recompiled. Build scans for non-cached build and cached build.

Publishing C++ libraries

The new plugins can publish C++ libraries to a Maven or Ivy repository. Support for other kinds of repositories will be added later. Here is the build for the library we saw earlier.

The build script adds a Maven repository to publish the binaries to:

plugins{id'cpp-library'id'maven-publish'}group='org.gradle.cpp-samples'version='1.5'publishing{repositories{maven{// In this sample, we used a local maven repository, // but Maven Central or Artifactory server can be used.url'http://localhost:8000/'}}}

Your Feedback Wanted

These plugins are a work in progress and have some limitations. For example, binary publishing doesn’t understand operating system or architecture yet. We’ll continue to improve these plugins, make them stable, and eventually will deprecate the software model plugins.

Please try these plugins out and let us know what you think. The easiest way to get started is to clone the native samples repository and follow the instructions. Our samples use a Gradle nightly build, so you’ll see the latest and greatest developments there. Some changes are already showing up in the 4.5 release candidates.

We’d love to hear what you think works well, what’s confusing, and what is missing that would block you from using Gradle to build C++ software. You can also leave feedback on the Gradle forums or raise issues on the Gradle native GitHub repository.