I am trying to make a very simple regression model that (among other things), builds and compiles a GCC target for coverage, executes, and then publishes a standard Cobertura coverage report (all within Jenkins). The Jenkins part is somewhat irrelevant here, I'm only concerned with CMake syntax at the moment. This is my CMake file so far:
cmake_minimum_required( VERSION 3.15 )
# Project's name
project( my_project )
# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/test/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set( CMAKE_VERBOSE_MAKEFILE on )
# Generate coverage on GCC.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(LDFLAGS "${LDFLAGS} -lgcov -fprofile-arcs")
endif()
# Includes and Sources
include_directories(${PROJECT_SOURCE_DIR}/inc)
file(GLOB APP_SRC "./src/*.c")
file(GLOB TEST_DEPENDS_SRC "./test/src/*.c")
# Add executable to list.
add_executable( ${PROJECT_NAME}_Test ${APP_SRC} ${TEST_DEPENDS_SRC} )
This generates my *.gcno and *.gcda files in the directory /test/build/gcc/CMakeFiles/my_project.dir/*, but for ease of post-processing, I think I want these files placed alongside their source. Is that possible? If so, how? Is that best practice? I'm still pretty green when it comes to CMake.
Related
I am new to Cmake and I am trying to create a CMakeLists.txt to build my project. I can build my project from command line using g++ compiler but when it comes to Cmake I am confused.
The directory structure is like this :
Project_folder
|--> Source
|--> main.cpp
|--> file1.cpp
|--> file2.cpp
|--> Header
|--> header1.h
|--> header2.h
|--> build (from where I run cmake .. and make)
CMakeLists.txt (this is under Project_folder)
Dependencies
|--> utils
|--> Utils.cpp
|--> include (has many folders in here)
|--> build (this path is in LD_LIBRARY_PATH as well)
|--> sharedlib1.so
|--> sharedlib2.so
Now from within the Project_Folder I can successfully run :
g++ ./Source/main.cpp ./Source/file1.cpp ./Source/file2.cpp ../Dependencies/utils/Utils.cpp -I ../Dependencies -I ../Dependencies/include/ -I ./Header/ -L ../Dependencies/build -std=c++11 -lsharedlib1 -lsharedlib2 -o ./build/main `pkg-config opencv --cflags --libs`
and generate the executable file.
Now I want to configure a CMakeLists.txt and try to replicate what the above compiler line is doing but with no success (I can cmake .., but I cannot make). CMakeLists.txt looks like this :
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
project(my_project)
#For the shared library:
set ( PROJECT_LINK_LIBS sharedlib1.so sharedlib2.so)
link_directories(${PROJECT_SOURCE_DIR}/../Dependencies/build/ )
include_directories(${PROJECT_SOURCE_DIR}/../Dependencies ${PROJECT_SOURCE_DIR}/../Dependencies/include ${PROJECT_SOURCE_DIR}/Header)
file(GLOB SOURCES "Source/*.cpp" )
set(CMAKE_CXX_FLAGS_RELEASE pkg-config opencv cflags libs)
## add_executable(name_of_output.o list_of_cpp_files)
add_executable(build ${SOURCES})
Running make after generating the makefile I get undefined reference to everything inside main.cpp. Is there anything obvious in the CMakeLists.txt that I should change?
Your call to g++ includes the ../Dependencies/utils/Utils.cpp file, but your call to add_executable is only using the files matched by Source/*.cpp. A quick solution would be to add ../Dependencies/Utils.cpp to the call to add_executable() making it
add_executable(build ${SOURCES} "${PROJECT_SOURCE_DIR}/../Dependencies/Utils.cpp")
On a related note: CMake discourages using file(GLOB ...) to get a list of source files, it's generally better to list the source files explicitly
You should use target_link_libraries after add_executable.
Please check the examples:
Executable with Static Library
Executable with Shared Library
While running the application you will also get some errors. Please be aware of RPATH.
Ok I managed to solve it ! :)
# set Cmake minimum version to use
cmake_minimum_required(VERSION 2.8.9)
# set the compiler
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# name your project
project(my_project)
set(CMAKE_BUILD_TYPE Release)
# Find and load the settings from the packages
find_package(PkgConfig REQUIRED)
find_package(OpenCV REQUIRED )
# set the extra flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -cflags -libs")
# set the shared libraries name (where the libraries are libsharedlib1.so and libsharedlib2.so + opencv runtime libraries)
set(PROJECT_LINK_LIBS sharedlib1 sharedlib2) ${OpenCV_LIBS}
# include the header files (.h)
include_directories(${PROJECT_SOURCE_DIR}/../Dependencies ${PROJECT_SOURCE_DIR}/../Dependencies/include ${PROJECT_SOURCE_DIR}/Header)
# add the source files (.cpp) using the set command as follow
set(SOURCES
Source/main.cpp
Source/file1.cpp
Source/file2.cpp
${PROJECT_SOURCE_DIR}/../Dependencies/utils/Utils.cpp)
# link the shared libraries (/build/libsharedlib1.so and /build/libsharedlib2.so)
link_directories(${PROJECT_SOURCE_DIR}/../Dependencies/build/)
# add_executable(name_of_output list_of_cpp_files)
add_executable(main ${SOURCES})
# link the executable with the shared libraries
target_link_libraries(main ${PROJECT_LINK_LIBS} )
and finally ./main will run the program !
I have a very simple CMake script. Unfortunately, the project uses a *.pde file which is plain C++ or C code.
CMake is working with any file ending, but I get a compiler error, because GCC does not know how to handle it. How can I add a global file extension to GCC, so that the *.pde file is compiled as a usual *.cpp file?
The -x c++ foo.pde command is nice if I want to use the console, but for CMake it is (I think) not applicable.
cmake_minimum_required(VERSION 2.8)
project(RPiCopter)
SET( RPiCopter
absdevice
containers
device
exceptions
navigation
frame
vehicle
receiver
scheduler
tinycopter.pde
)
message( STATUS "Include ArduPilot library directories" )
foreach( DIR ${AP_List} ${AP_List_Linux} ${AP_Headers} )
include_directories( "../libraries/${DIR}" )
endforeach()
include_directories( zserge-jsmn )
# ***************************************
# Build the firmware
# ***************************************
add_subdirectory ( zserge-jsmn )
#set(CMAKE_CXX_FLAGS "-x c++ *.pde")
ADD_EXECUTABLE ( RPiCopter ${RPiCopter} )
target_link_libraries ( RPiCopter -Wl,--start-group ${AP_List} ${AP_List_Linux} jsmn -Wl,--end-group )
You should be able to use set_source_files_properties along with the LANGUAGE property to mark the file(s) as C++ sources:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
As #steveire pointed out in his own answer, this bug will require something like the following workaround:
set_source_files_properties(${TheFiles} PROPERTIES LANGUAGE CXX)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_definitions("-x c++")
endif()
Normally you should be able to just extend CMAKE_CXX_SOURCE_FILE_EXTENSIONS. This would help, if you have a lot of files with unknown file extensions.
But this variable is not cached - as e.g. CMAKE_CXX_FLAGS is - so the following code in CMakeCXXCompiler.cmake.in will always overwrite/hide whatever you will set:
set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
I consider this non-caching being a bug in CMake, but until this is going to be changed I searched for a workaround considering the following:
You normally don't want to change files in your CMake's installation
It won't have any effect if you change CMAKE_CXX_SOURCE_FILE_EXTENSIONS after project()/enable_language() (as discussed here).
I have successfully tested the following using one of the "hooks"/configuration variables inside CMakeCXXCompiler.cmake.in:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_SYSROOT_FLAG_CODE "list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS pde)")
project(RPiCopter CXX)
message("CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS}")
add_executable(RPiCopter tinycopter.pde)
I decided to use this approach. I just remove the file ending by cmake in the temporary build directory.
So GCC is not confused anymore because of the strange Arduino *.pde file extension.
# Exchange the file ending of the Arduino project file
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tinycopter.pde ${CMAKE_CURRENT_BINARY_DIR}/tinycopter.cpp)
CMake doesn't do this for you:
http://public.kitware.com/Bug/view.php?id=14516
I have an existing project (wvdial) that has a working makefile. I'm trying to integrate it into our main build process which uses CMake. Can anyone advise on how to do this? I made an attempt below based on some of the other projects we build but the makefile is never called. All I want to do is call the makefile for wvdial and include the binary in the .deb package we build.
cmake_minimum_required(VERSION 2.6)
SET(COMPONENT_NAME roots-vendor-wvdial)
SET(DEBIAN_PACKAGE_VERSION 1.6.1)
SET(WVDIAL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
SET(WVDIAL_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
SET(WVDIAL_INSTALLED ${CMAKE_CURRENT_BINARY_DIR})
ADD_CUSTOM_TARGET(
wvdial ALL
DEPENDS ${WVDIAL_INSTALLED}
)
IF (${ROOTS_TARGET_ARCHITECTURE} STREQUAL "armhf")
SET(TARGET_FLAG "--host=arm-linux-gnueabihf")
ENDIF()
ADD_CUSTOM_COMMAND(
WORKING_DIRECTORY ${WVDIAL_BINARY_DIR}
OUTPUT ${WVDIAL_INSTALLED}
COMMAND env CXXFLAGS=${ROOTS_COMPILER_FLAGS} ./configure ${TARGET_FLAG} ${ROOTS_HOST_OPTION}
COMMAND make
COMMENT "Building wvdial"
VERBATIM
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/wvdial
DESTINATION usr/local/bin
COMPONENT ${COMPONENT_NAME}
PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
)
DEFINE_DEBIAN_PACKAGE(
NAME ${COMPONENT_NAME}
CONTROL_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/debian/control
CHANGELOG_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog
)
Take a look at the ExternalProject module.
This will add a dummy target to your CMake project that is responsible for building the dependency. The command is quite complex and supports a lot of stuff that you probably won't need in your case. Kitware (the company behind CMake) did a nice post called Building External Projects with CMake 2.8 a while back explaining the basic use of that command.
I want to build the package uci for ubuntu.
I download the source package and I found into the C files, header files and CMakeLists.txt
How to build the uci project with cmake?
CMakeLists.txt:
cmake_minimum_required(VERSION 2.6)
PROJECT(uci C)
SET(CMAKE_INSTALL_PREFIX /usr)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -g3 -I. -DUCI_PREFIX="${CMAKE_INSTALL_PREFIX}")
OPTION(UCI_PLUGIN_SUPPORT "plugin support" ON)
OPTION(UCI_DEBUG "debugging support" OFF)
OPTION(UCI_DEBUG_TYPECAST "typecast debugging support" OFF)
OPTION(BUILD_LUA "build Lua plugin" ON)
CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/uci_config.h.in ${CMAKE_SOURCE_DIR}/uci_config.h )
SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c)
ADD_LIBRARY(uci-shared SHARED ${LIB_SOURCES})
SET_TARGET_PROPERTIES(uci-shared PROPERTIES OUTPUT_NAME uci)
TARGET_LINK_LIBRARIES(uci-shared dl)
ADD_LIBRARY(uci-static STATIC ${LIB_SOURCES})
SET_TARGET_PROPERTIES(uci-static PROPERTIES OUTPUT_NAME uci)
ADD_EXECUTABLE(cli cli.c)
SET_TARGET_PROPERTIES(cli PROPERTIES OUTPUT_NAME uci)
TARGET_LINK_LIBRARIES(cli uci-shared dl)
ADD_EXECUTABLE(cli-static cli.c)
SET_TARGET_PROPERTIES(cli-static PROPERTIES OUTPUT_NAME uci-static)
TARGET_LINK_LIBRARIES(cli-static uci-static dl)
ADD_LIBRARY(ucimap STATIC ucimap.c)
ADD_EXECUTABLE(ucimap-example ucimap-example.c)
TARGET_LINK_LIBRARIES(ucimap-example uci-static ucimap dl)
ADD_SUBDIRECTORY(lua)
INSTALL(FILES uci.h uci_config.h ucimap.h
DESTINATION include
)
INSTALL(TARGETS uci-shared uci-static cli cli-static
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
I don't know about this particular case, but the generic mode of operation with CMake is as follows. Let's assume you unpacked the package sources so that the CMakeList is located at /some/path/to/source/CMakeLists.txt. Then:
> cd /path/where/you/want/to/build
> mkdir package_name
> cd package_name
> cmake /some/path/to/source
Next, an optional step to launch (console) GUI to edit options, if necessary:
> ccmake
After you're happy with the setup:
> make
> make install
CMake also has a non-console GUI, but I've never used it on Unix, so I can't comment there. The basic idea would be the same, though: set up a build directory, point the GUI to the source directory (the one containing CMakeLists.txt), configure, modify uptions and reconfigure as necessary, generate Makefiles, exit GUI and run make.
I know there is something like find_package(Threads) but it doesn't seem to make a difference (at least by itself). For now I'm using SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread"), but it doesn't look like a correct solution to me.
The Threads module in the latest versions (>= 3.1) of CMake generates the Threads::Threads imported target. Linking your target against Threads::Threads adds all the necessary compilation and linking flags. It can be done like this:
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
add_executable(test test.cpp)
target_link_libraries(test Threads::Threads)
Use of the imported target is highly recommended for new code, according to the CMake docs
find_package( Threads ) calls a CMake module that first, searches the file system for the appropriate threads package for this platform, and then sets the CMAKE_THREAD_LIBS_INIT variable (and some other variables as well). It does not tell CMake to link any executables against whatever threads library it finds. You tell CMake to link you executable against the "Threads" library with the target_link_libraries() command. So, for example lets say your program is called test. To link it against threads you need to:
find_package( Threads )
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )
How about the following:
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
find_package(Threads REQUIRED)
if(CMAKE_USE_PTHREADS_INIT)
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-pthread")
elseif(...)
...
endif()
add_executable( test test.cpp )
target_link_libraries( test ${CMAKE_THREAD_LIBS_INIT} )
If I explicitly specify the default entry point and the library to use, it compiles without problems. The default entry point here is to specify the version in cmake.
cmake_minimum_required(...), target_link_libraries(...)
Below is an example.
# important
cmake_minimum_required(VERSION 2.8)
project(main)
# set c++ version & etc...
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# important
find_package( Threads )
add_executable(main main.cpp)
# important
target_link_libraries(main ${CMAKE_THREAD_LIBS_INIT})