Years later, with CMake 3.23, we can use FILE_SET for public headers:
project(programming-network)
add_library(programming-network STATIC)
target_include_directories(programming-network PRIVATE "${PROJECT_SOURCE_DIR}")
target_sources(programming-network
PRIVATE send_string.c recv_line.c
PUBLIC FILE_SET HEADERS
BASE_DIRS ${PROJECT_SOURCE_DIR}
FILES publicheader1.h publicheader2.h)
install(TARGETS programming-network FILE_SET HEADERS)
Now let's see what these commands do:
add_library()
: defines the name of the target, STATIC for a static library, SHARED for a shared library, OBJECT for objects.
target_include_directories()
: this line here is only for when you have subdirectories and private headers referencing each other relative to the project directory. But generally, this command is used for including external headers in a project.
target_sources()
: This command is used to add definition files and private headers with PRIVATE
keyword. Also, it is used to add public headers via FILE_SET
keyword. BASE_DIRS
is to turn the absolute path of public headers into a relative path by deducting the base directory from their path. So the this public header
/home/someuser/programming-network/sub1/publicheader1.h
with base dir of
/home/someuser/programming-network/
will be installed in
/cmake/install/prefix/include/sub1/publicheader.h
Note target_sources()
can be used in CMakeLists.txt
of subdirectories as well.
install()
: is to install binaries, static/shared libraries and public headers. The default installation subdirectories are bin
, lib
and include
. You can also change that like this
install(TARGETS myTarget
# for executables and dll on Win
RUNTIME DESTINATION bin
# shared libraries
LIBRARY DESTINATION lib
# for static libraries
ARCHIVE DESTINATION lib
# public headers
INCLUDES DESTINATION include)
And finally, the project is built and installed with (for multi-configuration generators: MS Visual C++, Xcode)
# in project directory
mkdir build
cd build
cmake ..
cmake --build . --config Release
cmake --install . --prefix "/usr/local/" --config Release
For single-configuration generators (make, Ninja), drop the above --config Release
terms and change cmake ..
to cmake -DCMAKE_BUILD_TYPE=Release ..
.