cmake: forcing build type for a specific library fails

Hi,

I have a c++ project made of several executables and libraries. I use cmake for the compilation. Also in debug mode, I add “_d” as postfix for the libraries (i.e.: libfoo_d.so).

Now, one of those libraries (say lib1) is so slow in debug mode that I want to always build it in release mode. So, in the CMakeLists.txt of lib1 I am forcing the CMAKE_BUILD_TYPE to Release:

set(CMAKE_BUILD_TYPE "Release")

This library has dependencies (say lib2). Of course, lib2 should still be compiled in debug mode and its name should be liblib2_d.so (I only want lib1 to be in release mode).

Unfortunately, when building (in debug mode), I get the following error message:

[build] make[3]: *** No rule to make target 'binaries/lib/liblib2.so', needed by 'binaries/lib/liblib1_d.so'. Stop.

Here is the CMakeLists.txt file for lib1:

cmake_minimum_required(VERSION 2.8.9)

if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
   project (lib1)
endif()

if (NOT TARGET lib2)
   add_subdirectory(../lib2 lib2)
endif()

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/binaries/lib/)

set(CMAKE_BUILD_TYPE "Release")

include_directories(include)
include_directories(../lib2/include lib2)

add_library(lib1 SHARED src/src1.cpp include/lib1.h)

target_link_libraries(lib1 lib2)

I am using cmake version 3.18.4.

I have also uploaded here, a sample that shows the issue. Just unzip the content and run:

mkdir build && cd build && cmake --configure ../app -DCMAKE_BUILD_TYPE=Debug && cmake --build .

I don’t know how to solve this. Please can you help me?

You cannot do that. Build type is global.

But you can, for the target lib1, change the compilation options (for example adding optimization flag) in debug mode to speed up execution of this library:

add_library(lib1 ...)
set_property(TARGET lib1 PROPERTY COMPILE_OPTIONS "$<$<CONFIG:Debug>:-O2>")

Thanks.

This is not the ideal solution for me. I want lib1 to be exactly built as if I was in Release mode. This means:

  • The compiler flags should be exactly the same than in release mode (it’s not only about -O2). Those flags might be defined at a higher level. I want to lib1 to be compiled with those flags exactly.
  • Same for the linker flags
  • I also might be using cuda in lib1, and I want the cuda stuff to be compiled in release mode as well.

In the end, I don’t want to have to worry about how a release build is done and which flags or options should be set. I just want lib1 to be built exactly as if we were in Release mode.

Is there not a better way to do this?

In this case, have a look at ExternalProject or FetchContent modules.

These modules can be used to implement the concept of superbuild.

Probably ExternalProject because FetchContent pulls into the same build tree, so you’ll end up where you started just using different means :wink:

If you want a specific library to always be release then you could use a pre-built binary approach.

We have dependencies on a third party library so we just link against pre-built binaries because we don’t care about debugging this third party library. At a certain point large projects can’t build everything from source.

So you can start formalizing lib1 into a more formal library deliverable. And even consider using a C/C++ package manger liker Conan (Which works well with CMake).

This is what big game engines end up doing. At a certain point they break up their libraries into shared libraries gfx, physics, etc. Because if you are working on gfx you don’t need a debug physics library.

Thanks

lib1 as such is just an internal library, it has no value outside of my project. So making it an external project or packaging/compiling it independently from the rest of the project does not really make sense.

It’s a shame that there is no simple solution to this problem.

To be clear you can solve this problem with CMake. I just don’t recommend it. You’ll have to write a lot of custom CMake to make this work.

Or you maybe look into using a C++ package manager.

Also if another build system made this easy I’d say it’s a bad idea overall. For lots of reasons I can get into.

We had issues a while back where our debug builds were too slow. And it made us re-evaluate our codebase and it improved the perf of our debug/release builds. Even our debug builds can still run at 30-60 FPS.