Unexpected behavior when using target_sources

Hi.

I’m relatively new to cmake and learning it mostly doing small projects. I’ve got some questions related to target_sources. My understanding of it is that if i omit source files in add_library i should be able to add sources files with differing access with target_sources. But i’m encountering an issue where one of my external library headers that are included with find_package can not be found when using target_sources to add source file but works perfectly fine when adding source files in add_library.

The cmake configuration is fairly easy for my library as seen below.

# Public source files
set(PUBLIC_SOURCE_FILES)
list(APPEND PUBLIC_SOURCE_FILES Core.cpp)

list(TRANSFORM PUBLIC_SOURCE_FILES PREPEND "lib/")

# Private source files
set(PRIVATE_SOURCE_FILES)
list(APPEND PRIVATE_SOURCE_FILES Window.cpp)

list(TRANSFORM PRIVATE_SOURCE_FILES PREPEND "lib/")

add_library(Core)

target_link_libraries(Core PRIVATE glfw)
target_link_libraries(Core PRIVATE glbinding::glbinding glbinding::glbinding-aux)
target_link_libraries(Core PRIVATE glm::glm)

target_sources(Core PRIVATE ${PRIVATE_SOURCE_FILES})
target_sources(Core PUBLIC ${PUBLIC_SOURCE_FILES})

target_include_directories(Core PRIVATE lib)
target_include_directories(Core PUBLIC includes)

There are two specific source files with headers. The window source file and header are both meant to be private in the library. They are both including the GLFW external library. The core source file includes the window header file and the header file has public definitions with no includes.

When the window header is included in the core source file the GLFW headers can not be found in the Window header and source file. But the window header is removed from the core source file they can be found again. The happens if the GLFW headers are included in the core source files.

I’ve tried moving things around but nothing except adding source files with add_library seems to work.

Is there some obscure functionality that i’ve missed regarding adding source files to targets?

target_sources() has no impact on #include resolution when used in the demonstrated manner. (It has a separate keyword, FILE_SET, for handling headers but you’re using target_include_directories here)

You will need to post the complete project (preferably a Github or Gist link), or a minimal reproducible example, there is not enough information here to answer your question.

Here’s a git repo with the reproduced problem. The main issue lies in the Core.cpp source file

Also as a side note. I’m using clang 20.1.8 and ninja as my compiler and generator on a windows machine.

There’s really no such thing as a “public” implementation file. The problem is you’re putting Core.cpp in your PUBLIC source file list. The Enigma target tries to build this file, which it should not.

Since you marked glfw as a PRIVATE dependency of Core, the include directories it provides are not propagated to Enigma. Thus, when Enigma tries to build Core.cpp, it fails.

The answer here is to not have any PUBLIC implementation files. Such things have very limited and specialized use cases, and this is not such a use case.

Alright that makes a whole lot of sense. Thanks for the help.