CMake custom target name conflicts between subdirectories - c++

I am writing a game engine and I have a directory called thirdparty where all external libraries my engine uses are placed:
thirdparty/...
/zlib
/freetype2
/SDL2
/...
So, the engine directory structure looks like:
engine/actors
engine/memory_allocator
engine/renderer
engine/...
engine/thirdparty
engine/thirdparty/CMakeLists.txt
engine/CMakeLists.txt
The engine/CMakeLists.txt:
cmake_minimum_required (VERSION 3.2)
project(Engine)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Werror")
# Include build directory to be able to include generated files:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
file(GLOB GLAD_SOURCES thirdparty/glad/src/glad.c)
file(GLOB ACTOR_SOURCES actors/*.cpp)
file(GLOB LOGIC_SOURCES logic/*.cpp)
file(GLOB UI_SOURCES ui/*.cpp)
set(SOURCES ${GLAD_SOURCES}
${ACTOR_SOURCES}
${LOGIC_SOURCES}
${UI_SOURCES})
add_library(engine SHARED ${SOURCES})
include_directories(thirdparty/glm/)
include_directories(thirdparty/glad/include)
include_directories(thirdparty/tinyxml2/)
include_directories(thirdparty/zlib/)
include_directories(thirdparty/sdl2/SDL2-2.0.5/)
include_directories(./)
add_subdirectory(../../thirdparty thirdparty)
target_link_libraries(engine SDL2)
target_link_libraries(engine tinyxml2)
target_link_libraries(engine zlib)
The engine/thirdparty/CMakeLists.txt:
set(BUILD_CPU_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_EXTRAS OFF CACHE BOOL "" FORCE)
set(BUILD_BULLET2_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_UNIT_TESTS OFF CACHE BOOL "" FORCE)
set(FREETYPE_NO_DIST OFF CACHE BOOL "" FORCE)
set(OLD_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "")
# add_subdirectory(bullet3)
set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
add_subdirectory(freetype2)
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
add_subdirectory(tinyxml2)
add_subdirectory(sdl2/SDL2-2.0.5/)
add_subdirectory(zlib)
So, the main engine CMakeLists.txt is in the root directory of the engine's sources and there is another CMakeLists.txt for building third-party libraries in the thirdparty subdirectory of engine's root directory.
The problem is that some of subdirectories in the thirdparty, for example, SDL2 and zlib contain the same target names, added via add_custom_target and so CMake fails to generate the Makefile because of this naming conflicts:
zlib's CMakeLists.txt (in the end):
# uninstall target
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/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)
endif()
SDL2's CMakeLists.txt:
##### Uninstall target #####
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/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)
So the final error is:
CMake Error at /home/user/engine/thirdparty/sdl2/SDL2-2.0.5/CMakeLists.txt:1624 (add_custom_target):
add_custom_target cannot create target "uninstall" because another target
with the same name already exists. The existing target is a custom target
created in source directory
"/home/user/engine/thirdparty/zlib". See
documentation for policy CMP0002 for more details.
Is there any way to fix this? Perhaps, there is a way to rename these targets by adding any prefix to it so they will never conflict?

It mostly depends on which generators you are targeting. A solution that imposes limitations on them is using ALLOW_DUPLICATE_CUSTOM_TARGETS.
As from the documentation:
Allow duplicate custom targets to be created.
It works only for Makefile generators anyway:
For projects that care only about Makefile generators and do not wish to support Xcode or VS IDE generators, one may set this property to true to allow duplicate custom targets.
Otherwise consider to not pack dependencies with the project directly and use the other tools around (like Find*) to get them along with the right paths on the target systems.

Related

Detecting compiler configuration in cmake file

Either this is really easy and I'm just not able to find the correct way to do it, or I've wildly misunderstood something. I'm attempting to add a conditional to a CMakeLists.txt file to include the proper .lib file depending on which build configuration type is being used (within visual studio at the moment). So for example, if configuration in visual studio is set to Debug then use file zlibstaticd.lib vs zlibstatic.lib. Below is what I have that's not working:
add_library(ZLIB_LIBRARY OBJECT IMPORTED)
# zlib added via assimp, and I can't get CMAKE_DEBUG_POSTFIX value to overwrite (because it's set within zlibs cmake file when using MSVC)
# so we have to do this check
if($<CONFIG:Debug>)
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstaticd.lib)
else()
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstatic.lib)
endif()
I've also tried CMAKE_BUILD_TYPE but it's always an empty string. Below is my entire CMakeLists.txt file so you can see what it is I'm doing (building a singular static library which contains many other static libraries):
cmake_minimum_required(VERSION 3.20.0)
# Define our project name
set(PROJECT_NAME myProjectName)
project(${PROJECT_NAME})
# Make sure binary directory is not the same as source directory
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(
FATAL_ERROR
"In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there."
)
endif()
# This Project Depends on External Project(s)
include(ExternalProject)
set(libGLFW glfw)
ExternalProject_Add(${libGLFW}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}
GIT_REPOSITORY https://github.com/glfw/glfw.git
GIT_TAG 3.3.4
GIT_SHALLOW ON
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}/install
-DGLFW_BUILD_DOCS:BOOL=OFF
-DGLFW_BUILD_EXAMPLES:BOOL=OFF
-DGLFW_BUILD_TESTS:BOOL=OFF
)
set(libGLAD glad)
ExternalProject_Add(${libGLAD}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}
GIT_REPOSITORY https://github.com/Dav1dde/glad.git
GIT_TAG origin/master
GIT_SHALLOW ON
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}/install
-DGLAD_INSTALL:BOOL=ON
-DGLAD_PROFILE:STRING="core"
-DGLAD_ALL_EXTENSIONS:BOOL=ON
-DUSE_MSVC_RUNTIME_LIBRARY_DLL:BOOL=OFF
)
set(libGLM glm)
ExternalProject_Add(${libGLM}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLM}
GIT_REPOSITORY https://github.com/g-truc/glm.git
GIT_TAG origin/master
GIT_SHALLOW ON
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLM}/install
-DBUILD_SHARED_LIBS:BOOL=OFF
-DBUILD_STATIC_LIBS:BOOL=OFF
-DGLM_TEST_ENABLE:BOOL=OFF
)
set(libAssimp assimp)
ExternalProject_Add(${libAssimp}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dep/${libAssimp}
GIT_REPOSITORY https://github.com/assimp/assimp.git
GIT_TAG v5.0.1
GIT_SHALLOW ON
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/dep/${libAssimp}/install
-DASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT:BOOL=OFF
-DASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT:BOOL=OFF
-DBUILD_SHARED_LIBS:BOOL=OFF
-DASSIMP_BUILD_ASSIMP_TOOLS:BOOL=OFF
-DASSIMP_BUILD_TESTS:BOOL=OFF
-DASSIMP_BUILD_FBX_IMPORTER:BOOL=ON
-DASSIMP_BUILD_OBJ_IMPORTER:BOOL=ON
-DASSIMP_BUILD_OBJ_EXPORTER:BOOL=ON
-DASSIMP_LIBRARY_SUFFIX:STRING=
-DLIBRARY_SUFFIX:STRING=
-DCMAKE_DEBUG_POSTFIX:STRING=
-DASSIMP_INJECT_DEBUG_POSTFIX:BOOL=OFF
)
# Note set_target_properties will need conditionals for windows/linux since extensions differ
# Create the oject files we will join together to create our singular static library, using the projects
# that were previously added above via ExternalProject_Add
# INSTALL_DIR not being set to value of CMAKE_INSTALL_PREFIX, so manuallysetting
#ExternalProject_Get_Property(${libGLFW} INSTALL_DIR)
# SETUP GLFW
set(GLFW_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLFW}/install)
add_library(GLFW_LIBRARY OBJECT IMPORTED)
set_target_properties(GLFW_LIBRARY PROPERTIES IMPORTED_OBJECTS ${GLFW_INSTALL_DIR}/lib/glfw3.lib)
# SETUP GLAD
set(GLAD_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLAD}/install)
add_library(GLAD_LIBRARY OBJECT IMPORTED)
set_target_properties(GLAD_LIBRARY PROPERTIES IMPORTED_OBJECTS ${GLAD_INSTALL_DIR}/lib/glad.lib)
# SETUP GLM
# GLM is header only library, so we simply include it's include directory in target_include_directories below
set(GLM_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libGLM}/install)
# SETUP ASSIMP and it's dependencies
set(ASSIMP_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dep/${libAssimp}/install)
add_library(ASSIMP_LIBRARY OBJECT IMPORTED)
set_target_properties(ASSIMP_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/assimp.lib)
add_library(IRRXML_LIBRARY OBJECT IMPORTED)
set_target_properties(IRRXML_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/IrrXML.lib)
add_library(ZLIB_LIBRARY OBJECT IMPORTED)
# zlib added via assimp, and I can't get CMAKE_DEBUG_POSTFIX value to overwrite (because it's set within zlibs cmake file when using MSVC)
# so we have to do this check
if($<CONFIG:Debug>)
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstaticd.lib)
else()
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstatic.lib)
endif()
# Documentation states not to do this, but do it anyway for the time being since it prevents us from having
# to manually list all project files
file(GLOB_RECURSE headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/inc/*.h")
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
# Create a single .lib file containing our compiled objects, and the compiled objects of all other dependencies
add_library(${PROJECT_NAME} STATIC ${headers} ${sources}
$<TARGET_OBJECTS:GLFW_LIBRARY>
$<TARGET_OBJECTS:GLAD_LIBRARY>
$<TARGET_OBJECTS:ASSIMP_LIBRARY>
$<TARGET_OBJECTS:IRRXML_LIBRARY>
$<TARGET_OBJECTS:ZLIB_LIBRARY>
)
# Add all include file paths
target_include_directories(${PROJECT_NAME}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc
PUBLIC ${GLFW_INSTALL_DIR}/include
PUBLIC ${GLAD_INSTALL_DIR}/include
PUBLIC ${GLM_INSTALL_DIR}/include
PUBLIC ${ASSIMP_INSTALL_DIR}/include
)
# Specify the order in which libs depend on each other, use the name of the ExternalProject, not the name of the
# library object you create and use with add_library
add_dependencies(${PROJECT_NAME} ${libGLFW} ${libGLAD} ${libGLM} ${libAssimp})
add_library(ZLIB_LIBRARY OBJECT IMPORTED)
# zlib added via assimp, and I can't get CMAKE_DEBUG_POSTFIX value to overwrite (because it's set within zlibs cmake file when using MSVC)
# so we have to do this check
if($<CONFIG:Debug>)
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstaticd.lib)
else()
set_target_properties(ZLIB_LIBRARY PROPERTIES IMPORTED_OBJECTS ${ASSIMP_INSTALL_DIR}/lib/zlibstatic.lib)
endif()
Generator expressions are evaluated after the configuration step has run, so they're just literal strings when the if() statement sees them. Basically, the CMake configure step is meta-programming a declarative language of targets and generator expressions that gets compiled into Ninja build files (or whatever) by the generator.
You can set the library up as follows:
add_library(zlib OBJECT IMPORTED)
set_target_properties(
zlib
PROPERTIES
IMPORTED_OBJECTS_RELEASE "${ASSIMP_INSTALL_DIR}/lib/zlibstatic.lib"
IMPORTED_OBJECTS_DEBUG "${ASSIMP_INSTALL_DIR}/lib/zlibstaticd.lib"
)
CMake first tries IMPORTED_OBJECTS_$<CONFIG> before trying IMPORTED_OBJECTS when resolving a library path.
All that said, I have to wonder why you don't just use find_package, vcpkg, Conan, or maybe add_subdirectory / FetchContent to manage your dependencies. This seems like a lot of pain given that all of those libraries (I think) either provide their own find_package config packages or CMake provides a find module for them.

Finding Direct3D 12 using CMake

So I've been trying to learn CMake and use it with C++. I'd like to have a go at creating a portable game engine which uses Direct3D 12 on Windows.
Currently, I have the following CMakeLists.txt for my project:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(PsychoEngineCore)
set(SRCS_CXX ${CMAKE_CURRENT_LIST_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/src/dir_src.cmake)
set(LIB_TYPE "STATIC" CACHE STRING "Static or Dynamic Linking")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR
${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
set(warnings "-Wall -Wextra -Werror")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
set(warnings "/W4 /WX /EHsc")
endif()
if(NOT CONFIGURED_ONCE)
set(CMAKE_CXX_FLAGS "${warnings}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Do we want static libraries?
# When STATIC_LINKING is TRUE, then cmake looks for binaries ending in ".a".
# THIS IS FOR LINUX ONLY!
if(LIB_TYPE EQUAL STATIC)
if (UNIX AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES(".a"))
endif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set_target_properties(surface PROPERTIES LINK_SEARCH_END_STATIC 1)
endif(LIB_TYPE EQUAL STATIC)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include(GenerateExportHeader)
add_library(${PROJECT_NAME} ${LIB_TYPE} ${SRCS_CXX})
GENERATE_EXPORT_HEADER(
${PROJECT_NAME}
EXPORT_MACRO_NAME PE_API
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/Engine/API/${PROJECT_NAME}Export.hpp
DEPRECATED_MACRO_NAME PE_API_DEP
STATIC_DEFINE PE_STATIC
)
Currently I have my d3d12.lib file in the following location:
C:\Program Files (x86)\Windows Kits\10\Libs\10.0.16299.0\um\x64
Is there a way to keep the path dynamic and preferably "update" if a newer version is available on said system?
Thanks!
Turning my comment into an answer
Generally speaking, just add a
target_link_libraries((${PROJECT_NAME} d3d12.lib)
The Windows SDK (where the Direct3D SDK is now part of) is in the standard search paths e.g. of the linker for libraries. So it's found automatically by the MSVC compiler and linker.
And I don't think that upgrading to a newer (yet unknown) API version automatically is a good idea. You're writing your program for a specific API version.
Working Example
Here is a minimal working example (Tested VS2017 15.5.5, CMake 3.9.0):
cmake_minimum_required(VERSION 3.0)
project(Direct3DExample)
find_package(Git REQUIRED)
set(_path "${CMAKE_BINARY_DIR}/DirectX-Graphics-Samples/Samples/Desktop/D3D12HelloWorld/src/HelloTriangle")
if (NOT EXISTS "${_path}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/Microsoft/DirectX-Graphics-Samples.git
)
endif()
file(GLOB _files "${_path}/*")
list(APPEND _shader ${_files})
list(FILTER _files EXCLUDE REGEX "\\.vcxproj|\\.hlsl")
list(FILTER _shader INCLUDE REGEX "\\.hlsl")
get_filename_component(_name "${_path}" NAME)
add_executable(${_name} WIN32 ${_files})
target_compile_definitions(${_name} PRIVATE "UNICODE" "_UNICODE")
target_link_libraries(${_name} PRIVATE "d3d12.lib" "dxgi.lib" "d3dcompiler.lib")
add_custom_command(
TARGET ${_name}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${_shader} $<TARGET_FILE_DIR:${_name}>
)
If you need more (compilers/linkers that are not finding the Windows SDK automatically), you may want to look the following find_package() config code:
https://github.com/Microsoft/DirectXShaderCompiler/blob/master/cmake/modules/FindD3D12.cmake

CMake third party library undefined reference

I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).
I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp
In my own project I include the headers with #include "libsbp/sbp.h" which also works.
Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"
The relevant part of my Cmake for my own project:
link_directories(/usr/local/lib)
add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
As I said before, I tried some things:
find_library(SBP_LIB sbp /usr/local/lib) -> same error
same goes for using libsbp in target_link_libraries or searching for it
link_directory(/usr/local/lib)
trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}
Maybe you can help me!
edit:
this is the CMakeList.txt from the libsbp/c/src directory
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)
file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")
include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")
set(libsbp_SRCS
edc.c
sbp.c
)
add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})
if(BUILD_SHARED_LIBS)
add_library(sbp SHARED ${libsbp_SRCS})
install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)
install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)
this is the CMakeList.txt from /libsbp/c/
cmake_minimum_required(VERSION 2.8.9)
project(libsbp)
# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C++ compiler for building with code coverage."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C compiler for building with code coverage."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used for linking binaries with code coverage."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the shared libraries linker during builds with code coverage."
FORCE )
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE )
# Set project version using Git tag and hash.
execute_process(
COMMAND git describe --dirty --tags --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
# Set project version explicitly for release tarballs.
#set(VERSION foo)
message(STATUS "libsbp version: ${VERSION}")
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")
add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
It seems that your program uses C++ and the library is written in C.
Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".
extern "C" {
#include <libsbp/sbp.h>
}
Some libraries already include this in their headers, but not sbp.
You have (at least) two possibilities:
Installing the library (this is what you did)
Integrating the library in your CMake project
When installing the library, the target_link_libraries command needs to be modified slightly:
find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})
When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)

CMakeLists configuration to link two C++ projects

I have the following situation: a Project A depends on a Project B, but both are built at the same time. Project A has to include the includes of project B and it needs also to link its libraries. Up to now I've tried this way:
ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/other_project other_project)
and then:
INCLUDE_DIRECTORIES(includ ${CMAKE_SOURCE_DIR}/other_project/include})
LIST(APPEND LINK_LIBS other_project)
in the CMakeLists.txt of Project A
but it doesn't seem to work, the compiler also gives me error when including the headers of Project B saying that they do not exist.
What is the right way to add dependencies in A? How should the CMakeLists.txt look like?
EDIT:
as suggested in the comments, this question was addressed in this, however I'd like to see an example of how to use it in a CMakeList.txt file.
The following is a simple example which builds zlib and then builds libxml2 which depends on the zlib we build. One thing to note, I quickly pulled this example from stuff I've done before. The libxml2 example uses make, thus will only actually build on a system which has it, e.g. Linux, Mac ...
Here is the proposed directory structure for this example ...
src/
-- CMakeLists.txt
CMake/
---- External_ZLib.cmake
---- External_libxml2.cmake
Dowloads/ ( no need to create this directory, CMake will do it for you )
build/ ( Out of source build to prevent littering source tree )
Files:
CMakeLists.txt
# Any version that supports ExternalProject should do
cmake_minimum_required( VERSION 3.1)
project(test_ext_proj)
set(test_ext_proj_CMAKE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
set(CMAKE_MODULE_PATH ${test_ext_proj_CMAKE_DIR} ${CMAKE_MODULE_PATH})
set(test_ext_proj_BUILD_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
set(test_ext_proj_DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Downloads CACHE PATH "Directory to store downloaded tarballs.")
include(ExternalProject)
include(External_ZLib)
include(External_libxml2)
External_ZLib.cmake:
set(ZLib_version 1.2.8)
set(ZLib_url "http://zlib.net/zlib-${ZLib_version}.tar.gz")
set(ZLib_md5 "44d667c142d7cda120332623eab69f40")
ExternalProject_Add(ZLib
URL ${ZLib_url}
URL_MD5 ${ZLib_md5}
PREFIX ${vision-tpl_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
CMAKE_GENERATOR ${gen}
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=${test_ext_proj_BUILD_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
)
#This variable is required so other packages can find it.
set(ZLIB_ROOT ${test_ext_proj_BUILD_INSTALL_PREFIX} CACHE PATH "" FORCE)
External_libxml2.cmake:
set(libxml2_release "2.9")
set(libxml2_patch_version 0)
set(libxml2_url "ftp://xmlsoft.org/libxml2/libxml2-sources-${libxml2_release}.${libxml2_patch_version}.tar.gz")
set(libxml2_md5 "7da7af8f62e111497d5a2b61d01bd811")
#We need to state that we're dependent on ZLib so build order is correct
set(_XML2_DEPENDS ZLib)
#This build requires make, ensure we have it, or error out.
if(CMAKE_GENERATOR MATCHES ".*Makefiles")
set(MAKE_EXECUTABLE "$(MAKE)")
else()
find_program(MAKE_EXECUTABLE make)
if(NOT MAKE_EXECUTABLE)
message(FATAL_ERROR "Could not find 'make', required to build libxml2.")
endif()
endif()
ExternalProject_Add(libxml2
DEPENDS ${_XML2_DEPENDS}
URL ${libxml2_url}
URL_MD5 ${libxml2_md5}
PREFIX ${test_ext_proj_BUILD_PREFIX}
DOWNLOAD_DIR ${test_ext_proj_DOWNLOAD_DIR}
INSTALL_DIR ${test_ext_proj_BUILD_INSTALL_PREFIX}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./configure
--prefix=${test_ext_proj_BUILD_INSTALL_PREFIX}
--with-zlib=${ZLIB_ROOT}
BUILD_COMMAND ${MAKE_EXECUTABLE}
INSTALL_COMMAND ${MAKE_EXECUTABLE} install
)

OpenCV_FOUND to FALSE so package "OpenCV" is considered to be NOT FOUND

I am having problems at the moment trying to get my cmake to see my opencv.
I have installed opencv and can run the some of the sample problems and some give the same error as the the error I get in my cmake file (when running the sample programs through terminal)
I have tried to change the environment variable path as described in
http://answers.opencv.org/question/35125/cmake-linking-error-opencv_found-to-false-ubuntu/
My bashrc file now looks like
CMAKE_PREFIX_PATH=/home/durham/Desktop/OpenCV/opencv-2.4.9:$CMAKE_PREFIX_PATH
CPATH=/home/durham/Desktop/OpenCV/opencv-2.4.9/include:$CPATH LD_LIBRARY_PATH=/home/durham/Desktop/OpenCV/opencv-2.4.9/lib:$LD_LIBRARY_PATH PATH=/home/durham/Desktop/OpenCV/opencv-2.4.9bin:$PATH
PKG_CONFIG_PATH=/home/durham/Desktop/OpenCV/opencv-2.4.9/lib/pkgconfig:$PKG_CONFIG_PATH
PYTHONPATH=/home/durham/Desktop/OpenCV/opencv-2.4.9/lib/python2.7/dist-packages:$PYTHONPATH
and the contents of /etc/ld.so.conf are
include /etc/ld.so.conf.d/*.conf
include /home/durham/Desktop/OpenCV/opencv-2.4.9
The cmake file I am trying to run looks like this
cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0020) cmake_policy(SET CMP0020 NEW) endif(POLICY CMP0020)
SET(CMAKE_VERBOSE_MAKEFILE TRUE) SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/config)
ADD_DEFINITIONS(-DQT_THREAD_SUPPORT -D_REENTRANT -DQT_NO_DEBUG
-DIQRMODULE)
SET(QT_MT_REQUIRED TRUE) find_package(Qt5Widgets) FIND_PACKAGE(OpenCV REQUIRED)
IF(NOT DEFINED IQR_INCLUDE_DIR) set (IQR_INCLUDE_DIR "/usr/include/iqr") #default for linux ENDIF(NOT DEFINED IQR_INCLUDE_DIR)
IF(NOT EXISTS ${IQR_INCLUDE_DIR}) message(STATUS "not exists IQR_INCLUDE_DIR: ${IQR_INCLUDE_DIR}") set (IQR_INCLUDE_DIR $ENV{IQR_INCLUDE_DIR} CACHE PATH "" FORCE) IF(NOT EXISTS ${IQR_INCLUDE_DIR})
message(STATUS "IQR_INCLUDE_DIR set to ${IQR_INCLUDE_DIR}")
message(FATAL_ERROR "Please specify iqr include directory using IQR_INCLUDE_DIR env. variable") ENDIF(NOT EXISTS ${IQR_INCLUDE_DIR}) ENDIF(NOT EXISTS ${IQR_INCLUDE_DIR})
IF(WIN32) IF(NOT DEFINED IQR_LIB_DIR)
set (IQR_LIB_DIR $ENV{IQR_LIB_DIR} CACHE PATH "" FORCE) ENDIF(NOT DEFINED IQR_LIB_DIR)
IF(NOT EXISTS ${IQR_LIB_DIR})
message(FATAL_ERROR "Please specify phidgets include directory using IQR_LIB_DIR env. variable") ENDIF(NOT EXISTS ${IQR_LIB_DIR}) ENDIF(WIN32)
SET(libSrc
moduleArDroneBottomCamera.cpp
)
INCLUDE_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${IQR_INCLUDE_DIR} ${QT_INCLUDE_DIR} ${OPENCV_INCLUDE_DIR} ardrone_sdk/ ardrone_sdk/VP_SDK/ ardrone_sdk/VLIB/Stages/ ardrone_sdk/VP_SDK/VP_Os/ ardrone_sdk/VP_SDK/VP_Os/linux/ ardrone_sdk/VP_SDK/VP_Stages/ )
ADD_SUBDIRECTORY(ardrone_sdk)
ADD_LIBRARY(moduleArDroneBottomCamera SHARED ${libSrc})
IF(WIN32) set(IQR_LIBS "${IQR_LIB_DIR}/libIqrItem.dll") ENDIF(WIN32)
TARGET_LINK_LIBRARIES (moduleArDroneBottomCamera ${OPENCV_LIBRARIES} pc_ardrone ${QT_LIBRARIES} ${IQR_LIBS} )
qt5_use_modules(moduleArDroneBottomCamera Core Widgets Network)
SET_TARGET_PROPERTIES(moduleArDroneBottomCamera PROPERTIES PREFIX "")
IF(UNIX) set (IQR_INSTALL_DIR $ENV{HOME}) ENDIF(UNIX)
IF(WIN32) set (IQR_INSTALL_DIR $ENV{USERPROFILE}) ENDIF(WIN32)
INSTALL(TARGETS moduleArDroneBottomCamera LIBRARY DESTINATION ${IQR_INSTALL_DIR}/iqr/lib/Modules RUNTIME DESTINATION ${IQR_INSTALL_DIR}/iqr/lib/Modules )
But when I try to generate this using the cmake gui I get the following output (cant post images yet so its in the link)
http://postimg.org/image/4e553z6rh/
I am running Ubuntu 14.04. Any suggestions?
Thanks
D
Fast and dirty solution: try to install opencv (You know, make && sudo make install). After installation header files should be inc /usr/local/include and library files should be in /usr/local/lib .
The problem might lay somewhere ind FindOpenCV.cmake file, so You might as well try to understand what it is doing and maybe fix it - CMake syntax is fairly straightforward.
It might check in a default instalation location instead where it lies right now, or some rarely used environment variable.