CMakeLists: Adding source files from Github with ExternalProject - c++

I'm writing a small catkin wrapper for the Beckhoff ADS library. I would like to install the files from the AdsLib folder but without using the CMake file from Beckhoff.
I just want to copy the files in order to add them to my library in my own CMakeLists. This works fine if I copy the files manually. But I would like to build directly using the latest files from the Github source.
I tried every possible combination I could find here on stackoverflow, but somehow couldn't make it work.
cmake_minimum_required(VERSION 2.8.3)
project(ads_catkin)
find_package(catkin_simple REQUIRED)
catkin_simple()
include(ExternalProject)
ExternalProject_Add(ads
PREFIX ${CMAKE_BINARY_DIR}/ads
GIT_REPOSITORY https://github.com/Beckhoff/ADS.git
GIT_TAG master
CONFIGURE_COMMAND ""
#GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e
UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(ads source_dir)
cs_add_library(${PROJECT_NAME}
${source_dir}/AdsLib/AdsDef.cpp
)
cs_install()
cs_export()
The first time I'm building with catkin_tools, this gives me:
Errors << ads_catkin:cmake /home/xxx/xxx_ws/logs/ads_catkin/build.cmake.000.log
CMake Error at /home/xxx/xxx_ws/devel/share/catkin_simple/cmake/catkin_simple-extras.cmake:150 (add_library):
Cannot find source file:
/home/xxx/xxx/build/ads_catkin/ads/src/ads/AdsLib/AdsDef.cpp
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
Call Stack (most recent call first):
CMakeLists.txt:23 (cs_add_library)
CMake Error: CMake can not determine linker language for target: ads_catkin
CMake Error: Cannot determine link language for target "ads_catkin".
Then, the second time I run the build tool over the same code, the files get actually cloned, but I end up with this error:
Errors << ads_catkin:make /home/xxx/xxx_ws/logs/ads_catkin/build.make.000.log
make[2]: *** No rule to make target 'CMakeFiles/ads_catkin.dir/build'. Stop.
make[1]: *** [CMakeFiles/ads_catkin.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
Cloning into 'ads'...
Already on 'master'
make: *** [all] Error 2
Btw: cs_add_library is the catkin_simple form for add_library and target_link_libraries.
Update:
Getting closer... adapting the solution from #Tsyvarev to my file:
cmake_minimum_required(VERSION 2.8.3)
project(ads_catkin)
find_package(catkin_simple REQUIRED)
catkin_simple()
include(ExternalProject)
ExternalProject_Add(ads
PREFIX ${CATKIN_DEVEL_PREFIX}/ads
GIT_REPOSITORY https://github.com/Beckhoff/ADS.git
GIT_TAG 6b3a03009a757cf651fe44d8be7b6df698028f0e
#GIT_TAG master
CONFIGURE_COMMAND ""
UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
BUILD_BYPRODUCTS
<SOURCE_DIR>/AdsLib/AdsDef.cpp
<SOURCE_DIR>/AdsLib/AdsLib.cpp
<SOURCE_DIR>/AdsLib/AmsConnection.cpp
<SOURCE_DIR>/AdsLib/AmsPort.cpp
<SOURCE_DIR>/AdsLib/AmsRouter.cpp
<SOURCE_DIR>/AdsLib/Frame.cpp
<SOURCE_DIR>/AdsLib/Log.cpp
<SOURCE_DIR>/AdsLib/NotificationDispatcher.cpp
<SOURCE_DIR>/AdsLib/Sockets.cpp
<SOURCE_DIR>/AdsLib/AdsDef.h
<SOURCE_DIR>/AdsLib/AdsLib.h
<SOURCE_DIR>/AdsLib/AdsNotification.h
<SOURCE_DIR>/AdsLib/AmsConnection.h
<SOURCE_DIR>/AdsLib/AmsHeader.h
<SOURCE_DIR>/AdsLib/AmsPort.h
<SOURCE_DIR>/AdsLib/AmsRouter.h
<SOURCE_DIR>/AdsLib/Frame.h
<SOURCE_DIR>/AdsLib/Log.h
<SOURCE_DIR>/AdsLib/NotificationDispatcher.h
<SOURCE_DIR>/AdsLib/RingBuffer.h
<SOURCE_DIR>/AdsLib/Router.h
<SOURCE_DIR>/AdsLib/Semaphore.h
<SOURCE_DIR>/AdsLib/Sockets.h
<SOURCE_DIR>/AdsLib/wrap_endian.h
<SOURCE_DIR>/AdsLib/wrap_socket.h
)
ExternalProject_Get_Property(ads SOURCE_DIR)
include_directories(
${SOURCE_DIR}/AdsLib
)
cs_add_library(AdsLib
${SOURCE_DIR}/AdsLib/AdsDef.cpp
${SOURCE_DIR}/AdsLib/AdsLib.cpp
${SOURCE_DIR}/AdsLib/AmsConnection.cpp
${SOURCE_DIR}/AdsLib/AmsPort.cpp
${SOURCE_DIR}/AdsLib/AmsRouter.cpp
${SOURCE_DIR}/AdsLib/Frame.cpp
${SOURCE_DIR}/AdsLib/Log.cpp
${SOURCE_DIR}/AdsLib/NotificationDispatcher.cpp
${SOURCE_DIR}/AdsLib/Sockets.cpp
)
add_dependencies(AdsLib ads)
cs_install()
install(DIRECTORY ${SOURCE_DIR}/AdsLib/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
PATTERN ".cpp" EXCLUDE
)
cs_export()
I tried to include the header files in my AdsLib library. But I still get an error:
In file included from /home/xxx/xxx_ws/src/xxx/nav_controller/src/controller.cpp:19:0:
/home/xxx/xxx_ws/src/xxx/nav_controller/include/nav_controller/controller.h:27:10: fatal error: AdsLib.h: No such file or directory
#include "AdsLib.h"
^~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/nav_controller.dir/src/controller.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from /home/xxx/xxx_ws/src/xxx/nav_controller/src/test.cpp:22:0:
/home/xxx/xxx_ws/src/xxx/nav_controller/include/nav_controller/controller.h:27:10: fatal error: AdsLib.h: No such file or directory
#include "AdsLib.h"
^~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/nav_controller.dir/src/test.cpp.o] Error 1
make[1]: *** [CMakeFiles/nav_controller.dir/all] Error 2
make: *** [all] Error 2

The CMake error Cannot find source file means a simple thing: Nothing tells CMake that given source file is generated and the file itself is absent.
Because the file is generated in ExternalProject_Add, you need to adjust corresponded target-level dependency:
add_dependency(ads_catkin ads)
This command should be issued after both add_library() and ExternalProject_Add calls which create corresponded targets. This command tells CMake that the library should be built only after all steps for the external project has been performed.
You still need to tell CMake that the source file is generated. There are two ways for doing this.
Set GENERATED property:
set_source_files_properties(${source_dir}/AdsLib/AdsDef.cpp PROPERTIES GENERATED TRUE)
This prevents CMake to search the file on the configuration stage.
List file in the BYPRODUCTS option for the target which generates it. For the target created by ExternalProject_Add command this is achieved by additional option to that command
BUILD_BYPRODUCTS <SOURCE_DIR>/AdsLib/AdsDef.cpp
This also sets GENERATED property for the source file, as in the first case. But BYPRODUCTS also makes your project usable for Ninja users.
(In the option above expression <SOURCE_DIR> is a special way to refer to ExternalProject's source directory. It is usable for some ExternalProject's options, and BUILD_BYPRODUCTS is one of them).
Technically, CMake should be smart enough for adding target-level dependencies (the effect of add_dependency(ads_catkin ads)) automatically when it sees corresponded BYPRODUCTS option. But this feature is described only for 3.16 version, and I don't know whether it works in older versions.

In the end, even with the good help from #Tsyvarev, I couldn't make it work using ExternalProject_Add. Part of the solution is to manually export the library with cs_export(INCLUDE_DIRS ${ads}), which didn't work with ExternalProject_Add, because the files were not available at this time.
In the end, I included the DownloadProject module, which is a predecessor of FetchContent, in my package. This does what it should.

Related

Why does gcc can't find opencv.hpp file?

I'm quite new to CMake, but I want to build a test .cpp file that includes OpenCV and shows me an image. I have built OpenCV in the path /usr/local and I have here folder with opencv.hpp file - /usr/local/include/opencv4/opencv2/opencv.hpp. Here is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0)
project(cpp_proj)
find_package(OpenCV REQUIRED)
add_executable(cpp_proj opencv_cpp.cpp)
include_directories(${OPENCV4_INCLUDES})
target_link_libraries(cpp_proj )
I opened ~./bashrc and added there lines:
export OPENCV4_INCLUDES=/usr/local/include/
export OPENCV4_LIBRARIES=/usr/local/lib/
export PATH=$PATH:$OPENCV4_LIBRARIES
export PATH=$PATH:$OPENCV4_INCLUDES
When I run cmake in bash - everything is ok and even find_package finds OpenCV. But when I'm trying to run make it gives me a error:
pi#raspberrypi:~/Desktop/cpp_proj/build $ cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/pi/Desktop/cpp_proj/build
pi#raspberrypi:~/Desktop/cpp_proj/build $ make
[ 50%] Building CXX object CMakeFiles/cpp_proj.dir/opencv_cpp.cpp.o
/home/pi/Desktop/cpp_proj/opencv_cpp.cpp:1:10: fatal error: opencv2/opencv.hpp: No such file or directory
#include <opencv2/opencv.hpp>
^~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/cpp_proj.dir/build.make:63: CMakeFiles/cpp_proj.dir/opencv_cpp.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/cpp_proj.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I found questions with the same problem, but they didn't help me. What I am doing wrong? What could be the reason of this? Thanks!
In order to use a library you must specify the include directory as well as the libs.
With find_package (in module mode), in your case it should populate the variables OpenCV_INCLUDE_DIRS and OpenCV_LIBS for you to use.
So I recommend to add / alter your code to add the include directory & link the library (such as below)
target_include_directories(${CMAKE_PROJECT_NAME} public ${OpenCV_INCLUDE_DIRS})
target_link_libraries(${CMAKE_PROJECT_NAME} public ${OpenCV_LIBS})
I don't believe you ever need to touch ~./bashrc when using find_package

CMake GoogleTests can't find header file imported in my test file

We (three students) are very new to CMake. For a university project we have to include GoogleTest into our codebase, and we are having a lot of trouble with it.
We have a gtest_ours.cmake file:
project("googletests")
enable_testing()
include(GoogleTest)
file(GLOB_RECURSE MY_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
# header don't need to be included but this might be necessary for some IDEs
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
EXCLUDE
"${CMAKE_CURRENT_SOURCE_DIR}/src/MolSim.cpp"
)
add_subdirectory(googletest)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
add_executable(ParticleContainerTest ${sources} ${CMAKE_CURRENT_SOURCE_DIR}/test/ParticleContainerTest.cpp )
target_link_libraries(ParticleContainerTest ${MY_SRC} gtest gtest_main gmock gmock_main)
gtest_discover_tests(ParticleContainerTest)
set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10)
set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20)
and from the CMakeLists.txt file, we just call:
include(gtest_ours)
Our folder structure is:
main
- src
- test
- CMakeLists.txt
- others
Please help, we get the following error:
/home/lunaticcoding/psemoldyn_groupc/MolSim-master/test/ParticleContainerTest.cpp:9:10: fatal error: ../src/ParticleContainer.h: No such file or directory
#include "../src/ParticleContainer.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
CMakeFiles/ParticleContainerTest.dir/build.make:62: recipe for target 'CMakeFiles/ParticleContainerTest.dir/test/ParticleContainerTest.cpp.o' failed
make[2]: *** [CMakeFiles/ParticleContainerTest.dir/test/ParticleContainerTest.cpp.o] Error 1
CMakeFiles/Makefile2:144: recipe for target 'CMakeFiles/ParticleContainerTest.dir/all' failed
make[1]: *** [CMakeFiles/ParticleContainerTest.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2
There are a couple issues with the gtest_ours.cmake file. Your error is raised because you haven't defined the include directories for your ParticleContainerTest target to include ParticleContainer.h. You've only added gtest_SOURCE_DIR directories as include directories. To correct this, consider adding this line after add_executable():
target_include_directories(ParticleContainerTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
This way, the src directory will be an include directory, so you can modify test/ParticleContainerTest.cpp to have a more reasonable #include:
#include "ParticleContainer.h"
Also, I'm not sure where you intend to use the ${MY_SRC} source files, but you don't want to include this in the target_link_libraries() call. This call should only include pre-defined targets, library names, or linking options as arguments; do not add a list of source files to this call. I'm also not sure where you defined the ${sources} argument in the add_executable() call, but perhaps, you meant to put ${MY_SRC} there instead.
Finally, the EXCLUDE qualifier does not work with the file(GLOB_RECURSE ...) signature. However, you can remove a specific file from the list afterward, using list(REMOVE_ITEM ...):
file(GLOB_RECURSE MY_SRC CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
# header don't need to be included but this might be necessary for some IDEs
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
)
list(REMOVE_ITEM MY_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/MolSim.cpp)

What is the correct way to include llvm library in CLion?

I recently installed LLVM 7, and tried to include the necessary files to start a project using llvm library in CLion.
However, it complains that some files are not found.
My CMakeLists.txt file has the following:
cmake_minimum_required(VERSION 3.12)
project(TestCmake)
set(CMAKE_CXX_STANDARD 11)
link_directories(llvm/build/include/) # linked wrongly..
include_directories(llvm/llvm/include/) #linked wrongly.
set(BUILD_2 main_2)
set(SOURCE_FILES_2
# testing. llvm files.
tests/codegen_tests/fac.cpp
)
add_executable(${BUILD_2} ${SOURCE_FILES_2})
I know the way am linking is wrong, but I don't know how to fix it.
I let it like this, because CLion can find the defined libraries (so I can see when I call functions of the libraries that don't exist, and if it's available I get a pop-up).
Am currently getting the following error when I run the project:
In file included from c4/llvm/llvm/include/llvm/IR/Module.h:23:0,
from c4/tests/codegen_tests/fac.cpp:1:
c4/llvm/llvm/include/llvm/IR/Attributes.h:74:38: fatal error: llvm/IR/Attributes.inc: No such file or directory
compilation terminated.
CMakeFiles/main_2.dir/build.make:62: recipe for target 'CMakeFiles/main_2.dir/tests/codegen_tests/fac.cpp.o' failed
make[3]: *** [CMakeFiles/main_2.dir/tests/codegen_tests/fac.cpp.o] Error 1
CMakeFiles/Makefile2:109: recipe for target 'CMakeFiles/main_2.dir/all' failed
make[2]: *** [CMakeFiles/main_2.dir/all] Error 2
CMakeFiles/Makefile2:121: recipe for target 'CMakeFiles/main_2.dir/rule' failed
make[1]: *** [CMakeFiles/main_2.dir/rule] Error 2
Makefile:153: recipe for target 'main_2' failed
make: *** [main_2] Error 2
The project structure is shown here
Any help on this, is greatly appreciated. Thanks.
I had a similar problem and the LLVM documentation: solved my issue.
cmake_minimum_required(VERSION 3.4.3)
project(TestCmake)
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Set your project compile flags.
# E.g. if using the C++ header files
# you will need to enable C++11 support
# for your compiler.
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
# Now build our tools
add_executable(simple-tool tool.cpp)
# Find the libraries that correspond to the LLVM components
# that we wish to use
llvm_map_components_to_libnames(llvm_libs support core irreader)
# Link against LLVM libraries
target_link_libraries(simple-tool ${llvm_libs})

Build a project depending on the Swiften XMPP library with CMake

I am currently trying to setup my C++ project using CMake, I successfully included dependencies like OpenMPI, but when going to Swiften, this became complex. This is not delivered in the form a package, but as shown in the git repository linked up there. Building that wasn't an issue, but I searched quite a lot of time, without finding any way to include libraries that don't provide a .so, and no main headers.
Here's my current CMakeLists.txt, made for testing only.
cmake_minimum_required (VERSION 3.0.0)
#set the executable
project (mtest)
set(EXECUTABLE_OUTPUT_PATH .)
add_executable (mtest main.cpp)
#defines libs
find_package(MPI REQUIRED)
set(CMAKE_CXX_COMPILE_FLAGS ${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS})
set(CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS})
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
include_directories(SYSTEM Swiften)
target_link_libraries(mtest ${MPI_LIBRARIES})
add_library(swiften SHARED IMPORTED)
set_target_properties(swiften PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/Swiften/libSwiften.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/Swiften"
)
target_link_libraries(mtest swiften)
And when trying to run make, here's the error :
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/Documents/CTests/build
[ 50%] Building CXX object CMakeFiles/mtest.dir/main.cpp.o
/home/user/Documents/CTests/main.cpp:12:10: fatal error: Swiften/Client/Client.h: No such file or directory
#include <Swiften/Client/Client.h>
^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
CMakeFiles/mtest.dir/build.make:62: recipe for target 'CMakeFiles/mtest.dir/main.cpp.o' failed
make[2]: *** [CMakeFiles/mtest.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/mtest.dir/all' failed
make[1]: *** [CMakeFiles/mtest.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
By the way, if the directory structure may help you, here's a tree output : https://pastebin.com/giPb9229

CMAKE and MKOCTFILE

I'm working on a C/C++ project and I'm using CMAKE 3.5.2 for build. However, now I must to include a C++ file which uses Octave functions. I am able to compile this source file directly by line command using this command: mkoctfile --link-stand-alone new_oct_file -o final_library.
I'm struggling to do CMAKE execute this command. I've tried to use an add_custom_command, but it didn't work. Can someome help me?
My CMAKE has the following structure
cmake_minimum_required(VERSION 2.8)
project(final_library)
add_executable(final_library program.c
./Commons/util.c
./Tools/xulambs_tool.cpp)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
include_directories(/usr/include/octave-4.0.0/octave)
install(TARGETS final-library RUNTIME DESTINATION bin)
add_subdirectory(Commons)
add_subdirectory(Tools)
I've tried to add the following command (it does not work):
set(MKOCTFILE "mkoctfile")
set(OCTARG "--link-stand-alone")
add_custom_command(TARGET reordering-library
PRE_LINK
COMMAND ${MKOCTFILE} ARGS ${OCTARG} ./Tools/tool_octave.cpp)
The compilation output is
[ 4%] Linking CXX executable final-library
g++: error: ./Tools/tool_octave.cpp: No such file or directory
g++: fatal error: no input files
compilation terminated.
CMakeFiles/final-library.dir/build.make:694: recipe for target 'final-library' failed
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/final-library.dir/all' failed
Makefile:127: recipe for target 'all' failed
make[2]: *** [final-library] Error 1
make[1]: *** [CMakeFiles/final-library.dir/all] Error 2
make: *** [all] Error 2
Thanks.
I had the same problem as you and I fixed it by adding the liboctinterp.so in the target_link_libraries of the CMakeLists.txt file.
My current cmake file contains the following:
add_executable(MyEXE main.cc)
target_link_libraries(MyEXE liboctave.so liboctinterp.so)
The command at pre link is probably not executed in the source directory, so the relative path you used in the script will be invalid. Try using an absolute path, something like:
add_custom_command(TARGET reordering-library
PRE_LINK
COMMAND ${MKOCTFILE} ARGS ${OCTARG}
"${CMAKE_CURRENT_SOURCE_DIR}/Tools/tool_octave.cpp"
)