|
7 | 7 | import sys |
8 | 8 |
|
9 | 9 | from os import path |
| 10 | +from hashlib import blake2b |
10 | 11 |
|
11 | 12 | cwd = os.getcwd() |
12 | 13 |
|
@@ -161,12 +162,49 @@ def projectPathExists(args): |
161 | 162 |
|
162 | 163 | return path.isdir(projectPath) |
163 | 164 |
|
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(): |
165 | 197 | restoredPath = os.getcwd() |
166 | 198 |
|
167 | 199 | os.chdir(os.path.join(getSourceRoot(), 'std')) |
168 | 200 | os.makedirs("src/generated", exist_ok=True) |
169 | 201 |
|
| 202 | + if (isGeneratedStdLibUpToDate()): |
| 203 | + os.chdir(restoredPath) |
| 204 | + return |
| 205 | + else: |
| 206 | + print("Generating code for @std libraries, files are out of date.") |
| 207 | + |
170 | 208 | with open("src/generated/modules.cpp", "w") as cpp: |
171 | 209 | cpp.writelines([ |
172 | 210 | "// This file is auto-generated by luthier.py. Do not edit.\n", |
@@ -219,6 +257,9 @@ def generateStdLibFiles(): |
219 | 257 | f"extern const std::pair<std::string_view, std::string_view> lutestdlib[{numItems}];\n", |
220 | 258 | ]) |
221 | 259 |
|
| 260 | + with open("../src/generated/hash.txt", "w") as hash: |
| 261 | + hash.write(getStdLibHash()) |
| 262 | + |
222 | 263 | os.chdir(restoredPath) |
223 | 264 |
|
224 | 265 | def getExePath(args): |
@@ -386,26 +427,21 @@ def main(argv): |
386 | 427 | if subcommand == "fetch": |
387 | 428 | return fetchDependencies(args) |
388 | 429 | elif subcommand == "configure" or subcommand == "tune": |
389 | | - generateStdLibFiles() |
| 430 | + generateStdLibFilesIfNeeded() |
390 | 431 | return configure(args) |
391 | 432 | elif subcommand == "build" or subcommand == "craft": |
392 | | - generateStdLibFiles() |
| 433 | + generateStdLibFilesIfNeeded() |
393 | 434 | # auto configure if it's not already happened |
394 | 435 | if not projectPathExists(args): |
395 | 436 | check(configure(args)) |
396 | 437 | return build(args) |
397 | 438 | elif subcommand == "run" or subcommand == "play": |
| 439 | + generateStdLibFilesIfNeeded() |
398 | 440 | # auto configure if it's not already happened |
399 | | - configured = False |
400 | 441 | if not projectPathExists(args): |
401 | | - generateStdLibFiles() |
402 | 442 | check(configure(args)) |
403 | | - configured = True |
404 | 443 |
|
405 | 444 | if not exeExists(args) or args.clean: |
406 | | - if not configured: |
407 | | - generateStdLibFiles() |
408 | | - |
409 | 445 | check(build(args)) |
410 | 446 |
|
411 | 447 | return run(args, unparsed) |
|
0 commit comments