#include path
include_directories(
${PROJECT_SOURCE_DIR}/include
${HGE_INCLUDE_DIR}
${IKL_INCLUDE_DIR}
${BOOST_DIRECTORY}
)
#include all files
FILE(GLOB CORE_SRCS source/core/*.cpp)
FILE(GLOB TOOL_SRCS source/tools/*.cpp)
FILE(GLOB GAME_SRCS source/game/*.cpp)
#Making a compiled library
add_library(GAMECORE_LIBRARY ${CORE_SRCS} ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY})
#add executable
add_executable(DemoGame ${GAME_SRCS})
##link executable to HGE lib
TARGET_LINK_LIBRARIES(DemoGame ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY} ${IKL_LIBRARY} GAMECORE_LIBRARY)
if(BUILD_TOOLS)
add_executable(EntityTool ${TOOL_SRCS})
TARGET_LINK_LIBRARIES(EntityTool ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY} ${IKL_LIBRARY} GAMECORE_LIBRARY)
endif(BUILD_TOOLS)
this is my current cmake ..
I get a weird linker error for hgeGUI class
eg : DemoGame/source/core/GameMainMenu.cpp:74: undefined reference to `hgeGUI::hgeGUI()'
This only happens when I try to compile the core files into a static library.
When I add the executable with the CORE_SRCS and remove the dependencies on my current compiled library .. it will work fine..
Also I tried copy pasting the hgegui.cpp file into my core sources directory .. and change the #include "..\..\include\hgegui.h" to #include "hgegui.h"
After that my linker code resolves the issue but I get segmentation faults but I m guessing linking the file in the previous step was not right ..
Here's a link to their .h file
http://trac.assembla.com/snowscape/browser/hge/include/hgegui.h
It looks like you're misusing the ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} variables.
In an add_library call, you include all the source files which make up that library.
In a target_link_libraries call, you specify libraries or flags to use when linking the target.
So, if ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} specify paths to libraries which you want to specify as dependencies of GAMECORE_LIBRARY, you need to do:
add_library(GAMECORE_LIBRARY ${CORE_SRCS})
target_link_libraries(GAMECORE_LIBRARY ${HGE_LIBRARY} ${HGE_HELPER_LIBRARY})
The dependencies are transitive, so this means when you specify GAMECORE_LIBRARY as a dependency of DemoGame and EntityTool, then CMake recognises that ${HGE_LIBRARY} and ${HGE_HELPER_LIBRARY} are also dependencies, so you can remove them from the target_link_libraries calls for DemoGame and EntityTool if you want.
For further info on add_library and target_link_libraries, run:
cmake --help-command add_library
cmake --help-command target_link_libraries
Related
I'm trying to build a program, that is dependant on two other projects (ugh and thermough). thermough is dependant on ugh and both have multiple libraries.
The code species.cpp is the following:
#include "Test.h"
#include "tabstream.h"
#include <fstream>
int main()
{
ugh::Test tp("water");
std::ofstream file;
tabstream tfile(file,16);
file.open("water");
tfile << "T"
<< std::endl;
return 0;
}
This is my CMakeLists.txt:
####################################
# General setup
####################################
cmake_minimum_required (VERSION 3.5.2)
project (getSpeciesTest VERSION 1.0)
set(CMAKE_VERBOSE_MAKEFILE OFF)
include(CMakePrintHelpers)
####################################
# Executable
####################################
add_executable(specieTestEx species.cpp)
#configure_file(TutorialConfig.h.in TutorialConfig.h)
####################################
# Libraries, etc
####################################
set(PATH_TO_SRC ${PROJECT_SOURCE_DIR}/../src)
set(PATH_TO_THERMOUGH ${PROJECT_SOURCE_DIR}/../../build)
set(PATH_TO_UGH ${PROJECT_SOURCE_DIR}/../../../ugh/build)
set(PATH_TO_UGH_SRC ${PROJECT_SOURCE_DIR}/../../../ugh/git/src)
include_directories (${PATH_TO_SRC})
include_directories (${PATH_TO_SRC}/ughMixture)
include_directories (${PATH_TO_SRC}/mathUtils)
include_directories (${PATH_TO_UGH})
include_directories (${PATH_TO_UGH_SRC}/ughBase)
include_directories (${PATH_TO_UGH_SRC}/ughMixture)
include_directories (${PATH_TO_UGH_SRC}/ughMath)
include_directories (${PATH_TO_UGH_SRC}/ughMath/math1)
include_directories (${PATH_TO_UGH_SRC}/ughMath/math2)
include_directories (${PATH_TO_UGH_SRC}/ughMath/math3)
include_directories (${PATH_TO_UGH_SRC}/ughMath/math4)
list(APPEND LIBS_THERMOUGH [...])
list(APPEND LIBS_UGH [...])
##this is where the already built libraries are
link_directories(${PATH_TO_THERMOUGH})
link_directories(${PATH_TO_UGH})
target_link_libraries(specieTestEx ${LIBS_THERMOUGH})
target_link_libraries(specieTestEx ${LIBS_UGH})
I did not write both projects, I'm just trying to use so functionalities from thermough and therefore need to link both libraries. The libraries are as shared libraries in the build folders (.so files). I checked in the CMakeList.txt of thermough and the libraries of both projects are linked there.
My questions now:
As far as I understand it, in the libraries only the .cpp files and not the headers are compiled. Therefore I need to include all the directories to the header files (and if one called function is dependant on another file, i need to include the path to that directory and so on). This leads me to having so many include_directories commands. Is there an easier way?
Secondly I get the following error when compiling:
[SRCdirectory]/../../../ugh/git/src/ughMath/math4/mathImplementation.h:8:32: fatal error: ughMath/MathLog.h: No such file or directory
The path to ughMath is linked in my CMakeList.txt. Why does this happen then and what can I correct?
Thank you for your answer in advance.
Last but not least this is the structure of the code I'm working with:
code
ugh
git
build (contains all ugh_[..].so libraries)
thermough
git
- src
- myTestCase (contains species.cpp and the CMakeList.txt I'm talking about)
build (contains all thermough_[..].so libraries)
I have a catkin library under the Name mylib which I build with catkin build
Furthermore, I have a node in which uses functions from this library. I enabled this link as I usually do in the CMakeLists.txt of the node:
find_package(catkin REQUIRED COMPONENTS
mylib
)
add_executable(exec
src/main.cpp
)
target_link_libraries(exec
${catkin_LIBRARIES}
)
However it did not succeed this time. Linker error
I then added:
find_package(catkin REQUIRED COMPONENTS
mylib
)
find_library( MYLIB NAMES
mylib
)
message(${MYLIB})
add_executable(exec
src/main.cpp
)
add_dependencies(exec ${MYLIB})
target_link_libraries(exec
${catkin_LIBRARIES}
${MYLIB}
)
The thing is the message() statement prints the correct path of the library, where i can also find it in the explorer.
However I get the warning:
(add_dependencies): Policy CMP0046 is not set: Error on non-existent dependency in add_dependencies.
Which refers to the exact same path for the library and says it is not existent.
The linker error is
/usr/bin/ld: cannot find -lmylib
Remark: I could solve the error by adding the path to the library manually
link_directories($ENV{HOME}/test/devel/lib)
I do not understand why the library is found first, but cannot be linked as its package name. But it works by providing the full path.
I appreciate any insight!
The library is not in your linker path. E.g. your linker looks in /link and you have a lib in /home. You know where to look and can see it in your file browser but the linker won't find it because it only looks in '/link'.
'find_package' looks for the package and sets some variables but it doesn't change the linker path.
You have to set the linker path by yourself. In most cases find_package sets a variable containing the linker path.
find_package provides some functions like catkin_package(). These functions set your build environment.
catkin_package() is a catkin-provided CMake macro. This is required to specify catkin-specific information to the build system which in turn is used to generate pkg-config and CMake files.
This function must be called before declaring any targets with add_library() or add_executable().
I am somewhat new to cmake and completely new to glew, glfw, and the like. I'm following a youtube channel to learn more about game engines and programming.
My problem is linking the static glew library in my project using cmake.
First, I start with the glew source code from http://mcs.une.edu.au/doc/glew-devel/index.html.
I compile it by:
cd build; cmake ./cmake; make glew_s
This adds a lib directory into the build directory with libGLEW.a
A shortened version of my CMakeLists.txt looks like:
cmake_minimum_required (VERSION 3.5 FATAL_ERROR)
project (TestProject CXX)
set(CMAKE_CXX_FLAGS "-std=c++11")
###########################
# GLEW
###########################
add_subdirectory(${CMAKE_SOURCE_DIR}/Dependencies/GLEW)
target_link_libraries(${PROJECT_NAME} glew)
and in Dependencies/GLEW I have another CMakeLists.txt:
# Add glew source and header files
file(GLOB_RECURSE glew-lib ${CMAKE_CURRENT_SOURCE_DIR}/lib/*)
file(GLOB_RECURSE glew-headers ${CMAKE_CURRENT_SOURCE_DIR}/include/GL/*)
add_library(glew ${glew-lib} ${glew-headers})
target_include_directories(glew PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/GL")
I put a copy of the libGLEW.a file into the lib directory and the include directory is copied from the glew source code include directory. It holds the GL directory, which contains the header files glew.h, wglew.h, eglew.h, and glxew.h.
When I run cmake I get the error:
CMake Error: Cannot determine link language for target "glew".
CMake Error: CMake can not determine linker language for target: glew
The glew source code also has a src directory with glew.c in it, but if I put it in the libs directory and include it in the Dependencies/GLEW/CMakeLists.txt like:
# Add glew source and header files
file(GLOB_RECURSE glew-lib ${CMAKE_CURRENT_SOURCE_DIR}/lib/*.c)
file(GLOB_RECURSE glew-headers ${CMAKE_CURRENT_SOURCE_DIR}/include/GL/*)
add_library(glew ${glew-lib} ${glew-headers})
target_include_directories(glew PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
I get the error:
CMake Error: Error required internal CMake variable not set, cmake may
be not be built correctly.
Missing variable is: CMAKE_C_COMPILE_OBJECT
CMake Error: Error required internal CMake variable not set, cmake may
be not be built correctly.
Missing variable is: CMAKE_C_CREATE_STATIC_LIBRARY
Lastly, I have tried just including the glew.c and headers in the root CMakeLists.txt like:
#########################
# GLEW
#########################
include_directories("${CMAKE_SOURCE_DIR}/Dependencies/GLEW/lib/")
include_directories("${CMAKE_SOURCE_DIR}/Dependencies/GLEW/include/GL/")
Here cmake will finish, but it won't be able to compile, saying classes do not name a type and/or are not declared in this scope.
Any help would be appreciated. I was under the impression that the libGLEW.a was the static library, and all I would have to do is link and compile it along with the headers, but that did not work.
First of all, I forgot to use
make install
after using make the first time, so I was using the incorrect libGLEW.a file.
After including the proper libGLEW.a file, my directory structure had
./Dependencies/GLEW/include/GL/*.h //header files
./Dependencies/GLEW/lib/libGLEW.a //source file
Finally, the TopLevel CMakeLists.txt is changed to include:
add_library(glew STATIC IMPORTED GLOBAL)
set_target_properties(glew PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/Dependencies/GLEW/lib/libGLEW.a )
set_target_properties(glew PROPERTIES INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/Dependencies/GLEW/include )
If I want to include the library from a lower CMakeLists.txt such as /Dependencies/GLEW/CMakeLists.txt Then I would have to first export the library from there and then import it at the topLevel CMakeLists.txt file.
Now, in order to use glew headers in my project I can just use #include .
Here is a sample project I am trying to build with a "Packages" directory which includes all the libraries to be used in the main code.
I am trying to keep my root cmake file as clean as possible and avoid relative path such as
include_directory(packages/lib1)
but I am struggling. Is there a way of including sub-directories of a directory for the purposes of header inclusion.
First a few minor remarks:
always name the CMake configuration files CMakeLists.txt (because of)
bookmark the documentation on CMake: https://cmake.org/documentation/
Sometimes it's not that easy to read, but very specific once you adopt your head to the "CMake world" ;-)
make yourself comfortable with the scope of CMake variables
include_directories(DIR1 [DIR2 [...]])
Tells CMake where the compiler should look for header files, i.e. -IDIR1 -IDIR2 ....
add_library(NAME [STATIC|SHARED] SOURCES)
This command creates the required compiler commands to create a static or shared library out of a given list of source files. No need to add in the header files. The make target will be called NAME and the library target is known to CMake as NAME.
add_subdirectory(DIR)
Tells CMake to look into DIR and parse the included CMakeLists.txt with all its content.
target_link_libraries(TARGET LIB1 [LIB2 [...]])
Tells CMake to instruct the linker to link LIB1, LIB2, etc. to the TARGET, i.e. -LLIB1 -LLIB2 .... TARGET is a CMake/make target previously defined/created with a call to add_{library,executable,custom_target}.
CMakeLists.txt:
include_directories(libraries)
# a header file in `libraries/lib1/foo.hpp` can be included
# in the whole CMake project by `#include "lib1/foo.hpp"`.
add_subdirectory(libraries)
add_subdirectory(tests)
libraries/CMakeLists.txt:
add_subdirectory(lib1)
add_subdirectory(lib2)
libraries/lib1/CMakeLists.txt:
add_library(lib1 STATIC ${LIB1_SOURCES})
libraries/lib2/CMakeLists.txt:
add_library(lib2 STATIC ${LIB2_SOURCES})
tests/CMakeLists.txt:
add_executable(tests ${TEST_SOURCES})
target_link_libraries(tests lib1 lib2)
On Ubuntu, I have two directories: build and src. In src, my CMakeLists.txt file has the lines:
add_executable(Test main.cpp)
target_link_libraries(Test libCamera.so)
After running cmake in the build directory (cmake ../src), I then copy my library file libCamera.so into the build directory. After running make, the main.cpp.o file compiles successfully, but I receive the following error during linking:
/usr/bin/ld: cannot find -lCamera
Why is this? The shared library is in the same directory that I am building in... and the same thing happens if I copy the library to /usr/bin...
You should not put prefix lib and suffix .so of the library, so just use:
target_link_libraries(Test Camera)
if your library not found you may need to add directory, where library is located:
link_directories( /home/user/blah ) # for specific path
link_directories( ${CMAKE_CURRENT_BINARY_DIR} ) # if you put library where binary is generated
Note: you copied lib to /usr/bin but unlike Windows where dll files stored with executables, in Linux that is not the case, so it would be /usr/lib, not /usr/bin. Also you may change LD_LIBRARY_PATH variable to make your program to find a library in a custom location.