Skip to content

Commit 6212731

Browse files
authored
Generate hash checksum for std/libs libraries to track stale generated files (#205)
The generated hash is stored in the .gitignored `std/src/generated/hash.txt` file. Files are processed in sorted order to keep the hash deterministic. In addition to providing each file's contents to the hash function, we also provide each file's path within the `std/libs` directory.
1 parent c6f8e08 commit 6212731

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

tools/luthier.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88

99
from os import path
10+
from hashlib import blake2b
1011

1112
cwd = os.getcwd()
1213

@@ -161,12 +162,49 @@ def projectPathExists(args):
161162

162163
return path.isdir(projectPath)
163164

164-
def generateStdLibFiles():
165+
def getStdLibHash():
166+
restoredPath = os.getcwd()
167+
os.chdir(os.path.join(getSourceRoot(), 'std/libs'))
168+
169+
hasher = blake2b()
170+
for dirpath, _, filenames in os.walk('.'):
171+
for filename in sorted(filenames):
172+
filepath = os.path.join(dirpath, filename)
173+
hasher.update(filepath.encode('utf-8'))
174+
with open(filepath, 'rb') as f:
175+
while chunk := f.read(1024):
176+
hasher.update(chunk)
177+
178+
os.chdir(restoredPath)
179+
return hasher.hexdigest()
180+
181+
def isGeneratedStdLibUpToDate():
182+
hashFile = os.path.join(getSourceRoot(), 'std/src/generated/hash.txt')
183+
184+
if not os.path.isfile(hashFile):
185+
return False
186+
187+
with open(hashFile, 'r') as f:
188+
lines = f.readlines()
189+
assert(len(lines) == 1)
190+
actual = lines[0]
191+
expected = getStdLibHash()
192+
return actual == expected
193+
194+
return False
195+
196+
def generateStdLibFilesIfNeeded():
165197
restoredPath = os.getcwd()
166198

167199
os.chdir(os.path.join(getSourceRoot(), 'std'))
168200
os.makedirs("src/generated", exist_ok=True)
169201

202+
if (isGeneratedStdLibUpToDate()):
203+
os.chdir(restoredPath)
204+
return
205+
else:
206+
print("Generating code for @std libraries, files are out of date.")
207+
170208
with open("src/generated/modules.cpp", "w") as cpp:
171209
cpp.writelines([
172210
"// This file is auto-generated by luthier.py. Do not edit.\n",
@@ -219,6 +257,9 @@ def generateStdLibFiles():
219257
f"extern const std::pair<std::string_view, std::string_view> lutestdlib[{numItems}];\n",
220258
])
221259

260+
with open("../src/generated/hash.txt", "w") as hash:
261+
hash.write(getStdLibHash())
262+
222263
os.chdir(restoredPath)
223264

224265
def getExePath(args):
@@ -386,26 +427,21 @@ def main(argv):
386427
if subcommand == "fetch":
387428
return fetchDependencies(args)
388429
elif subcommand == "configure" or subcommand == "tune":
389-
generateStdLibFiles()
430+
generateStdLibFilesIfNeeded()
390431
return configure(args)
391432
elif subcommand == "build" or subcommand == "craft":
392-
generateStdLibFiles()
433+
generateStdLibFilesIfNeeded()
393434
# auto configure if it's not already happened
394435
if not projectPathExists(args):
395436
check(configure(args))
396437
return build(args)
397438
elif subcommand == "run" or subcommand == "play":
439+
generateStdLibFilesIfNeeded()
398440
# auto configure if it's not already happened
399-
configured = False
400441
if not projectPathExists(args):
401-
generateStdLibFiles()
402442
check(configure(args))
403-
configured = True
404443

405444
if not exeExists(args) or args.clean:
406-
if not configured:
407-
generateStdLibFiles()
408-
409445
check(build(args))
410446

411447
return run(args, unparsed)

0 commit comments

Comments
 (0)