There is no way to do it without a hack. You need at least one *.c or *.cpp file.
What I do is make a dummy null.cpp file (zero bytes) and use that. You can also use /dev/null but that only works on Linux.
file(WRITE null.cpp "")
add_executable(tester
null.cpp
)
target_link_libraries(tester
-Wl,--whole-archive
libtest1
libtest2
libtest3
libtest4
-Wl,--no-whole-archive
gtest_main
)
Answer from Mark Lakata on Stack OverflowThere is no way to do it without a hack. You need at least one *.c or *.cpp file.
What I do is make a dummy null.cpp file (zero bytes) and use that. You can also use /dev/null but that only works on Linux.
file(WRITE null.cpp "")
add_executable(tester
null.cpp
)
target_link_libraries(tester
-Wl,--whole-archive
libtest1
libtest2
libtest3
libtest4
-Wl,--no-whole-archive
gtest_main
)
There are mainly two reasons why a source file is enforced by CMake:
- To determine the
LINKER_LANGUAGEfrom the file ending(s) - Not all compilers do support an object/library only link step (for details see below)
And if you move the main() function to library please keep the following in mind: Why does the order in which libraries are linked sometimes cause errors in GCC?
So if you build the libraries with CMake in the same project, I would recommend to change your libraries (at least the one containing your main() function) to an object library:
cmake_minimum_required(VERSION 2.8.8)
project(NoSourceForExe)
file(WRITE main.cc "int main() { return 0; }")
add_library(MyLibrary OBJECT main.cc)
add_executable(MyExecutable $<TARGET_OBJECTS:MyLibrary>)
The add_library() documentation lists a warning here:
Some native build systems may not like targets that have only object files, so consider adding at least one real source file to any target that references $<TARGET_OBJECTS:objlib>.
But those are rare and listed in Tests/ObjectLibrary/CMakeLists.txt:
# VS 6 and 7 generators do not add objects as sources so we need a
# dummy object to convince the IDE to build the targets below.
...
# Xcode does not seem to support targets without sources.
Not knowing which host OS(s) you are targeting, you may just give it a try.
References
- CMake Object Lib containing main
- CMake/Tutorials/Object Library
CMake Error : Cannot find source file -> No SOURCES given to target
c++ - Issue regarding CMake Error: No source given to target - Stack Overflow
CMake No SOURCES given to target ERROR
add_library, sources as list not producing DLL, no error either
!!!
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!
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.
Hello Everyone,
Been trying to learn cmake and wanted to include the newer features into my sample project. The project currently is a simple QT window. Been trying to modify cmake generated by qt to have some modern features. Example like target_sources.
underneath this line is my cmake code
cmake_minimum_required(VERSION 3.8)
project(test LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_PREFIX_PATH C:/Qt/5.11.1/mingw53_32)
set(CMAKE_EXPORT_COMPILE_COMMANDS OFF)
add_library(mylib
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/window.cpp
${CMAKE_CURRENT_SOURCE_DIR}/include/window.hpp
)
target_sources(mylib
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/window.cpp
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include/window.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
)
find_package(Qt5 COMPONENTS Core Quick QuickControls2 Widgets REQUIRED)
add_executable(${PROJECT_NAME} mylib)
target_compile_definitions(mylib PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(mylib PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 Qt5::Widgets)
The cmake file is in top directory that contains the src and include file. But i been getting a error called:
CMake Error at CMakeLists.txt:27 (add_executable):No SOURCES given to target: test
Does anyone know what i am doing wrong currently or push me to right direction ?
I added a new type of library, the INTERFACE library to the upcoming CMake 3.0.0 release. That is designed as the solution to this problem:
http://www.cmake.org/cmake/help/git-master/manual/cmake-buildsystem.7.html#interface-libraries
add_library(all_branches INTERFACE)
target_link_libraries(all_branches INTERFACE branch1 branch2)
add_executable(myexe ...)
target_link_libraries(myexe all_branches)
In CMAKE the add_executable and add_library are very similar. They just tell to CMAKE that it should create a MAKE instruction for a library or executable based on the list of src files that you provide after the name of the library/executable and options (such as SHARED, etc).
What you can do is to add the names of your libs that you want to link in a name variable that you increase such as
SET(TARGET_LIBS ${TARGET_LIBS} myFirstLib)
SET(TARGET_LIBS ${TARGET_LIBS} myNextLib)
and then simply:
target_link_libraries(myExe ${TARGET_LIBS})
In this way you can easily define groups of libraries that may be needed for different sub projects without creating a meta-lib.
This solution seemed to work.
add_library(library1 SHARED
file1.cpp
file2.cpp
)
add_library(library2 SHARED
file3.cpp
file4.cpp
)
# dummy file is required to avoid a cmake error, but this
# "dummy" file serves no other purpose and is empty.
add_library(master_library SHARED
dummy.cpp
)
# Link the master library with the other libraries
target_link_libraries(master_library
library1
library2
)
After doing this, I was able to compile and link code using ONLY the master library.
If all you want is a convenient target for use by others and don't care about whether you have one or multiple libraries, cmake can do that with an interface library:
add_library(library1 SHARED
file1.cpp
file2.cpp
)
add_library(library2 SHARED
file3.cpp
file4.cpp
)
add_library(master_library INTERFACE)
# Link the master library with the other libraries
target_link_libraries(master_library INTERFACE
library1
library2
)
Then in another location if you have
target_link_libraries(my_executable PRIVATE
master_library
)
my_executable will link against library1 and library2