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 OverflowAs 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>
)
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.
I've got a really simple header-only library:
libname/
CMakeLists.txt
include/
libname.hI 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?
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.
A .lib is when you create a STATIC (.lib) or SHARED (.lib and .dll) library on Windows. What you want is an INTERFACE library and it generates no files. http://mariobadr.com/creating-a-header-only-library-with-cmake.html has an example. Then you can use the following commands listed here, https://cmake.org/cmake/help/latest/command/add_library.html#interface-libraries, to populate the interface. Notice that it uses INTERFACE not PUBLIC.
target_link_libraries(INTERFACE),
target_link_options(INTERFACE),
target_include_directories(INTERFACE),
target_compile_options(INTERFACE),
target_compile_definitions(INTERFACE), and
target_sources(INTERFACE),
I've never actually used this but I assume it works as documented.
A simple add_library(${XML_NAME} INTERFACE) (not specifying any source files), while having target_include_directories(${XML_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/deps/tinyxml2) and target_link_libraries(${XML_NAME} INTERFACE tinyxml2) will do the trick.
The tinyxml2 includes are made available to the parent project, and the tinyxml2 library is linked in the parent project.
For me (came here from Google), this error occurred when CMake target_sources had only PRIVATE sources, and no PUBLIC sources.
I had to make at least one PUBLIC source file:
old:
target_sources(${PROJECT_NAME}
PRIVATE
External/dbscan.cpp
main.cpp
)
new:
target_sources(${PROJECT_NAME}
PRIVATE
External/dbscan.cpp
PUBLIC
main.cpp
)
The error says what it means: there are no sources for libraries.
#adding entries for lib_third_party_ti_mmcsdlib
include_directories("${PROJECT_SOURCE_DIR}/lib/third_party/ti/mmcsdlib")
include_directories("${PROJECT_SOURCE_DIR}/lib/third_party/ti/mmcsdlib/include")
add_library(lib_third_party_ti_mmcsdlib "") # NO SOURCES HERE!!!!
target_compile_definitions(lib_third_party_ti_mmcsdlib
PRIVATE -DBOOT=MMCSD -DCONSOLE=UARTCONSOLE
)
subdirs("${PROJECT_SOURCE_DIR}/lib/third_party/ti/mmcsdlib")
subdirs("${PROJECT_SOURCE_DIR}/lib/third_party/ti/mmcsdlib/include")
You should read the docs about add_library in cmake. If you don't provide any source files, you should declare it as INTERFACE
add_library(LibName INTERFACE)
In this case no compilation target would be generated.
Otherwise, you can declare it as IMPORTED, then cmake will not try to create a target for compilation either.
For SHARED, STATIC or OBJECT you always need to supply sources.
You should check ProjectIncludes.cmake for what you really want to do: compile new libs or import them.
!!!
https://cmake.org/cmake/help/v3.11/release/3.11.html https://cmake.org/cmake/help/v3.11/command/target_sources.html
The target_*() for interface targets are also great!