34__COMPILATION_DB_ENTRIES = []
39if not SCons.Util.case_sensitive_suffixes(
'.c',
'.C'):
40 _CSuffixes.append(
'.C')
42_CXXSuffixes = [
'.cpp',
'.cc',
'.cxx',
'.c++',
'.C++']
43if SCons.Util.case_sensitive_suffixes(
'.c',
'.C'):
44 _CXXSuffixes.append(
'.C')
50 def __init__(self, value):
51 SCons.Node.Python.Value.__init__(self, value)
52 self.Decider(changed_since_last_build_node)
55def changed_since_last_build_node(node, target, prev_ni, repo_node=None):
56 """ Dummy decider to force alwasy building"""
60def makeEmitCompilationDbEntry(comstr):
62 Effectively this creates a lambda function to capture:
66 :param comstr: unevaluated command line
67 :
return: an emitter which has captured the above
69 user_action = SCons.Action.Action(comstr)
71 def EmitCompilationDbEntry(target, source, env):
73 This emitter will be added to each c/c++ object build to capture the info needed
75 :param target: target node(s)
76 :param source: source node(s)
77 :param env: Environment
for use building this node
78 :
return: target(s), source(s)
83 entry = env.__COMPILATIONDB_Entry(
84 target=dbtarget, source=[], __COMPILATIONDB_UTARGET=target,
85 __COMPILATIONDB_USOURCE=source, __COMPILATIONDB_UACTION=user_action,
86 __COMPILATIONDB_ENV=env)
91 env.AlwaysBuild(entry)
94 __COMPILATION_DB_ENTRIES.append(dbtarget)
98 return EmitCompilationDbEntry
101def CompilationDbEntryAction(target, source, env, **kw):
103 Create a dictionary with evaluated command line, target, source
104 and store that info
as an attribute on the target
105 (Which has been stored
in __COMPILATION_DB_ENTRIES array
106 :param target: target node(s)
107 :param source: source node(s)
108 :param env: Environment
for use building this node
113 command = env['__COMPILATIONDB_UACTION'].strfunction(
114 target=env[
'__COMPILATIONDB_UTARGET'],
115 source=env[
'__COMPILATIONDB_USOURCE'],
116 env=env[
'__COMPILATIONDB_ENV'],
120 "directory": env.Dir(
'#').abspath,
"command": command,
121 "file": str(env[
'__COMPILATIONDB_USOURCE'][0])
124 target[0].write(entry)
127def WriteCompilationDb(target, source, env):
130 for s
in __COMPILATION_DB_ENTRIES:
131 entries.append(s.read())
133 with open(str(target[0]),
'w')
as target_file:
134 json.dump(entries, target_file, sort_keys=
True, indent=4, separators=(
',',
': '))
137def ScanCompilationDb(node, env, path):
138 return __COMPILATION_DB_ENTRIES
141def generate(env, **kwargs):
143 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
145 env[
'COMPILATIONDB_COMSTR'] = kwargs.get(
'COMPILATIONDB_COMSTR',
146 'Building compilation database $TARGET')
148 components_by_suffix = itertools.chain(
149 itertools.product(_CSuffixes, [
150 (static_obj, SCons.Defaults.StaticObjectEmitter,
'$CCCOM'),
151 (shared_obj, SCons.Defaults.SharedObjectEmitter,
'$SHCCCOM'),
153 itertools.product(_CXXSuffixes, [
154 (static_obj, SCons.Defaults.StaticObjectEmitter,
'$CXXCOM'),
155 (shared_obj, SCons.Defaults.SharedObjectEmitter,
'$SHCXXCOM'),
159 for entry
in components_by_suffix:
161 builder, base_emitter, command = entry[1]
164 emitter = builder.emitter[suffix]
165 builder.emitter[suffix] = SCons.Builder.ListEmitter([
167 makeEmitCompilationDbEntry(command),
170 env[
'BUILDERS'][
'__COMPILATIONDB_Entry'] = SCons.Builder.Builder(
171 action=SCons.Action.Action(CompilationDbEntryAction,
None), )
173 env[
'BUILDERS'][
'__COMPILATIONDB_Database'] = SCons.Builder.Builder(
174 action=SCons.Action.Action(WriteCompilationDb,
"$COMPILATIONDB_COMSTR"),
175 target_scanner=SCons.Scanner.Scanner(function=ScanCompilationDb, node_class=
None))
177 def CompilationDatabase(env, target):
178 result = env.__COMPILATIONDB_Database(target=target, source=[])
180 env.AlwaysBuild(result)
185 env.AddMethod(CompilationDatabase,
'CompilationDatabase')