I have a folder with only headers.
In my config project I need some interfaces of the param project
src
CMakeList.txt
- config
- CMakeList.txt
- param
- CMakeList.txt
- parameter.h
This is inside my config CMakeList.txt
project(config)
file(GLOB_RECURSE SOURCES "${config_SOURCE_DIR}/*.cpp")
add_library(config ${SOURCES})
target_include_directories(config PUBLIC "${param_SOURCE_DIR}")
target_include_directories(config PUBLIC "${Utils_SOURCE_DIR}/include")
qt5_use_modules(config Core)
target_link_libraries(config)
My param library CMakeList.txt is (it needs Utils too)
project(param)
file(GLOB_RECURSE HEADERS "${param_SOURCE_DIR}/*.h")
add_library(param INTERFACE)
Then in my config project I have a class that include one of the interface and when building it doesn't find it. "parameter.h" file not found.
/usr/local/bin/clang++ -DQT_CORE_LIB -DQT_NO_DEBUG -I/builds/modules/project/src/config -I~/modules/project/src/config -I/usr/include/eigen3 -I~/modules/libs/utils/include -isystem ~/devel/qt5/qtbase/include -isystem ~/devel/qt5/qtbase/include/QtCore -isystem ~/devel/qt5/qtbase/./mkspecs/linux-g++ -fPIC -std=gnu++11 -o CMakeFiles/config.dir/configuration.cpp.o -c ~/modules/project/src/config/configuration.cpp
One of the source file in config cannot compile because of :
fatal error: 'parameter.h' file not found
#include "parameter.h"
In src/CMakeLists.txt you obviously need
include_directories(param)
line. Alternatively, you can use include_directories(../param) in src/config/CMakeLists.txt.
The include_directories() command adds specified directories to compiler search paths for all targets declared below it in current CMakeLists.txt and every add_subdirectoryed one.
Related
I am trying to write a proper CMake script for building an embedded project(STM32). Our project structure looks like this:
App/
....Module1/
....Module2/
Core/
....OwnFramework/
........CoreModule1/
........CoreModule2/
....CubeMXGeneratedCode/
........Core/ (there are more files and dirs, but they are not relevant)
...........Src/main.c (only important info is that main is here)
........Drivers/
....Libs/
........Lib1/ (for example ETL)
Right now there is one CMakeLists.txt file in root project dir, but this seems like a bad solution. I've tried adding CMakeLists into App/ and App/Module but then I would get linking errors (while looking at compile_commands I've seen that they were compiled with almost no flags).
./CMakeLists.txt (removed some non-important parts, like set variables that are obvious, so it's little bit shorter)
set(APP_INCLUDE_DIRECTORIES
${APP_DIR}/Module1
${APP_DIR}/Module2
)
set(CORE_INCLUDE_DIRECTORIES
${Core_DIR}/CoreModule1
${Core_DIR}/CoreModule2
)
set(FLAGS
"-Wl,--gc-sections")
set(CPP_FLAGS
"-fno-rtti -fno-exceptions -fno-threadsafe-statics")
set(CPU_PARAMETERS
-mcpu=cortex-m4
-mthumb
-mfpu=fpv4-sp-d16
-mfloat-abi=hard)
set(STARTUP_SCRIPT ${CUBEMX_DIR}/startup_stm32fxxxxx.s)
set(MCU_LINKER_SCRIPT ${CUBEMX_DIR}/STM32Fxxxxxxx_FLASH.ld)
set(CUBEMX_INCLUDE_DIRECTORIES
${CUBEMX_DIR}/Core/Inc
... and some more Inc dirs
set(PROJECT_INCLUDE_DIRECTORIES
${CMAKE_SOURCE_DIR}
${APP_INCLUDE_DIRECTORIES}
${CORE_INCLUDE_DIRECTORIES})
file(GLOB_RECURSE STM32CUBEMX_SOURCES
${CUBEMX_DIR}/Core/*.c
${CUBEMX_DIR}/Drivers/*.c
${CUBEMX_DIR}/Middlewares/Third_Party/FreeRTOS/Source/*.c)
file(GLOB_RECURSE PROJECT_SOURCES FOLLOW_SYMLINKS
${APP_DIR}/*.cpp
${APP_DIR}/*.c
${CORE_DIR}/*.cpp
${CORE_DIR}/*.c)
add_executable(${EXECUTABLE}
${STM32CUBEMX_SOURCES}
${PROJECT_SOURCES}
${STARTUP_SCRIPT})
target_compile_definitions(${EXECUTABLE} PRIVATE
${MCU_MODEL}
USE_HAL_DRIVER)
target_include_directories(${EXECUTABLE} PRIVATE
${CUBEMX_INCLUDE_DIRECTORIES}
${PROJECT_INCLUDE_DIRECTORIES})
target_compile_options(${EXECUTABLE} PRIVATE
${CPU_PARAMETERS}
${FLAGS}
-Wall
-Wextra
-Wpedantic
-Wno-unused-parameter
$<$<COMPILE_LANGUAGE:CXX>:
${CPP_FLAGS}
-Wno-volatile
-Wold-style-cast
-Wuseless-cast
-Wsuggest-override>
$<$<CONFIG:Debug>:-Og -g3 -ggdb>
$<$<CONFIG:Release>:-Og -g0>)
target_link_options(${EXECUTABLE} PRIVATE
-T${MCU_LINKER_SCRIPT}
${CPU_PARAMETERS}
-Wl,-Map=${CMAKE_PROJECT_NAME}.map
--specs=nosys.specs
-Wl,--start-group
-lc
-lm
-lstdc++
-lsupc++
-Wl,--end-group
-Wl,--print-memory-usage)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${EXECUTABLE}>)
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}>
${EXECUTABLE}.hex
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}>
${EXECUTABLE}.bin)
There is also toolchain file:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(FLAGS
"-fdata-sections -ffunction-sections \
--specs=nano.specs -Wl,--gc-sections")
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc ${FLAGS})
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++ ${FLAGS})
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size)
set(CMAKE_EXECUTABLE_SUFFIX_ASM ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX ".elf")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
I am building everything with this command:
cmake -B${workspaceFolder}/build -DCMAKE_TOOLCHAIN_FILE=gcc-arm-none-eabi.cmake -DCMAKE_BUILD_TYPE=Debug
And this setup works, but I have a feeling that this is a vary bad way of doing it. When I tried adding subdirectories in App and each module, I've got linking erros due to problems with compile flags (arm none eabi elf uses VFP register arguments linking error).
I am also not sure how well will it work when I start adding libs like Embedded Template Library.
So my question is, how do I add subdirectories so they compile the same way my root CMakeLists does? I've tried doing this following multiple guides and examples like this one: https://github.com/rgujju/STM32_Base_Project/blob/master/modules/simple_module/CMakeLists.txt.
But when I've put this in my App/Module/CMakeLists.txt
set(MODULE_NAME simple_module)
file(GLOB SOURCES ./*.c)
add_library(${MODULE_NAME} STATIC
${SOURCES}
)
target_include_directories(${MODULE_NAME}
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${PROJECT_SOURCE_DIR}/include
)
And added add_subdirectory(App) to main, my generated commands for modules where without most of my flags and didn't link.
If anyone has experience with dividing CMake project into modules, libs and subdirectories, I would gladly accept any help.
I am trying the example below :
add_library(
mylib
src/my_code.cpp)
target_include_directories(mylib
PUBLIC include ${catkin_INCLUDE_DIRS} ${thirdPartyLib_INCLUDE_DIRS})
add_dependencies(
mylib
${mylib_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(mylib
PUBLIC
${thirdPartyLib_LIBRARY} ${catkin_LIBRARIES})
target_compile_options(mylib PRIVATE -Werror -Wall -Wextra)
The issue is that the compile options also propagate to thirdPartyLib, yet I need them only for mylib.
I think that the problem is compiler warnings, which are generated by included thirdPartyLib header files when compiling file my_code.cpp.
If you want your compiler not to generate warnings from included third-party header files, you can for example in gcc/clang include them as "system headers" (command line option -isystem instead of -I).
To do this in CMake use SYSTEM option in target_include_directories:
target_include_directories(mylib
SYSTEM
PUBLIC ${thirdPartyLib_INCLUDE_DIRS}
)
I am working on a project were I maintain a CMakeLists.txt file to keep track of the dependencies when I need to compile.
I recently, started using a new library that I need to integrate in my project. The library comes with some examples on how to compile but this is purely a Makefile. I would like to integrate the logic of the Makefile into my project's CMakeLists.txt file.
The Makefile of this library is as follows:
COMMON=-O2 -I/home/john/.mujoco/mjpro200/include -L/home/john/.mujoco/mjpro200/bin -std=c++11 -mavx -pthread -Wl,-rpath,'$$ORIGIN'
all:
g++ $(COMMON) basic.cpp -lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3 -o basic
gcc -c -O2 -mavx -I/home/john/.mujoco/mjpro200/include /home/john/.mujoco/mjpro200/include/uitools.c
rm *.o
I would like to convert this Makefile into CMakeLists.txt exactly if possible. I see that they provide some flags for threading (pthread) and I want to keep these flags and settings in my CMakeLists.txt in case they are needed for performance.
Here is my CMakeLists.txt:
cmake_minimum_required (VERSION 2.6.0)
project(myproject)
add_compile_options(-std=c++11) # CMake 2.8.12 or newer
if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
add_definitions("-fno-strict-aliasing -Wall")
endif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
# optional in case boost is used
find_package(Boost 1.58 EXACT)
find_package(Eigen REQUIRED)
set(mujocoCommon "-O2 -I/home/john/.mujoco/mjpro200/include -L/home/john/.mujoco/mjpro200/bin -std=c++11 -mavx -pthread -Wl,-rpath,'$$ORIGIN'")
set(Mujoco_INCLUDE_DIRS "/home/john/.mujoco/mjpro200/include")
include_directories(${Boost_INCLUDE_DIRS} ${Eigen_INCLUDE_DIRS} ${Mujoco_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_executable(myproject mycode.cpp)
install(TARGETS myproject DESTINATION .)
So I tried to define a variable mujocoCommon similar to the COMMON in the Makefile as well as the Mujoco_INCLUDE_DIRS that I then use in the CMake's include_directories.
Note that in the myproject.cpp I have MuJoCo code and other dependencies that I need to correctly link against. In the Makefile things looks a bit more simpler because in there the code has only MuJoco dependencies.
I need some heads-up on how to add in my CMakeLists.txt the following:
-mavx -pthread -Wl,-rpath,'$$ORIGIN' part of Makefile's COMMON variable.
-lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3
-c -O2 -mavx -I/home/john/.mujoco/mjpro200/include /home/john/.mujoco/mjpro200/include/uitools.c
Currently with the minimal knowledge on CMake and what I have in my CMakeLists.txt when I compile using "make" I get many errors of the kind:
myproject.cpp:(.text+0xfa9): undefined reference to `glfwSetMouseButtonCallback'
Basically I would like to link (?) my code with MuJoco library as is done in their Makefile.
Thanks.
Edit
In regards with the possible duplicate flag, I added the following flag:
set(Mujoco_LIBRARIES "/home/john/.mujoco/mjpro200/bin")
target_link_libraries(myproject ${Mujoco_LIBRARIES} -lboost_system)
But it didn't solved the problem.
Edit 2:
I have also added this one:
set(CMAKE_CXX_FLAGS "-lmujoco200 -lGL -lglew /home/john/.mujoco/mjpro200/bin/libglfw.so.3")
The errors I am getting:
/usr/bin/x86_64-linux-gnu-ld: cannot find -lmujoco200
/usr/bin/x86_64-linux-gnu-ld: cannot find -lglew
You also need to add the opengl libraries to the link libraries, target_link_libraries. Don't add them with -l.
I am learning to build a library using Cmake. The code structure for building library is like below:
include:
Test.hpp
ITest.hpp // interface
src:
Test.cpp
ITest.cpp
In CMakeLists.txt, the sentences I used to build library is :
file(GLOB SRC_LIST "src/iTest.cpp" "src/Test.cpp" "include/Test.hpp"
"include/iTest.hpp" "include/deadreckoning.hpp")
add_library(test SHARED ${SRC_LIST})
target_link_libraries( test ${OpenCV_LIBS}) // link opencv libs to libtest.so
Then I wrote another test file (main.cpp), copy and paste the library under the same directory, link library and call functions inside the library.
This CMakeLists.txt is
cmake_minimum_required(VERSION 2.8)
project(myapp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -O3 -Wall -ftree-vectorize -ffast-math -funroll-loops")
add_executable(myapp main.cpp)
target_link_libraries(myapp "/home/labUser/test_lib/libtest.so")
The main.cpp compiles and runs succussfully if I don't include the header files inside the library:
#include <iostream>
using namespace std;
int main(){
cout << "hello world" << endl;
return -1;
}
But when I include the header file #include "ITest.hpp", it has error:
fatal error: iTest.hpp: No such file or directory
#include "iTest.hpp"
compilation terminated.
I don't understand why it happens.I think I have already linked the library successfully because when I run main.cpp without including header file, it doesn't give any "linking" error. And I think apparently the header files are inside the library. Why I can't include it? Can anyone help me figure this out?
Big thanks!
You have a couple of issues here.
Propagating headers to users of your target:
Whilst you've added the include file to your library target, you need to let consumers of your library target know how to find the header.
As such, when your app myapp links against your library target test, you need to tell cmake to add ./include to myapp's include search path.
There is a special cmake variable, ${CMAKE_CURRENT_LIST_DIR} which resolves to the path to the directory in which the current CMakeLists.txt being processed is.
In your instance, that is the parent folder of both src and include.
./ <-- ${CMAKE_CURRENT_LIST_DIR} is this directory
+--- CMakeLists.txt
+--- src/
| +---Test.cpp
| +---ITest.cpp
+--- include/
+---Test.hpp
+---ITest.hpp
In order to tell cmake to add a path to its include search path you use target_include_directories
For this the path will then be ${CMAKE_CURRENT_LIST_DIR}/include
So the syntax you'd be looking for is:
target_include_directories(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
Note that this means you don't have to add "include/iTest.hpp" and "include/Test.hpp" to your SRC_LIST glob, as the compiler will be able to find them from the above target_include_directories
Linking to your test library:
Now that you've created your library and added the include directories, to actually use it in your app, you should again use target_link_libraries, but don't specify the path to the generated .so file, instead refer to the name of the library target you created, test
target_link_libraries(myapp test)
Now myapp will know how to find Test.hpp because it will get that information from the "dependency link" you've created between myapp and test
As such, assuming the following directory structure, the following CMakeLists.txt files may work
src/
+--- library/
| +--- < sources for your shared library >
+--- app/
+--- < sources for your application >
src/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(myapp)
add_subdirectory(library)
add_subdirectory(app)
src/library/CMakeLists.txt
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}
-std=c++11
-pthread
-O3
-Wall
-ftree-vectorize
-ffast-math
-funroll-loops")
find_package(OpenCV REQUIRED)
add_library(test SHARED "src/iTest.cpp src/Test.cpp")
target_link_libraries(test ${OpenCV_LIBS}) // link opencv libs to libtest.so
target_include_directories(test PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
src/app/CMakeLists.txt
add_executable(myapp main.cpp)
target_link_libraries(myapp test)
I have a simple bouncing ball program that I wrote in QtCreator on Windows a couple years ago, and now I'm trying to rebuild it on Linux (Ubuntu 14.04) using CMakeLists instead of the Qt project files. My CMakeLists.txt file (loosely based off the cmake file in this question is below.
cmake_minimum_required ( VERSION 2.6 )
project ( BouncyBall )
find_package ( Qt4 COMPONENTS QtGui QtOpenGL REQUIRED )
set (QT_USE_QTOPENGL TRUE)
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
include_directories( ${QT_QTOPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} )
find_package ( Bullet REQUIRED )
add_executable ( BouncyBall main.cpp BouncyBall.cpp BulletWidget.cpp )
target_link_libraries( BouncyBall ${QT_LIBRARIES} ${BULLET_LIBRARIES} )
Cmake configures and generates the build files without any errors, but fails to compile with the following error:
[ 33%] Building CXX object CMakeFiles/BouncyBall.dir/main.cpp.o
/usr/bin/c++ -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_OPENGL_LIB -isystem /usr/include/qt4 -isystem /usr/include/qt4/QtOpenGL -isystem /usr/include/qt4/QtGui -I/home/user/Programs/BuildArea/Games/BouncyBall -o CMakeFiles/BouncyBall.dir/main.cpp.o -c /home/user/Programs/Games/BouncyBall/main.cpp
In file included from /home/user/Programs/Games/BouncyBall/main.cpp:2:0:
/home/user/Programs/Games/BouncyBall/BulletWidget.h:4:30: fatal error: QtOpenGl/QGLWidget: No such file or directory
#include <QtOpenGl/QGLWidget>
I've verified that the file is indeed in /usr/include/qt4/QtOpenGL. I've looked online, but all the solutions I've found refer to adding QT += opengl to a project file (but I'm using CMake) or to not having the dev-tools or qt-sdk packages installed (which I do have).
What am I missing?
Isn't there a typo in your code 'QtOpenGl/QGLWidget'? QtOpenGl should be changed to QtOpenGL. If you do it on Linux the case matters.