Cmake on windows, loading static library - c++

I'm preparing windows build for my qt5 application and I have problem with loading static library .lib.
My application is using 3d engine and originally was build on linux (gcc+cmake), now on windows I'm trying to use msvc+cmake. 3d engine static lib is called engined.lib. To load library I do something like that:
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
find_library(engine NAMES engined PATHS path_to_lib)
target_link_libraries(${PROJECT_NAME}
Qt5::Widgets
Qt5::OpenGL
Qt5::Xml
engine)
But during process compilation there are erros for example in my cpp file I'm loading headers:
#include "engine/Engine.h"
but, msvc do not see .h file and I have error. I'm doing something wrong?

You are linking against the library, but you still need to configure CMake so that the engine's headers are found. One way to do this is to set the location of the headers through a cache variable:
# CMakeLists.txt
set(ENGINE_INCLUDE_DIR "" CACHE PATH "Include directory")
target_include_directories(engine PRIVATE ${ENGINE_INCLUDE_DIR})
And set the variable when configuring your build directory:
cmake -DENGINE_INCLUDE_DIR=/path/to/include/dir /path/to/project

Related

Using 3rd Party Shared Object Library and header files in CMake

I am trying to use this ZED Open Capture library for using the ZED Mini camera for my project on RaspberryPi. I succesfully installed the library and the shared object file is at /usr/local/lib/libzed_open_capture.so and the include headers are at the location /usr/local/include/zed-open-capture/.
To include this library I am adding the following lines to my CMakeLists.txt
find_library(ZED_LIB zed_open_capture)
include_directories("/usr/local/include/zed-open-capture/")
add_executable(zed_pub src/zed_pub.cpp)
target_link_libraries(zed_pub ${ZED_LIB})
Now when I use this code , it shows this error "‘sl_oc::video’ has not been declared"
#include "videocapture.hpp" //Library Header File
sl_oc::video::VideoCapture cap;
cap.initializeVideo();
const sl_oc::video::Frame frame = cap.getLastFrame();
Can someone please explain me how a Shared Object Library file along with header files should be used in CMake? The library has already been installed using CMake build and sudo make install on my Linux system.
The github repo of the library is at https://github.com/stereolabs/zed-open-capture
Also I cannot find Find_PKG_name.cmake so I cannot use find_package() option.
videocapture.hpp wraps the definitions you need inside #ifdef VIDEO_MOD_AVAILABLE. It seems likely that this is not defined. The root CMakeLists.txt in the ZED package defaults BUILD_VIDEO to ON, so this was likely all defined for the package build. But as others have pointed out, the package does not persist this information anywhere in the installation. The "right" way for the package to do it would be EITHER to configure/modify the include files at install time to account for the build configuration, probably by generating a "config.hpp" file with the appropriate definitions. OR to include a zed-config.cmake file in the installation, with all the necessary imports and definitions.
Your short-circuit solution should be fine. Just add target_compile_definitions(zed_pub PUBLIC VIDEO_MOD_AVAILABLE). If you want to do it more cleanly for the future, create an IMPORTED target for zed_lib, and set both the include_directories and compile_definitions on that target, so that all users of the library get this defined automatically.
According to the ZED Open Capture's CMakeLists.txt:
...
# Install rules
set_target_properties(${PROJECT_NAME} PROPERTIES
PUBLIC_HEADER "${HDR_FULL}"
)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include/zed-open-capture)
ref: https://github.com/stereolabs/zed-open-capture/blob/dfa0aee51ccd2297782230a05ca59e697df496b2/CMakeLists.txt#L142-L148
ZED Open Capture seems to not provide any "CMake config" file...
So you must create your own FindZED.cmake module and/or improve the CMakeLists.txt of this project...

How can I use CMake and FindLibXml2 to link against a static version of LibXml2 that requires no DLL

I am modernizing our CMake build system and switching to static compilation of all dependencies so I can deploy the application as single binary. One of the dependencies is LibXml2 which is statically compiled (Environment MSVC 2019 x64 Native):
cscript configure.js iconv=no compiler=msvc cruntime=/MT debug=yes static=yes prefix=libxml
nmake Makefile.msvc libxml install
This generates the DLL win32\libxml\bin\libxml2.dll and the LIB files win32\libxml\lib\libxml2.liband win32\libxml\lib\libxml2_a.lib.
My CMake file looks like this:
find_package(LibXml2 REQUIRED)
add_executable(testapp WIN32)
target_sources(testapp
PRIVATE
Main.cpp
)
target_include_directories(testapp PUBLIC ${LIBXML_LIBRARIES})
target_link_libraries(testapp PRIVATE LibXml2::LibXml2)
Problem: It looks like the find module FindLibXml2 picks up the relocatable shared DLL, but not the static LIB archive. Thus the application is linked against the dynamic library.
Question: How can I use the find module script, but link against the static version of LibXml2? Is this even possible or do I have to write an own find script?
User #alex-reinking gave the important tip: Set the cached variable before calling the find module - and not afterwards.
Because I don't want to hardcode the path (and can't because I have a debug and release build of LibXml2), I use find_library to find the static library (Note: I added the libxml directory via CMAKE_PREFIX_PATH):
find_library(STATIC_LIBXML2_LIBRARY NAMES libxml2_a)
message(STATUS "Found library: ${STATIC_LIBXML2_LIBRARY}")
set(LIBXML2_LIBRARY ${STATIC_LIBXML2_LIBRARY})
find_package(LibXml2 REQUIRED)

