Skip to content

Commit 5f07d12

Browse files
committed
compilation_db: regenerate the db only if the content has changed
1 parent eb669cb commit 5f07d12

File tree

2 files changed

+32
-73
lines changed

2 files changed

+32
-73
lines changed

SCons/Tool/compilation_db.py

+23-73
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,6 @@
4545
__COMPILATION_DB_ENTRIES = []
4646

4747

48-
# We make no effort to avoid rebuilding the entries. Someday, perhaps we could and even
49-
# integrate with the cache, but there doesn't seem to be much call for it.
50-
class __CompilationDbNode(SCons.Node.Python.Value):
51-
def __init__(self, value):
52-
SCons.Node.Python.Value.__init__(self, value)
53-
self.Decider(changed_since_last_build_node)
54-
55-
56-
def changed_since_last_build_node(child, target, prev_ni, node):
57-
""" Dummy decider to force always building"""
58-
return True
59-
60-
6148
def make_emit_compilation_DB_entry(comstr):
6249
"""
6350
Effectively this creates a lambda function to capture:
@@ -79,74 +66,40 @@ def emit_compilation_db_entry(target, source, env):
7966
:return: target(s), source(s)
8067
"""
8168

82-
dbtarget = __CompilationDbNode(source)
83-
84-
entry = env.__COMPILATIONDB_Entry(
85-
target=dbtarget,
86-
source=[],
87-
__COMPILATIONDB_UOUTPUT=target,
88-
__COMPILATIONDB_USOURCE=source,
89-
__COMPILATIONDB_UACTION=user_action,
90-
__COMPILATIONDB_ENV=env,
91-
)
92-
93-
# TODO: Technically, these next two lines should not be required: it should be fine to
94-
# cache the entries. However, they don't seem to update properly. Since they are quick
95-
# to re-generate disable caching and sidestep this problem.
96-
env.AlwaysBuild(entry)
97-
env.NoCache(entry)
98-
99-
__COMPILATION_DB_ENTRIES.append(dbtarget)
69+
entry = {
70+
"directory": env.Dir("#").abspath,
71+
"command": user_action.strfunction(
72+
target=target, source=source, env=env
73+
),
74+
"file": {
75+
"abspath": source[0].srcnode().abspath,
76+
"path": source[0].srcnode().path
77+
},
78+
"output": {
79+
"abspath": target[0].abspath,
80+
"path": target[0].path
81+
}
82+
}
83+
84+
__COMPILATION_DB_ENTRIES.append(entry)
10085

10186
return target, source
10287

10388
return emit_compilation_db_entry
10489

10590

106-
def compilation_db_entry_action(target, source, env, **kw):
107-
"""
108-
Create a dictionary with evaluated command line, target, source
109-
and store that info as an attribute on the target
110-
(Which has been stored in __COMPILATION_DB_ENTRIES array
111-
:param target: target node(s)
112-
:param source: source node(s)
113-
:param env: Environment for use building this node
114-
:param kw:
115-
:return: None
116-
"""
117-
118-
command = env["__COMPILATIONDB_UACTION"].strfunction(
119-
target=env["__COMPILATIONDB_UOUTPUT"],
120-
source=env["__COMPILATIONDB_USOURCE"],
121-
env=env["__COMPILATIONDB_ENV"],
122-
)
123-
124-
entry = {
125-
"directory": env.Dir("#").abspath,
126-
"command": command,
127-
"file": env["__COMPILATIONDB_USOURCE"][0],
128-
"output": env['__COMPILATIONDB_UOUTPUT'][0]
129-
}
130-
131-
target[0].write(entry)
132-
133-
13491
def write_compilation_db(target, source, env):
13592
entries = []
13693

13794
use_abspath = env['COMPILATIONDB_USE_ABSPATH'] in [True, 1, 'True', 'true']
13895

139-
for s in __COMPILATION_DB_ENTRIES:
140-
entry = s.read()
141-
source_file = entry['file']
142-
output_file = entry['output']
143-
96+
for entry in __COMPILATION_DB_ENTRIES:
14497
if use_abspath:
145-
source_file = source_file.srcnode().abspath
146-
output_file = output_file.abspath
98+
source_file = entry['file']['abspath']
99+
output_file = entry['output']['abspath']
147100
else:
148-
source_file = source_file.srcnode().path
149-
output_file = output_file.path
101+
source_file = entry['file']['path']
102+
output_file = entry['output']['path']
150103

151104
path_entry = {'directory': entry['directory'],
152105
'command': entry['command'],
@@ -162,7 +115,8 @@ def write_compilation_db(target, source, env):
162115

163116

164117
def scan_compilation_db(node, env, path):
165-
return __COMPILATION_DB_ENTRIES
118+
value = json.dumps(__COMPILATION_DB_ENTRIES, sort_keys=True)
119+
return [SCons.Node.Python.Value(value)]
166120

167121

168122
def compilation_db_emitter(target, source, env):
@@ -230,10 +184,6 @@ def generate(env, **kwargs):
230184
[emitter, make_emit_compilation_DB_entry(command), ]
231185
)
232186

233-
env["BUILDERS"]["__COMPILATIONDB_Entry"] = SCons.Builder.Builder(
234-
action=SCons.Action.Action(compilation_db_entry_action, None),
235-
)
236-
237187
env["BUILDERS"]["CompilationDatabase"] = SCons.Builder.Builder(
238188
action=SCons.Action.Action(write_compilation_db, "$COMPILATIONDB_COMSTR"),
239189
target_scanner=SCons.Scanner.Scanner(

test/CompilationDatabase/basic.py

+9
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,28 @@ def get_db(workdir, use_abspath, ccflags):
7878
]
7979

8080

81+
stat_info = {}
82+
8183
example_rel_file = get_db(test.workdir, False, [])
8284

8385
for f in rel_files:
8486
# print("Checking:%s" % f)
8587
test.must_exist(f)
8688
test.must_match(f, example_rel_file, mode='r')
89+
stat_info[f] = os.stat(f)
8790

8891

8992
example_abs_file = get_db(test.workdir, True, [])
9093

9194
for f in abs_files:
9295
test.must_exist(f)
9396
test.must_match(f, example_abs_file, mode='r')
97+
stat_info[f] = os.stat(f)
98+
99+
100+
test.run()
101+
for f in stat_info.keys():
102+
test.fail_test(stat_info[f] != os.stat(f))
94103

95104

96105
test.run(arguments='CCFLAGS=-g')

0 commit comments

Comments
 (0)