1

I'm working on a C++ codebase targeted at multiple platforms, and we've just moved over to CMake as our buildsystem.

Previously our buildsystem was a pretty ad-hoc affair; getting our code under a single common buildsystem has been a real step forward.

The next pain point I've encountered, though, is that I'd like to be able to build our project at a variety of scopes. For example:

  • Sometimes I want to build a particular module, plus its tests. Or a suite of modules, plus their tests.
  • Sometimes I want to build one of our production packages (which will have build products organized in an entirely different way than for testing during development).
  • Sometimes I want to build the whooole codebase, including secondary tools and utilities.

...and of course, I'd rather avoid building absolutely everything as a "default" option that's hard to change. But this precisely seems to be CMake's default option - everything in the source tree is included, unless you specify individual targets by name.


Two options that seem promising, but I feel unsatisfied with, are:

1. Use CMake's INSTALL and COMPONENT features. This seems to give me what I want - different installation configurations for the same codebase. However,

  • As far as I can tell, INSTALL depends on all other targets, so for most configurations I'd be building lots of products I don't need.
  • COMPONENT is a parameter to CMake itself; I'd need entirely independent build directories in order to build different install components. If I switch from one component to the other, I need to rebuild everything.

2. Create custom targets representing my different scopes/components, describing what targets each "component" depends on.

  • This seems to involve giving up on INSTALL functionality entirely. And if any of my use-cases needs the build products set up in any particular layout, or anything else INSTALL-like (most of them do), I'd need to recreate that functionality manually as part of each of these custom targets. This seems awfully cumbersome.

Is there a better way to define different "types" of builds? (Or, am I missing a better way of handling this?)

  • If there's any helpful terminology here that I've missed or misused (e.g. for different build "types"), I'd be happy to hear of it - both to make the question clearer, and to be able to embark on some Educational and Improving Google Searches. – Standback Jul 25 '16 at 7:43
1

Just create multiple targets, one target per component:

# Setup three "components"
add_library(first source1.cpp source2.cpp)
add_library(second source3.cpp source4.cpp)
add_executable(third source5.cpp source6.cpp)

# 'third' depends on the other libraries
add_dependency(third first second)

In this example you'd be able to call make first to only build the first library, e.g. first.dll or first.so. Issuing make third you'd build first and second, then third and link everything.

Of course you could create, mix, and match other types of targets, like executables, static libraries, tests, etc.

For example, to add some test code (using CTest) above:

enable_testing()
add_test(test-first some/command/to/run)
add_dependency(test-first first)

Now whenever you'd run make test-first, it would first build first and then run the test-first test.

As for your custom packaging and stuff, I'd probably just use add_custom_target() for that.

  • This is what I was trying to describe with my option #2. (Which may, indeed, be the best option.) But for big projects - and particularly for big components, depending on a lot of different targets scattered across the build tree and between lots of different directories - it seems to me that using custom commands and targets to organize binary products from all over the (quasi-opaque) binary build tree would be pretty cumbersome. (I'd say that's why install is a thing in the first place.) – Standback Jul 25 '16 at 8:11
  • How should make automagically know what of the different targets scattered across the build tree to choose from? It's your custom structure that makes a custom build process necessary. I don't think there's a way around that. – null Oct 23 '16 at 11:14
  • @null Of course, but that code is all generated by CMake and you don't have to touch it yourself. That's the whole point in using it in the first place. – Mario Oct 23 '16 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.