Git Product home page Git Product logo

Comments (15)

dirk-thomas avatar dirk-thomas commented on August 20, 2024

At the moment ament_cmake neither generates any .pc files nor does it use pkg-config to look for packages. Therefore I don't see why ament_cmake should use / handle / set / touch the environment variable PKG_CONFIG_PATH.

A package which installs .pc files should probably export an environment hook which prepends the installed location to the environment variable PKG_CONFIG_PATH. Then downstream packages can find it without modifying the environment themselves.

If the package doesn't extend the environment variable packages trying to use it can do it for them before trying to call pkg-config. Assuming that you are using pkg-config in your package and dependency provides a .pc file but doesn't extend the environment variable PKG_CONFIG_PATH it seems appropriate to me that your package extends the environment variable.

If you think ament_cmake should "support" this use case somehow can you please describe how you expect this to happen. "When" do you expect it to do "what" exactly? Probably best with a specific step-by-step example.

from ament_cmake.

wjwwood avatar wjwwood commented on August 20, 2024

If the "plain cmake" packages are built as part of the workspace I could see an argument for ament_tools adding those plain cmake package's to the pkg-config path. But not ament_cmake, since ament_cmake packages can provide their own environment hooks and do it themselves.

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

With this use-case I am specifically targeting plain cmake packages (e.g. directly from upstream) without any additional package.xml. The motivation is that reusing existing repositories of libraries is facilitated without patching ros2 or ament specific build information into it.

Say you want to use a library A (libA) in a ros2 node B (nodeB). Typically, libA will install its *.pc files in <prefix>/lib/pkgconfig (e.g. /usr/lib/pkgconfig when built as plain cmake). When a workspace wsA containing libA is built, the pc files will be installed to install/lib/pkgconfig and this folder should be prepended to PKG_CONFIG_PATH and exported with the workspace's setup scripts.

When sourcing workspace wsA with libA and building a new workspace wsB with nodeB, PKG_CONFIG_PATH should contain <path_to_wsA>/install/lib/pkgconfig such that ament_cmake can find libA for building nodeB.

