Boost logo

Boost :

Subject: Re: [boost] [CMake] what to do now?
From: Paul Fultz II (pfultz2_at_[hidden])
Date: 2016-04-15 13:13:49


On Thursday, April 14, 2016 at 8:47:45 PM UTC-5, Robert Ramey wrote:
>
> On 4/14/16 4:02 PM, Andrey Semashev wrote:
>
> > I think you misunderstood me. You can build sources, docs and tests
> > separately. You can place CMakeLists.txt at the places where Jamfiles
> > currently are. Each of these CMakeLists.txt would declare their own
> > project and could be independent from others.
> >
> > However, the common practice is a bit different. There is typically a
> > single root CMakeLists.txt, which defines a project and then includes a
> > number of nested CMakeLists.txt. The nested CMakeLists.txt may or may
> > not define their projects, that doesn't really matter if you invoke
> > cmake with the root CMakeLists.txt because you're generating makefiles
> > for the whole tree in this case. You can also build targets selectively
> > in this case.
>
> My understanding is quite different.
>
> In each directory one has a CMakeLists.txt file. This would closely
> correspond to current boost practice.
>
> In addition in the parent directory one creates a CMakeLists.txt
> directory. It's primary function is to factor common CMake commands
> corresponding to the child directories. It includes a statement
> add_directory(<child directory name>) for each subdirectory.
> Then when you CMake the parent all the children are "CMaked" after
> having processed the common code in the parent. As it stands this makes
> sense. But if you include common CMake commands in the parent you won't
> be able to run CMake on the subdirectories. So if you want to that,
> just refrain from factoring common code in the parent directory CMake.
> I believe that CMake has an "include" facility so you could have it both
> ways - start from the parent or the children.
>

Unifying common utilities is not the only reason to have a top-level
directory. The other reason is so users don't have to create multiple build
directories.

Because Cmake creates build artefacts when it runs, its best practice to
create a separate build directory to run cmake. This avoids build artefacts
from overwriting source files, and it makes it easier to clear out the build
directory(necessary sometimes). To support multiple toolchains, I need to
configure a build directory for each toolchain:

    mkdir build-4.6 && cd build-4.6 && CXX=g++-4.6 cmake .. && cd ..
    mkdir build-4.7 && cd build-4.7 && CXX=g++-4.7 cmake .. && cd ..
    mkdir build-4.8 && cd build-4.8 && CXX=g++-4.8 cmake .. && cd ..
    mkdir build-4.9 && cd build-4.9 && CXX=g++-4.9 cmake .. && cd ..
    mkdir build-clang && cd build-clang && CXX=clang++ cmake .. && cd ..

Then if I want to build the tests for each toolchain, I need to build each
directory:

    ls -1 build-* | xargs -n1 cmake --target check --build

Of course creating multiple build directories is something developers would
do
in order to test the library. Users would never want to create multiple
build
directories. However, scattering cmake files throughout the library without
a
top-level cmake would require the user to do that. So to build the test the
user would need to:

    # Configure the build directory
    mkdir build-test && cd build-test && cmake ../test && cd ..
    # Build the tests
    cmake --build build-test --target check

Then when the user wants to build the docs, they would need to create
another
build directory:

    # Configure the build directory
    mkdir build-doc && cd build-doc && cmake ../doc && cd ..
    # Build the docs
    cmake --build build-doc --target doc

Then another build directory when the user wants to build and install the
library:

    # Configure the build directory
    mkdir build-build && cd build-build && cmake ../build && cd ..
    # Build the library and install
    cmake --build build-build
    cmake --build build-build --target install

This is entirely unconventional and requires multiple builds between
directories
because the builds aren't shared across directories. I understand that boost
developers want to build in a directory-oriented way because thats how
Boost.Build works, but that is not how cmake works. Cmake does provide
things
like `include` and `add_subdirectory` that can help split the build scripts
across the library, but there must be top-level cmake if you expect users to
sanely build your library.

Paul


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk