How to properly use file GLOB? - c++

I'm trying to use GLOB_RECURSE to specify my sources and headers files. Currently, my CMakeLists.txt for a static library is:
project(LinearSystemLib)
file(GLOB_RECURSE ${PROJECT_NAME}_headers ${PROJECT_SOURCE_DIR}/*.h)
file(GLOB_RECURSE ${PROJECT_NAME}_sources ${PROJECT_SOURCE_DIR}/*.cpp)
add_library(
${PROJECT_NAME} STATIC ${${PROJECT_NAME}_headers}
${${PROJECT_NAME}_sources}
)
install(
TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION libs
ARCHIVE DESTINATION archives
)
The library directory looks like this:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
When I run command cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug (in the build directory) everything goes ok. Yet, command make it displays the following:
/home/felipe/Documents/Dados/SINMEC/Eclipse/LinearSystemLib/source/LinearSystemLib.cpp:1:29: fatal error: LinearSystemLib.h: No such file or directory
Is my CMakeLists wrong? I don't want to set specify the sources and headers files by name. I'm not finding information about glob_recurse easily.
I can make it work by listing the sources and headers files by name. However, it MUST be done with the glob_recurse or with glob.

I solved my problem, here's what LinearSystemLib directory looks like:
LinearSystemLib
CMakeLists.txt
source
LinearSystemLib.cpp
include
LinearSystemLib.h
The CMakeLists.txt contains:
project(LinearSystemLib)
#INCLUDE DIRECTORIES
include_directories(${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include)
#SEARCH FOR .CPP AND .H FILES
file(GLOB ${PROJECT_NAME}_headers ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/include/*.h)
file(GLOB ${PROJECT_NAME}_sources ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/*.cpp)
#ADD LIBRARY
add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_sources})
#DEFINE OUTPUT LOCATION
install(
TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION static_libs
)
You don't actually NEED to add the .h/.hpp files using GLOB. I did it because otherwise, Visual Studio (or CodeBlocks) wouldn't create a "Header Files" folder on the project menu.
I wasn't properly specifying the path where GLOB would find the files.
${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/source/

You need to add
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
so the correct -I argument is added to your compilation step. Use make VERBOSE=1 to see exactly what commands make is executing.

Related

CMake cannot link executable -ljsoncpp: no such file using github submodules

I am working in a project which uses jsoncpp for parsing and cmake for compilation. I added the jsoncpp official git repository as a submodule to my project with git submodule add REPO_URL external/jsoncpp, so as to keep every dependency together.
When running cmake -B out/build, it works normally. But when I do make, I get the following error:
/usr/bin/ld: cannot find -ljsoncpp: No such file or directory.
The files are organized the following way:
- root
- out/build
- external
- jsoncpp (cloned repo)
- include
foo.h
bar.h
- src
foo.cpp
bar.cpp
main.cpp
CMakeLists.txt
The CMakeLists.txt is like this:
cmake_minimum_required(VERSION 3.22.1)
project(ants)
# ".cpp" files in folder "src" into cmake variable "SOURCE"
file(GLOB SOURCE "src/*.cpp")
# Executable
add_executable(${PROJECT_NAME} ${SOURCE})
# Directory where cmake will look for include files
include_directories(include)
# Tells cmake to compile jsoncpp
add_subdirectory(external/jsoncpp)
# Tells cmake where to look for jsoncpp include files
target_include_directories(${PROJECT_NAME}
PUBLIC external/jsoncpp/include
)
target_link_libraries(${PROJECT_NAME} jsoncpp)
The jsoncppConfig.cmake defines property INTERFACE_INCLUDE_DIRECTORIES for targets jsoncpp_lib and jsoncpp_lib_static.
You need to query the target property and set it manually:
get_target_property(JSON_INC_PATH jsoncpp_lib INTERFACE_INCLUDE_DIRECTORIES)
include_directories(${JSON_INC_PATH})
Linking is done via:
target_link_libraries(${PROJECT_NAME} jsoncpp_lib)
Source.
Try this:
cmake_minimum_required(VERSION 3.22.1)
project(ants)
# ".cpp" files in folder "src" into cmake variable "SOURCE"
file(GLOB SOURCE "src/*.cpp")
# Executable
add_executable(${PROJECT_NAME} ${SOURCE})
# Directory where cmake will look for include files
include_directories(include)
# Tells cmake to compile jsoncpp
add_subdirectory(external/jsoncpp)
get_target_property(JSON_INC_PATH jsoncpp_lib INTERFACE_INCLUDE_DIRECTORIES)
include_directories(${JSON_INC_PATH})
target_link_libraries(${PROJECT_NAME} jsoncpp_lib)

CMakeLists include Header File from subdirectories

I am trying to work with CMake for the first time and am struggling to link header files into my main. My cmake directory looks like this:
Project
| CmakeLists.txt
| src
|| CMakeLists.txt
|| Main.cpp
| Libs
|| CMakeLists.txt
|| headers
|||obstacle_detection.hpp
||source
|||obstacle_detection.cpp
|build
||"build files"
I would like to link the files in the headers folder to main, but what I currently have does not appear to work. The following runs the CMake command correctly but fails to compile with the make command, being unable to find the given header file. My CMakeLists files are as follows:
Project:
cmake_minimum_required(VERSION 3.17)
project(Sensivision)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
find_package(OpenCV REQUIRED)
find_package(realsense2 REQUIRED)
find_library(darknet REQUIRED)
add_subdirectory(libs)
add_subdirectory(src)
target_link_libraries(${PROJECT_NAME} obstacle_detection)
Libs:
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
target_link_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
src:
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
target_link_libraries(${PROJECT_NAME} ${realsense2_LIBRARY})
My include in main.cpp is
include <obstacle_detection.hpp>
I have also tried
include <headers/obstacle_detection.hpp>
and
include <obstacle_detection>
Each gives the error:
obstacle_detection.hpp: no such file or directory
What am I doing incorrectly to link the header to the main?
You haven't added any include directories to the obstacle_detection library. By listing the header file in the add_library call, this may allow the header to be displayed in an IDE, but it doesn't do anything for compilation. You should use target_include_directories to add the headers directory as an include directory for the obstacle_detection library. Otherwise, it, and other consuming targets, will have no knowledge of the headers in that directory.
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
# Add this line.
target_include_directories(obstacle_detection PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/headers)
# Not sure this line is necessary, as it doesn't appear you actually link anything...
target_link_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
You haven't shown the CMake code in the src directory, but be sure to link the obstacle_detection library target to the main target, e.g.:
target_link_libraries(MyExeTarget PRIVATE obstacle_detection)
In addition, because this header file is local, it is best if you use quotes to include the header:
#include "obstacle_detection.hpp"
You can use target_include_directories to add folder where your headers are located and #include <header.hpp> where needed.
Ex:
libs cmake:
add_library(
obstacle_detection
headers/obstacle_detection.hpp
sources/obstacle_detection.cpp
)
target_include_directories(obstacle_detection PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
cpp:
#include <headers/obstacle_detection.hpp>

CMake - Include directories outside project

So I want to include a global header file that is in a different folder. The code for the CMakeList.txt is below. In my .cpp when I include something from the local include folder it works, but not for the something that is in a different folder.
cmake_minimum_required(VERSION 2.8)
#Project name
project(Server-Client)
#Add all cpp files as source files
file(GLOB_RECURSE SOURCES "src/*.cpp")
#Build executable 'Server' with all files in SOURCES
add_executable(Server ${SOURCES})
#Include all files in include directory
include_directories("include")
target_include_directories(Server PUBLIC "../../GlobalFiles/include")
find_package(Threads REQUIRED)
#Build executable 'localization' with all files in SOURCES
target_link_libraries(Server ${CMAKE_THREAD_LIBS_INIT})
Don't use a relative paths, instead use CMAKE_CURRENT_SOURCE_DIR variable like this:
target_include_directories(Server PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../GlobalFiles/include")
Other than that, it might be a good idea to use a Macro to find the global header you are looking for.

CMake + Qt Creator: Add header files to project files

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
)

CMake and absolute header paths

I'm trying to use CMake to build my C++ project and I have a problem in the header paths.
Since I'm using a lot of classes organized in several directories, all my include statements are with absolute paths (so no need to use "../../") but when try to make the CMake-generated Makefile it just doesn't work.
Does anyone know how to specify in CMakeLists.txt that all the includes are with absolute paths?
My output when trying to make
~/multiboost/BanditsLS/GenericBanditAlgorithmLS.h:45:25: Utils/Utils.h: No such file or directory
~/multiboost/BanditsLS/GenericBanditAlgorithmLS.h:46:35: Utils/StreamTokenizer.h: No such file or directory
My CMakeLists.txt file :
#The following command allows the use of the "file" command
cmake_minimum_required(VERSION 2.6)
#The declaration of the project
project(multiboost)
#This allows recursive parsing of the source files
file(
GLOB_RECURSE
source_files
*
)
list(REMOVE_ITEM source_files ./build/* )
#This indicates the target (the executable)
add_executable(
multiboost
${source_files} #EXCLUDE_FROM_ALL build/
)
You need something like this in CMakeLists.txt:
SET(BASEPATH "${CMAKE_SOURCE_DIR}")
INCLUDE_DIRECTORIES("${BASEPATH}")
set the correct include path: suppose your Utils directory is in /exp/appstat/benbou/multiboost, then cmake (well actually, gcc) has to know this:
include_directories( /exp/appstat/benbou/multiboost )
or it might be more convenient to pass this as an option which is passed on the command line:
include_directories( ${MyProjectRoot} )
cmake -DMyProjectRoot=/exp/appstat/benbou/multiboost