Linking external HDFql library in CMake - c++

I have downloaded the HDFql library and put the whole lot in /usr/local/ in my linux system. I now wish to use this library in a ROS application, so I have tried to link it in my CMakeList, which looks as following:
cmake_minimum_required(VERSION 3.2)
project(data_generator)
add_compile_options(-std=c++11)
set(CMAKE_BUILD_TYPE Release) # Release, RelWithDebInfo
set(CMAKE_CXX_FLAGS "-std=c++11 -pthread ${CMAKE_CXX_FLAGS}")
find_package(catkin_simple REQUIRED)
catkin_simple(ALL_DEPS_REQUIRED)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
set(HDFQL_ROOT "/usr/local/hdfql-2.1.0")
include_directories(${HDFQL_ROOT}/include)
find_library(HDFQL_LIB HDFql)
if (HDFQL_LIB)
message("Library(HDFQL_LIB) found in ${HDFQL_LIB}")
else()
message(FATAL_ERROR "Library (HDFQL_LIB) not found")
endif()
cs_add_executable(
${PROJECT_NAME}
src/main.cpp
src/data_create.cpp
src/event_definitions.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC "${HDFQL_ROOT}/include"
)
target_link_libraries(${PROJECT_NAME}
${OpenCV_LIBRARIES}
${HDFQL_LIB}
)
# CMake Indexing
FILE(GLOB_RECURSE LibFiles "include/*")
add_custom_target(headers SOURCES ${LibFiles})
cs_install()
cs_export()
When I build this, it works fine and outputs the message:
Library(HDFQL_LIB) found in /usr/local/hdfql-2.1.0/lib/libHDFql.so
with the following in my main.cpp file:
#include <HDFql.hpp>
....
std::cout <<"HDFql version: " << HDFql::Version << std::endl;
the output is: HDFql version: 2.1.0.
However, as soon as I try to actually use functions of the library - for example:
#include <HDFql.hpp>
....
std::cout <<"HDFql version: " << HDFql::Version << std::endl;
HDFql::execute("CREATE FILE /home/user/test.h5");
I get the error:
main.cpp:(.text+0x1858): undefined reference to `HDFql::execute(char const*)'
This suggests to me that while CMake has no issue with the includes, it is having trouble linking the actual library (ie including the libHDFql.a/libHDFql.so files). Can anyone tell me what I'm doing wrong here?
Many thanks!

The problem was that I needed to include the library /usr/local/hdfql-2.1.0/wrapper/cpp/libHDFql.so, where I was using /usr/local/hdfql-2.1.0/lib/libHDFql.so. It's pretty maddening, since the reference manual doesn't make any mention of this and I spent way too long figuring this out. Ohwell, I hope this helps anyone else with this problem.
For reference, here is a minimal catkin-style CMakeLists that will work:
cmake_minimum_required(VERSION 3.2)
project(project_name)
add_compile_options(-std=c++11)
find_package(catkin_simple REQUIRED)
catkin_simple(ALL_DEPS_REQUIRED)
set(HDFQL_ROOT "path/to/hdfql-2.1.0")
include_directories(${HDFQL_ROOT}/include)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "-std=c++11 -pthread ${CMAKE_CXX_FLAGS}")
cs_add_executable(
${PROJECT_NAME}
# your source file 1
# your source file 2
# ...
)
target_include_directories(${PROJECT_NAME}
PUBLIC "${HDFQL_ROOT}/include"
)
target_link_libraries(
${PROJECT_NAME}
${OpenCV_LIBRARIES}
)
target_link_libraries(
${PROJECT_NAME}
"${HDFQL_ROOT}/wrapper/cpp/libHDFql.so"
)
Of course the absolute paths aren't very pretty, the alternative is to add /usr/local/hdfql-2.1.0/lib to the environment variable CMAKE_PREFIX_PATH (eg export CMAKE_PREFIX_PATH="/usr/local/hdfql-2.1.0/lib:$CMAKE_PREFIX_PATH").

Related

How can I make fat execuatable file in CMAKE?

I am newbie on CMAKE. I am trying to make "fat executable file".
The term, fat executeable file, I mentioned, is a executable binary file which contains all shared libraries and can be just run in another environment.
Example (Trouble Situation)
There is ComputerA which is a computer that I used for developing. There is GCC, Boost libraries, librados etc.
And there is ComputerB which is a computer that I wanted to execute the binary that I built.
* Of course, Both Computer A and B have some conditions. Same Intel CPU Arch. (i7), Same CentOS.
I built binary file in ComputerA using CMAKE with this command, cmake .. && make. And I copied this file to ComputerB and executed.
When I execute the copied binary file in Computer B, it said like below.
[root#ComputerB ~]# ./binaryFile 123.123.123.123
./binaryFile: error while loading shared libraries: libboost_json.so.1.80.0: cannot open shared object file: No such file or directory
I understand what this error message say. There is no shared library which it needed. So, what I want to ask in this community is, What is CMAKE Command for containing shared libraries.
Similar thing :: fat JAR
The reason, why I called "fat executable file", is that there is a word "fat JAR" in Java. I am not familiar with Java. But it is commonly used word in Java community.
My CMAKE File
It contains some libraries like Boost, Rados, RBD etc. (There will be more according to progress of developing)
cmake_minimum_required(VERSION 3.2.0)
project(BinaryHelper VERSION 0.1.0)
find_package(Boost REQUIRED COMPONENTS json)
include_directories(${Boost_INCLUDE_DIR})
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrados -std=c++17")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_executable(
${PROJECT_NAME}
main.cpp
utils/binary.cpp
utils/message.cpp
utils/header.cpp
)
target_link_libraries (
${PROJECT_NAME}
${Boost_LIBRARIES}
rados
rbd
Threads::Threads
)
Thanks to #HolyBlackCat, I solved the problem with static link.
Modified CMAKE
cmake_minimum_required(VERSION 3.2.0)
project(BinaryHelper VERSION 0.1.0)
find_package(Boost REQUIRED COMPONENTS json)
include_directories(${Boost_INCLUDE_DIR})
set(Boost_USE_STATIC_LIBS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrados -std=c++17")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
add_library(
boost_json
STATIC
IMPORTED
)
set_target_properties(
boost_json
PROPERTIES
IMPORTED_LOCATION /usr/local/lib/libboost_json.a
)
add_executable(
${PROJECT_NAME}
main.cpp
utils/binary.cpp
utils/message.cpp
utils/header.cpp
)
# target_link_libraries (
# ${PROJECT_NAME}
# ${Boost_LIBRARIES}
# rados
# rbd
# Threads::Threads
# )
target_link_libraries(
${PROJECT_NAME}
boost_json
rados
rbd
Threads::Threads
)
There is additional(modified) keywords, add_library, set_target_properties, target_link_libraries.

Cmake using git-submodule inside a shared library

I try to add the library spdlog to a dll (.so file). The spdlog is just a git submodule from the spdlog library. Looking at the documentation, it's recommended to use it as a static library. So i think i have a problem trying to compile it inside a .so file.
To get a clear view of what i'm doing, here is a pic of my system:
My root CMakeLists.txt is :
cmake_minimum_required(VERSION 3.23)
# set the project name
project(Test VERSION "0.1.0" LANGUAGES CXX)
configure_file(config/config.h.in config.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")
# Set location for .so files
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}")
# Set location for executables
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
add_subdirectory(Engine)
list(APPEND EXTRA_LIBS Engine)
add_subdirectory(Game)
target_link_libraries(Test PUBLIC ${EXTRA_LIBS})
target_include_directories(Test PUBLIC
"${PROJECT_BINARY_DIR}"
)
And inside the Engine folder:
message(STATUS "BUILD Engine shared library File")
add_subdirectory(spdlog)
add_library(Engine SHARED Log.cpp Log.h)
target_include_directories(Engine
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(Engine
spdlog
)
target_include_directories(Engine
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/spdlog/include
)
Inside the Game (not relevant at my opinion)
message(STATUS "BUILD .exe File")
# add the executable
add_executable(Test main.cpp)
But currently, if i try to use the spdlog inside my Log file, i have this cryptic error:
[build] /usr/bin/ld: spdlog/libspdlogd.a(spdlog.cpp.o): relocation R_X86_64_TPOFF32 against `_ZGVZN6spdlog7details2os9thread_idEvE3tid' can not be used when making a shared object; recompile with -fPIC
Does anyone have an idea?
Thanks to fabian in the comments, I add
set(CMAKE_POSITION_INDEPENDENT_CODE 1)
Just before adding the spdlog subdirectory and it just works fine.

