0
$\begingroup$

Rosanswers logo

I'm trying to run catkin_make_isolated on my workspace and it fails.

==> Processing catkin package: 'motor_driver_pkg'
==> Building with env: '/home/user/catkin_ws/devel_isolated/kinematics/env.sh'
Makefile exists, skipping explicit cmake invocation...
==> make cmake_check_build_system in '/home/user/catkin_ws/build_isolated/motor_driver_pkg'
==> make -j6 -l6 in '/home/user/catkin_ws/build_isolated/motor_driver_pkg'
[ 50%] Linking CXX executable /home/user/catkin_ws/devel_isolated/motor_driver_pkg/lib/motor_driver_pkg/dc_motor_driver
/usr/bin/ld: cannot find -lkinematics
collect2: error: ld returned 1 exit status
CMakeFiles/dc_motor_driver.dir/build.make:119: recipe for target '/home/user/catkin_ws/devel_isolated/motor_driver_pkg/lib/motor_driver_pkg/dc_motor_driver' failed
make[2]: *** [/home/user/catkin_ws/devel_isolated/motor_driver_pkg/lib/motor_driver_pkg/dc_motor_driver] Error 1
CMakeFiles/Makefile2:1091: recipe for target 'CMakeFiles/dc_motor_driver.dir/all' failed
make[1]: *** [CMakeFiles/dc_motor_driver.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2
<== Failed to process package 'motor_driver_pkg': 
  Command '['/home/user/catkin_ws/devel_isolated/kinematics/env.sh', 'make', '-j6', '-l6']' returned non-zero exit status 2

Reproduce this error by running:
==> cd /home/user/catkin_ws/build_isolated/motor_driver_pkg && /home/user/catkin_ws/devel_isolated/kinematics/env.sh make -j6 -l6

Command failed, exiting.

I have a package called kinematics, this is the CMakeLists.txt of that package

cmake_minimum_required(VERSION 2.8.3)
project(kinematics)

find_package(catkin REQUIRED COMPONENTS
  controller_interface
  roscpp
)

###################################
## catkin specific configuration ##
###################################
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package()

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
 include
  ${catkin_INCLUDE_DIRS}
)

add_library(kinematics 
  src/ackermann.cpp
  src/diff_drive.cpp)
target_link_libraries(kinematics ${catkin_LIBRARIES})


#############
## Install ##
#############

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  FILES_MATCHING PATTERN "*.h"
  PATTERN ".svn" EXCLUDE)

install(TARGETS kinematics
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)

I have another package called motor_driver_pkg that takes uses the library "kinematics" from kinematics package. This is the CMakeLists.txt for that package.

cmake_minimum_required(VERSION 2.8.3)
project(motor_driver_pkg)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  tf
  kinematics
)

###################################
## catkin specific configuration ##
###################################
catkin_package()

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(include 
  ${catkin_INCLUDE_DIRS}
  ${kinematics_INCLUDE_DIRS}
)

add_executable(dc_motor_driver src/dc_motor_driver.cpp)
target_link_libraries(dc_motor_driver kinematics ${catkin_LIBRARIES})

This works completely fine with catkin_make. But fails when I run catkin_make_isolated. I understand that the motor_driver_pkg is not able to find the kinematics library. Need help. Don't know what is going wrong.


Originally posted by venkisagunner on ROS Answers with karma: 89 on 2019-01-29

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

tl;dr: change the catkin_package() call in the CMakeLists.txt of your kinematics package to the following:

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES kinematics)

Refer to Building and installing C++ libraries and headers in the Catkin documentation for more information about exporting information from Catkin packages.


Longer explanation:

Don't know what is going wrong.

You have this in the motor_driver_pkg:

target_link_libraries(dc_motor_driver kinematics ${catkin_LIBRARIES})

Thing is, CMake assumes that if you provide the name of a library directly (as you do with kinematics) you're referring to something it calls a target. It takes the name of the target you specify and then tries to look up information about it in its internal data structures.

If the target is defined in the same CMake context, this will work fine. It'll find the information it needs (such as the actual filename and path associated with that target) and then essentially replace the name of the target with whatever information is required by the particular CMake statement that the target's name is being used in.

In this case that would be the absolute path to the actual file that constitutes the kinematics library (probably something like /path/to/your/catkin_ws/devel/lib/kinematics/libkinematics.so (or something like that, could be different)).

This works completely fine with catkin_make. But fails when I run catkin_make_isolated.

So the issue here is the "CMake context": catkin_make combines all of the CMakeLists.txt it finds in your workspace into one and then begins the build process (it doesn't really do this, but for this explanation we're pretending it does). That creates a single context, in which the target name kinematics actually means something, namely: the target defined in the CMakeLists.txt of your kinematics package. So when CMake encounters the target_link_libraries(dc_motor_driver kinematics ..) it can look up the name kinematics and it'll find the information it needs to make that statement succeed.

With catkin_make_isolated things are completely different: as the isolated in the name implies, catkin_make_isolated does not coalesce all CMakeLists.txt into a single context, but keeps everything .. isolated.

It should now be clear why looking up the target name kinematics fails in this case: kinematics is only a defined target in the context of the CMakeLists.txt of your kinematics package. Nowhere else. So CMake fails to lookup the information it needs with the error message you show as a result.

I understand that the motor_driver_pkg is not able to find the kinematics library

It should also be clear that motor_driver_pkg is not actually looking for anything. It's CMake.


To fix this, we need to make some information available to consuming packages that allows them to find the information (and files) they need.

For Catkin packages that would like to make libraries available to other Catkin packages, that is done by the catkin_package(..) statement, in particular with the LIBRARIES argument followed by a list of library targets of which the information should be exported.

Your kinematics package does have a catkin_package() statement there, but it's completely empty. So Catkin does not export any information from the kinematics package, leading to CMake not being able to do anything when it encounters the kinematics target name in the build script of motor_driver_pkg.

To fix this, change the CMakeLists.txt of kinematics to contain the following call to catkin_package(..):

catkin_package(LIBRARIES kinematics)

(and perhaps even catkin_package(LIBRARIES ${PROJECT_NAME}), as the name of the library is identical to the name of the project).

You'll probably also want to be able to export information about the include directories that are needed to be able to use the headers of kinematics. You'd do that as follows:

catkin_package(
  INCLUDE_DIRS include
  LIBRARIES kinematics)

Now consuming packages can just add kinematics to their find_package(catkin COMPONENTS ..) call and then the catkin_INCLUDE_DIRS and catkin_LIBRARIES will contain all the necessary bits for linking and compiling to succeed.


Originally posted by gvdhoorn with karma: 86574 on 2019-01-30

This answer was ACCEPTED on the original site

Post score: 2


Original comments

Comment by gvdhoorn on 2019-01-30:
Note also that this is a CMake problem: you cannot just refer to target names that are not defined (or imported) in the current context.

Comment by venkisagunner on 2019-01-30:
Yes. Thank you very much. That was the issue. While linking shared libraries while performing catkin_make_isolated, we have to use the catkin_package macro and do not use target_link_libraries. It was actually working and I broke it by adding a library to the target_link_libraries.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.