[CMake] Using a toplevel CMakeList.txt to build all sub projects at once.

Clifford Yapp cliffyapp at gmail.com
Thu Feb 6 08:32:22 EST 2014


On Thu, Feb 6, 2014 at 1:14 AM, PCMan <pcman.tw at gmail.com> wrote:

> libqtxdg - a base lib required by others
> liblxqt - a library depends on libqtxdg
> lxqt-config - a tool depends on liblxqt and libqtxdg.

> To build lxqt-config, liblxqt and libqtxdg need to be "installed" first.

The key is whether you can avoid the need to actually have these
installed.  The first step is to use CMake's RPATH support so things
work both from the build directory and the install directory:

http://www.cmake.org/Wiki/CMake_RPATH_handling

The settings BRL-CAD has been using for this purpose are:

# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)

# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_
RPATH FALSE)

# the RPATH/INSTALL_NAME_DIR to be used when installing
if (NOT APPLE)
  set(CMAKE_INSTALL_RPATH
"${CMAKE_INSTALL_PREFIX}/${LIB_DIR}:\$ORIGIN/../${LIB_DIR}")
endif(NOT APPLE)
# On OSX, we need to set INSTALL_NAME_DIR instead of RPATH
# http://www.cmake.org/cmake/help/cmake-2-8-docs.html#variable:CMAKE_INSTALL_NAME_DIR
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_DIR}")

# add the automatically determined parts of the RPATH which point to
# directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

> So simply adding them using add_subdirectoy() won't work.

The second step (after the above) is to populate the *LIBNAME*_LIBRARY
and related variables that the Find*LIBNAME*.cmake (or whatever your
sub-projects are using to find their needed libraries) with the build
target names of the libraries instead of the paths.  CMake will
successfully interpret the build targets in place of the installed
library paths if those libraries are part of the current CMake build.

> When configuring lxqt-config, liblxqt needs to be installed first.
> To configure and compile liblxqt, cmake modules and headers from
> libqtxdg are required so libqtxdg needs to be installed first.

Using the above steps, lxqt-config's configure step should see the
build target location for liblxqt.  The question now becomes a matter
of whether there is anything in the libraries or lxqt-config that
assumes absolute placement of resource files in install paths during
compilation.  If you don't have anything making such assumptions, the
above two steps may be enough.

> Is it possible to use CMake to build them all at once since one
> component requires that the other is installed first.

"Building them all at once" shouldn't be necessary, barring other
issues...  Since you're building libraries and then an executable, I'd
be fairly surprised if you encounter major difficulties - the
meta-project including the others with add_subdirectory should sort
out the build dependencies.

The *real* challenge is if you need to not just build lxqt-config but
also *run* it from the build directory without installing it.  If
lxqt-config or its libraries make assumptions about the location of
resource files that involve install paths, those assumptions will
naturally fail in the build directory.  BRL-CAD encountered a number
of these issues (Tcl packages were especially entertaining) but in the
end all of them proved solvable and today you can run all of BRL-CAD
from the build directory.  If you *don't* need to run programs in the
build directory as part of your build and/or testing process, things
are much simpler.

> Even worse, two of our components are still automake-based.
> The cmake ExternalProject_Add() command did not solve the problem that
> some of them needs to be "installed" first before others can be
> compiled.

Ah.  This is probably the fly in the soup.  There may be other
solutions, but in the end I wound up creating several CMake build
systems for third party components simply to make everything work
without requiring the install step as part of the CMake build step.
This proved worthwhile for several other reasons, not the least of
which was that at least some of the autotools projects we were using
would have needed new build system work anyway to function with Visual
Studio, but if you're not interested in Windows/MSVC it's a bit more
of a dilemma.  How come two of the components have remained with
Autotools?  Is the plan to eventually migrate them?

> I tried to google and read the existing docs but remain clueless.
> We're stuck! Any help is really appreciated.
> Thank you very much!

You can take a look at what BRL-CAD does since we do solve this
problem or at least a very similar one, but unfortunately our
third-party logic is rather complicated - we have a system that allows
for using system or bundled components in a variety of combinations
based on user settings and autodetection, which may prove to be
overkill for your situation:

http://sourceforge.net/p/brlcad/code/HEAD/tree/brlcad/trunk/src/other/CMakeLists.txt
http://sourceforge.net/p/brlcad/code/HEAD/tree/brlcad/trunk/misc/CMake/ThirdParty.cmake

See http://www.arl.army.mil/arlreports/2013/ARL-TR-6475.pdf page 18
(page 26 of the PDF) for a diagram illustrating the logic flow of the
ThirdParty macro.  With any luck, you can skip all that and just get
away with assigning the build targets to the _LIBRARY variables, but
it will depend on the specifics of your needs.  If you *always* build
liblxqt and lxqt-config at the same time it's easy, but if you really
do want to optionally use a pre-built liblxqt (which is sort of
suggested by liblxqt being a separate CMake project) then you may have
to go deeper.

Hope that's of some help.  Is there a github branch or some such where
the CMake conversion is taking place that we could look at?

Cheers,
CY


More information about the CMake mailing list