[CLN-list] Why CMake (Was: Re: CMake build patches)

Alexey Sheplyakov asheplyakov at yandex.ru
Fri Jan 8 13:44:35 CET 2021


Dear Richard,

On 1/1/21 11:06 PM, Richard B. Kreckel wrote:

> Maintaining a second build system /is/ an additional burden and requires
> good justification. If it helps people build CLN on common platforms,
> well, that seems to be a good enough justification! That /I/ neither use
> or care about these platforms is, then, clearly subordinate.


Portability is nice and important. However I prefer CMake for a different
reason: dependency management. Consider tools/CMakeLists.txt:

```
add_executable(viewgar viewgar.cpp)
target_link_libraries(viewgar ginac::ginac)
```

What happens here is similar to

$CXX `pkg-config --cflags --libs ginac` viewgar.cpp

I.e. there's no need to set includes/definitions like in Makefile.am:

AM_CPPFLAGS = -I$(srcdir)/../ginac -DIN_GINAC ...`

It's enough to specify dependencies of `ginac` target once, and
`target_link_libraries(viewgar ginac::ginac)` applies them automatically.
The dependencies of `ginac` target are (see ginac/CMakeLists.txt)

```
target_compile_definitions(ginac
	PUBLIC $<BUILD_INTERFACE:IN_GINAC>
	PRIVATE -DLIBEXECDIR="${LIBEXECDIR}/" HAVE_CONFIG_H
)
target_link_libraries(ginac PUBLIC cln::cln ${LIBDL_LIBRARIES})
target_include_directories(ginac PUBLIC
	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
	$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
	$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/..>
	$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
```

This is roughly equivalent to

a) `CPPFLAGS += -DLIBEXECDIR=$(LIBEXECDIR) HAVE_CONFIG_H`
    when compiling (lib)ginac itself (but NOT targets which depend on it)
b) `CPPFLAGS += -DIN_GINAC` when compiling both (lib)ginac _and_ targets
    which depend on it. But if `ginac` target is exported (i.e. installed)
    this definition should NOT be added
c) `CPPFLAGS += -I$(srcdir) -I$(builddir) -I$(builddir)/..`
    for both libginac and targets which depend on it. However, if libginac
    is exported (installed) use `-I${CMAKE_INSTALL_INCLUDEDIR}` instead
    (usually something like `$(PREFIX)/include/ginac`).
d) LIBS += -lcln
    when linking both libginac and targets which depend on it. This also
    sets proper rpath when linking with shared libraries.
e) Also add PUBLIC and INTERFACE definitions/includes/libraries from
    cln::cln target. Thus when compiling libcln as a shared library
    `-lgmp` is added only to libcln itself, but not to libginac
    (and viewgar, tests, etc)

And EXPORT installs this information along with the target (library) itself.
So that `target_link_libraries(viewgar ginac::ginac)` works when libginac
is installed (exported).

There's no way to express such dependencies with autotools.
libtool tracks dependencies between libraries, so it's enough to

viewgar_LDADD = ../ginac/libginac.la

However

a) includes, definitions, etc have to be specified manually
b) libtool does not distinguish between private and public dependencies
    (this is why Linux distros don't include .la files in -devel packages)

On the other hand pkg-config handles both --libs and --cflags, but

a) it's not designed to handle dependencies between **targets**
b) using uninstalled packages is next to impossible
c) one has to describe the dependencies twice: both in .pc file
    and Makefile.am (as a result .pc files often get out of sync)
d) rpath should be handled manually too (unlike libtool)


As a result reusing code is much easier with CMake. For instance, to
build a program one can put the whole CLN source into a subdirectory
(git submodule) and use the following CMakeLists.txt:

```
cmake_minimum_required(VERSION 3.10)
project(pi)

add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/cln)

add_executable(pi src/pi.cc)
target_link_libraries(pi cln::cln)
```

This automatically builds CLN (and its dependencies) before building `pi`.
No more

cd cln && ./autogen.sh && ./configure && make && make install
env PKG_CONFIG_PATH=/oh/let/me/guess g++ src/pi.cc `pkg-config --libs --cflags cln`



Best regards,
    Alexey


More information about the CLN-list mailing list