I am trying to set up a learning project using Catch2 and I decided that it was
best to clone the repository in a Cpp folder, so I could get updates and use it
for other C++ projects. The installing method is as described here.
The basic folder structure is:
Cpp
├───TestProject
│ ├───main.cpp
│ ├───.vscode
│ └───build
│ ├───CMakeFiles
│ └───Testing
└───Catch2
├─── ...
...
As per Catch2 documentation I put this on my CMake file:
find_package(Catch2 REQUIRED)
target_link_libraries(tests Catch2::Catch2)
However, when I try to configure the project in VS Code, I get the following error message:
[cmake] CMake Error at CMakeLists.txt:5 (target_link_libraries):
[cmake] Cannot specify link libraries for target "tests" which is not built by this
[cmake] project.
main.cpp is just a Hello World file and the complete CMakeLists.txt file contents are:
cmake_minimum_required(VERSION 3.0.0)
project(TestProject VERSION 0.1.0)
find_package(Catch2 REQUIRED)
target_link_libraries(tests Catch2::Catch2)
enable_testing()
add_library(TestProject TestProject.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
I am unsure why this happens. I am a complete newcomer to CMake, save for very
basic commands I had to use at work. I guess it would be less work to just drop
it as a header file like it's intended to, but this approach made more sense to
me...
Note: I have read this SO question. However his question had to do with
Catch2 as a header file inside the project.
Note 2: desired behaviour is to build the project using Catch2 as an external
library.
(Additional information: CMake --version is 3.13.3, using CMakeTools in VS Code,
OS is Windows 10)
First, since the library has been installed through CMake (same applies for installs using a package manager), it is recommended to flag find_package with CONFIG (read about Config mode here).
This is because even if Catch2 repository is in a parent, common folder to the project, the CMake installation process installs it in your Program Files folder (in Windows); i.e. the repository is just that.
Additionally you should add_executable(tests main.cpp) so CMake has "tests" as a target.
This solves the original problem.
However, for it to completely work, you need to follow these additional steps:
Use catch_discover_tests(tests)
include(CTest) possibly necessary.
The include preprocessor command should be: #include <catch2/catch.hpp> instead of simply #include "catch.hpp".
Also, make sure your editor is aware of the environmental variables created
during the installation of Catch2. That is, if you are having problems, restart
the editor so it re-reads environmental variables.
Full CMakeLists.txt:
cmake_minimum_required(VERSION 3.5.0)
project(TestProject LANGUAGES CXX VERSION 0.1.0)
find_package(Catch2 REQUIRED)
add_executable(tests main.cpp) # solution to the original problem
target_link_libraries(tests Catch2::Catch2)
include(CTest) # not sure if this is 100% necessary
include(Catch)
catch_discover_tests(tests)
enable_testing()
Note: Instead of add_executable, we should use add_library, although no
tests are recognized in library mode for some reason; however that is beyond the
scope of this question as it lies more in the knowledge of use pf Catch2.
Related
I recently installed vcpkg on my windows system and the cmake (and cmake tools) extension for vscode, because I wanted to use a json file for my c++ project. I had put vcpkg in a random location just to mess around with it and learn how it works. However, when I moved it to another location as its final spot, CMake got confused and couldn't find lib files for jsoncpp.
Here's the error:
Unable to open 'json_value.cpp': Unable to read file 'c:\path\to\old\location\vcpkg\buildtrees\jsoncpp\src\3918c327b1-034a82149a.clean\src\lib_json\json_value.cpp' (Error: Unable to resolve non-existing file 'c:\path\to\old\location\vcpkg\buildtrees\jsoncpp\src\3918c327b1-034a82149a.clean\src\lib_json\json_value.cpp').
I had moved vcpkg from C:\path\to\old\location\vcpkg to C:\vcpkg
And here's my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.0.0)
project(myProgram VERSION 0.1.0)
include(CTest)
enable_testing()
add_executable(myProgram main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
set(CMAKE_BUILD_TYPE debug)
# set_target_properties(${PROJECT_NAME}
# PROPERTIES
# RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR})
include(CPack)
include_directories(C:/vcpkg/installed/x64-windows/include)
link_directories(C:/vcpkg/installed/x64-windows/lib)
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp_lib jsoncpp_object)
I have already tried updating the CMAKE_TOOLCHAIN_FILE property in settings.json, deleting cmake's cache, resetting the extension, and reinstalling jsoncpp, vcpkg and the cmake extensions fresh (I had made sure that their files were deleted).
I had to take out the find package function. The find package function made cmake expect the source code to be in the buildtrees folder, which in this case isn't (I think it was at some point, but I don't know why it wont come back). Just by using target_link_libraries(${PROJECT_NAME} jsoncpp), as well as the include/link directories statements gave cmake everything it needed to include the library. One thing I still don't understand however is why cmake was looking in the old location for that bit of source code.
I'm trying to use Caffe in my C++ project which I compile with CMakeLists.txt, but it doesn't want to work. My only line in the code is
#include <caffe/caffe.hpp>
I compiled Caffe myself, it is installed in the directory "/home/tamas/caffe". My CMakeLists.txt looks like this so far:
cmake_minimum_required (VERSION 3.5)
include(FindPkgConfig)
project (main)
set (CMAKE_CXX_STANDARD 11)
set (CMAKE_CXX_STANDARD_REQUIRED TRUE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++11 -pthread")
set (source_dir "${PROJECT_SOURCE_DIR}/src/")
set (OpenCV_DIR "/home/tamas/opencv/include/opencv2")
set (Caffe_DIR "/home/tamas/caffe")
file (GLOB source_files "${source_dir}/ssd_video.cpp")
find_package(OpenCV 4.4.0 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
find_package(Caffe REQUIRED)
include_directories(${Caffe_INCLUDE_DIRS})
add_executable (main ${source_files})
target_link_libraries(main ${OpenCV_LIBS})
target_link_libraries(main ${Caffe_LIBRARIES})
The error is the following:
CMake Error at CMakeLists.txt:24 (find_package):
By not providing "FindCaffe.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Caffe", but
CMake did not find one.
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake
Add the installation prefix of "Caffe" to CMAKE_PREFIX_PATH or set
"Caffe_DIR" to a directory containing one of the above files. If "Caffe"
provides a separate development package or SDK, be sure it has been
installed.
-- Configuring incomplete, errors occurred!
The problem is that I have searched and I don't have a FindCaffe.cmake file on my computer. I found an example for CaffeConfig.cmake, but I tried it and it doesn't work either.
Is there a way I can link Caffe with my C++ project? Thanks!
To fix this issue you may do the following:
Download this FindCAFFE.cmake file
Create cmake dir in your repo root directory and put the downloaded file there.
Modify your CMake file:
add set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
change set (Caffe_DIR "/home/tamas/caffe") to set (CAFFE_ROOT_DIR "/home/tamas/caffe")
change find_package(Caffe REQUIRED) to find_package(CAFFE REQUIRED)
use CAFFE_INCLUDE_DIRS and CAFFE_LIBRARIES for include directories and link libraries respectively
Clean up your build dir and run cmake command again
<library>_DIR should not be set manually in CMake code usually. There are better alternatives that should be used as setting these variable won't necessarily do what you want. It won't change where find_package finds its libraries.
The CaffeConfig.cmake file is generated when building Caffe. You should never download another one, these files are compatible only with a specific build configuration.
The Caffe library supports to be used with CMake, so FindCaffe.cmake is unnecessary.
For find_package to work, either set the <package>_ROOT variable (require CMake 3.12 minimum) or you must append the install path in CMAKE_PREFIX_PATH. Here's a CMake example that uses the prefix path:
# If you only built the library
list (APPEND CMAKE_PREFIX_PATH "/home/tamas/caffe/build-dir")
# If you installed the library there
list (APPEND CMAKE_PREFIX_PATH "/home/tamas/caffe/")
find_package(Caffe REQUIRED)
Note that the Caffe_LIBRARIES and Caffe_INCLUDE_DIRS won't be set. This is old CMake style and the Caffe library uses the new style. This is what you should do:
target_link_libraries(main PUBLIC caffe caffeproto)
This line add both include directory and adds linking to the libraries too.
I have the following simple CMake project. It's basically an executable which links dynamically to Qt Widgets (I'm using Qt just as an example). What I'm trying to figure out is whether it is possible to copy all the linked libraries (not only the ones built by the current project) to the executable output directory using CMake.
cmake_minimum_required(VERSION 3.12)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
set(QT_CMAKE_DIR "/Users/huser/Qt/5.11.1/clang_64/lib/cmake")
set(CMAKE_PREFIX_PATH ${CMAKE_MODULE_PATH} ${QT_CMAKE_DIR})
find_package(Qt5 REQUIRED COMPONENTS Widgets)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_LIST_DIR}/build)
The issue is that the output directory only contains the MyProject executable (which is the expected behaviour). However, if I were to distribute that executable to someone who doesn't have Qt installed, they would not be able to open it. Hence, I would like to bundle only the necessary libraries/ frameworks with the executable.
Running otool -L MyProject lists the dependencies:
MyProject:
#rpath/QtWidgets.framework/Versions/5/QtWidgets
#rpath/QtGui.framework/Versions/5/QtGui
#rpath/QtCore.framework/Versions/5/QtCore
/usr/lib/libc++.1.dylib
/usr/lib/libSystem.B.dylib
What I'm looking for is a common way through CMake to get these 3 frameworks copied in the output directory right after the build step. That would result in the following directory structure:
build/
MyProject
QtWidgets.framework
QtGui.framework
QtCore.framework
Any help would be greatly appreciated!
There are two aspects to consider:
the build tree
the install tree
The build tree is what you work with as a developer, the install tree is what is "created" after executing the install target or after extracting the content of a package.
To redistribute your Qt5 based project, I suggest you leverage two tools:
CPack: This allow to create generate packages or archives that can be distributed to users. These includes windows installers, .tar,gz, .dmg, ...
macdeployqt: Tools provided by Qt allowing to copy all libraries, plugins, ... required by your application.
Using the BundleUtilities would still require you to explicitly identify and install all Qt plugins. For more complex application, with dependencies other than Qt, is is indeed helpful but for a simple application, I would suggest to use the approach described below.
You will find below a modified version of your example including some suggestions regarding the best practices as well as the integration of CPack and macdeployqt.
After configuring and building project, building the Package target will create a MyProject-0.1.1-Darwin.dmg package.
Note that more would need to be done but that should give a good starting point.
Reading the following may also be helpful: https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling
To configure the project, consider passing the variable -DQt5_DIR:PATH=/path/to/lib/cmake/Qt5 instead of hardcoding the path.
Assuming the sources or the project are in a directory named src, you would configure the project with:
mkdir build
cd build
cmake -DQt5_DIR:PATH=/Volumes/Dashboards/Support/Qt5.9.1/5.9.1/clang_64/lib/cmake/Qt5 ../src/
src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(MyProject)
set(CMAKE_CXX_STANDARD 14)
# Suggestions:
# (1) EXECUTABLE_OUTPUT_PATH is deprecated, consider
# setting the CMAKE_*_OUTPUT_DIRECTORY variables
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_MACOSX_BUNDLE 1)
set(CMAKE_INSTALL_RPATH "#executable_path/../Frameworks")
# Suggestions:
# (1) Do not hardcode path to Qt installation
# (2) Configure the project specifying -DQt5_DIR
# See https://blog.kitware.com/cmake-finding-qt5-the-right-way/
# (3) By convention, "REQUIRED" is added at the end
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Widgets)
install(TARGETS ${PROJECT_NAME} DESTINATION . COMPONENT Runtime)
# Get reference to deployqt
get_target_property(uic_location Qt5::uic IMPORTED_LOCATION)
get_filename_component( _dir ${uic_location} DIRECTORY)
set(deployqt "${_dir}/macdeployqt")
if(NOT EXISTS ${deployqt})
message(FATAL_ERROR "Failed to locate deployqt executable: [${deployqt}]")
endif()
# Execute deployqt during package creation
# See https://doc.qt.io/qt-5/osx-deployment.html#macdeploy
install(CODE "set(deployqt \"${deployqt}\")" COMPONENT Runtime)
install(CODE [===[
execute_process(COMMAND "${deployqt}" "${CMAKE_INSTALL_PREFIX}/MyProject.app")
]===] COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop")
include(CPack)
I'm trying to set up a really basic project with Cmake and OpenCV 3.0.
My folder structure looks like this:
OpenCVTest
|
|--- build
|--- data
|--- include
|--- src
|--- CMakeLists.txt
The CMakeLists.txt file has the following content:
cmake_minimum_required(VERSION 3.4)
project(OpenCVTest)
find_package(OpenCV REQUIRED)
include_directories(
${CMAKE_SOURCE_DIR}/include
${OpenCV_INCLUDE_DIRS})
set(SOURCES
src/main.cpp
src/MyData.cpp
include/MyData.h)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
I extracted OpenCV, set the environment variable OPENCV_DIR = <PATH_TO_OPEN_CV>\opencv\build\x86\vc12, and added %OPENCV_DIR%\bin to the PATH variable in Windows, as suggested by the OpenCV + CMake tutorial.
When running CMake, the following error message occurs:
CMake Error at CMakeLists.txt:4 (find_package):
By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has asked
CMake to find a package configuration file provided by "OpenCV", but CMake did
not find one.
Could not find a package configuration file provided by "OpenCV" with any
of the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set
"OpenCV_DIR" to a directory containing one of the above files. If "OpenCV"
provides a separate development package or SDK, be sure it has been
installed
I therefore changed the value of the environment variable OpenCV_DIR = <PATH_TO_OPEN_CV>\opencv\build, where the OpenCVConfig.cmake file is located.
After doing so (and restarting to Windows to update the environment variables!!!), CMake is able to configure and generate the project successfully.
However, CMake uses static library linking...
OpenCV STATIC: ON
Found OpenCV 3.0.0 in <PATH_TO_CMAKE>/opencv/build/x86/vc12/staticlib
... and you have to switch the Runtime Library in Visual Studio (C/C++ --> Code Generation --> Runtime Library) to /MTd.
Adding...
set(BUILD_SHARED_LIBS ON)
before
find_package(OpenCV REQUIRED)
will force CMake to use dynamic linking, however, then the PATH variable does not contain the correct path to the OpenCV DLL's, and <PATH_TO_OPEN_CV>\opencv\build\x86\vc12\bin needs to be added (for 32bit and VS2013).
All ob the above solutions seem quite inelegant and not really portable to me. I also tried several FindOpenCV.cmake files, however, none of them were able to correctly find the OpenCV directory.
My question is: Can anybody provide a solution for setting up a very basic CMake + OpenCV 3.0 example project, that does not have the above described shortcomings?
I'm trying to learn cmake and have started converting an old make project over to cmake. Here is a simplified version of the directory structure I now have:
CMakeLists.txt
src/
CMakeLists.txt
main.cpp
core/
CMakeLists.txt
/sourcecode, other cmakes, etc.
test/
CMakeLists.txt
someTest.cpp
Currently, in my root CMakeLists.txt file I simply have this:
cmake_minimum_required(VERSION 2.8)
project(all)
add_subdirectory(src)
add_subdirectory(test)
What I wanted to do, was have a library created by core/CMakeLists.txt that can be used by both src/CMakeLists.txt to build the main executable, but also loaded by test/CMakeLists to build the unit tests.
So my src/core/CMakeLists.txt file currently looks sort of like this:
cmake_minimum_required(VERSION 2.8)
project(core)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wpedantic -Wreorder -DBOOST_TEST_DYN_LINK -DBOOST_LOG_DYN_LINK ")
#some other directories in my core code:
add_subdirectory(display)
add_subdirectory(training)
add_subdirectory(utility)
#some packages I use...
find_package(Boost 1.55.0
COMPONENTS
log
program_options
serialization
thread
system
filesystem
REQUIRED)
find_package(GLUT REQUIRED)
find_package(OpenGL REQUIRED)
find_package(Eigen3 REQUIRED)
include_directories(
${PROJECT_SOURCE_DIR}
${EIGEN3_INCLUDE_DIR})
target_link_libraries(core
display
training
utility
${Boost_LIBRARIES}
${OPENGL_LIBRARIES}
${GLUT_LIBRARY}
${OpenMP_LIBRARIES})
So the idea is that I now have a core target I can simply link against to run my tests, and everything should work. However, when I try to build main, for example, I get:
Cannot specify link libraries for target "core" which is not built by this
project.
I thought this might be because core doesn't have a add_library command, but if I add add_library(core) I get this error:
You have called ADD_LIBRARY for library core without any source files. This typically indicates a problem with your CMakeLists.txt file
But I don't want to add any source files; I just want this target to link the targets in the core directory and produce a target I can link against from test.
Clearly I'm missing some core knowledge here, either with cmake or the toolchain itself. Help is appreciated :)
If you only want to create a core target without source files, you need to declare it like an INTERFACE target. So, try to add the following code to your src/core/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0) # REQUIRED 3.x.x version
project(core)
...
# Here declare your core_interface target
add_library(core_interface INTERFACE)
target_link_libraries(core_interface INTERFACE
display
training
utility
${Boost_LIBRARIES}
${OPENGL_LIBRARIES}
${GLUT_LIBRARY}
${OpenMP_LIBRARIES})
As you can see, if you make this, you'll need to upgrade your CMake installed version.
Then, you'll build your tests or any executable, linking with this interface target directly:
add_executable(main main.cpp)
target_link_libraries(main core_interface)