As stated in the comments, target_include_directories should be given a path to a directory, not to a file.

Moreover, if you want to create a dependency for lib2 on lib1, you should do it through target_link_libraries: a dependency is not only about include directories, but also about compile options, definitions, target properties...

target_sources doesn't work with interface libraries. From this answer, You can use a custom target without commands to associate the sources to a target without impacting the build process (for msvc, QtCreator and other GUI-based tools, this makes the sources accessible through the IDE; AFAIK it's useless for other build tools).

Your cmake may look like this:

add_library(lib1 INTERFACE)
target_sources(lib1 INTERFACE lib1.h)

target_include_directories(lib1 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib1"
)

add_library(lib2 INTERFACE)
if(MSVC)
    add_custom_target(lib2.headers SOURCES lib2.h)
endif()

target_include_directories(lib2 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib2"
)

target_link_libraries(lib2 INTERFACE lib1)

add_executable(project main.cc)
target_link_libraries(project lib2)

Advanced tip: you can specify a different directory in target_include_directories for the build tree and the install tree (see documentation):

target_include_directories(lib1 INTERFACE
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib1>
    $<INSTALL_INTERFACE:${YOUR_INSTALL_DIR}/lib1>
)
Answer from rocambille on Stack Overflow
🌐
CMake
cmake.org › cmake › help › latest › command › add_library.html
add_library — CMake 4.3.0-rc3 Documentation
Add a symbolic Interface Library target. Symbolic interface libraries are useful for representing optional components or features in a package. They have no usage requirements, do not compile sources, and do not produce a library artifact on disk, but they may be exported and installed.
🌐
GitHub
github.com › cartoonist › kseqpp › issues › 2
Unable to install the library using provided CMakeLists.txt · Issue #2 · cartoonist/kseqpp
September 11, 2020 - -- The CXX compiler identification ... in pthread - found -- Found Threads: TRUE CMake Error at CMakeLists.txt:17 (add_library): add_library INTERFACE library requires no source arguments....
Author   alphahmed
Top answer
1 of 3
29

As stated in the comments, target_include_directories should be given a path to a directory, not to a file.

Moreover, if you want to create a dependency for lib2 on lib1, you should do it through target_link_libraries: a dependency is not only about include directories, but also about compile options, definitions, target properties...

target_sources doesn't work with interface libraries. From this answer, You can use a custom target without commands to associate the sources to a target without impacting the build process (for msvc, QtCreator and other GUI-based tools, this makes the sources accessible through the IDE; AFAIK it's useless for other build tools).

Your cmake may look like this:

add_library(lib1 INTERFACE)
target_sources(lib1 INTERFACE lib1.h)

target_include_directories(lib1 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib1"
)

add_library(lib2 INTERFACE)
if(MSVC)
    add_custom_target(lib2.headers SOURCES lib2.h)
endif()

target_include_directories(lib2 INTERFACE
    "${PROJECT_SOURCE_DIR}/lib2"
)

target_link_libraries(lib2 INTERFACE lib1)

add_executable(project main.cc)
target_link_libraries(project lib2)

Advanced tip: you can specify a different directory in target_include_directories for the build tree and the install tree (see documentation):

target_include_directories(lib1 INTERFACE
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib1>
    $<INSTALL_INTERFACE:${YOUR_INSTALL_DIR}/lib1>
)
2 of 3
5

I've used an empty _only_for_compiling_the_lib.cpp file as the simplest and fastest workaround, but clearly the above solution is strongly advised.

I simply wasn't aware of INTERFACE keyword.

🌐
Reddit
reddit.com › r/cmake › how to make a header-only library which shows up as a project in visual studio?
r/cmake on Reddit: How to make a header-only library which shows up as a project in Visual Studio?
April 3, 2020 -

I've got a really simple header-only library:

libname/
    CMakeLists.txt
    include/
        libname.h

