Skip to content

Commit cde0c76

Browse files
committed
Avoid writing even sanity.txt if FROZEN_CACHE is enabled
These improvements to the FROZE_CACHE setting allow for a pre-populated read-only cache. In thie senario the cache is cannot ever be locked, and that we don't even write the sanity file. Users can still forece a sanity check with `emcc --check` but no sanity file will ever be written.
1 parent 38485ce commit cde0c76

File tree

4 files changed

+54
-40
lines changed

4 files changed

+54
-40
lines changed

tests/test_sanity.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,8 @@ def test_em_config_env_var(self):
399399

400400
self.assertContained('hello from emcc with no config file', self.run_js('a.out.js'))
401401

402-
def erase_cache(self):
403-
Cache.erase()
402+
def clear_cache(self):
403+
self.run_process([EMCC, '--clear-cache'])
404404
self.assertCacheEmpty()
405405

406406
def assertCacheEmpty(self):
@@ -415,7 +415,7 @@ def test_emcc_caching(self):
415415
BUILDING_MESSAGE = 'generating system library: %s'
416416

417417
restore_and_set_up()
418-
self.erase_cache()
418+
self.clear_cache()
419419

420420
# Building a file that *does* need something *should* trigger cache
421421
# generation, but only the first time
@@ -455,7 +455,7 @@ def test_cache_clearing_auto(self):
455455
# FROZEN_CACHE prevents cache clears, and prevents building
456456
def test_FROZEN_CACHE(self):
457457
restore_and_set_up()
458-
self.erase_cache()
458+
self.clear_cache()
459459
self.ensure_cache()
460460
self.assertTrue(os.path.exists(Cache.dirname))
461461
# changing config file should not clear cache
@@ -634,19 +634,19 @@ def test():
634634

635635
print('normal build')
636636
with env_modify({'EMCC_FORCE_STDLIBS': None}):
637-
Cache.erase()
637+
self.clear_cache()
638638
build()
639639
test()
640640

641641
print('wacky env vars, these should not mess our bootstrapping')
642642
with env_modify({'EMCC_FORCE_STDLIBS': '1'}):
643-
Cache.erase()
643+
self.clear_cache()
644644
build()
645645
test()
646646

647647
def test_vanilla(self):
648648
restore_and_set_up()
649-
Cache.erase()
649+
self.clear_cache()
650650

651651
def make_fake(report):
652652
with open(config_file, 'a') as f:
@@ -690,10 +690,10 @@ def test_embuilder_force(self):
690690
def test_embuilder_wasm_backend(self):
691691
restore_and_set_up()
692692
# the --lto flag makes us build wasm-bc
693-
self.do([EMCC, '--clear-cache'])
693+
self.clear_cache()
694694
self.run_process([EMBUILDER, 'build', 'libemmalloc'])
695695
self.assertExists(os.path.join(config.CACHE, 'sysroot', 'lib', 'wasm32-emscripten'))
696-
self.do([EMCC, '--clear-cache'])
696+
self.clear_cache()
697697
self.run_process([EMBUILDER, 'build', 'libemmalloc', '--lto'])
698698
self.assertExists(os.path.join(config.CACHE, 'sysroot', 'lib', 'wasm32-emscripten', 'lto'))
699699

tools/cache.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ def __init__(self, dirname):
3737
self.filelock = filelock.FileLock(self.filelock_name)
3838

3939
def acquire_cache_lock(self):
40+
if config.FROZEN_CACHE:
41+
# Raise an exception here rather than exit_with_error since in practice this
42+
# should never happen
43+
raise Exception('Attempt to lock the cache but FROZEN_CACHE is set')
44+
4045
if not self.EM_EXCLUSIVE_CACHE_ACCESS and self.acquired_count == 0:
4146
logger.debug('PID %s acquiring multiprocess file lock to Emscripten cache at %s' % (str(os.getpid()), self.dirname))
4247
try:
@@ -115,10 +120,11 @@ def erase_lib(self, name):
115120
self.erase_file(self.get_lib_name(name))
116121

117122
def erase_file(self, shortname):
118-
name = os.path.join(self.dirname, shortname)
119-
if os.path.exists(name):
120-
logging.info('Cache: deleting cached file: %s', name)
121-
tempfiles.try_delete(name)
123+
with self.lock():
124+
name = os.path.join(self.dirname, shortname)
125+
if os.path.exists(name):
126+
logging.info('Cache: deleting cached file: %s', name)
127+
tempfiles.try_delete(name)
122128

123129
def get_lib(self, libname, *args, **kwargs):
124130
name = self.get_lib_name(libname)
@@ -134,14 +140,14 @@ def get(self, shortname, creator, what=None, force=False):
134140
if os.path.exists(cachename) and not force:
135141
return cachename
136142

