Closed genemerewether closed 7 years ago
@genemerewether IIUC you want your cross-compiled target to link to your host's console_bridge. How can that be desirable?
@rojkov - Sorry for the misunderstanding... The console_bridge on the host that I refer to is a cross-compiled version and is the correct library to link against. ROS2 builds console_bridge from source and places it in a directory on the host.
All other find_package macros in the build work as they should, but the additional
find_library(onelib ${lib} PATHS "@CMAKE_INSTALL_FULL_LIBDIR@" NO_DEFAULT_PATH )
in console_bridge-config.cmake fails because I've set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
@dirk-thomas what do you think?
I can't say much since I don't have a similar use case like this. I don't understand why the library is not found in the location it has been installed to (CMAKE_INSTALL_FULL_LIBDIR
) in the first place.
Doesn't the new argument CMAKE_FIND_ROOT_PATH_BOTH
kind of contradict NO_DEFAULT_PATH
?
The library isn't found because I've set CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
to ONLY
, which makes sense to me in a cross-compile build. The problem is the nested find_library call: I've got CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
set to BOTH
, but because console_bridge-config.cmake calls find_library, that call fails and the package is not found.
I rebuilt using NO_CMAKE_FIND_ROOT_PATH
instead of CMAKE_FIND_ROOT_PATH_BOTH
and the library is found successfully - this seems like the right way here. Without either option, the library is not found.
From CMake find_library
documentation:
The CMake variable
CMAKE_FIND_ROOT_PATH
specifies one or more directories to be prepended to all other search directories. This effectively “re-roots” the entire search under given locations. IfNO_CMAKE_FIND_ROOT_PATH
is used thenCMAKE_FIND_ROOT_PATH
will not be used
I interpret this as: even with NO_DEFAULT_PATH
, the supplied paths to find_library()
will still be re-rooted and the call will fail, unless NO_CMAKE_FIND_ROOT_PATH
is also supplied
A possible more radical approach to solve this problem at the root is to remove all the logic for finding the console_bridge
library in the console_bridge-config.cmake.in
and substitute it with the more idiomatic approach of exporting console_bridge targets.
A quick sketch of this approach (just edited through the web interface, I did not checked if it is actually working) can be found in https://github.com/ros/console_bridge/compare/master...traversaro:patch-3 .
This change would also simplify transforming console_bridge
in a relocatable CMake package.
@genemerewether BTW what exactly do you use for cross-compiling?
@rojkov
For reference (I did some digging), NO_CMAKE_FIND_ROOT_PATH
matches the way catkin works internally for generating a package_nameConfig.cmake:
(https://github.com/ros/catkin/blob/kinetic-devel/cmake/templates/pkgConfig.cmake.in#L128)
I use a Linaro Trusty developer sysroot & toolchain and I define CMAKE_TOOLCHAIN_FILE in the cmake-args to ament. That toolchain file sets the CMAKE_SYSROOT variable.
Unfortunately I've never used Linaro (I'm using OpenEmbedded for cross-compilation). Can't give any advice on that. But I find it strange too that the tool installs cross-compiled binaries to host instead of sysroot.
Regarding the code in pkgConfig.cmake.in... I had to patch it the other way around to make it work correctly for my use cases. The current logic in upstream makes wrong assumptions about build environment. In my case catkin looks for libraries in locations provided by package dependencies. The list of locations often includes not only paths inside the target sysroot, but also legitimate host paths. If it happens that the native version of a library is installed on hosts then catkin is happily trying to link to that library and fails because of wrong architecture. Here's my custom patch:
diff --git a/cmake/templates/pkgConfig.cmake.in b/cmake/templates/pkgConfig.cmake.in
index d99b811..c692108 100644
--- a/cmake/templates/pkgConfig.cmake.in
+++ b/cmake/templates/pkgConfig.cmake.in
@@ -125,9 +125,9 @@ foreach(library ${libraries})
foreach(path @PKG_CONFIG_LIB_PATHS@)
find_library(lib ${library}
PATHS ${path}
- NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+ NO_DEFAULT_PATH ONLY_CMAKE_FIND_ROOT_PATH)
if(lib)
- set(lib_path ${path})
+ get_filename_component(lib_path ${lib} DIRECTORY)
break()
endif()
endforeach()
The second change for setting lib_path
is needed because in case a lib is found in sysroot catkit continues to think that the lib resides in the host's root, not target sysroot. But I'm afraid this patch breaks the use case ROS developers need more than cross-compilation support: having ROS installed in a workspace with the possibility to link to system libraries should they be installed on the host.
I think this issue was resolved by #45; please re-open if I am mistaken
My cross-compiling toolchain sets
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
and console_bridge-config.cmake fails at the find_library line because the console_bridge library is on the host (ROS2 build). Is this a workable solution? Supported since cmake < 2.8