I have a library with several source files under several directories. I want to write a cmake in a way that it add all of them to project without asking to writ them separately.
I am using this line in my cmake:
FILE(GLOB_RECURSE ALL_Lib_CPP_SRCS src/Library/ *.cpp)
add_library(MyLibrary STATIC ALL_Lib_CPP_SRCS)
but generate msvc project doesn't have all files included and I am getting this message when I am running cmake:
CMake Error at CMakeLists.txt:49 (add_library):
Cannot find source file:
ALL_Lib_CPP_SRCS
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx
What is the problem with this cmake?
It should be:
FILE(GLOB_RECURSE ALL_Lib_CPP_SRCS "src/Library/*.cpp")
add_library(MyLibrary STATIC ${ALL_Lib_CPP_SRCS})
In my opinion, it's better that you defined manually the sources:
set (_SOURCES source3.cpp source2.cpp source1.cpp main.cpp)
# now use ${_SOURCES}
this way, you can know the exact order of compilation...sometimes the order is important
The correct syntax according to the manual is:
file(GLOB_RECURSE variable [RELATIVE path] [FOLLOW_SYMLINKS] [globbing expressions]...)
I suspect you're either missing RELATIVE:
FILE(GLOB_RECURSE ALL_Lib_CPP_SRCS RELATIVE "src/Library/" "*.cpp")
Or you have an extra space in the globbing expression:
FILE(GLOB_RECURSE ALL_Lib_CPP_SRCS "src/Library/*.cpp")
I suspect the second option above is what you want. The quotes are optional, but I would recommend their use, as it makes the line easier to read IMO.
The second issue is that you need a ${} when you reference the variable:
add_library(MyLibrary STATIC ${ALL_Lib_CPP_SRCS})
Related
I am trying to build a project (c++ code files) that is to be applied on different type of target machines, and I am trying to include cpp files according to the machine type, for this I created options in the CMakeLists file in order to use them to whether include the cpp file or not.
option (MACHINE1 "MACHINE1 DESCRIPTION" OFF)
option (MACHINE2 "MACHINE1 DESCRIPTION" OFF)
...
...
...
add_library (SO_LIBRARY
SHARED FILE1.cpp
if (MACHINE1)
FILE2.cpp
endif ()
if (MACHINE2)
FILE3.cpp
endif ()
)
...
I already have a linked bitbake file where I can set these options on and off, it is not the problem, the issue is that CMakeFile does not accept this type of writing :
| CMake Error at CMakeLists.txt:52 (add_library):
| Cannot find source file:
|
| if
|
| Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
| .hpp .hxx .in .txx
|
|
| CMake Error at CMakeLists.txt:52 (add_library):
| No SOURCES given to target: SO_LIBRARY
is there any possible way to do it ?
Thank you very much.
cmake_minimum_required(VERSION 3.1)
option (MACHINE1 "MACHINE1 DESCRIPTION" OFF)
option (MACHINE2 "MACHINE1 DESCRIPTION" OFF)
add_library(SO_LIBRARY SHARED)
if(MACHINE1)
target_sources(SO_LIBRARY
PRIVATE
FILE2.cpp
)
endif()
if(MACHINE2)
target_sources(SO_LIBRARY
PRIVATE
FILE3.cpp
)
endif()
In modern CMake (since 3.1) you should avoid using custom variables in arguments of project commands and prefer to use target_sources
Try the following, Based on the type of the machine, assign the file name to a variable and then use it to add to sources.
if(MACHINE1)
set(SOURCEFILES "file1.cpp");
if(MACHINE2)
set(SOURCEFILES "file2.cpp");
if (MACHINE3)
set(SOURCEFILES "file3.cpp");
now add the file to add library
add_library (SO_LIBRARY
SHARED ${SOURCEFILES})
I would do something along these lines instead of option:
set(COMMON_SRC File1.cpp)
set(MACHINE1_SRC File2.cpp)
set(MACHINE1_SRC File3.cpp)
if(MACHINE1)
add_library (SO_LIBRARY SHARED ${COMMON_SRC} ${MACHINE1_SRC_SRC}
elseif(MACHINE2)
add_library (SO_LIBRARY SHARED ${COMMON_SRC} ${MACHINE2_SRC_SRC}
else()
...
endif()
Your goal is to create a list of sources which content will depend on some conditions.
Start with defining a variable and put there all common source files:
set(SOURCES
file_common_1.cpp
file_common_2.cpp
)
Then, APPEND elements to SOURCES list depending on conditions:
if(OPTION1)
list(APPEND SOURCES file_specific_machine1.cpp)
endif()
if(OPTION2)
list(APPEND SOURCES file_specific_machine2.cpp)
endif()
Finally, use SOURCES list to create a library:
add_library(SO_LIBRARY ${SOURCES})
I am really new to C++ and I am a bit confused.
I am trying to add this lib to my project (https://github.com/mrtazz/restclient-cpp).
I have installed it using Homebrew
brew tap mrtazz/oss
brew install restclient-cpp
then I tried adding the library to my CMakeLists by including and linking the Homebrew install directories.
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(POS)
set(CMAKE_CXX_STANDARD 14)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
add_library(
restclient-cpp STATIC
connection.h
helpers.h
restclient.h
version.h
)
add_executable(POS main.cpp program.cpp program.h programs/find.cpp programs/find.h tools/db.cpp tools/db.h)
target_link_libraries(POS PUBLIC restclient-cpp)
then I get this error...
CMake Error at CMakeLists.txt:16 (add_library):
Cannot find source file:
connection.h
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
.hpp .hxx .in .txx
CMake Error at CMakeLists.txt:16 (add_library):
No SOURCES given to target: restclient-cpp
I know something is wrong with the directories but I just cannot figure it out, I would greatly appreciate as much information as possible. I'm just trying to have some fun with this and I cannot figure out why I cannot add this simple library to my build.
Thank you.
You are trying to add header files to the add_library command. Those files need to be in a directory that you include via include_directory. You also should not put header files into the add_executable command.
To link an existing library you can call target_link_libraries.
example:
include_directories(${MY_INCLUDE_DIRS})
add_executable(main source.cpp)
target_link_libraries(main extlib)
It's probably best to find a simple CMake setup and try to use it as template.
If I have .h and .cpp files in the directory src, where the .cpp files include the .h files, using these commands in CMake:
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
And opening that CMake file in Qt Creator, gets all the files (sources + headers) in the list of project files (the file tree on the left by default).
Now, on the other hand, if I put all the .h files in a directory include, and use this:
include_directories(include)
aux_source_directory(src SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
The header files disappear from the project files!
How can I keep the header files in that directory, and still have them listed in Qt Creator's project files?
You shouldn't use aux_source_directory() for your task. That command is for something different. Just list the source files (or put them in a variable).
You shouldn't use include_directory() for defining include directories any more. This command will just populate the -I flag of the compiler. Define a variable with the header files and add that to the executable.
In case you don't want to list every file manually, use file(GLOB ...). But be aware of the caveats mentioned frequently all over the web with using that command.
Afterwards, tell CMake to populate the -I flag only for that executable with the include directory. That way, other targets don't get polluted by includes, they shouldn't use.
set(SOURCES
src/main.cpp
src/whatever.cpp)
set(HEADERS
include/whatever.h)
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
target_include_directories(${PROJECT_NAME} PUBLIC include)
I add my header files always explicit to avoid any surprise.
But on MacOS using QtCreator 4.2.0 and cmake 3.7.1 I can't reproduce your issue.
However I recommend to use following structure to know which files are within project and to trigger update of cmake's data during update of CMakeLists.txt.
In project/CMakeLists.txt:
add_subdirectory(src)
include_directory(include)
add_executable(foo ${SRC_LIST})
In project/src/CMakeLists.txt:
set(SRC_LIST
${SRC_LIST}
${CMAKE_CURRENT_SOURCE_DIR}/a.cpp
${CMAKE_CURRENT_SOURCE_DIR}/b.cpp
PARENT_SCOPE
)
I'm trying to link in a pre-compiled shared library file called libtest-lib.so. This is what I have at the bottom of my CMakeLists.txt:
link_directories("/projectspath/LinkTest/TestLib/app/build/intermediates/cmake/debug/obj/armeabi-v7a")
add_library(testlib libtest-lib.so)
target_link_libraries(testlib libtest-lib.so)
As above, I get the following error:
CMake Error at CMakeLists.txt:49 (add_library):
Cannot find source file:
libtest-lib.so
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
CMake Error: CMake can not determine linker language for target: testlib
If I comment out the add_library line, I get the following:
CMake Error at CMakeLists.txt:51 (target_link_libraries):
Cannot specify link libraries for target "testlib" which is not built by this project.
It seems that source files (.c, cpp, etc) are absolutely required when linking in a library. But how do I link in an .so file? The docs say the following about target_link_libraries():
The named must have been created in the current directory by a command such as add_executable() or add_library().
If I substitute add_library() with add_executable() I get the same error. What is the proper way to link an .so file in CMake?
I think that what you want is to import a library for CMake:
add_library(testlib SHARED IMPORTED)
set_property(TARGET testlib PROPERTY IMPORTED_LOCATION "/projectspath/LinkTest/TestLib/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libtest-lib.so")
See https://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/Exporting-and-Importing-Targets for more information
add_library creates a new library.
Instead you want to link your library to some other target.
Let's say
add_executable(main main.cpp)
target_link_libraries(main libtest-lib)
This should already work.
You should have:
link_directories("/projectspath/LinkTest/TestLib/app/build/intermediates/cmake/debug/obj/armeabi-v7a")
set(MY_SOURCES mylib.cpp)
add_library(testlib ${MY_SOURCES})
target_link_libraries(testlib libtest-lib)
which means that you should specify the sources of YOUR library as second argument to add_library() or add_executable() and not the library that is already compiled.
You need your sources because generally you build something (a library or an executable) that requires linking to some library that already exist.
Otherwise, what would you build? Nothing? And link the library to what? Who would be the consumer of that library?
I found another workaround, to mention path where the library is present while linking lib to the executable file.
INCLUDE_DIRECTORIES(/path/to/headers)
ADD_EXECUTABLE(TARGET target.c)
TARGET_LINK_LIBRARIES(TARGET_FILE "-L/path/to/shared/library" SHARED_LIB_name)
Which is indirect including library search path flag. One might also have to link the location of header files while using the library.
The proper way to do this is:
target_link_libraries(native-lib "/projectspath/LinkTest/TestLib/app/build/intermediates/cmake/debug/obj/${ANDROID_ABI}/libtest-lib.so")
Starting up CLion outputs me the following:
Error:Cannot find source file:
sinclude/MathCompiler.h
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx
Error:CMake can not determine linker language for target: MathCompiler
Error:Cannot determine link language for target "MathCompiler".
Warning:Configuration Debug
Unable to determine product file path for target MathCompiler (Debug). Running and debugging will be unavailable.
Warning:Configuration Release
Unable to determine product file path for target MathCompiler (Release). Running and debugging will be unavailable.
Warning:Configuration RelWithDebInfo
Unable to determine product file path for target MathCompiler (RelWithDebInfo). Running and debugging will be unavailable.
Warning:Configuration MinSizeRel
Unable to determine product file path for target MathCompiler (MinSizeRel). Running and debugging will be unavailable.
I didn't change anything since the last build.
Here is CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(MathCompiler)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp cpp/MathCompiler.cpp include/MathCompiler.h cpp/MathException.cpp include/MathException.h cpp/MathematicString.cpp include/MathematicString.h include/str_cmp.h include/typedefs.h)
add_executable(MathCompiler ${SOURCE_FILES})
.h-files usually aren't included into the list of source files