ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
Short answer is no.
catkin workspaces do not support multiple inheritance of workspaces. For example:
Consider that you have some binary debians installed, and you want to build workspace A, you would do so like this:
Then you separately build B (in a new terminal):
Now you have a workspace C which you want to use A and B, so you try:
The C_ws will likely fail to build if it relies on packages which only exist in workspace A. Why? because the setup.bash files overwrite each other. In fact when if I build workspace A like this:
And then do this:
Then you will not find the /opt/ros/groovy/ install space in your environment.
This is the rule you have to remember:
The setup.bash/zsh/sh file generated by catkin has the current environment plus the workspace which was just built.
That means that each time you source a setup.bash file which was generated by catkin it is reconstructing the environment in which it was created. The reason for this is to provide a consistent build and run environment for your packages. It in fact does not make sense to build packages in one environment and run them in another.
If you want to build workspace C on top of A and B, then you should follow this pattern:
In this way you are always building your current workspace on top of exactly one other workspace.
This is a necessary constraint to prevent other less obvious errors from arising. For example, consider this:
You build a workspace A which contains a library foo
.
Next you build a workspace B, after sourcing A, which contains a library bar
which is linked against foo
from A.
But then you have a modified version of foo
in a workspace C which you build after source A. You source A first to get the dependencies of foo
from workspace A, but now the version of foo
from workspace C is overlaying the version from A.
Next you want to build a package in workspace D which uses bar
and foo
, but you want to test your changes to foo
from C. So you do this:
But workspace D fails because it cannot find bar
. So you try sourcing B again:
Now D builds, finding bar
in B and foo
from A, but you do not get your modified version of foo
from C.
Lets assume for a second that you could add the environment from C onto the environment from B. Now D builds and finds foo
from C and bar
from B. But there is still a problem, because bar
from B is compiled against foo
from A, so your package in D is now linking against foo
from C AND foo
from A via bar
from B. This problem is not easy to catch and not all changes to foo
would actually cause a problem. But to prevent this from occurring catkin enforces no multiple workspace inheritance. Because any time you do this multiple workspace inheritance you will be using a product from one workspace which was built without influence from the other, e.g. bar
from B was not built in the presence of foo
from C.
Now if you take the recommendation from above, you would do this:
Now D builds against a bar
from B which linked against a foo
from C which is overlaying the foo
from A. By enforcing this single workspace inheritance model, catkin tries to prevent inconsistent build/run environments.
Hopefully this helps a little bit to explain why this is and why catkin workspaces have this limitation, and I would like to hear feedback on ways to improve this use case, because I cannot think of any.
2 | No.2 Revision |
Short answer is no."yes", longer answer is "it can be dangerous".
You can call any setup.bash/zsh/sh with the --extend
option which will "extend" your current environment. If you do not do this then the setup.bash/zsh/sh will overwrite your current environment to restore the environment which existed when it was generated (the setup.bash/zsh/sh).
So you can do something like this:
BUT this can be dangerous, read on if you care:
catkin workspaces do not support multiple inheritance of workspaces. workspaces by default in order to prevent inconsistent build and run environments. For example:
Consider that you have some binary debians installed, and you want to build workspace A, you would do so like this:
Then you separately build B (in a new terminal):
Now you have a workspace C which you want to use A and B, so you try:
The C_ws will likely fail to build if it relies on packages which only exist in workspace A. Why? because the setup.bash files overwrite each other. In fact when if I build workspace A like this:
And then do this:
Then you will not find the /opt/ros/groovy/ install space in your environment.
This is the rule you have to remember:
The setup.bash/zsh/sh file generated by catkin has the current environment plus the workspace which was just built.
That means that each time you source a setup.bash file which was generated by catkin it is reconstructing the environment in which it was created. The reason for this is to provide a consistent build and run environment for your packages. It in fact does not make sense to build packages in one environment and run them in another.
If you want to build workspace C on top of A and B, then you should follow this pattern:
In this way you are always building your current workspace on top of exactly one other workspace.
This is a necessary constraint to prevent other less obvious errors from arising. For example, consider this:
You build a workspace A which contains a library foo
.
Next you build a workspace B, after sourcing A, which contains a library bar
which is linked against foo
from A.
But then you have a modified version of foo
in a workspace C which you build after source A. You source A first to get the dependencies of foo
from workspace A, but now the version of foo
from workspace C is overlaying the version from A.
Next you want to build a package in workspace D which uses bar
and foo
, but you want to test your changes to foo
from C. So you do this:
But workspace D fails because it cannot find bar
. So you try sourcing B again:
Now D builds, finding bar
in B and foo
from A, but you do not get your modified version of foo
from C.
Lets assume for a second that you could used the --extend
option to add the environment from C onto the environment from B. Now D builds and finds foo
from C and bar
from B. But there is still a problem, because bar
from B is compiled against foo
from A, so your package in D is now linking against foo
from C AND foo
from A via bar
from B. This problem is not easy to catch and not all changes to foo
would actually cause a problem. But to prevent this from occurring catkin enforces no multiple workspace inheritance. Because any time you do this multiple workspace inheritance you will be using a product from one workspace which was built without influence from the other, e.g. bar
from B was not built in the presence of foo
from C.
Now if you take the recommendation from above, you would do this:
Now D builds against a bar
from B which linked against a foo
from C which is overlaying the foo
from A. By enforcing this single workspace inheritance model, catkin tries to prevent inconsistent build/run environments.
Hopefully this helps a little bit to explain why this is and why catkin workspaces have this limitation, and I would like to hear feedback on ways to improve this use case, because I cannot think of any.