Creating and installing nested libraries using CMakeLists - c++

Installing nested libraries brings compilation errors.
I try to have a project called CROSP that contains multiple internal libraries, namely : StrainParameterisation, RodProperties, PolynomialRepresentation. These libraries are then linked to one base library : CROSP.
This one is the library that is then installed in my usr/local/...
The problem is that when I try to include the library from one external package, I get some errors saying that the compiler did not found the .so file for the internal libraries.
In the following I detail the topology of my project.
The layout of the project is the following:
.
├── cmake
│   ├── cmake_uninstall.cmake.in
│   ├── Config.cmake.in
│   └── installation_module.cmake
├── CMakeLists.txt
└── src
├── CMakeLists.txt
├── CROSP
│   └── cosserat_rod.cpp
├── include
│   └── CROSP
│   ├── CROSP
│   │   └── cosserat_rod.hpp
│   ├── polynomial_representation
│   │   └── polynomial_representation.hpp
│   ├── rod_properties
│   │   └── rod_properties.hpp
│   └── strain_parameterisation
│      └── strain_parameterisation.hpp
├── polynomial_representation
│   └── polynomial_representation.cpp
├── rod_properties
│   └── rod_properties.cpp
└── strain_parameterisation
   └── strain_parameterisation.cpp
The CMakeLists are :
Top level CMakeLists
cmake_minimum_required(VERSION 3.22 FATAL_ERROR)
project(CROSP LANGUAGES CXX VERSION 2.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(Eigen3 3.4 NO_MODULE REQUIRED)
# External utilities to configure the package
include(GNUInstallDirs)
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
# Give different names for debug and Release
set(CMAKE_RELEASE_POSTFIX "")
set(CMAKE_DEBUG_POSTFIX "-debug")
add_subdirectory(src)
# Install the library using the default routine
include(cmake/installation_module.cmake)
The installation_module.cmake
# Generates ${PROJECT_NAME}Config.cmake file to use our package in other projects
include(CMakePackageConfigHelpers)
configure_package_config_file(
cmake/Config.cmake.in # input template
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake # output config file
INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake # where to put the config file during install
PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR # paths to be used
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
# Generates a config file to ensure that URL's version is checked when importing it
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
# When running make install, config files should be copied as well
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake
)
# Add the possibility tu run 'make uninstall' to remove files added via 'make install'
configure_file(
cmake/cmake_uninstall.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
IMMEDIATE #ONLY
)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
The Config.cmake.in module :
#PACKAGE_INIT#
set(#PROJECT_NAME#_VERSION #PROJECT_VERSION#)
set_and_check(#PROJECT_NAME#_INCLUDE_DIRS #PACKAGE_INCLUDE_INSTALL_DIR#/#PROJECT_NAME#)
set_and_check(#PROJECT_NAME#_LIBRARY_DIR #PACKAGE_LIB_INSTALL_DIR#)
find_library(#PROJECT_NAME#_LIBRARIES NAMES #PROJECT_NAME# PATHS ${#PROJECT_NAME#_LIBRARY_DIR} NO_DEFAULT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(#PROJECT_NAME# DEFAULT_MSG #PROJECT_NAME#_INCLUDE_DIRS #PROJECT_NAME#_LIBRARIES)
Then We have the CMakeLists in src
include_directories(include)
add_library(PolynomialRepresentation SHARED
include/${PROJECT_NAME}/polynomial_representation/polynomial_representation.hpp
polynomial_representation/polynomial_representation.cpp
)
target_link_libraries(PolynomialRepresentation
PRIVATE
Eigen3::Eigen
)
target_compile_options(PolynomialRepresentation
PRIVATE
-Wall
-Wextra
)
add_library(RodProperties SHARED
include/${PROJECT_NAME}/rod_properties/rod_properties.hpp
rod_properties/rod_properties.cpp
)
target_link_libraries(RodProperties
PRIVATE
Eigen3::Eigen
PolynomialRepresentation
)
target_compile_options(RodProperties
PRIVATE
-Wall
-Wextra
)
add_library(StrainParameterisation SHARED
include/${PROJECT_NAME}/strain_parameterisation/strain_parameterisation.hpp
strain_parameterisation/strain_parameterisation.cpp
)
target_link_libraries(StrainParameterisation
PRIVATE
Eigen3::Eigen
PolynomialRepresentation
)
target_compile_options(RodProperties
PRIVATE
-Wall
-Wextra
)
add_library(${PROJECT_NAME} SHARED
include/${PROJECT_NAME}/${PROJECT_NAME}/cosserat_rod.hpp
${PROJECT_NAME}/cosserat_rod.cpp
)
target_link_libraries(${PROJECT_NAME}
PRIVATE
Eigen3::Eigen
PUBLIC
StrainParameterisation
RodProperties
PolynomialRepresentation
)
target_compile_options(RodProperties
PRIVATE
-Werror
-Wall
-Wextra
)
add_executable(main main.cpp)
target_link_libraries(main ${PROJECT_NAME} Eigen3::Eigen)
install(
TARGETS
${PROJECT_NAME}
DESTINATION
${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY include/${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
I can run and install this library.
The following code compiles and runs fine.
#include "CROSP/CROSP/cosserat_rod.hpp"
int main(int argc, char *argv[])
{
::CROSP::polynomial_representation::PolynomialRepresentation poly(5);
::CROSP::rod_properties::MaterialProperties material(200, 100, 10);
::CROSP::CosseratRod rod(poly, material);
::CROSP::CosseratRod rod2(15);
::CROSP::CosseratRod rod3;
return 0;
}
The installation in my usr folder has the following layout
usr
└── local
   ├── include
│   └── CROSP
│   ├── CROSP
│ │ └── cosserat_rod.hpp
│   ├── polynomial_representation
│ │ └── polynomial_representation.hpp
│   ├── rod_properties
│ │ └── rod_properties.hpp
│   └── strain_parameterisation
│ └── strain_parameterisation.hpp
   ├── lib
│   ├── libCROSP-debug.so
│   └── libCROSP.so
   └── share
   └── CROSP
   └── cmake
   ├── CROSPConfig.cmake
   └── CROSPConfigVersion.cmake
From another project, I can include the library without problem.
Here there is an example
cmake_minimum_required(VERSION 3.5)
project(test_crosp_library LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(CROSP REQUIRED)
find_package(Eigen3 3.4 NO_MODULE REQUIRED)
add_executable(test_crosp_library main.cpp)
target_link_libraries(test_crosp_library
PUBLIC
CROSP
Eigen3::Eigen
)
And the main.cpp looks like this
#include "CROSP/CROSP/cosserat_rod.hpp"
int main()
{
::CROSP::CosseratRod rod; // errors
return 0;
}
I get the following errors
[ 50%] Linking CXX executable test_crosp_library
/usr/bin/ld: warning: libStrainParameterisation.so, needed by /usr/local/lib/libCROSP.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libRodProperties.so, needed by /usr/local/lib/libCROSP.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: /usr/local/lib/libCROSP.so: undefined reference to `LieAlgebra::SE3Pose::getRotationMatrix() const'
/usr/bin/ld: /usr/local/lib/libCROSP.so: undefined reference to `CROSP::strain_parameterisation::StrainParameterisation::StrainParameterisation(CROSP::polynomial_representation::PolynomialRepresentation, unsigned int)'
/usr/bin/ld: /usr/local/lib/libCROSP.so: undefined reference to `CROSP::strain_parameterisation::StrainParameterisation::StrainParameterisation(CROSP::polynomial_representation::PolynomialRepresentation, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, unsigned int)'
/usr/bin/ld: /usr/local/lib/libCROSP.so: undefined reference to `CROSP::rod_properties::RodProperties::RodProperties(CROSP::polynomial_representation::PolynomialRepresentation)'
/usr/bin/ld: /usr/local/lib/libCROSP.so: undefined reference to `CROSP::strain_parameterisation::StrainParameterisation::updateStacks(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test_crosp_library.dir/build.make:97: test_crosp_library] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/test_crosp_library.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Can you tell what is wrong ?
Moreover, I would like to know if I can use the INTERFACE functionality in order to install the internal libraries in my usr/local with namespaces.
So the CMakeLists.txt of a package using CROSP will be:
find_package(CROSP REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main
CROSP::MaterialProperties
CROSP::StrainParameterisation
)

Related

CMake linking error (collect2: ld returned 1 exit status) /usr/bin/ld: cannot find -lexpression

The project structure is as below
├── ast
│   ├── CMakeLists.txt
│   ├── expression
│   │   ├── CMakeLists.txt
│   │   ├── Expression.cpp
│   │   ├── Expression.hpp
│   │   ├── NumericExpression.cpp
│   │   └── NumericExpression.h
│   ├── Visitor.cpp
│   └── Visitor.hpp
├── callSlang
│   ├── CMakeLists.txt
│   └── main.cpp
├── CMakeLists.txt
├── contexts
│   ├── CMakeLists.txt
│   ├── Context.hpp
│   ├── Symbol.cpp
│   ├── Symbol.hpp
│   └── SymbolTable.hpp
├── frontend
│   ├── CMakeLists.txt
│   ├── Parser.cpp
│   └── Parser.hpp
├── Makefile
├── meta
│   ├── CMakeLists.txt
│   └── Meta.hpp
└── README.md
CMakeLists.txt
cmake_minimum_required(VERSION 3.16.3)
# set the project name
# https://stackoverflow.com/questions/71740678/cmake-error-in-findterminfo-with-clang-15-on-macos
project(slangLLvm VERSION 1.0 LANGUAGES C CXX)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_BUILD_TYPE "Debug")
set(LLVM_DIR /usr/lib/llvm-14/lib/cmake/llvm)
find_package(LLVM REQUIRED CONFIG
PATHS ${search_paths}
NO_DEFAULT_PATH)
add_subdirectory(meta)
add_subdirectory(contexts)
add_subdirectory(ast)
add_subdirectory(frontend)
add_subdirectory(callSlang)
callSlang/CMakeLists.txt
set(SOURCE_FILE main.cpp)
# add the files for creating executable
add_executable(slangLLVM ${SOURCE_FILE})
#link the libs
target_link_libraries(slangLLVM
PRIVATE
ast
frontend
)
ast/CMakeLists.txt
set(SOURCE_FILES Visitor.cpp)
add_library(ast ${SOURCE_FILES})
target_link_libraries(ast
PUBLIC
meta
contexts
LLVMSupport
expression
PRIVATE
frontend
)
# get the include dirs
target_include_directories(ast
INTERFACE
.
PUBLIC
${LLVM_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/meta
${PROJECT_SOURCE_DIR}/ast/expression
)
add_subdirectory(expression)
expression/CMakeLists.txt
set(SOURCE_FILES Expression.cpp NumericExpression.cpp)
add_library(experssion ${SOURCE_FILES})
target_link_libraries(experssion
PUBLIC
ast
)
# get the include dirs
target_include_directories(experssion
INTERFACE
.
PUBLIC
${LLVM_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/contexts
${PROJECT_SOURCE_DIR}/ast
${PROJECT_SOURCE_DIR}/meta
)
# INTERFACE tells to use includes to other libs but on the ast
frontend/CMakeLists.txt
set(SOURCE_FILES Parser.cpp)
add_library(frontend STATIC ${SOURCE_FILES})
target_link_libraries(frontend
PRIVATE
ast
)
# get the include dirs
target_include_directories(frontend
INTERFACE
.
PRIVATE
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/ast
${PROJECT_SOURCE_DIR}/contexts
${PROJECT_SOURCE_DIR}/ast/expression
)
meta/CMakeLists.txt
add_library(meta INTERFACE)
# get the include dirs
target_include_directories(meta INTERFACE .)
This compiles without error but fails during linking with the following error
[100%] Linking CXX executable slangLLVM
/usr/bin/ld: cannot find -lexpression
collect2: error: ld returned 1 exit status
make[3]: *** [callSlang/CMakeFiles/slangLLVM.dir/build.make:93: callSlang/slangLLVM] Error 1
make[3]: Leaving directory '/home/nithin/learn/c-cpp/slang-llvm/build'
make[2]: *** [CMakeFiles/Makefile2:392: callSlang/CMakeFiles/slangLLVM.dir/all] Error 2
make[2]: Leaving directory '/home/nithin/learn/c-cpp/slang-llvm/build'
make[1]: *** [Makefile:84: all] Error 2
make[1]: Leaving directory '/home/nithin/learn/c-cpp/slang-llvm/build'
make: *** [Makefile:4: all] Error 2
CallSlang depends on ast, ast depends on the expression and vice versa.
I have tried the solution in the link but it not-working so far for me. I am really new to CMake. Is it caused by the circular call by ast and expression, if so how can correct the same?
The complete code can be found in this link
Could someone please tell me the possible cause and solution? If I've missed out anything, over- or under-emphasized a specific point, please let me know in the comments. Thank you so much in advance for your time.

How to make my project find header file from my own separate library imported with FetchContent?

I'm trying to use my own library in a different project using CMake and FetchContent. My library is a static one that's built with CMake in a separate git repo, and it works fine when built with a demo in the same repo. When I use FetchContent to use it in a separate project it can't find the header files and I don't know how to include them.
dynamic-shadow-lib tree:
.
├── CMakeLists.txt
├── demo
│   ├── CMakeLists.txt
│   └── main.cpp
├── include
│   ├── line2D.hpp
│   ├── math.hpp
│   ├── mathplotUtil.hpp
│   ├── shape2D.hpp
│   ├── square2D.hpp
│   ├── triangle2D.hpp
│   └── vec2f.hpp
├── LICENSE
├── README.md
├── src
│   ├── line2D.cpp
│   ├── math.cpp
│   ├── square2D.cpp
│   ├── triangle2D.cpp
│   └── vec2f.cpp
└── tests
├── CMakeLists.txt
├── unit_tests
│   ├── CMakeLists.txt
│   ├── line2DTests.cpp
│   ├── main.cpp
│   ├── mathTests.cpp
│   ├── square2DTests.cpp
│   └── vec2fTests.cpp
└── visual_tests
├── CMakeLists.txt
├── main.cpp
└── visualTests.hpp
dynamic-shadow-lib root CmakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(
dynamic-shadows
VERSION 1.0
LANGUAGES CXX
)
# Build config variables
set(BUILD_DEMO FALSE)
set(BUILD_TESTS FALSE)
# Set C++ to version 14
set(CMAKE_CXX_STANDARD 14)
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
# Set a name for the target
set(TARGET_LIB ${CMAKE_PROJECT_NAME}-lib)
# Make library ${TARGET_LIB}
add_library(
${TARGET_LIB} STATIC
${SOURCE_DIR}/math.cpp
${SOURCE_DIR}/vec2f.cpp
${SOURCE_DIR}/line2D.cpp
${SOURCE_DIR}/square2D.cpp
${SOURCE_DIR}/triangle2D.cpp
)
if (${BUILD_TESTS})
# Enable testing (GoogleTests)
include(CTest)
enable_testing()
add_subdirectory(tests)
endif()
if (${BUILD_DEMO})
# Demo
add_subdirectory(demo)
endif()
Project that I'm trying to include my lib in (tree):
.
├── CMakeLists.txt
├── include
│   ├── Game.hpp
│   └── Primitive.hpp
├── LICENSE
├── README.md
├── src
│   ├── Game.cpp
│   └── main.cpp
└── tests
├── CMakeLists.txt
└── main.cpp
Projects root CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(realtime-light-shadow-2D
LANGUAGES CXX
VERSION 1.0
)
# Set extra compiler flags
set(CMAKE_CXX_FLAGS "-W -Wall -std=c++14 -fopenmp")
# Set binary destinations
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Dependencies
include(FetchContent)
set (FETCHCONTENT_QUIET FALSE)
# SFML
message (STATUS "Adding SFML..")
FetchContent_Declare(
sfml
GIT_REPOSITORY "https://github.com/SFML/SFML"
GIT_TAG 218154cf0098de3f495e31ced489da24b7318638 # Latest
GIT_PROGRESS TRUE
)
# No need to build audio and network modules
set(SFML_BUILD_AUDIO FALSE)
set(SFML_BUILD_NETWORK FALSE)
FetchContent_MakeAvailable(sfml)
# ImGui
message (STATUS "Adding ImGui")
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG 5c8f8d031166765d2f1e2ac2de27df6d3691c05a # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(imgui)
# ImGui-SFML
message (STATUS "Adding ImGui-SFML")
FetchContent_Declare(
imgui-sfml
GIT_REPOSITORY https://github.com/eliasdaler/imgui-sfml
GIT_TAG 4129d276d45845581b6ba99ede50db6f761e5089 # Latest
GIT_PROGRESS TRUE
)
set(IMGUI_DIR ${imgui_SOURCE_DIR})
set(IMGUI_SFML_FIND_SFML OFF)
set(IMGUI_SFML_IMGUI_DEMO ON)
FetchContent_MakeAvailable(imgui-sfml)
# dynamic-shadows-lib
message( STATUS "Adding dynamic-shadow-lib")
FetchContent_Declare(
dynamic-shadows-lib
GIT_REPOSITORY https://github.com/JesperGlas/dynamic-shadows-lib/
GIT_TAG 59c7884caac7cc98f902fd880ccb1c9b0f50cca0 # Latest
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(dynamic-shadows-lib)
# Set header dir
set(HEADERS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${HEADERS_DIR})
# Set source dir
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(TARGET_BIN ${CMAKE_PROJECT_NAME})
add_executable(
${TARGET_BIN}
${SOURCE_DIR}/main.cpp
${SOURCE_DIR}/Game.cpp
)
target_link_libraries(
${TARGET_BIN}
PUBLIC
sfml-system
sfml-graphics
ImGui-SFML::ImGui-SFML
dynamic-shadows-lib
)
When I try to build the project (sfml-dynamic-light-demo) I get the following error:
[build] /home/jesper/dev/cpp/sfml-dynamic-light-demo/include/Primitive.hpp:4:10: fatal error: vec2f.hpp: No such file or directory
[build] 4 | #include "vec2f.hpp"
Which tells me that the libraries include folder might not be available to the project. I've tried to include it as an install(DIRECTORY ${HEADER_DIR}) in the libs root CMakeLists, but it has no effect. I suspect I'm using it wrong since when I build the project I still get "No install step for 'dynamic-shadows-lib-populate'".
What am I doing wrong? If it's a concept that I'm missing, what should I read up on to make it work?
Thanks to the comments I was able to solve this. In my library (Built with CMake) I used the variable CMAKE_PROJECT_NAME when creating my library (CMAKE_PROJECT_NAME-lib). This variable references the top root CMakeLists.txt which resultet in my library getting the wrong name when I used it in another project. By changing all of those variables to PROJECT_NAME, and other similar ones, everything worked as it should.
TLDR: Make sure to use local variables when you want to use a CMake project as a subproject. (In this case PROJECT_NAME, instead of CMAKE_PROJECT_NAME etc...).

cmake target_link_libraries() cannot find renamed lib target by set_target_properties(archive_output_name)

RT~ ps: cmake version 3.9.2
My codebase just like this.
suzanwen#n224-004-133:~/repos/C++/ttt:)$ tree -L 2
.
├── build
│   ├── bin
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── cmake_install.cmake
│   ├── lib
│   ├── Makefile
│   ├── test
│   └── thirdparty
├── build.sh
├── CMakeLists.txt
├── Makefile
├── test
│   ├── CMakeLists.txt
│   └── main.cc
└── thirdparty
├── CMakeLists.txt
├── gflags
└── hellolib
10 directories, 9 files
my thirdparty/hellolib/CMakeLists.txt is
PROJECT(hello)
SET(LIBHELLO_SRC hello.cc)
MESSAGE(STATUS "LIBRARY PATH=" ${LIBRARY_OUTPUT_PATH})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello")
my test/CMakeLists.txt is
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/thirdparty/hellolib
${PROJECT_SOURCE_DIR}/thirdparty/gflags/include)
IF(LIBRARY_OUTPUT_PATH)
LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH})
ENDIF(LIBRARY_OUTPUT_PATH)
ADD_EXECUTABLE(main main.cc)
TARGET_LINK_LIBRARIES(main hello)
# TARGET_LINK_LIBRARIES(main hello_static)
when I build my top-level project, an error occurs like this.
/usr/bin/c++ -rdynamic CMakeFiles/main.dir/main.cc.o -o ../bin/main -L/home/suzanwen/repos/C++/ttt/build/lib -Wl,-rpath,/home/suzanwen/repos/C++/ttt/build/lib -lhello
/usr/bin/ld: cannot find -lhello
But when I comment the line # SET_TARGET_PROPERTIES(hello_static PROPERTIES ARCHIVE_OUTPUT_NAME "hello") and TARGET_LINK_LIBRARIES with hello_static, everything goes fine.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target. Could anyone explain it? thanks in advance.
It seems that TARGET_LINK_LIBRARIES cannot find renamed lib target.
Setting ARCHIVE_OUTPUT_NAME property renames not a target, but an output file. So linking with a target still works:
TARGET_LINK_LIBRARIES(main hello_static)
One cannot rename the target once it is created, but it is possible to create ALIAS for a target:
ADD_LIBRARY(hello ALIAS hello_static)
After that it is possible to link with the alias:
TARGET_LINK_LIBRARIES(main hello)

C++ Armadillo library gives undefined reference to `arma::arma_rng_cxx11_instance'

I used CMake to build my project and Catch2 to do the testing. The following is my project structure
├── build
├── CMakeLists.txt
├── compile_commands.json
├── include
│   ├── node.h
│   ├── rrt.h
│   └── tree.h
├── Makefile
├── package.xml
├── scripts
├── src
│   ├── main.cpp
│   ├── node.cpp
│   ├── rrt.cpp
│   └── tree.cpp
├── test
│   ├── CMakeLists.txt
│   └── test.cpp
└── third_party
└── catch.hpp
In ./CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.3)
project(rrt_ros)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/include/rrt.h
${CMAKE_CURRENT_SOURCE_DIR}/include/tree.h
${CMAKE_CURRENT_SOURCE_DIR}/include/node.h
${CMAKE_CURRENT_SOURCE_DIR}/src/rrt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/tree.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/node.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)
find_package(Armadillo REQUIRED)
FIND_PACKAGE(Eigen3 REQUIRED)
add_executable(
rrt
${SOURCES}
)
target_include_directories(
rrt
PUBLIC
${catkin_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
${ARMADILLO_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(rrt ${catkin_LIBRARIES} ${ARMADILLO_LIBRARIES})
add_subdirectory(test)
In test/CMakeLists.txt, I have
project(rrt_ros)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs)
find_package(Armadillo REQUIRED)
FIND_PACKAGE(Eigen3 REQUIRED)
message("TESTING......" ${CMAKE_CURRENT_SOURCE_DIR}/../include/rrt.h)
add_executable(rrt_test test.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../include/rrt.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/tree.h
${CMAKE_CURRENT_SOURCE_DIR}/../include/node.h
${CMAKE_CURRENT_SOURCE_DIR}/../src/rrt.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../src/tree.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../src/node.cpp
)
target_include_directories(
rrt_test
PUBLIC
${catkin_INCLUDE_DIRS}
${Armadillo_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../third_party
${CMAKE_CURRENT_SOURCE_DIR}/../include
)
target_link_libraries(
rrt_test
${catkin_LIBRARIES}
${Aramdillo_LIBRARIES}
)
In rrt.cpp, I have a function that calls armadillo's sampling function
arma::randi<arma::mat>(1, 2, arma::distr_params(1, 10))
When I compile the project, it gives me an undefined error:
rrt.cpp:(.text._ZTWN4arma23arma_rng_cxx11_instanceE[_ZTWN4arma23arma_rng_cxx11_instanceE]+0x15): undefined reference to 'arma::arma_rng_cxx11_instance'
collect2: error: ld returned 1 exit status
However, when I comment out ${CMAKE_CURRENT_SOURCE_DIR}/../src/rrt.cpp in ./test/CMakeLists.txt, it compiles fine.
I went through the same problem recently.
In your test/CmakeLists.txt, ${ARMADILLO_LIBRARIES} should be used instead of ${Aramdillo_LIBRARIES} (spelling mistake and upper case problem).

Error while including Caffe in C++ Project using cmake

I want to include caffe in my project. This is the folder structure of the project:
.
├── AUTHORS
├── ChangeLog
├── cmake
│   ├── FindCaffe.cmake
│   └── FindCUDA.cmake
├── CMakeLists.txt
├── CMakeLists.txt.user
├── data
│   └── info.plist
├── deep-app.pro.user
├── LICENSE.txt
├── README.md
├── [reference]
│   ├── deep-app.pro
│   ├── deep-app.pro.user
│   ├── deployment.pri
│   ├── main.cpp
│   ├── main.qml
│   ├── Page1Form.ui.qml
│   ├── Page1.qml
│   └── qml.qrc
└── src
├── CMakeLists.txt
├── code
│   └── main.cpp
├── icons.yml
└── res
├── assets
│   ├── assets.qrc
│   ├── book-open-page.svg
│   └── book-open.svg
├── icons
│   ├── action_home.svg
│   ├── action_list.svg
│   ├── action_search.svg
│   ├── action_settings.svg
│   ├── file_cloud_done.svg
│   ├── icons.qrc
│   ├── maps_place.svg
│   ├── navigation_check.svg
│   └── social_school.svg
└── qml
├── main.qml
├── Page1Form.ui.qml
├── Page1.qml
└── qml.qrc
Here is the root/CMakeLists.txt:
project(generic-object-detection)
cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
cmake_policy(VERSION 3.4.1)
ENABLE_LANGUAGE(C)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc and rrc automatically when needed
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
# Apple-specific configuration
set(APPLE_SUPPRESS_X11_WARNING ON)
# Build flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Werror -Wall -Wextra -Wno-unused-parameter -pedantic -std=c++11")
### Set libraries' locations
# Set Caffe
set(Caffe_DIR "/home/ubuntu/Libraries/caffe")
set(Caffe_INCLUDE_DIRS "/home/cortana/Libraries/caffe/include")
set(Caffe_LIBRARIES "/usr/lib/x86_64-linux-gnu/libcaffe.so")
# Disable debug output for release builds
if(CMAKE_BUILD_TYPE MATCHES "^[Rr]elease$")
add_definitions(-DQT_NO_DEBUG_OUTPUT)
endif()
# Minimum version requirements
set(QT_MIN_VERSION "5.4.0")
# Find Qt5
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Core
Qml
Quick
Concurrent)
# Find OpenCV 3.1
find_package(OpenCV 3.1.0 REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
# Find Boost
FIND_PACKAGE(Boost COMPONENTS program_options REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
# Find CUDA
FIND_PACKAGE(CUDA REQUIRED)
# Find Caffe
FIND_PACKAGE(Caffe REQUIRED)
if(UNIX)
if(APPLE)
set(MACOSX_BUNDLE_INFO_STRING "generic-object-detection")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mybitchinapp.generic-object-detection")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "generic-object-detection")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
else()
# Assume linux
# TODO: Install desktop and appdata files
endif()
elseif(WIN32)
# Nothing to do here
endif()
add_subdirectory(src)
The file root/src/CMakeLists.txt:
file(GLOB_RECURSE SOURCES
*.cpp *.h
code/*.cpp code/*.h)
set(SOURCES ${SOURCES}
res/assets/assets.qrc
res/icons/icons.qrc
res/qml/qml.qrc)
add_executable(deep-app ${SOURCES})
target_link_libraries(deep-app
Qt5::Core
Qt5::Qml
Qt5::Quick
Qt5::Concurrent
${OpenCV_LIBS}
${Boost_LIBRARIES}
${CUDA_LIBRARIES})
set_target_properties(deep-app PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/data/Info.plist)
install(TARGETS deep-app
RUNTIME DESTINATION bin
DESTINATION ${CMAKE_INSTALL_BINDIR})
The error is:
CMake Error at CMakeLists.txt:55 (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!
I have setup Caffe_DIR and other required variables. But it still gives the same errors. I removed the previous [cmake] cache so thats not the problem. I cant figure out how to resolve this problem and I need to use Caffe in the project. Please help.
You want to set your CMAKE_MODULE_PATH to location where cmake module files are located for Caffe project, which would be directory pointed to below:
.
├── AUTHORS
├── ChangeLog
├── cmake <---------Set Caffe_DIR it to this directory
│ ├── FindCaffe.cmake
│ └── FindCUDA.cmake
If that doesn't work then you should set your Caffe_DIR to the above directory and make sure your rename the files under that directory to one of the names mentioned in the following error:
Could not find a package configuration file provided by "Caffe" with any of
the following names:
CaffeConfig.cmake
caffe-config.cmake