diff options
-rw-r--r-- | SConstruct | 2 | ||||
-rw-r--r-- | site_scons/site_tools/forceincludes.py | 83 |
2 files changed, 85 insertions, 0 deletions
diff --git a/SConstruct b/SConstruct index fb573d5513c..540b41ae0fe 100644 --- a/SConstruct +++ b/SConstruct @@ -2183,6 +2183,8 @@ def link_guard_libdeps_tag_expand(source, target, env, for_signature): env['LIBDEPS_TAG_EXPANSIONS'].append(link_guard_libdeps_tag_expand) +env.Tool('forceincludes') + # ---- other build setup ----- if debugBuild: env.SetConfigHeaderDefine("MONGO_CONFIG_DEBUG_BUILD") diff --git a/site_scons/site_tools/forceincludes.py b/site_scons/site_tools/forceincludes.py new file mode 100644 index 00000000000..7238a54f0e3 --- /dev/null +++ b/site_scons/site_tools/forceincludes.py @@ -0,0 +1,83 @@ +# Copyright 2021 MongoDB Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +import SCons + +def _add_scanner(builder): + # We are taking over the target scanner here. If we want to not do + # that we need to invent a ListScanner concept to inject. What if + # the other scanner wants a different path_function? + assert builder.target_scanner is None + + def new_scanner(node, env, path, argument): + # Use the path information that FindPathDirs gave us to resolve + # the forced includes into nodes given the search path. + fis = [env.FindFile(f, path) for f in env.get('FORCEINCLUDES', [])] + + # Use the nodes *source* scanner, which was provided to us as + # `argument` when we created this scanner, to scan the forced + # includes for transitive includes. + node.get_executor().scan(scanner=argument, node_list=fis) + + # The forced includes will be added as implicit dependencies + # for us when we return them. + return fis + + # The 'builder.builder' here is because we need to reach inside + # the CompositeBuilder that wraps the object builders that come + # back from createObjBuilders. + builder.builder.target_scanner = SCons.Scanner.Scanner( + function=new_scanner, + path_function=SCons.Script.FindPathDirs('CPPPATH'), + argument=builder.source_scanner, + ) + +def generate(env, **kwargs): + if not 'FORCEINCLUDEPREFIX' in env: + if 'msvc' in env.get('TOOLS', []): + env['FORCEINCLUDEPREFIX'] = '/FI' + else: + env['FORCEINCLUDEPREFIX'] = '-include ' + + if not 'FORCEINCLUDESUFFIX' in env: + env['FORCEINCLUDESUFFIX'] = '' + + # Expand FORCEINCLUDES with the indicated prefixes and suffixes. + env['_FORCEINCLUDES'] = '${_concat(FORCEINCLUDEPREFIX, FORCEINCLUDES, FORCEINCLUDESUFFIX, __env__, lambda x: x, TARGET, SOURCE)}' + + env.Append( + # It might be better if this went in _CPPINCFLAGS, but it + # breaks the MSVC RC builder because the `rc` tool doesn't + # honor /FI. It should be OK to put it in CCFLAGS, unless + # there is a compiler that requires that an forced include + # only come after the include file search path arguments that + # would enable discovery. + CCFLAGS=[ + '$_FORCEINCLUDES', + ] + ) + + for object_builder in SCons.Tool.createObjBuilders(env): + _add_scanner(object_builder) + +def exists(env): + return True |