Unable to run roslint on all packages in a workspace?
To use roslint for a pkg foo I used to do:
catkin_make roslint_foo
However, I cannot figure out to get this working in catkin tools. I tried:
catkin build roslint_foo
catkin build --catkin-make-args roslint_foo
catkin build --make-args roslint_foo
catkin build --cmake-args roslint_foo
But none of this works... Doing it the old way works, but I need to clear my ws after that if I want to build using catkin build again. So essentially I recompile my full ws, which takes a lot of time...
So: does catkin tools not yet support roslint? Or am I doing it wrong?
The positional arguments to catkin build are package names, unlike catkin_make where they are target names. To pass a target name to make via catkin build, you're correct in using --make-args, but I suspect that the warnings just aren't being printed to the console
If that's the case, then this should work:
catkin build -v foo --make-args roslint_foo
As an aside, roslint has unfortunately been designed to accommodate catkin_make's merged devel pattern, which is why it needs to create targets with the package name in them.
Thanks for the quick reply. Found the solution. You also need to add --no-deps. I guess otherwise it will check the dependencies too, running make roslint_foo on each of them. This causes errors, as the dependencies of foo don't have these make targets... So the working command is:
catkin build --no-deps foo --make-args roslint_foo
I understand how this comes from the different design that catkin tools follows, with separate devels. However, it would be nice if a more convenient way of running roslint would be added eventually, don't you agree?
However, it would be nice if a more convenient way of running roslint would be added eventually, don't you agree?
Absolutely.
Until that point, however, feel free to add this to your bashrc:
roslint () {
catkin build --no-deps $1 --make-args roslint_$1
}
When roslint was originally created, catkin_make was what we had to use. It is not clear to me what should be done differently with catkin_tools. If you can figure out how to make it work better, please open a roslint issue, so it can better support both build approaches.
FWIW, I have had reasonable luck first running catkin build, then change to the build/PACKAGENAME directory and running make roslint there.
@jack-oquin Is roslint a valid target for any given package? Then catkin build could simply implement an alias like:
roslint: build --no-deps --make-args roslint --
Then the following would work quite well:
catkin roslint PKG1 [PKG2...]
catkin roslint --this
@jbohren For any package with a CMakeLists.txt that contains a roslint_cpp(...) block, the roslint_PKGNAME target exists... So I think your proposal makes sense.
Jon: I seem to remember that for every CMake build, roslint depends on all the individual package roslint_PKGNAME targets. That should be true for each single catkin build package as well.
It will only be defined if at least one package in the build uses roslint.
Let me know if I am wrong about that.
Ideally, roslint would behave similar to run_tests, which is that it always creates a run_tests target whether or not you're building one package (catkin build) or many (catkin_make). That way you can always just run the roslint target and not have to run the roslint_package_name target. Also just like run_tests it can keep the package specific target name and just add it as a dependency of the general target, i.e. run_tests_foo vs. run_tests.
I'd rather not bake roslint specific knowledge into catkin_tools, but there's always the opportunity to extend catkin_tools externally if that is necessary.
I'd rather not bake roslint specific knowledge into catkin_tools, but there's always the opportunity to extend catkin_tools externally if that is necessary.
Agreed, but that doesn't mean we can't have a second repo / package that just adds a bunch of contributed aliases, and in the meantime, people can add them as they see fit.
If my earlier comment was unclear: I believe the roslint target does work like run_tests. As long as at least one package uses roslint, the general target exists and depends on all the package targets.
If my earlier comment was unclear: I believe the roslint target does work like run_tests. As long as at least one package uses roslint, the general target exists and depends on all the package targets.
Oh, in that case, @jbohren's verb aliases should work just fine. That's for clarifying @jack-oquin.
If my earlier comment was unclear: I believe the roslint target does work like run_tests. As long as at least one package uses roslint, the general target exists and depends on all the package targets.
@jack-oquin, I doubt that. To my knowledge there is no generic target similar to run_tests for roslint.
Works for me. I just tried it.
What happens when you go to the relevant build directory and type: make roslint?
So what command did you use? I am not at work currently, so in about 12 hours I can give it a shot…
I did something like this:
cd ~/catkin_ws
catkin build
cd build/your_package
make roslint
That worked, so this works too:
catkin build --no-deps foo --make-args roslint
However, there is no generic target to run all roslints (which is impossible with catkin_make as well btw), as there is for running tests:
catkin build --catkin-make-args run_tests
I thought you meant that when stating that there is a generic target... So such a generic target does not exits for roslint I still think.
Also, I don't really like the --no-deps trick. Without it, make will try to build a roslint target for all dependencies of foo, preceding the actual foo build... This throws errors, as they don't exist. However, I think that (generally speaking), building a specific target of a package does require the dependencies to be build first. Hence, maybe two different categories should be added:
--make-args // for general make arguments, passed to all packages in the scope of the current catkin build command.
--make-targets //for make targets, passed only to the specified package.
What do you think?
However, there is no generic target to run all roslints (which is impossible with catkin_make as well btw), as there is for running tests:
catkin build --catkin-make-args run_tests
For catkin_make, roslint is a generic target:
catkin_make roslint
works just like:
catkin_make run_tests
Suggestions for how to make that work similarly with catkin build are welcome.
I think a separate --make-targets option which runs make with the target iff it has that target is a good idea. We'd need to make that clear from the docs, or the name of the option (maybe --try-make-target?).
Maybe: --make-if-target?
Why could it not just work like the generic run_tests currently works in catkin_tools?
catkin build --catkin-make-args run_tests already works, so why not similarly support:
catkin build --catkin-make-args roslint?
I am not sure how the run_tests 'target' is currently implemented?
I think the --try-make-target makes more sense than --make-if-target, which is a bit confusing/ambiguous to me. But why not just call it --make-target and only make that target plus its dependencies without passing those dependencies the same target (which is what essentially makes --make-target``` different from--make-args). And if you pass a --make-target to a package that does not know it, just print a warning? This way I think one can safely runcatkin build --make-targets roslint``` (although it will print a lot of warnings).
Alternatively, one could add both --make-target and --try-make-target, for which the first prints errors/warnings if targets do not exists, while the latter suppresses those...
Why could it not just work like the generic run_tests currently works in catkin_tools?
That's because the run_tests target is created for all catkin packages.
Alternatively, one could add both --make-target and --try-make-target, for which the first prints errors/warnings if targets do not exists, while the latter suppresses those...
This sounds like it's nearly duplicating the behavior of combining --continue-on-failure and --make-args roslint. Is there a reason why that's insufficient?
Aha, I just confirmed for myself that indeed, a catkin package always has a run_tests target, even if there are no tests specified in the CMakeLists.txt. Unfortunately this doesn't go for roslint...
So far I found no catkin tools equivalent for running all roslints:
catkin_make roslint
This does not work:
catkin build -v --no-deps --continue-on-failure --make-args roslint
From my ws, it fails to build about half of the packages, and half it "did not try to build", as stated in the build summary.
To me, it still seems that --make-targets and/or --try-make-targets would be the best solution... They could btw be combined: just use a strict version of --make-targets when called for a specific package, e.g.:
catkin build foo --make-targets roslint (would be equiv. to: catkin_make roslint_foo)
It should then report errors if the target does not exist for pkg foo.
And make it behave like --try-make-targets when applied to a full workspace, e.g.:
catkin build --make-targets roslint (would be equiv. to: catkin_make roslint)
It should then for each package in the ws try to build the target if it exists, and continue without any errors otherwise...
P.s. I changed --make-targets to plural, like --make-args and friends... Makes more sense to me.
Is anyone yet aware of a way to run all roslints?
@koenlek How about this:
catkin build $(catkin list --depends-on roslint -u) --catkin-make-args roslint
Ideally it would be --depends-on-direct or --depends-on-1 so that only packages with direct deps are built. (PR for that would be welcome, I think)
@jbohren Thanks for the suggestion. You are right in your 'self-reply' directly after that: --depends-on does not work right, because of indirect dependencies. I'd still prefer --make-targets or --try-make-targets, but the --depends-on-direct would also be an option. I myself don't plan to look into creating a PR any time soon, so hopefully someone else will be able to pick it up...
Maybe at some point I might make some script that finds all roslint targets and builds them one by one. If so, I'll give an heads-up here.
You are right in your 'self-reply' directly after that: --depends-on does not work right, because of indirect dependencies.
Actually I'm not right. The --depends-on in catkin list is actually a --depends-on-direct. So this will work assuming people properly depend on roslint in their package.xml files.
It does not work for our workspace, here part of an error I get (I get several of these).
Starting ==> voxel_grid
[hardware_interface] ==> '/home/koenlek/catkin_ws/build/hardware_interface/build_env.sh /usr/bin/make roslint --jobserver-fds=3,5 -j' in '/home/koenlek/catkin_ws/build/hardware_interface'
make: *** No rule to make target `roslint'. Stop.
[hardware_interface] <== '/home/koenlek/catkin_ws/build/hardware_interface/build_env.sh /usr/bin/make roslint --jobserver-fds=3,5 -j' failed with return code '2'
Failed <== hardware_interface [ 0.3 seconds ]
However, if I do grep -Hrn roslint in the top level src folder of the hardware_interface pkg, there are zero results. Which means that both the package.xml and CMakeLists.txt do not contain a dependency on roslint, don't you agree?
It does not work for our workspace, here part of an error I get (I get several of these).
What's the output of this in your workspace:
catkin list --depends-on roslint -u