143+
if config.FROZEN_CACHE:
144+
# Raise an exception here rather than exit_with_error since in practice this
145+
# should never happen
146+
raise Exception('FROZEN_CACHE is set, but cache file is missing: %s' % shortname)
147+
137148
with self.lock():
138149
if os.path.exists(cachename) and not force:
139150
return cachename
140-
# it doesn't exist yet, create it
141-
if config.FROZEN_CACHE:
142-
# it's ok to build small .txt marker files like "vanilla"
143-
if not shortname.endswith('.txt'):
144-
raise Exception('FROZEN_CACHE disallows building system libs: %s' % shortname)
145151
if what is None:
146152
if shortname.endswith(('.bc', '.so', '.a')):
147153
what = 'system library'

tools/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def normalize_config_settings():
7575
JS_ENGINES = [listify(engine) for engine in JS_ENGINES]
7676
WASM_ENGINES = [listify(engine) for engine in WASM_ENGINES]
7777
if not CACHE:
78-
if root_is_writable():
78+
if FROZEN_CACHE or root_is_writable():
7979
CACHE = path_from_root('cache')
8080
else:
8181
# Use the legacy method of putting the cache in the user's home directory

tools/shared.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,21 @@ def generate_sanity():
239239

240240

241241
def perform_sanity_checks():
242+
# some warning, mostly not fatal checks - do them even if EM_IGNORE_SANITY is on
243+
check_node_version()
244+
check_llvm_version()
245+
246+
llvm_ok = check_llvm()
247+
248+
if os.environ.get('EM_IGNORE_SANITY'):
249+
logger.info('EM_IGNORE_SANITY set, ignoring sanity checks')
250+
return
251+
242252
logger.info('(Emscripten: Running sanity checks)')
243253

254+
if not llvm_ok:
255+
exit_with_error('failing sanity checks due to previous llvm failure')
256+
244257
with ToolchainProfiler.profile_block('sanity compiler_engine'):
245258
try:
246259
run_process(config.NODE_JS + ['-e', 'console.log("hello")'], stdout=PIPE)
@@ -264,11 +277,21 @@ def check_sanity(force=False):
264277
"""
265278
if not force and os.environ.get('EMCC_SKIP_SANITY_CHECK') == '1':
266279
return
280+
267281
# We set EMCC_SKIP_SANITY_CHECK so that any subprocesses that we launch will
268282
# not re-run the tests.
269283
os.environ['EMCC_SKIP_SANITY_CHECK'] = '1'
284+
285+
if config.FROZEN_CACHE:
286+
if force:
287+
perform_sanity_checks()
288+
return
289+
290+
if os.environ.get('EM_IGNORE_SANITY'):
291+
perform_sanity_checks()
292+
return
293+
270294
with ToolchainProfiler.profile_block('sanity'):
271-
check_llvm_version()
272295
if not config.config_file:
273296
return # config stored directly in EM_CONFIG => skip sanity checks
274297
expected = generate_sanity()
@@ -280,14 +303,11 @@ def check_sanity(force=False):
280303
if sanity_data != expected:
281304
logger.info('old sanity: %s' % sanity_data)
282305
logger.info('new sanity: %s' % expected)
283-
if config.FROZEN_CACHE:
284-
logger.info('(Emscripten: config changed, cache may need to be cleared, but FROZEN_CACHE is set)')
285-
else:
286-
logger.info('(Emscripten: config changed, clearing cache)')
287-
Cache.erase()
288-
# the check actually failed, so definitely write out the sanity file, to
289-
# avoid others later seeing failures too
290-
force = False
306+
logger.info('(Emscripten: config changed, clearing cache)')
307+
Cache.erase()
308+
# the check actually failed, so definitely write out the sanity file, to
309+
# avoid others later seeing failures too
310+
force = False
291311
else:
292312
if force:
293313
logger.debug(f'sanity file up-to-date but check forced: {sanity_file}')
@@ -297,18 +317,6 @@ def check_sanity(force=False):
297317
else:
298318
logger.debug(f'sanity file not found: {sanity_file}')
299319

300-
# some warning, mostly not fatal checks - do them even if EM_IGNORE_SANITY is on
301-
check_node_version()
302-
303-
llvm_ok = check_llvm()
304-
305-
if os.environ.get('EM_IGNORE_SANITY'):
306-
logger.info('EM_IGNORE_SANITY set, ignoring sanity checks')
307-
return
308-
309-
if not llvm_ok:
310-
exit_with_error('failing sanity checks due to previous llvm failure')
311-
312320
perform_sanity_checks()
313321

314322
if not force:

0 commit comments

Comments
 (0)