Skip to content

Commit ce693ff

Browse files
authored
buildcache create: avoid prefix copy (#35173)
1 parent 18027d0 commit ce693ff

File tree

1 file changed

+40
-37
lines changed

1 file changed

+40
-37
lines changed

lib/spack/spack/binary_distribution.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,48 +1198,56 @@ def _build_tarball(
11981198
):
11991199
raise NoOverwriteException(url_util.format(remote_specfile_path))
12001200

1201-
# make a copy of the install directory to work with
1202-
workdir = os.path.join(tmpdir, os.path.basename(spec.prefix))
1203-
# install_tree copies hardlinks
1204-
# create a temporary tarfile from prefix and exract it to workdir
1205-
# tarfile preserves hardlinks
1206-
temp_tarfile_name = tarball_name(spec, ".tar")
1207-
temp_tarfile_path = os.path.join(tarfile_dir, temp_tarfile_name)
1208-
with closing(tarfile.open(temp_tarfile_path, "w")) as tar:
1209-
tar.add(name="%s" % spec.prefix, arcname=".")
1210-
with closing(tarfile.open(temp_tarfile_path, "r")) as tar:
1211-
tar.extractall(workdir)
1212-
os.remove(temp_tarfile_path)
1201+
pkg_dir = os.path.basename(spec.prefix.rstrip(os.path.sep))
1202+
workdir = os.path.join(tmpdir, pkg_dir)
1203+
1204+
# TODO: We generally don't want to mutate any files, but when using relative
1205+
# mode, Spack unfortunately *does* mutate rpaths and links ahead of time.
1206+
# For now, we only make a full copy of the spec prefix when in relative mode.
1207+
1208+
if relative:
1209+
# tarfile is used because it preserves hardlink etc best.
1210+
binaries_dir = workdir
1211+
temp_tarfile_name = tarball_name(spec, ".tar")
1212+
temp_tarfile_path = os.path.join(tarfile_dir, temp_tarfile_name)
1213+
with closing(tarfile.open(temp_tarfile_path, "w")) as tar:
1214+
tar.add(name="%s" % spec.prefix, arcname=".")
1215+
with closing(tarfile.open(temp_tarfile_path, "r")) as tar:
1216+
tar.extractall(workdir)
1217+
os.remove(temp_tarfile_path)
1218+
else:
1219+
binaries_dir = spec.prefix
1220+
mkdirp(os.path.join(workdir, ".spack"))
12131221

12141222
# create info for later relocation and create tar
12151223
write_buildinfo_file(spec, workdir, relative)
12161224

12171225
# optionally make the paths in the binaries relative to each other
12181226
# in the spack install tree before creating tarball
1219-
if relative:
1220-
try:
1227+
try:
1228+
if relative:
12211229
make_package_relative(workdir, spec, allow_root)
1222-
except Exception as e:
1223-
shutil.rmtree(workdir)
1224-
shutil.rmtree(tarfile_dir)
1225-
shutil.rmtree(tmpdir)
1226-
tty.die(e)
1227-
else:
1228-
try:
1229-
check_package_relocatable(workdir, spec, allow_root)
1230-
except Exception as e:
1231-
shutil.rmtree(workdir)
1232-
shutil.rmtree(tarfile_dir)
1233-
shutil.rmtree(tmpdir)
1234-
tty.die(e)
1230+
elif not allow_root:
1231+
ensure_package_relocatable(workdir, binaries_dir)
1232+
except Exception as e:
1233+
shutil.rmtree(workdir)
1234+
shutil.rmtree(tarfile_dir)
1235+
shutil.rmtree(tmpdir)
1236+
tty.die(e)
12351237

12361238
# create gzip compressed tarball of the install prefix
12371239
# On AMD Ryzen 3700X and an SSD disk, we have the following on compression speed:
12381240
# compresslevel=6 gzip default: llvm takes 4mins, roughly 2.1GB
12391241
# compresslevel=9 python default: llvm takes 12mins, roughly 2.1GB
12401242
# So we follow gzip.
12411243
with closing(tarfile.open(tarfile_path, "w:gz", compresslevel=6)) as tar:
1242-
tar.add(name="%s" % workdir, arcname="%s" % os.path.basename(spec.prefix))
1244+
tar.add(name=binaries_dir, arcname=pkg_dir)
1245+
if not relative:
1246+
# Add buildinfo file
1247+
buildinfo_path = buildinfo_file_name(workdir)
1248+
buildinfo_arcname = buildinfo_file_name(pkg_dir)
1249+
tar.add(name=buildinfo_path, arcname=buildinfo_arcname)
1250+
12431251
# remove copy of install directory
12441252
shutil.rmtree(workdir)
12451253

@@ -1567,16 +1575,11 @@ def make_package_relative(workdir, spec, allow_root):
15671575
relocate.make_link_relative(cur_path_names, orig_path_names)
15681576

15691577

1570-
def check_package_relocatable(workdir, spec, allow_root):
1571-
"""
1572-
Check if package binaries are relocatable.
1573-
Change links to placeholder links.
1574-
"""
1578+
def ensure_package_relocatable(workdir, binaries_dir):
1579+
"""Check if package binaries are relocatable."""
15751580
buildinfo = read_buildinfo_file(workdir)
1576-
cur_path_names = list()
1577-
for filename in buildinfo["relocate_binaries"]:
1578-
cur_path_names.append(os.path.join(workdir, filename))
1579-
allow_root or relocate.ensure_binaries_are_relocatable(cur_path_names)
1581+
binaries = [os.path.join(binaries_dir, f) for f in buildinfo["relocate_binaries"]]
1582+
relocate.ensure_binaries_are_relocatable(binaries)
15801583

15811584

15821585
def dedupe_hardlinks_if_necessary(root, buildinfo):

0 commit comments

Comments
 (0)