I want another project to be able to do add_subdirectory(libname) and then see the libname project in solution explorer in VS.

My problem is that when I do add_subdirectory(libname) from another project, I can access libname.h (it's under External Dependencies) but there is no libname project.

How can I make there be a project?

Do I have to add a dummy libname.c that just imports libname.h in order to do that?

🌐
GitHub
github.com › mlc-ai › mlc-llm › issues › 899
[Bug] Windows: `Cannot specify link libraries for target "tokenizers_c" which is not built by this project` · Issue #899 · mlc-ai/mlc-llm
September 12, 2023 - 🐛 Bug I'm trying to build the mlc runtime from source following these instructions, but am getting: CMake Error at 3rdparty/tokenizers-cpp/CMakeLists.txt:131 (add_library): add_library INTERFACE library requires no source arguments. CMak...
Author   jparismorgan
🌐
Narkive
cmake-developers.cmake.narkive.com › V2LNUKVT › header-only-library-targets
[cmake-developers] Header-only library targets
An open question is where to specify this information. Perhaps it should simply be in the add_library call: add_library(myHeaderLib INTERFACE a.h b.h) Currently that produces an error: CMake Error at CMakeLists.txt:... (add_library): add_library INTERFACE library requires no source arguments.
🌐
Reddit
reddit.com › r/linuxaudio › issues compiling paulxstretch on debian
r/linuxaudio on Reddit: Issues compiling PaulxStretch on debian
May 5, 2022 -

I am trying to compile PaulXStretch, but when I am running the build script I get the following result. Does anybody have a clue what I am doing wrong?

PieterAV@mx:~/Downloads/paulxstretch-main/linux

$ ./build.sh

-- Configuring juceaide

-- Building juceaide

-- Exporting juceaide

CMake Error at deps/clap-juce-extensions/clap-libs/clap-helpers/CMakeLists.txt:8 (set_target_properties):

INTERFACE_LIBRARY targets may only have whitelisted properties. The

property "POSITION_INDEPENDENT_CODE" is not allowed.

CMake Error at deps/clap-juce-extensions/clap-libs/clap-helpers/CMakeLists.txt:8 (set_target_properties):

INTERFACE_LIBRARY targets may only have whitelisted properties. The

property "CXX_STANDARD" is not allowed.

CMake Error at deps/clap-juce-extensions/CMakeLists.txt:36 (add_library):

add_library INTERFACE library requires no source arguments.

CMake Error at deps/clap-juce-extensions/CMakeLists.txt:37 (set_property):

set_property could not find TARGET clap_juce_sources. Perhaps it has not

yet been created.

CMake Error at deps/clap-juce-extensions/CMakeLists.txt:41 (target_include_directories):

Cannot specify include directories for target "clap_juce_sources" which is

not built by this project.

-- Creating CLAP PaulXStretch_CLAP from PaulXStretch

CMake Error at deps/clap-juce-extensions/CMakeLists.txt:69 (get_property):

get_property could not find TARGET clap_juce_sources. Perhaps it has not

yet been created.

Call Stack (most recent call first):

CMakeLists.txt:184 (clap_juce_extensions_plugin)

CMakeLists.txt:488 (sono_add_custom_plugin_target)

-- Configuring incomplete, errors occurred!

See also "/home/PieterAV/Downloads/paulxstretch-main/build/CMakeFiles/CMakeOutput.log".

ERROR setting up cmake, look for errors above and report them if asking for help.

🌐
GitHub
github.com › TheWaveWarden › odin2 › issues › 449
Compile error with CLAP on RPi · Issue #449 · TheWaveWarden/odin2
February 9, 2023 - CMake Error at libs/clap-juce-... is not allowed. CMake Error at libs/clap-juce-extensions/CMakeLists.txt:35 (add_library): add_library INTERFACE library requires no source arguments....
Author   coax75ohm
Find elsewhere
🌐
GitHub
github.com › mlc-ai › mlc-llm › issues › 1912
[Bug] CMake Error at ../../3rdparty/tokenizers-cpp/CMakeLists.txt:132 (target_link_libraries): Cannot specify link libraries for target "tokenizers_c" which is not built by this project. · Issue #1912 · mlc-ai/mlc-llm
July 25, 2023 - Call Stack (most recent call first): ... -Qunused-arguments -- Build without FlashInfer -- system-nameAndroid -- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE) -- VERSION: 0.2.00 CMake Error at ../../3rdparty/tokenizers-cpp/CMakeLists.txt:131 (add_library): add_library INTERFACE library requires no source ...
Author   LumenScopeAI
🌐
Gitlab
cliutils.gitlab.io › modern-cmake › chapters › basics.html
Introduction to the basics — Modern CMake
Making a library is done with add_library, and is just about as simple: ... You get to pick a type of library, STATIC, SHARED, or MODULE. If you leave this choice off, the value of BUILD_SHARED_LIBS will be used to pick between STATIC and SHARED. As you’ll see in the following sections, often you’ll need to make a fictional target, that is, one where nothing needs to be compiled, for example, for a header-only library. That is called an INTERFACE library, and is another choice; the only difference is it cannot be followed by filenames.
🌐
CMake
cmake.org › cmake › help › latest › command › target_link_libraries.html
target_link_libraries — CMake 4.3.0 Documentation
In CMake versions prior to 4.0, if policy CMP0022 is not NEW, then this mode also appends libraries to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent. Added in version 3.12. Object Libraries may be used as the <target> (first) argument of target_link_libraries to specify dependencies of their sources ...
🌐
GitHub
hsf-training.github.io › hsf-training-cmake-webpage › 04-targets › index.html
Working with Targets – More Modern CMake
January 28, 2026 - First, you might have a library that conceptually should be a target, but doesn’t actually have any built components - a “header-only” library. These are called interface libraries in CMake and you would write: ... Notice you didn’t need to add any source files.
🌐
GitLab
gitlab.kitware.com › cmake › cmake › merge requests › !3113
[WIP] add_library: Allow associate headers with INTERFACE library (!3113) · Merge requests · CMake / CMake · GitLab
[WIP] add_library: Allow associate headers with INTERFACE library · Review changes · Check out branch · Download · Patches · Plain diff · Expand sidebar · Bartoszrequested to merge · gang65/cmake:feature/headers-associated-with-interface-library
🌐
CMake
cmake.cmake.narkive.com › O4Wigz8x › add-library-without-source-code
[CMake] add_library without source code
So there are the following Modules ... interface of each of the D* modules) | +- Da (static library with implementation of Da) | +- Db (static library with implementation of Da) +- B (static library with implementation of basic functionality) +- config +- 1a (executable B, C1, Da) +- 1b (executable B, C1, Db) +- 2a (executable B, C2, Da) +- 2b (executable B, C2, Db) +- 3a (executable B, C3, Da) +- 3b (executable B, C3, Db) There would not have to be a single source file in the ...
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › In-Depth CMake Library Concepts.html
Step 5: In-Depth CMake Library Concepts — CMake 4.3.0 Documentation
Interface libraries are those which only communicate usage requirements for other targets, they do not build or produce any artifacts of their own. As such all the properties of an interface library must themselves be interface properties, specified with the INTERFACE scope keywords. add_library(MyInterface INTERFACE) target_compile_definitions(MyInterface INTERFACE MYINTERFACE_COMPILE_DEF)
🌐
DevDoc
devdoc.net › linux › cmake-3.9.6 › command › add_library.html
add_library — CMake 3.9.6 Documentation
If EXCLUDE_FROM_ALL is given the corresponding property will be set on the created target. See documentation of the EXCLUDE_FROM_ALL target property for details. Source arguments to add_library may use “generator expressions” with the syntax $<...>. See the cmake-generator-expressions(7) ...