The workaround that I am using (set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")) only works if libA and nodeB are in the same workspace.

I hope the motivation for this is clearer now. I think this is a very relevant issue since ros nodes are mostly used as wrappers around libraries and using libraries directly from upstream simplifies development.

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

Thanks for detailed description. From what I understand ament_cmake can't do much about this. Instead the build tool ament_tools could "introspect" the install space after installing a plain CMake package and if there is a file matching lib/pkgconfig/*.pc then it could add an environment hook which extends PKG_CONFIG_PATH when sourcing the setup file of the plain CMake package.

One (big?) downside would be that if a user builds A and B manually (using the command cmake, make, make install) that "magic" is not available and therefore the .pc file wouldn't be found.

While extending ament_tools is certainly an option I am wondering if this shouldn't be better taken care of in package B. Since B uses A and knows that A doesn't provide the correct environment to be used it can fix that before trying to use it, e.g.:

find_package(a REQUIRED)
set(a_prefix "${a_DIR}/../../..")  # depending on where the CMake config file for package A is located
set(ENV{PKG_CONFIG_PATH} "${a_prefix}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}")
find_package(PkgConfig REQUIRED)
pkg_check_modules(pkg_a REQUIRED a)

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

Libraries (3rd party, upstream) that install pc files usually install them to <prefix>/lib/pkgconfig. It would not be required to search for all *.pc files and add their folders; adding <prefix>/lib/pkgconfig per workspace should be sufficient.

When libA gets built and installed without ament, e.g. the usual cmake & make way, it typically gets installed to a default directory (e.g. /usr/lib/pkgconfig). For a ros2/ament package like nodeB, is there a scenario where one wants to build it with plain cmake commands (e.g. outside a workspace without ament)? I would not see the missing "magic" outside of ament as a problem.

I would like to see PKG_CONFIG_PATH extended by install/lib/pkgconfig for each sourced workspace instead of dealing with this in each ament package to prevent duplicated cmake code.
Would there be a downside of extending PKG_CONFIG_PATH this way?

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

I would not see the missing "magic" outside of ament as a problem.

When a Debian package is being built that toolchain uses only the "plain" tools. So that might be a problem if pkg A is installed in a non-standard location like /opt/ros/r2b3.

If you don't want to duplicate the CMake logic you could create an ament_cmake package named a_wrapper which depends on A and exports the necessary environment variable. All downstream packages should then use the wrapper package.

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

@christianrauch Can this be closed?

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

Even if this issue is related to ament_tools I still don't see how ament is supporting plain cmake library packages. E.g. CMakeLists.txt projects that install their *.pc or *.cmake files to locations that are different from where regular ament packages install their *.cmake files.
A more concrete example would be the apriltag2 library, which can (and should) also be used outside of ament. At the moment, I am using the workaround of manually adding lib/pkgconfig/ of the same workspace to PKG_CONFIG_PATH if I want to use that library in a ROS2 node. But this has the mentioned drawbacks. How is ament going to support the use of this library?

What will be a more systematic way of supporting plain cmake library packages?

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

For the example of the apriltag2 library: how do you expect a user to use the library? Well, I would argue if they don't use a build tool like ament_tools they would need to read your README file and then build the package using cmake, make, make install and then in order to use it (if they have installed to a custom location rather than /usr) set environment variables to e.g. find the .pc file.

When a package decides to be a plain CMake package it means that it is not using any of the benefits provided by ament_cmake (which includes generating CMake config files, setting up environment variables, etc.). Therefore it is the responsibility of that package to do "everything" on its own.

If the user does use a build tool like ament_tools it can provide "some level" of support for plain CMake packages. It e.g. add the <install-prefix>/bin folder to the PATH environment variable if the package installs executables into that location. Something similar happens for libraries and LD_LIBRARY_PATH as well as CMake config files and CMAKE_PREFIX_PATH. It is certainly possible to extend it to do something for pkg-config (as suggested in this comment).

As mentioned before relying on the build tool to help you out in this case will not work when users build with the "normal" tools or when a packages is being released. Therefore I suggested to consider handling this within your package. If you don't want to do that and only care about the use case with ament_tools than extending the build tool to look for .pc files will be sufficient.

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

A user that wants to use a library that provides *.pc files, would request the package in cmake via pkg_search_module(apriltag REQUIRED apriltag) and links against ${apriltag_LIBRARIES}. If the package is system wide installed, a user does not need to know it installation path.

If ament could be extended to behave like in your suggestion:

Instead the build tool ament_tools could "introspect" the install space after installing a plain CMake package and if there is a file matching lib/pkgconfig/*.pc then it could add an environment hook which extends PKG_CONFIG_PATH when sourcing the setup file of the plain CMake package.

this would simplify the use of plain cmake packages.

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

If ament could be extended to behave like in your suggestion this would simplify the use of plain cmake packages.

As long as you are aware that this only works when the user uses the build tool ament_tools. Imo this is kind of a lock-in which we typically try to avoid.

Anyway please see ament/ament_tools#171 which should add that feature. Please comment there if it works for your use case. For trying it you will also need the patch from the referenced ament_package PR.

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

@christianrauch It would be great if you could comment on the PR ament/ament_tools#171.

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

@dirk-thomas Sorry for responding so late. I couldn't find time earlier to look into this this again.

While looking into this issue, I found a workspace setup that does not require special handling of the plain cmake package in my ROS node to build. I couldn't figure out yet, why it is like that.

My workspace is consisting of three packages

I found that adding apriltag_msgs to my CMakeLists.txt by:

find_package(apriltag_msgs REQUIRED)
ament_target_dependencies(AprilTag2Node ... apriltag_msgs ...)

makes my workspace compile successfully.

If you checkout all packages at master (using apriltag_msgs), e.g.:

mkdir -p apriltag_ws/src
cd apriltag_ws/src
git clone [email protected]:christianrauch/apriltag2.git
git clone [email protected]:christianrauch/apriltag_msgs.git
git clone [email protected]:christianrauch/apriltag2_node.git
cd ..
source /opt/ros/r2b3/setup.bash
ament build

the workspace will successfully build, event though there is no special workarounds in apriltag2_node.

If you switch apriltag2_node to branch no_msgs_cmake (not using apriltag_msgs):

mkdir -p apriltag_ws/src
cd apriltag_ws/src
git clone [email protected]:christianrauch/apriltag2.git
git clone [email protected]:christianrauch/apriltag_msgs.git
git clone -b no_msgs_cmake [email protected]:christianrauch/apriltag2_node.git
cd ..
source /opt/ros/r2b3/setup.bash
ament build

the build will fail with with None of the required 'apriltag' found because of the missing pkg-config path.

Why does the workspace build successfully by adding apriltag_msgs?
Which part of apriltag_msgs makes the ROS2 node apriltag2_node find the library apriltag?

from ament_cmake.

dirk-thomas avatar dirk-thomas commented on August 20, 2024

It looks like your package apriltag2_node doesn't declare a dependency on the plain CMake package aprilta. If you add <depend>apriltag</depend> to the apriltag2_node package.xml file the build tool will make sure to source the environment of the apriltag package when building apriltag2_node. This will then define/extend the PKG_CONFIG_PATH environment variable and you shouldn't need to patch the CMake code anymore.

from ament_cmake.

christianrauch avatar christianrauch commented on August 20, 2024

@dirk-thomas Thanks for this hint. I didn't know that an ament package can depend on a plain cmake package this way. I thought that ament packages can only depend on other ament packages (e.g. those that have a package.xml)

from ament_cmake.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.