I have two C++ libraries, which I am using on Ubuntu. One of them, let's call it foo, I installed through apt-get, e.g. sudo apt-get install libfoo-dev. The other, let's call it bar, I installed by downloading the source files, and running make install. After these installations, I then have header files from foo in locations such as /usr/include/foo/foo.h, and header files from bar in locations such as /usr/local/include/bar/bar.h. From my knowledge, foo is a dependency of bar.
I then created my own C++ project, and included the line #include "bar/bar.h". But when compiling my project, I get an error saying error: foo.h: No such file or directory. If I click on the error in my debugger, it opens the file bar.h, and highlights the line #include <foo.h>. So, my project is able to find bar.h, but not foo.h. I do not mention either foo or bar in my CMakeLists.txt file.
So my questions are:
How does my project know how to find bar.h, when I have not told it where to find it in CMakeLists.txt?
What do I need to do to get my project to find foo.h and compile properly?
Thank you!
Edit: Here is my CMakeLists.txt file (the foo and bar libraries are none of the ones mentioned here):
cmake_minimum_required(VERSION 2.8.1)
set(CMAKE_CXX_FLAGS "-std=c++11 -O3")
project(Grasping_Simulator)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(GLUT REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Boost REQUIRED)
find_package(OpenCV REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLUT_INCLUDE_DIR} ${EIGEN3_INCLUDE_DIR} ${BOOST_INCLUDE_DIRS} ${OPENCV_INCLUDE_DIRS})
file(GLOB SRCS *.cpp *.h)
add_executable(${PROJECT_NAME} ${SRCS})
target_link_libraries(${PROJECT_NAME} ${GLEW_LIBRARY} ${GLUT_LIBRARY} ${OpenCV_LIBS} pthread GL boost_system)
You need to add the option -I/usr/include/foo/ to your compilation command.
By default, locations such as /usr/include/ and /usr/local/include are already in the include search path. However, your library bar does something naughty by using #include <foo.h>. Really, it should be using things like #include <foo/foo.h> (by the way if you can make this change that would be cleaner). That would allow the compiler to search all its include paths, including the path /usr/include/, and try appending /foo/foo.h - which would succeed. As it stands, there is nothing in the default include path which would work merely by appending /foo.h, so it fails to find it.
EDIT: Given your CMake code above, most likely you need to append a variable that contains the value /usr/include/foo to the include_directories line to achieve the desired effect (this being the inclusion of -I/usr/include/foo/ on the compilation line).
Related
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 want to use the SQLAPI library, i have copied all files in the include directory to usr/local/include/SQLAPI and all files from the lib directory to usr/local/lib. The lib files are named libsqlapi.a /libsqlapi.so and libsqlapiu.a /libsqlapiu.so .
My cmakeLists.txt looks like this:
project(gsl_test)
cmake_minimum_required(VERSION 2.8)
SET(CMAKE_CXX_FLAGS "-std=c++0x")
aux_source_directory(. SRC_LIST)
include_directories(usr/local/include)
link_directories(usr/local/lib)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} libsqlapi)
I get the build/linker error: cannot find -llibsqlapi.
I did also try target_link_libraries(${PROJECT_NAME} sqlapi), but it gives me additional "skipping incompatible //usr/local/lib/libsqlapi.so"
(and the same for .a) with cannot find -lsqlapi
Ok, i'll change my edit to an answer:
The reason linker complained was the fact that you specified the library in the wrong manner. lib is just prefix - if you use target_link_libraries you use the rest of library name. Changing to
target_link_libraries(${PROJECT_NAME} sqlapi)
solved that issue. The error you receive now
skipping incompatible //usr/local/lib/libsqlapi.so
Is most probably caused by the fact that you have copied all the files from some pre-build package and it's not compatible with your system. You need to recompile the library on your own.
I'm having trouble compiling my application using cmake and make. The source files of the project are organized as follows:
SOURCE/
CMakeLists.txt
myApp.cc
include/
classA.hh
classB.hh
src/
classA.cc
classB.cc
classB.cu
My CMakeLists.txt file is as follows:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(myApp)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
FIND_PACKAGE(GDCM REQUIRED)
IF(GDCM_FOUND)
INCLUDE(${GDCM_USE_FILE})
SET(GDCM_LIBRARIES gdcmCommon vtkgdcm)
ELSE(GDCM_FOUND)
MESSAGE(FATAL_ERROR "Cannot find GDCM, did you set GDCM_DIR?")
ENDIF(GDCM_FOUND)
SET(CUDA_TOOLKIT_ROOT_DIR="/Developer/NVIDIA/CUDA-7.5/")
FIND_PACKAGE(CUDA REQUIRED)
SET(CUDA_PROPAGATE_HOST_FLAGS ON)
SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -gencode arch=compute_30,code=sm_30)
SET(LIB_TYPE SHARED)
SET(CUDA_SEPARABLE_COMPILATION ON)
LINK_DIRECTORIES(/lib/FFTW/INSTALL/lib)
INCLUDE_DIRECTORIES(/lib/FFTW/INSTALL/include)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
FILE(GLOB headers ${PROJECT_SOURCE_DIR}/include/*.hh)
FILE(GLOB sources ${PROJECT_SOURCE_DIR}/src/*.cc)
FILE(GLOB cudafile ${PROJECT_SOURCE_DIR}/src/*.cu)
CUDA_ADD_EXECUTABLE(myApp myApp ${headers} ${sources} ${cudafile})
TARGET_LINK_LIBRARIES(myApp ${VTK_LIBRARIES} ${GDCM_LIBRARIES} fftw3)
When I try to compile the project using make (after successfully running cmake) I get:
nvcc fatal : A single input file is required for a non-link phase when an outputfile is specified
CMake Error at myApp_generated_classB.cu.o.cmake:207 (message):
Error generating
../BUILD/CMakeFiles/myApp.dir/src/./myApp_generated_classB.cu.o
Is breaking up the source file of a class into .cc and .cu files problematic?
This is not a comprehensive explanation of what exactly causes the problem stated in the question; nevertheless it solves the problem in a fairly satisfactory way.
First, apparently there is a conflict between using FIND_PACKAGE(VTK) (and hence FIND_PACKAGE(GDCM) which seems to require VTK CMake files for vtkgdcm) and nvcc. This has been recently reported on Mantis. To avoid this conflict, I use:
LINK_DIRECTORIES( {VTK_Directory}/INSTALL/lib)
INCLUDE_DIRECTORIES({VTK_Directory}/INSTALL/include/vtk-6.2)
LINK_DIRECTORIES( {GDCM_Directory}/INSTALL/lib)
INCLUDE_DIRECTORIES({GDCM_Directory}/INSTALL/include/gdcm-2.4)
instead of,
FIND_PACKAGE(VTK REQUIRED)
FIND_PACKAGE(GDCM REQUIRED)
Second, as for the CUDA part of the project, I put everything into a .cu file and use CUDA_COMPILE(cuda_o myCUDAstudff.cu) to create an object file. Then I use the native C++ compiler to create an executable as usual using ADD_EXECUTABLE( ... ${cuda_o}). Since I am using the native C++ compiler as opposed to nvcc, I need to include the following header files in my kernel (myCUDAstudff.cu) file:
#include <cuda.h>
#include <cuda_runtime.h>
and also link to libcudart in TARGET_LINK_LIBRARIES(), for which I used the shared library. I couldn't figure out a way to do the same with libcudart_static.a though.
Alternatively, one can use CUDA_ADD_EXECUTABLE(... myCUDAstudff.cu) instead of all the above steps (i.e., CUDA_COMPILE(), ADD_EXECUTABLE(),...).
I have the following folder hieararchy in my QT project and I need to use some classes of the Utility folder in the classes of the ImageProcessing folder.
CMAKE file of Utilities:
file(GLOB Utilities_Files *.cpp *.h *.hpp)
# add component
add_library(Utilities ${Utilities_Files})
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(Utilities ${OpenCV_LIBRARIES})
CMAKE file of ImageProcessing:
file(GLOB ImageProcessing_FILES *.cpp *.h *.hpp)
# add component
add_library(ImageProcessing ${ImageProcessing_FILES})
include_directories(../Utilities)
target_link_libraries(ImageProcessing Utilities)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(ImageProcessing ${OpenCV_LIBRARIES})
when I try to include classes from Utilities in classes of ImageProcessing:
#include "Utilities/className.h"
The compiler always fails.. Not sure why? It seems there is something missed or misunderstood.
Thanks.
Your line include_directories(../Utilities) adds the path ../Utilities to include directories. However, you include Utilities/className.h in the source file which makes the compiler search for files ./Utilities/className.h and ../Utilities/Utilities/className.h.
Remove one of the Utilities in either include_directories or #include.
include_directories(..)
or
#include "className.h"
I'm trying to use cmake to build my little project using protocol buffers.
There's a root directory with a number of subdirectories with a number of libraries and executables. My first thought was to have my .proto-files in a subdirectory, but when I read this answer I made a library out of it instead. But when I try to include a messages header in my executable it can't find it.
Error message:
fatal error: msgs.pb.h: No such file or directory
#include "msgs.pb.h"
^
compilation terminated.
I'm running it by creating a dir "build" and then "cmake .. && make" from inside it.
I've looked and it seems the generated files get put in build/messages, so I could do include_directories(build/messages) but that doesn't seem...proper. Is there a proper way of doing this with protobuf? The reason I want the messages file in their own folder is they they'll be used in a lot of different small executables.
Any other general tips for improvements to my CMake-structure is also appreciated :)
Directories:
root
messages
core
server
root/CMakeLists.txt:
project(lillebror)
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0015 NEW)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost COMPONENTS date_time log thread system)
find_package(Protobuf REQUIRED)
if(Boost_FOUND)
add_definitions(-std=c++11)
add_subdirectory(messages)
add_subdirectory(core)
add_subdirectory(server)
add_subdirectory(testserver)
endif()
messages/CMakeLists.txt:
file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles})
add_library(messages STATIC ${ProtoSources} ${ProtoHeaders})
target_link_libraries(messages ${Boost_LIBRARIES} ${PROTOBUF_LIBRARY})
core/CMakeLists.txt:
aux_source_directory(src SRC_LIST)
add_library(core STATIC ${SRC_LIST})
target_link_libraries(core messages ${Boost_LIBRARIES})
server/CMakeLists.txt:
aux_source_directory(src SRC_LIST)
include_directories(../messages) <---- I thought this would sove my problem
include_directories(../core/src)
link_directories(../core/build)
add_executable(server ${SRC_LIST})
target_link_libraries(server core ${Boost_LIBRARIES})
server/main.cpp:
#include "msgs.pb.h"
int main()
{
return 0;
}
I think the problem here is that the PROTOBUF_GENERATE_CPP function sets up the .pb.h and .pb.cc files to exist in the build tree, not in the source tree.
This is good practice (not polluting the source tree), but it means that your call include_directories(../messages) is adding the wrong value to the search paths. This is adding the source directory "root/messages", whereas you want "[build root]/messages".
You could probably just replace that line with:
include_directories(${CMAKE_BINARY_DIR}/messages)
However, a more robust, maintainable way might be to set the required include path inside the messages/CMakeLists.txt. To expose this value to the parent scope, this would need to either use set(... PARENT_SCOPE) or:
set(ProtobufIncludePath ${CMAKE_CURRENT_BINARY_DIR}
CACHE INTERNAL "Path to generated protobuf files.")
Then in the top-level CMakeLists.txt, you can do:
include_directories(${ProtobufIncludePath})
If your messages library itself needs to #include the generated protobuf files (this would be normal), then it too should have a similar include_directories call.
Having said all that, if you can specify CMake v2.8.12 as the minimum, you can use the target_include_directories command instead.
In messages/CMakeLists.txt after the add_library call, you'd simply do:
target_include_directories(messages PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
Then any other target which depends on messages automatically has the appropriate "messages" include dirs added to its own - you don't need to explicitly call include_directories at all.