23

Using scons I can easily set my include paths:

env.Append( CPPPATH=['foo'] )

This passes the flag

-Ifoo

to gcc

However I'm trying to compile with a lot of warnings enabled. In particular with

env.Append( CPPFLAGS=['-Werror', '-Wall', '-Wextra'] )

which dies horribly on certain boost includes ... I can fix this by adding the boost includes to the system include path rather than the include path as gcc treats system includes differently.

So what I need to get passed to gcc instead of -Ifoo is

-isystem foo

I guess I could do this with the CPPFLAGS variable, but was wondering if there was a better solution built into scons.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187

4 Answers4

12

There is no built-in way to pass -isystem include paths in SCons, mainly because it is very compiler/platform specific.

Putting it in the CXXFLAGS will work, but note that this will hide the headers from SCons' dependency scanner, which only looks at CPPPATH.

This is probably OK if you don't expect those headers to ever change, but could cause weird issues if you use the build results cache and/or implicit dependency cache.

BenG
  • 1,292
  • 8
  • 11
  • Thanks for the confirmation of what I expected (but hoped was wrong) – Michael Anderson Mar 14 '10 at 05:44
  • 1
    Good answer but actually, I believe it is a good thing that those includes are excluded from the dependency chain as they would slow down the whole build process for no real gain. There are a lot of Boost headers and those wouldn't likely change (and when they do, you know it and can decide to clean everything). – ereOn Oct 25 '12 at 08:25
  • 1
    Indeed, excluding "read-only" headers is a great way to speed up your build. A good practice is to make sure the library version is part of its directory path (ie. /foo/bar/boost/1.38/include). That way, the boost version number shows up on the compilation command lines. Since SCons includes the command line in its signature, any boost upgrade would land in a different directory, thereby invalidating any existing build product. This makes a build cache much more robust, especially for large teams. – BenG Oct 25 '12 at 13:44
  • Yes, it is much more efficient to depend on the library version number for such rarely changing libraries. Assuming the library update is disciplined, and versions never mix :) By the way, anybody knows the corresponding option for the Microsoft compiler? – Evgen Mar 28 '17 at 22:24
6

If you do

  print env.Dump()

you'll see _CPPINCFLAGS, and you'll see that variable used in CCCOM (or _CCCOMCOM). _CPPINCFLAGS typically looks like this:

  '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)'

From this you can probably see how you could add an "isystem" set of includes as well, like _CPPSYSTEMINCFLAGS or some such. Just define your own prefix, path var name (e.g. CPPSYSTEMPATH) and suffix and use the above idiom to concatenate the prefix. Then just append your _CPPSYSTEMINCFLAGS to CCCOM or _CCCOMCOM and off you go.

Of course this is system-specific but you can conditionally include your new variable in the compiler command line as and when you want.

GaryO
  • 5,873
  • 1
  • 36
  • 61
4

According to the SCons release notes, "-isystem" is supported since version 2.3.4 for the environment's CCFLAGS.

So, you can, for example, do the following:

env.AppendUnique(CCFLAGS=('-isystem', '/your/path/to/boost'))

Still, you need to be sure that your compiler supports that option.

LangerJan
  • 165
  • 1
  • 9
0

Expanding on the idea proposed by @LangerJan and @BenG... Here's a full cross-platform example (replace env['IS_WINDOWS'] with your windows platform checking)

from SCons.Util import is_List
def enable_extlib_headers(env, include_paths):
    """Enables C++ builders with current 'env' to include external headers
    specified in the include_paths (list or string value).
    Special treatment to avoid scanning these for changes and/or warnings.
    This speeds up the C++-related build configuration.
    """
    if not is_List(include_paths):
        include_paths = [include_paths]

    include_options = []
    if env['IS_WINDOWS']:
        # Simply go around SCons scanners and add compiler options directly
        include_options = ['-I' + p for p in include_paths]
    else:
        # Tag these includes as system, to avoid scanning them for dependencies,
        # and make compiler ignore any warnings
        for p in include_paths:
            include_options.append('-isystem')
            include_options.append(p)
   env.Append(CXXFLAGS = include_options)

Now, when configuring the use of external libraries, instead of

env.AppendUnique(CPPPATH=include_paths)

call

enable_extlib_headers(env, include_paths)

In my case this reduced the pruned dependency tree (as produced with --tree=prune) by 1000x on Linux and 3000x on Windows! It sped up the no-action build time (i.e. all targets up to date) by 5-7x The pruned dependency tree before this change had 4 million includes from Boost. That's insane.

Evgen
  • 194
  • 1
  • 11