CMake build error: undefined reference to 'deflateEnd'

I'm trying to use zlib in my project. The CMakeLists.txt is as follows:
cmake_minimum_required(VERSION 3.5)
project(cmake-demo LANGUAGES CXX)
# The version number.
set(CMDemo_VERSION_MAJOR 0)
set(CMDemo_VERSION_MINOR 1)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(${PROJECT_SOURCE_DIR}/build/conan_paths.cmake)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/build)
find_package(uwebsockets)
#ZLIB
if(ZLIB_FOUND)
set(INC_DIRS ${INC_DIRS} ${ZLIB_INCLUDE_DIRS})
set(LINK_LIBS ${LINK_LIBS} ${ZLIB_LIBS})
endif()
# Global approach
if(uwebsockets_FOUND)
set(INC_DIRS ${INC_DIRS} ${uwebsockets_INCLUDE_DIRS})
set(LINK_LIBS ${LINK_LIBS} ${uwebsockets_LIBS})
endif()
#libuv
if(libuv_FOUND)
set(INC_DIRS ${INC_DIRS} ${libuv_INCLUDE_DIRS})
set(LINK_LIBS ${LINK_LIBS} ${libuv_LIBS})
endif()
#usockets
if(usockets_FOUND)
set(INC_DIRS ${INC_DIRS} ${usockets_INCLUDE_DIRS})
set(LINK_LIBS ${LINK_LIBS} ${usockets_LIBS})
endif()
include_directories(${INC_DIRS})
add_executable(${PROJECT_NAME} main.cpp)
message("libs=${LINK_LIBS}")
target_link_libraries(${PROJECT_NAME} ${LINK_LIBS})
#output of message("${LINK_LIBS}")
C:/ProgramData/Miniconda3/Library/lib/z.lib;C:/Users/Sunway/.conan/data/libuv/1.41.0/_/_/package/9965605309592d7e617ec929633249a2031e4263/lib/libuv_a.a;C:/Users/Sunway/.conan/data/usockets/0.7.1/_/_/package/a24f5291464b4270092bce2e738cbf9f3cd53bb7/lib/libuSockets.a
I'm sure that ${LINK_LIBS} is correct, but it still doesn't work:
CMakeFiles/cmake-demo.dir/main.cpp.obj: In function `ZN3uWS15DeflationStreamD1Ev':
C:/Users/Sunway/.conan/data/uwebsockets/19.2.0/_/_/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/uWebSockets/PerMessageDeflate.h:186: undefined reference to `deflateEnd'
os: Windows10 x64
IDE: QtCreator4.14.2
compiler: MinGW 32-bit
The thing is, that you have to set the path to the library file as the target_link_libraries argument.
According to the documentation, if you want to link the library, each argument of target_link_libraries can be:
A library target name
A full path to a library file (e.g. /usr/lib/foo.so)
A plain library name (e.g. foo)
In your case I suggest you to add the complete path to the library.
I don't have all the code of your project, so I suggest you consider this minimal example:
add_executable(test main.cpp)
SET (ZLIB_ROOT "/tmp/zlib")
SET (ZLIB_INCLUDE_DIR "/tmp/zlib/include/")
SET (ZLIB_LIBRARY "/tmp/zlib/lib/libz.so.1.2.11")
FIND_PACKAGE (ZLIB REQUIRED)
MESSAGE (" zlib version major is " ${ZLIB_VERSION_MAJOR})
MESSAGE (" zlib version minor is " ${ZLIB_VERSION_MINOR})
MESSAGE (" zlib include is " ${ZLIB_INCLUDE_DIR})
MESSAGE (" zlib libraries are " ${ZLIB_LIBRARIES})
target_link_libraries(test ${ZLIB_LIBRARIES})
After downloading the latest zlib release and installing it in /tmp, everything works as expected.
Update: as #uilianries mentioned, since you are using conan, you have cmake_find_package generator that defines variables with all the necessary paths. So you don't need to set the paths in CMakeLists.txt manually.
It is because the libzlib.a is for x86_64 while the compiler is MinGW-32bit; I solved the problem by execute the command
$conan install .. --build=missing --pr=x86_32
the x86_64 is a profile(x86) generated by conan.

