install targets after pybind11_add_module in cmake and Yocto - cmake

I am trying to use python to interfacing my own c++ library. Actually I can do it manually copying pybind11_example.so to the target device. I hope to do this by using install(TARGETS...
I found this link. But it doesn't help in my Yocto build.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.14.4)
project(pybind11_example)
set(CMAKE_INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../lib/math/include")
find_package(PythonLibs REQUIRED)
set(PYTHON_MODULE_EXTENSION ".so" CACHE INTERNAL "Cross python lib extension")
find_package(pybind11 REQUIRED)
pybind11_add_module(${PROJECT_NAME} pybind11_wrapper.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_INCLUDE_PATH})
target_link_libraries(${PROJECT_NAME} PRIVATE simplemath)
include(GNUInstallDirs)
# without lines below, yocto build works fine
install(TARGETS ${PROJECT_NAME}
COMPONENT python
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
This is the error from devtool build:
ERROR: pybind11-example-1.0+git999-r0 do_package: QA Issue: pybind11-example: Files/directories were installed but not shipped in any package:
/usr/lib/pybind11_example.so
Please set FILES such that these items are packaged. Alternatively if they are unneeded, avoid installing them or delete them within do_install.
pybind11-example: 1 installed and not shipped files. [installed-vs-shipped]
ERROR: pybind11-example-1.0+git999-r0 do_package: Fatal QA errors found, failing task.

Oops, I found the reason. The problem was not in cmake but in .bb file.
After I add FILES_${PN} += "/usr/lib" in the .bb, it works fine.
For more detail, please see this link.

Related

CMake TARGET_RUNTIME_DLLS is empty

I have git cloned, built (with MSVC for both Debug and Release) and then installed wxWidgets:
cmake -B build wxWidgets
cmake --build build --config <CONFIG>
cmake --install build --prefix my_install --config <CONFIG>
with <CONFIG> = Debug and <CONFIG> = Release.
Then I used the following CMake script to link against it, as suggested by the wiki:
cmake_minimum_required(VERSION 3.16)
project(Test)
add_executable(Test WIN32 Main.cpp)
# wxWidgets
SET(wxWidgets_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../thirdparty/my_install)
find_package(wxWidgets COMPONENTS core base REQUIRED)
include(${wxWidgets_USE_FILE})
target_link_libraries(Test PRIVATE ${wxWidgets_LIBRARIES})
# Copy runtime DLLs to the directory of the executable.
add_custom_command(TARGET Test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Runtime Dlls: $<TARGET_RUNTIME_DLLS:Test>"
)
My goal is to automatically copy the DLLs into the directory of the built executable, so that they can be found at runtime. For that I'm using the TARGET_RUNTIME_DLLS generator expression (follwing the sample code in the docs). In the code above, I only print out the expression at build time for testing purposes. The problem is that it is empty.
The approach worked for me before when installing and linking SDL, but SDL provides package configuration files which create imported targets, defining the DLL location(s) via IMPORTED_LOCATION_RELEASE or IMPORTED_LOCATION_DEBUG. For wxWidgets one is apparently supposed to use the FindwxWidgets.cmake script shipped with CMake, which sadly doesn't define the produced binaries. Maybe that's why TARGET_RUNTIME_DLLS isn't populated.
Does anyone know, either how to get TARGET_RUNTIME_DLLS filled or how to obtain the list of built wxWidgets DLLs for the current configuration (Release/Debug) post build copying?
Thanks a lot in advance!
I am dealing with a similar problem.
First sanity checks:
You have to work on windows platform otherwise this feature does not
work.
Your Cmake is 3.21 or above
Next comes fuzzy part. I think the library that you are trying to include have to be a Shared Imported library and you have to set a set_target_properties for IMPORTED_IMPLIB which is a path to a .lib file of sort (dll import library, I think it is called) So you have to make sure that it is all set in the package library that you trying to link with your executable.
If you have those dll avaiable and you just want to use them and not actually build them then you can write your own cmake script that will do just what I said above. Then you can include that cmake file in your project and then link against your app.
Note: I also work on similar issue right now and what I just said have not been working very reliably. I got some dlls to be copied and some do not.
Edit:
Cmake docs give a more detailed explanation on how this library setting should look like if you use find_package feature.
Found here: https://cmake.org/cmake/help/latest/command/add_library.html#imported-libraries
An UNKNOWN library type is typically only used in the implementation
of Find Modules. It allows the path to an imported library (often
found using the find_library() command) to be used without having to
know what type of library it is. This is especially useful on Windows
where a static library and a DLL's import library both have the same
file extension.

Cmake and vcpkg - find the correct library name

I have troubles finding out the right "library target name" to be used in a cmake file, for packages installed using vcpkg.
In example, I installed the gtest package using vcpkg install gtest. My sample cmake file looks like:
#CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(example)
add_executable(main main.cpp)
find_package(gtest REQUIRED)
target_link_libraries(main gtest) # here, "gtest" is not the right name!
Running cmake, a solution for Visual Studio is generated, but after running cmake --build ., I get the error:
../use-cmake-vcpkg\main.cpp(1): fatal error C1083: Cannot open include file: 'gtest/gtest.h': No such file or directory ..
Turns out the line: target_link_libraries(main gtest) isn't correct, and I need to use another "name" to include/link the gtest package.
Is there a way (using cmake or vcpkg) to find out what is the correct target name to be used? (for gtest in this case, but also for any other pacakage?)
When use find_package(XXX), it can work in two modes: MODULE and CONFIG. And resulted variables and targets of this call depend on the mode.
If FindXXX.cmake file exists (and can be found), the MODULE mode is used and given file is processed. Otherwise, if the package is shipped with XXXConfig.cmake file, CONFIG mode is used and given file is processed. If none of this file exists, CMake emits an error (if called with REQUIRED keyword) or a warning (without REQUIRED keyword).
In case of gtest package, CMake is shipped with FindXXX.cmake script, so this script is processed in MODULE mode. You may find description of this script in the documentation, which tells that you need to use GTest::GTest target for link with gtest:
target_link_libraries(main GTest::GTest)
Not all packages provide a CMake library definition. If you're lucky, then vcpkg install will show you the name:
$ ./vcpkg install openssl
The package openssl is compatible with built-in CMake targets:
find_package(OpenSSL REQUIRED)
target_link_libraries(main PRIVATE OpenSSL::SSL OpenSSL::Crypto)
This will work even if you've already installed the package, so you can use it anytime to query the package name.
On the other hand, if vcpkg install <pkg> doesn't say anything about CMake, then you need to include it manually in your CMake file, by finding the include path and the library files.
Here is an example of such a case, here for the live555 library:
# Use one of the headers to locate the include location
find_path(LIVE555_INCLUDE_DIR liveMedia.hh)
# Find the libraries
find_library(LIVE555_LIBRARY1 liveMedia)
find_library(LIVE555_LIBRARY2 groupsock)
find_library(LIVE555_LIBRARY3 BasicUsageEnvironment)
find_library(LIVE555_LIBRARY4 UsageEnvironment)
add_executable(rtsp testRTSPClient.cpp)
target_include_directories(rtsp PRIVATE ${LIVE555_INCLUDE_DIR})
target_link_libraries(rtsp PRIVATE ${LIVE555_LIBRARY1} ${LIVE555_LIBRARY2} ${LIVE555_LIBRARY3} ${LIVE555_LIBRARY4})

Why does CMAKE installed target fail to link to provided libraries?

I'm building a target that depends on some provided libraries. My src directory hierarchy looks like this:
I use the following CMakeLists.txt to build a target and install it within the build/install directory:
cmake_minimum_required(VERSION 2.8.3)
project(example)
include_directories(include)
link_directories(lib)
add_executable(${PROJECT_NAME}
src/example.cpp)
target_link_libraries(${PROJECT_NAME}
curlpp)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
install(TARGETS ${PROJECT_NAME}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)
install(FILES lib/libcurlpp.a lib/libcurlpp.so lib/libcurlpp.so.1 lib/libcurlpp.so.1.0.0 DESTINATION deps)
When I do a simple build, everything is fine and the target is properly linked to the provided libraries. But when I do make install, the target is generated but fails to link to the libraries:
I understand the linkage failure of the installed target: the install/deps directory is not in the LD_LIBRARY_PATH of my environment. But what has cmake done to make the directly built target link correctly? Can I do something similar to make the installed target work properly?
Here is a minimal replication of the problem

Cmake GNUInstallDirs variables empty

When trying to compile my project using cmake ., variable CMAKE_INSTALL_LIBDIR is empty and I have no idea why.
I'm trying to issue the following (on line 40):
install(TARGETS fpthread
EXPORT fpthread_config
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
I get the following error message:
CMake Error at CMakeLists.txt:40 (install):
install TARGETS given no LIBRARY DESTINATION for shared library target
"fpthread".
Issuing the following results in an empty string:
MESSAGE(STATUS ${CMAKE_INSTALL_LIBDIR})
I've tried both Cmake 3.5 (installed through package manager) and Cmake 3.11 (latest release, compiled from source).
Reformulating my previous comment as answer:
To access variables from the GNUInstallDirs module you need to add
include(GNUInstallDirs)
to your CMakeLists.txt file. The module is not included by default.

CMake not able to find Debug Library

I am a CMake noob trying to put together a package installer so i can move between my windows development machine and my cluster.
I have the following directory tree for my files (an example)
-Primary
--Library Source
--CMakeLists.txt
--src1.cpp
--src1.h
--Application Source
--CMakeLists.txt
--src1.cpp
--src1.h
--CMakeLists.txt
Each CMakeLists.txt is
Primary/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(BloodVesselRadiationDamageSimulations CXX)
SET(FIND_LIBRARY_USE_LIB64_PATHS true)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}) #only for testing
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_ROOT}/ ${CMAKE_SOURCE_DIR}/cmake/Modules/")
FIND_PACKAGE(OpenMP)
FIND_PACKAGE(MPI)
FIND_PACKAGE(HDF5)
FIND_PACKAGE(GTest)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
SET(CMAKE_DEBUG_POSTFIX _d)
ADD_SUBDIRECTORY(Source)
ADD_SUBDIRECTORY(SourceUnitTest)
Library Source/CMakeLists.txt
ADD_LIBRARY(VesselProjectBaseLibrary STATIC Src1.cpp
Src1.h)
INSTALL(TARGETS VesselProjectBaseLibrary DESTINATION x64/Debug CONFIGURATIONS Debug)
INSTALL(TARGETS VesselProjectBaseLibrary DESTINATION x64/Release CONFIGURATIONS Release|RelWithDebInfo)
Application Source/CMakeLists.txt
INCLUDE_DIRECTORIES("${GTEST_INCLUDE_DIRS}")
ADD_EXECUTABLE (SourceUnitTests Src1.cpp
Src1.h)
TARGET_LINK_LIBRARIES(SourceUnitTests ${GTEST_LIBRARY})
TARGET_LINK_LIBRARIES(SourceUnitTests debug VesselProjectBaseLibrary_d optimized VesselProjectBaseLibrary)
I am able to generate the projects correctly; I see all the correct files in the projects. However, when i go to compile the debug build I get the following error:
1>ipo: : error #11018: Cannot open VesselProjectBaseLibrary_d.lib
1>LINK : fatal error LNK1104: cannot open file 'VesselProjectBaseLibrary_d.lib'
If i compile my release build everything works perfectly and compilation is successful. The library compiles successfully under both builds.
When you link against a library created within the project, you need to specify library target name, not a library file. CMake will care about proper filename, path and other things:
TARGET_LINK_LIBRARIES(SourceUnitTests VesselProjectBaseLibrary)
Variable CMAKE_DEBUG_POSTFIX affects on library's filename. While file VesselProjectBaseLibrary_d.lib is actually created in debug build, it cannot be found automatically by the linker. Again, use target name and let CMake do all other work.