Coder Social home page Coder Social logo

Comments (26)

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

No, while ament might pass specific options any command line invocation can contain the same arguments.

Can you explain a bit more why you want differentiate those two cases?

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

I want to create a project I can build via

ament build

like described in the tutorial,
but I also want to do a build where I can use cmake directly.

An example:
workspace
-project
- package 1
- package 2
- package 3

Package 3 depends on package 2 and 1. I can provide a findPackage1.cmake and a findPackage2.cmake inside of package 3 in order to build it inside the package folder.
I need this kind of build process due to some legacy reasons.
It is also nice to be able to build a ros 2 project the classical cmake way. But I also want to be able to build some parts of this project with ament (especially it's easier if these components should be used by someone else)

My idea was to check inside the cmake file if the build process was called via ament build(Especially the cmake invokation). If not i would provide my own findPackageX.cmake file for resolving the cmake find_package statement.

I think this should be quite easy if the ament build command would set a cmake variable i could check.

from ament_cmake.

jacquelinekay avatar jacquelinekay commented on August 27, 2024

We have some packages that attempt to do this, like rttest, but I believe we don't run CI on the CMake-only build for that package. You can do a find_package(ament_cmake) and then condition the logic for the ament build on ament_cmake_FOUND.

from ament_cmake.

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

From your example it is not clear to me which folder is the actual ament package with the package.xml file.

Each package specifies its build type. If it is ament_cmake the CMake file is expected to call ament_package(). If it is cmake the CMake code can do whatever it wants (but should provide a way to let downstream packages find it). See http://design.ros2.org/articles/ament.html for more details.

The flag ament_cmake_FOUND does not allow you to distinguish how the build of the package was triggered. It only indicates that ament_package() was called (or the package faked that by setting the flag manually).

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

I took some time to think about this question. I probably don't have enough understanding of ament, but still think my question ist kind of valid. I use ament_cmake in all my packages. (In the example package 1, package 2 and so on). So I can use ament build in this environment to build the packages an determine dependencies between the packages.

But I also want to be able to build the packages locally without ament build. So I go for example into the package 1 folder, create a build folder, call cmake .. and then make. I have solved the problem of finding upstream packages by providing the fitting packageX_Config.cmake and setting the correct CMAKE_PREFIX_PATH .See https://github.com/firesurfer/ros2_components_demo/blob/master/CMakeLists.txt#L12

If I could check if the build was started via ament build, I would not need to uncomment that line manually.

The reason why I want to do this kind of build: I have some weird legacy components (low level control software that uses another framework) that are nasty to build with ament build , furthermore it's faster to just build the package I need to rebuild. Ament always checks all packages in the workspace.

from ament_cmake.

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

I don't see a way to distinguish a build done by ament build from a manual cmake invocation. Since the tool is at the end of the day just doing the same, invoking cmake. While the tool could pass a specific flag to CMake the user is free to also pass that flag to the manual CMake invocation.

Is your questions answered by this thread?

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

I would appreciate if ament could pass cmake a flag. I don't think that it would be wrong if the user can set the flag himself, but usually the user should check what can happen before he sets a flag.

from ament_cmake.

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

What do you suggest for the name of such a flag?

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

Something that contains AMENT and BUILD. How about USES_AMENT_BUILD or do you have any better ideas for a name?

from ament_cmake.

wjwwood avatar wjwwood commented on August 27, 2024

@firesurfer is it not sufficient to do something like this:

find_package(ament_cmake)
if(ament_cmake_FOUND)
  # ... use ament
else()
  # ... use plain cmake
endif()

Or are you trying to detect if the package is being built with the tool provided in ament_tools?

I don't think it makes sense for our tool to pass something like USES_AMENT_BUILD because cmake packages which do not use it will produce a cmake warning like this:

CMake Warning:
  Manually-specified variables were not used by the project:

    USES_AMENT_BUILD

If we were to indicate to packages that they're being built with our tool, then I'd say an environment variable is the best way, but I'm not yet convinced that's helpful. @firesurfer perhaps you could point us at an example package and explain the ways you'd like to use it so we could better understand your use case (I looked at what you linked above https://github.com/firesurfer/ros2_components_demo/blob/master/CMakeLists.txt#L12, but that no longer points to a line of code)? For what it's worth you can take any ament_cmake based package and just do mkdir build; cd build; cmake ..; make so long as ament_cmake and its dependencies have been installed and are on the CMAKE_PREFIX_PATH.

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

Please have a look at https://github.com/firesurfer/ros2_components_demo/blob/master/CMakeLists.txt#L14
At the moment I have specified an option so I can tell cmake to do a "LocalBuild" which means I use my own cmake script for searching packages that provide a Config.cmake inside of a specified workspace. I use this in case I want to do a build with: mkdir build; cd build; cmake ..; make

It would be nice if I could just check if the build was started via ament and in case it wasn't started via ament use my own script for finding other packages inside of a workspace: findPackageInWorkspace(ros2_components_msg)

from ament_cmake.

wjwwood avatar wjwwood commented on August 27, 2024

Ok so you do mean you want to know when it's being built with the ament build tool. In that case I still think an environment variable like BUILT_WITH_AMENT_BUILD is the best strategy.

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

I agree with you, I wasn't aware that cmake complains about unused flags.
Would you mind adding the setting of said variable to ament ?

from ament_cmake.

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

Adding the environment variable BUILT_WITH_AMENT_BUILD as suggested above is fine.

But I still don't see how your custom logic in that case is supposed to work. You can simply not make general assumptions about the location of other packages. They might be in a completely separate workspace and / or built with / without ament build. Also the way you search for any CMake config files completely bypasses the dependency hierarchy. I might not understand your use case but there might be a much cleaner solution that this.

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

Okey, I try to explain my usecase to you. I'm also sorry that I couldn't carve out my scenario before.

I agree with you that I can't make assumptions about the location or the build order of other packages in a general usecase. In this case my usage is tied to a specific workspace, so I may do some assumptions.

My workspace is structured like that:

  • workspace
    • src
      • package_1
      • package_2
      • ....more packages
      • legacy package with a custom cmake based build system that doesn't like ament

There are three things I want to be able to do:

  1. Build every package inside of it's directory in it's own build folder
  2. Depend from a package to another package in that workspace (that was build locally)
  3. But also do a build with ament

At the moment I do this in the way that I create a Config.cmake for each package in the workspace I want to use (I know they are doing assumptions about the workspace). These files can be found via a cmake script (findPackageInWorkspace) that looks for the Config.cmake files and add a CMAKE_PREFIX_PATH according to them.

Why I'd like to automatically check if this build is done via ament:

  1. exclude the legacy package if build via ament (this package can be build by hand afterwards)
  2. disable the search for Config.cmake in case the build is done via ament

Why I'd want to build my packages locally:

  1. It's faster (I know i can go into the build dir ament creates and call make in the correct sub directory)
  2. Having full control over my build (Ok I know this doesn't sound like a good argument...)
  3. Being able to build my legacy package I unfortunately need in order to access the robot hardware
  4. Qt creator doesn't load the correct include files if I use it for debugging the binaries created with ament (Perhaps I'm just doing it wrong)

I think there might be more use cases where checking for a BUILT_WITH_AMENT_BUILD variable might be usefull.

from ament_cmake.

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

While I see your use case I don't understand why you need to perform all this custom CMake logic within your packages. An important goal of ament is to allow you to build the exact same packages with the native tools and workflows. Without any modification to your packages I would expect you to be able to do the standard CMake workflow. Each package will still provide you with a setup file to prepare your environment to build the next package:

  1. `cd /path/to/first/pkg
  2. mkdir build
  3. cmake .. -DCMAKE_INSTALL_PREFIX=/some/install/path (plus any flags you like to use)
  4. make (plus any flags you like to use)
  5. . /some/install/path/local_setup.sh (or bash or zsh)
  6. Currently you need to set your CMAKE_PREFIX_PATH but ament/ament_tools#76 would even get rid of that manual step
  7. rinse and repeat with the next package

from ament_cmake.

wjwwood avatar wjwwood commented on August 27, 2024
  1. Build every package inside of it's directory in it's own build folder

You can already do that. All ament packages can be built by doing cd path/to/project; mkdir build; cd build; cmake ..; make.

  1. Depend from a package to another package in that workspace (that was build locally)

This is why you've created findPackageInWorkspace (I assume). However, I would suggest trying to find a way that you can accomplish this without modifying the source of the packages. Ideally you could build with or without ament.py build without any special logic in your packages.

My recommendation in that case would be to do what catkin from ROS 1 does and have a top level CMakeLists.txt. Let me set up a simple example. Consider you have a CMake project "foo" with a CMakeLists.txt like this:

cmake_minimum_required(VERSION 2.8.3)
project(foo)

find_package(ament_cmake REQUIRED)

Then you have a project "bar" with a CMakeLists.txt like this:

cmake_minimum_required(VERSION 2.8.3)
project(bar)

find_package(ament_cmake REQUIRED)
find_package(foo REQUIRED)

Notice that it does find_package(foo REQUIRED). Then if you build with ament.py build (and you have a dependency in the package.xml of bar on foo) it will just work.

If you wanted to build without ament build, then you could create another CMakeLists.txt just above those projects like this:

cmake_minimum_required(VERSION 2.8.3)

# Include foo's CMakeLists.txt
add_subdir(foo)
# Add the directory where foo creates a fooConfig.cmake file
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_BINARY_DIR}/foo)
# Include bar's CMakeLists.txt
add_subdir(bar)
# Add the directory where foo creates a fooConfig.cmake file
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_BINARY_DIR}/bar)
# and so on...

Your workspace would like this now:

├── CMakeLists.txt  <-- This is the "top level" cmake file
├── bar
│   └── CMakeLists.txt  <-- This is bar's cmake file
└── foo
    └── CMakeLists.txt  <-- This is foo's cmake file
  1. exclude the legacy package if build via ament (this package can be build by hand afterwards)

This can be done by placing an AMENT_IGNORE file in the folder of your legacy project. ament will not traverse the filesystem past this file to look for more packages to build. However, depending on your legacy package, there should be no reason ament could not build it for you. We build fastrtps and fastcdr as they are (plain cmake projects) just fine and we can do the same for python setuptools based packages. You would only need to extend ament_tools to support the build system of your legacy package. That's somewhat involved, but completely possible. Support for plain cmake and plain python projects dogfood a plugin system for this.

  1. It's faster (I know i can go into the build dir ament creates and call make in the correct sub directory)

You can also use the --only, --start-with, and --end-with options to ament build.

  1. Having full control over my build (Ok I know this doesn't sound like a good argument...)

That's an understandable reaction to a relatively exotic system like ament or catkin. However, I hope you come to see that the tools exist for a reason and that we've worked hard to make sure it is as non-intrusive and modular as possible.

  1. Qt creator doesn't load the correct include files if I use it for debugging the binaries created with ament (Perhaps I'm just doing it wrong)

I don't know about that one, but since each package can be treated as a plain CMake project, I imagine it should work. Others in the catkin_tools repository have been talking about generating a file that could be used across several packages at once: catkin/catkin_tools#266 That's for XCode, but I think a similar thing could be done for QtCreator or Eclipse.

from ament_cmake.

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

The "feature" of catkin of building multiple CMake project within a single CMake invocation has been intentionally dropped in ament. Simply because there are various ways it can break:

  • all targets across package need to be unique
  • targets need dependencies on targets in other projects
  • global side effects in a single package affect other packages

Therefore I wouldn't recommend to use a single CMake file in the root of the workspace. Just for the record this rational is also mentioned in http://design.ros2.org/articles/ament.html#building-within-a-single-cmake-context

from ament_cmake.

wjwwood avatar wjwwood commented on August 27, 2024

That's all true, and the same could be said of the approach that @firesurfer described with findPackageInWorkspace. I agree that using the build tool or emulating the build tool (by building, installing, sourcing, repeat) is the better way.

from ament_cmake.

firesurfer avatar firesurfer commented on August 27, 2024

I see your points and agree that it is more comfortable to use a build tool. (I actually managed to use ament for all packages now) But from my point of view also more exotic ways for building a project should be made as easy as possible. From my experiences especially in an academic environment there are very strange ways of dealing with code. If you want more people to use ROS 2 I think it is necessary to think about ways how to integrate ROS 2 in other build environments/ let people build their projects the way they want. (Ament already makes this already fairly easy - just wanted to note that there are many ways of building c++ code)

from ament_cmake.

wjwwood avatar wjwwood commented on August 27, 2024

@firesurfer I agree with all your points in the most recent comment. I think we should have the environment variable to let people know that they're being built with the ament tools, especially for scenarios that we can't imagine right now. I haven't had time to look into that, but it should be fairly easy to do since the tool is written in Python. We'd appreciate help with this change, either from you or someone else in the community.

Separately, I hope we've pointed out a few things with your particular situation which suggests that you don't actually need to know when you're being built with the ament tools. Which is not to say no one needs it, but that in this case we don't think you do. This isn't obvious, but since this is sort of how catkin's non-isolated build worked we have some unique insight into the pattern 😄.

from ament_cmake.

barbalberto avatar barbalberto commented on August 27, 2024

Hi guys, I have the same issue, any news on this topic?
Thanks!

from ament_cmake.

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

@barbalberto Since we don't have any use case for this it is unlikely that we will spend time implementing this feature. Please consider to provide a pull request for it.

from ament_cmake.

barbalberto avatar barbalberto commented on August 27, 2024

Ok, I'll try.

from ament_cmake.

barbalberto avatar barbalberto commented on August 27, 2024

I found what I think it is a suitable entry point for setting the variable and made a PR.

from ament_cmake.

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

Addressed by ament/ament_tools#142.

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.