Creation of a cmake module for using a library

I am new to C++ and have just started to use Cmake for linking the libraries to my project. I need to use a library:
https://github.com/Gnimuc/FastPD
Fortunately, I managed to build the library using Cmake (in my build there is no *.lib file at all), but I don't know how to link it to my project. I mean that I don't know how to add it to my cmakelists.txt :
(PS. I'm also using two other libraries ITK and VTK; but I can't link the above mentioned library to my project or main.cpp.)
################################################
cmake_minimum_required(VERSION 2.8)
project(My_project)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
add_executable(My_project MACOSX_BUNDLE main.cpp)
target_link_libraries(My_project
${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES})
################################################
Thanks in advance for your helps,
Assuming you installed the library and its header files, you can then search for the header files using find_path, and add the found path to the include directories. Then you can search for the library by using find_library, and add the library with the target_link_libraries command.
I tried both shared and static types for creation of the library. In the case of shared, no *.lib file was created, and in the case of static, my project couldn't link to the library. Therefore, in my project's CmakeLists.txt, I decided to add all the *.cpp and headers as libraries and then link them together (as I didn't know the dependency among them!!!), and finally, I linked them to my project. Perhaps it does not make sense but it works; hope it helps you:
CmakeLists.txt
##############################################
cmake_minimum_required(VERSION 2.6)
set(PROJ_NAME PROJECT46)
PROJECT(${PROJ_NAME})
# Prevent compilation in-source
if( ${CMAKE_BINARY_DIR} STREQUAL ${PROJECT_SOURCE_DIR} )
Message( " " )
Message( FATAL_ERROR "Source and build directories are the same.
Create an empty build directory,
change into it and re-invoke cmake")
endif()
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support.
Please use a different C++ compiler.")
endif()
##############################################
## External libraries
##############################################
list( APPEND CMAKE_MODULE_PATH
${PROJECT_SOURCE_DIR}/cmake
)
# Blitz
find_package( Blitz++ REQUIRED )
list( APPEND PROJ_INCLUDE_DIRS
${Blitz++_INCLUDE_DIR}
)
list( APPEND
PROJ_LIB
${Blitz++_LIBRARIES}
)
# ITK and VTK
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
##############################################
# FASTPD
add_library(FASTPD Fast_PD.cpp Fast_PD.h common.h block.h)
add_library(GRAPH graph.h graph.cpp)
add_library(linked LinkedBlockList.h LinkedBlockList.cpp)
add_library(MAXFLOW maxflow.cpp)
include_directories(${PROJ_INCLUDE_DIRS})
add_executable(${PROJ_NAME} main.cpp)
target_link_libraries(linked MAXFLOW)
target_link_libraries(GRAPH linked)
target_link_libraries(FASTPD GRAPH)
target_link_libraries(${PROJ_NAME} FASTPD)
target_link_libraries(${PROJ_NAME}
${PROJ_LIB} ${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES}
)

C / C++ Library Linking with CMake

I need to use MongoDB C Drivers in a c++ project. I want to use CMake because the IDE i'm using is well integrated with it but the compiler doesn't recognize the MongoDB drivers
So, I've tried a couple more things and to provide you with a bit more information. I've made the following script:
cmake_minimum_required(VERSION 3.2)
project(sorting)
set(ENV{PKG_CONFIG_PATH} "/usr/lib64")
find_package(PkgConfig REQUIRED)
pkg_search_module(MONGO REQUIRED mongoc-1.0)
message(SEND_ERROR "A ${MONGO_FOUND}") # Error:A 1
message(SEND_ERROR "B ${MONGO_LIBRARIES}") # Error:B ssl;crypto;rt;mongoc-1.0;bson-1.0
message(SEND_ERROR "C ${MONGO_LIBRARY_DIRS}") # Error:C /usr/lib64
message(SEND_ERROR "D ${MONGO_LDFLAGS}") # Error:D -L/usr/lib64;-lssl;-lcrypto;-lrt;-lmongoc-1.0;-lbson-1.0
message(SEND_ERROR "E ${MONGO_LDFLAGS_OTHER}")# Error:E
message(SEND_ERROR "F ${MONGO_INCLUDE_DIRS}") # Error:F /usr/include/libmongoc-1.0;/usr/include/libbson-1.0
message(SEND_ERROR "G ${MONGO_CFLAGS}") # Error:G -I/usr/include/libmongoc-1.0;-I/usr/include/libbson-1.0
message(SEND_ERROR "H ${MONGO_CFLAGS_OTHER}") # Error:H
include_directories(${MONGO_LIBRARY_DIRS})
include_directories(${MONGO_INCLUDE_DIRS})
#link_directories(${MONGO_LIBRARY_DIRS})
#link_directories(${MONGO_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(sorting ${SOURCE_FILES})
target_link_libraries(sorting ${MONGO_LIBRARIES})
When i remove all the message() functions from my cmake file and try to build run the project whith the include_directories uncomented i get this error:
error while loading shared libraries: libmongoc-1.0.so.0: cannot open shared object file: No such file or directory
When i comment the include_directories and uncomment link_directories i get this error:
fatal error: mongoc.h: No such file or directory
#include <mongoc.h>
Also, just out of curiosity why is it that if i chage the name MONGO in pkg_search_module to something like MONGODB or MONG i get this error:
Error:None of the required 'mongoc-1.0' found
You need to tell cmake to link to the monog library, that is achieved by means of the
TARGET_LINK_LIBRARIES
command, in your specific case it would go right after the ADD_EXECUTABLE command, and exactly like
TARGET_LINK_LIBRARIES(sorting ${MONGO_DB_LIBRARIES})
Also, your PKG_SEARCH_MODULE seems to be wrong, it seems that it should be
PKG_SEARCH_MODULE(MONGO_DB REQUIRED libmongoc-1.0)
I am able to compile the mongo sample code given using
cmake_minimum_required(VERSION 2.8)
project(sorting)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
include_directories(/usr/include/libmongoc-1.0 /usr/include/libbson-1.0)
find_library(MONGODB_LIBRARY mongoc-1.0)
find_library(BSON_LIBRARY bson-1.0)
add_executable(sorting ${SOURCE_FILES})
target_link_libraries(sorting ${MONGODB_LIBRARY} ${BSON_LIBRARY})
Can you try with this CMakeFiles.txt ?
BTW it exists a mongo driver c++ for c++ projects !
I was finally able to do it!
The environment variable LD_LIBRARY_PATH was being overwritten by my IDE (CLION). I set it in the IDE settings to point to the library dir and now everything works fine.
This was the configuration i used:
cmake_minimum_required(VERSION 3.2)
project(sorting C)
set(ENV{PKG_CONFIG_PATH} "")
find_package(PkgConfig REQUIRED)
pkg_search_module(MONGO REQUIRED mongoc)
include_directories(${MONGO_INCLUDE_DIRS})
include_directories(${MONGO_LIBRARY_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.c)
add_executable(sorting ${SOURCE_FILES})
target_link_libraries(sorting ${MONGO_LIBRARIES} )