Object libraries

As documentation states OBJECT library is a non-archival collection of object files. OBJECT libraries have few limitations which makes them harder to use.

Target name

Even if an OBJECT library is not a “real” target you will still have to name it carefully as a regular target since it will occupy slot in pool of names. As a result you can’t use it as a local temporary helper tool:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

add_subdirectory(boo)
add_subdirectory(bar)
# boo/CMakeLists.txt

add_library(core OBJECT x1.cpp x2.cpp)
add_executable(boo $<TARGET_OBJECTS:core> boo.cpp)
# bar/CMakeLists.txt

add_library(core OBJECT y1.cpp y2.cpp)
add_executable(bar $<TARGET_OBJECTS:core> bar.cpp)

Error:

CMake Error at bar/CMakeLists.txt:1 (add_library):
  add_library cannot create target "core" because another target with the
  same name already exists.  The existing target is created in source
  directory "/.../boo".  See documentation
  for policy CMP0002 for more details.

Usage requirements

Usage requirements will not be propagated:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

include_directories("${CMAKE_CURRENT_LIST_DIR}")

add_library(boo OBJECT boo.cpp boo.hpp)
target_compile_definitions(boo PUBLIC FOO_WITH_BOO)

add_executable(baz $<TARGET_OBJECTS:boo> baz.cpp)
// boo.hpp

#ifndef BOO_HPP_
#define BOO_HPP_

#if !defined(FOO_WITH_BOO)
# error "FOO_WITH_BOO is not defined!"
#endif

#endif // BOO_HPP_
// baz.cpp

#include <boo.hpp>

int main() {
}

boo.cpp source will compile fine because FOO_WITH_BOO will be added:

/usr/bin/g++ -DFOO_WITH_BOO ... -o CMakeFiles/boo.dir/boo.cpp.o -c /.../boo.cpp

But not baz.cpp:

/usr/bin/g++ ... -o CMakeFiles/baz.dir/baz.cpp.o -c /.../baz.cpp
In file included from /.../baz.cpp:3:0:
/.../boo.hpp:7:3: error: #error "FOO_WITH_BOO is not defined!"
 # error "FOO_WITH_BOO is not defined!"
   ^

No real sources

As mentioned in documentation you can’t have target with only OBJECT files. E.g. this code will not work with Xcode:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

add_library(boo OBJECT boo.cpp)
add_executable(foo $<TARGET_OBJECTS:boo>)

enable_testing()
add_test(NAME foo COMMAND foo)

No warnings or build errors but when you will try to test it:

1: Test command:
Unable to find executable: /.../_builds/Release/foo
1/1 Test #1: foo ..............................***Not Run   0.00 sec

Note

As a workaround you can add dummy source file to the executable.

Name conflict

You can’t have two source files with the same names even if they are located in different directories. This code will not work with Xcode generator:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

add_library(boo OBJECT x.cpp boo/x.cpp)
add_executable(foo foo.cpp $<TARGET_OBJECTS:boo>)

As a workaround source files can be renamed:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

add_library(boo OBJECT x.1.cpp boo/x.2.cpp)
add_executable(foo foo.cpp $<TARGET_OBJECTS:boo>)

Or additional target can be introduced:

# CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(foo)

add_library(boo.1 OBJECT x.cpp)
add_library(boo.2 OBJECT boo/x.cpp)
add_executable(foo foo.cpp $<TARGET_OBJECTS:boo.1> $<TARGET_OBJECTS:boo.2>)