Skip to content

Commit b5c4961

Browse files
committed
Fix sysroot installation when emscripten itself is read-only
The resulting header tree need to be at least user-writable so that we can incrementally copy files into it, adding new files and also updating previously copied ones. Sadly, python's shutil doesn't seem to have any options for disabling the copying of mode bits. Fixes: #24404
1 parent 2ca9ace commit b5c4961

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

tools/system_libs.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import shutil
1414
import textwrap
1515
import shlex
16+
import stat
1617
from enum import IntEnum, auto
1718
from glob import iglob
1819
from typing import List, Optional
@@ -2453,9 +2454,29 @@ def calculate(options):
24532454
return ret
24542455

24552456

2456-
def copytree_exist_ok(src, dst):
2457+
def ensure_writable(filename):
2458+
if not os.access(filename, os.W_OK):
2459+
current_mode = stat.S_IMODE(os.stat(filename).st_mode)
2460+
os.chmod(filename, current_mode | stat.S_IWUSR)
2461+
2462+
2463+
def copy_header_tree(src, dst):
24572464
shutil.copytree(src, dst, dirs_exist_ok=True)
24582465

2466+
# Python's `shutil.copytree` will unconditonally copy the mode bits.
2467+
# However, because we install header incrementally (including overwriting
2468+
# earlier ones) we need the tree to at least be user-writable. The use
2469+
# case for this is OS distributions where the entire emscripten tree is
2470+
# completely read-only (e.g. NixOs apparently).
2471+
ensure_writable(dst)
2472+
for root, dirs, files in os.walk(dst):
2473+
for d in dirs:
2474+
fullname = os.path.join(dst, root, d)
2475+
ensure_writable(fullname)
2476+
for f in files:
2477+
fullname = os.path.join(dst, root, f)
2478+
ensure_writable(fullname)
2479+
24592480

24602481
def install_system_headers(stamp):
24612482
install_dirs = {
@@ -2477,15 +2498,15 @@ def install_system_headers(stamp):
24772498
for src, dest in install_dirs.items():
24782499
src = utils.path_from_root('system', *src)
24792500
dest = os.path.join(target_include_dir, dest)
2480-
copytree_exist_ok(src, dest)
2501+
copy_header_tree(src, dest)
24812502

24822503
pkgconfig_src = utils.path_from_root('system/lib/pkgconfig')
24832504
pkgconfig_dest = cache.get_sysroot_dir('lib/pkgconfig')
2484-
copytree_exist_ok(pkgconfig_src, pkgconfig_dest)
2505+
copy_header_tree(pkgconfig_src, pkgconfig_dest)
24852506

24862507
bin_src = utils.path_from_root('system/bin')
24872508
bin_dest = cache.get_sysroot_dir('bin')
2488-
copytree_exist_ok(bin_src, bin_dest)
2509+
copy_header_tree(bin_src, bin_dest)
24892510

24902511
# Create a version header based on the emscripten-version.txt
24912512
version_file = cache.get_include_dir('emscripten/version.h')

0 commit comments

Comments
 (0)