cmake + cpp: No such file or directory

I've I'm trying to build this "Hello World" wxWidgets example on Linux, using the following cmake script:
cmake_minimum_required (VERSION 2.6)
project (wxL)
find_package(wxWidgets 3.0.0 REQUIRED
COMPONENTS base core net xml html adv qa richtext
)
file(GLOB SOURCES "src/*.cpp")
add_executable(wxL ${SOURCES})
Building the project yields this error:
src/wxL.cpp:3:10: fatal error: wx/wxprec.h: No such file or directory
The file specified in the include, wx/wxprec.h can be found on disk at this location:
/usr/include/wx-3.0/wx/wxprec.h
Furthermore, another program that I have built from source includes the same file (also using cmake) and builds just fine.
So, how do I use cmake to tell the compiler that the file should be included from somewhere in the system directories?
I know I'm missing something basic, but I can't figure out what.
Although you've found the package, your executable does not know anything about it.
For the executable to compile correctly, it needs to find header files for your package together with the .so / .a files. Following example should get you started:
include_directories(${wxWidgets_INCLUDE_DIRS})
add_executable(wxL <add-source-files-here>)
target_link_libraries(wxL ${wxWidgets_LIBRARIES}) // links wxWidgets libraries to your executable
Please note that using glob is not a recommended way of adding source files to your project.

Import an external library into a ROS node

It is my first time using stack overflow so I am a bit new with this. I've been working on a personal robotics project and I have downloaded a GitHub directory. I've already compiled it, tested it (it works) and I've generated the library.a file (because I'm working with Ubuntu 16.04 and ROS Kinetic). What I do not know is what I have to add to my CMakeLists.txt file in order to load the communication functions on a ROS node cpp file.
My actual description for compilation on the CMakeLists.txt file is the following one:
...
add_executable(test_node src/test_node.cpp)
add_dependencies(test_node ${catkin_EXPORTED_TARGETS})
target_link_libraries(test_node ${catkin_LIBRARIES})
...
I know that I have to add the library on the target_link_libraries if the library was an *.sofile, but it isn't. What should I add to my CMakeLists.txt file in order to load my library functions into my ROS node?
Your answer is based in a property on function add_library()
See this example block:
add_library(library_name STATIC IMPORTED)
set_target_properties(library_name PROPERTIES IMPORTED_LOCATION path/to/your/lib.a)
With this you can proceed to add this library with:
target_link_libraries(your_target library_name)
But don't forget to add this static library include files to your target.
The problem is solved with the following code:
...
find_package(Threads)
add_library(github_library STATIC IMPORTED GLOBAL)
set_target_properties(my_library PROPERTIES IMPORTED_LOCATION
my_library_directory/my_library.a)
...
target_link_libraries(my_cpp_ros_node ${catkin_LIBRARIES} my_library ${CMAKE_THREAD_LIBS_INIT})
...

Adding compiled libraries and include files to a CMake Project?

What is the best method to include a prebuilt library to a cmake project? I want to include FreeType into the project I am working on and the file structure is like this:
Build
MacOS
Make/
XCode/
Windows
VisualStudio/
Source
libs
MacOS
libfreetype
Windows
freetype.dll
includes
freetype/ (Various header files that are included automatically by ftbuild.h)
ftbuild.h (this is what is included in code from my understanding.)
MyProject
main.cpp
foo.cpp
foo.h
The library is already compiled. MyProject is the name of the current project.
Thanks!
Mike
Just use target_link_libraries with the full path to the prebuilt lib.
So, something like:
# In the file Source/MyProject/CMakeLists.txt
add_executable(my_exe main.cpp foo.cpp foo.h)
if(WIN32)
target_link_libraries(my_exe ${CMAKE_CURRENT_SOURCE_DIR}/../libs/Windows/freetype.lib)
endif()
if(APPLE)
target_link_libraries(my_exe ${CMAKE_CURRENT_SOURCE_DIR}/../libs/MacOS/libfreetype.a)
endif()
Recent versions already have a module for finding FreeType. Here's the kind of thing I've done in the past:
INCLUDE(FindFreetype)
IF(NOT FREETYPE_FOUND)
FIND_LIBRARY(FREETYPE_LIBRARIES NAMES libfreetype freetype.dll PATHS "./libs/MacOS" "./libs/Windows" DOC "Freetype library")
FIND_PATH(FREETYPE_INCLUDE_DIRS ftbuild.h "./includes" DOC "Freetype includes")
ENDIF(NOT FREETYPE_FOUND)
INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(MyProject ${FREETYPE_LIBRARIES})
You'll need to change the paths to be relative to your CMakeLists.txt.
This snippet first invokes the FindFreetype module to check in the standard system locations. If it fails to find the library there, then this falls back to checking directories relative to the your CMakeLists.txt script. If that still fails, you can still set or override the locations via the usual CMake UI. In any event, it tries to add something to the list of includes and libraries to link.