System headers

In an attempt to start enforcing warnings with -Werror in a snap I discovered that headers pulled from system libraries were throwing a number of warnings. In a non-snapcraft environment these warnings are masked because the header files are coming from system include directories. When built in snapcraft the directory that these headers are accessed from is not one of the built in system directories but instead from something like parts/part1/install/include.

What I’m wondering is if it would be reasonable to add these paths to the compiler flags with -isystem instead of -I? I’ve got changes that accomplish this and modify the tests to account for the change but per the contributing file I’m starting a discussion here first.

The system header files should still be found in /usr/include for Snapcraft’s build environment. Are you instead talking about other people’s code that you’ve added to your snap through extra parts?

If you can’t fix the warnings in those projects’ headers, one option is to selectively disable warnings while including those headers. For example, if a header triggers the -Wcast-align warning, you can include it like so:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
#include <problem-header.h>
#pragma GCC diagnostic pop

The push/pop pair make sure that any diagnostic changes you make don’t affect code lower down in the file. And by only ignoring specific warnings, you’re not just giving them a free pass. More details of the compiler feature can be found here:

https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html

for include paths, headers that are staged are preferred over headers on the system. If you would like to exclude a given header you can use the stage keyword in the part that is adding it. (https://snapcraft.io/docs/snapcraft-parts-metadata#heading--stage)

So while I could pragma away the warnings that could get very cumbersome. Removing packages from the stage isn’t actually enough because it’s not from the stage path that it is getting the header files in the case I am looking at. I’ve got the following simple snap created to demonstrate what I’m talking about: https://github.com/dandedrick/snap-test .

So this will fail on boost header files because they get installed to the parts/part1/install/usr/include directory, which is not a system path but is added with -I. The header files are never making it to the stage path itself.

Can some of those stage-packages actually be build-packages instead? I spotted ROS in your snapcraft.yaml, feels like a good time to invoke @kyrofa

1 Like

You almost certainly don’t want to stage libboost-dev, since there is no reason to ship headers as part of your snap. As @sergiusens said, you probably want libboost-dev in build-packages (i.e. packages needed to build your code, rather than packages whose contents should be included in your snap). If the Boost features you’re using aren’t header-only, add the corresponding library packages to stage-packages.

Thanks for the ping. If one of the ROS plugins is being used here that may very well be why this is being staged. ROS dependencies share a number of limitations:

  1. They come from a third-party deb repo, and snapcraft doesn’t add it to the host (just fetches packages from it)
  2. They don’t split runtime and dev into separate packages
  3. While the package.xml spec includes the ability to specify run and build dependencies separately, no tool exists to actually pull them out as separate entities (i.e. rosdep only talks in terms of dependencies, not types of dependencies)

As a side effect of these limitations, all ROS dependencies (and their dependencies) end up as stage-packages, not build-packages. The case could be made to get rid of (1) now that build VMs are a thing, but without (2) and (3) it seems somewhat pointless.