3

I'm working on a CMake based project that has a dependency on a gigantic third party codebase that also uses CMake. I'm including the third party project via the ExternalProject_Add mechanism. That project defaults to using Makefiles, although the parent is an Xcode project.

The resulting build of the external project is painfully slow because it's only using a single core. I don't think that I can force the project to generate Xcode projects instead of Makefiles.

Assuming that I'm stuck with Makefiles, how can I inform ExternalProject_Add to use all the cores available for the titanic third party project?

Note that the addition of the inevitable '-j N' option (why doesn't 'make' do this by default?) needs to conditionally be present for the Mac and Linux builds, but not Windows/Visual Studio.

acronce
  • 383
  • 4
  • 9
  • Just a quick note that I was able to conditionally generate an Xcode project for the external project. I suspect that the reason why this project defaulted to Makefiles might have been due to the fact that I had to override the ExternalProject_Add CONFIGURE_COMMAND in order to specify a subdirectory where the main CMakeLists.txt was located (which was not in the SOURCE_DIR). The Xcode build is much faster now. But I will still have the same issue on Linux, so I'll need to solve the problem of telling make to use multiple cores. – acronce Mar 15 '19 at 13:32

1 Answers1

2

You've basically already answered the question yourself: Use another build generator. Ninja does parallel builds buy default and CMake uses it just fine.

include(ExternalProject)
ExternalProject_Add(foobar
    [...]
    ## configure options
    # cmake is used by default
    #CONFIGURE_COMMAND cmake
    # cmake will use the same generator as the main project, unless we override it
    CMAKE_GENERATOR Ninja
    ## build options
    BUILD_COMMAND ninja
    [...]
)

If you don't want to use a different generator, use make's options. Set MAKEFLAGS in your shell. In your CMakeLists.txt do something like:

include(ProcessorCount)
ProcessorCount(N)

if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin")
    include(ExternalProject)
    ExternalProject_Add(foobar
        BUILD_COMMAND make -j${N}
    )
else()
    ## do windows stuff
endif()

Also, remember many of the ExternalProject_Add() options (including the *_COMMAND options) override sensible defaults. So, when defining your external project, start small, and add options as needed.

tl;dr

  • Be sparse when defining your external project. Build up as needed.
  • Use another build generator that understands parallelism better than 'make'
  • If you want to use a different CMake build generator for your external project than for your main project, you must specify it.
nega
  • 2,526
  • 20
  • 25