Skip to content

Commit

Permalink
Support package variants for dev packages
Browse files Browse the repository at this point in the history
This allows compiling development packages partially (e.g. using a
non-standard CMake target) to save time when developing locally.

It also allows packages to depend on "variants" of other packages, e.g.
O2Physics -> O2#Analysis and O2sim -> O2#Simulation. aliBuild merges variants
if multiple are required, e.g. aliBuild build O2sim O2Physics in the above
case would build O2 with ALIBUILD_BUILD_VARIANT=Analysis,Simulation. "Full"
builds (no variants) always take precedence, and are the only possible
behaviour for non-development packages (e.g. to allow reusing tarballs as
before, and to avoid heisenbugs in CI).
  • Loading branch information
TimoWilken committed Oct 9, 2023
1 parent 066bb09 commit 145852e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
12 changes: 12 additions & 0 deletions alibuild_helpers/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,13 @@ def doBuild(args, parser):
", ".join({x.strip() for x, _ in develPkgsUpper} - set(develPkgs)))
return 1

# We must not apply variants to non-development packages (so that the full
# package can be downloaded from the remote, for example). Delete the
# relevant packages' variants, now that we know the dev packages.
for spec in specs.values():
if spec["package"] not in develPkgs:
spec.pop("variants", None)

if buildOrder:
banner("Packages will be built in the following order:\n - %s",
"\n - ".join(x+" (development package)" if x in develPkgs else "%s@%s" % (x, specs[x]["tag"])
Expand Down Expand Up @@ -510,6 +517,9 @@ def doBuild(args, parser):
out = git(("rev-parse", "HEAD"), directory=spec["source"])
spec["commit_hash"] = out.strip()
spec["devel_hash"] = spec["commit_hash"] + hash_local_changes(spec["source"])
if spec.get("variants", ()):

Check warning on line 520 in alibuild_helpers/build.py

View check run for this annotation

Codecov / codecov/patch

alibuild_helpers/build.py#L520

Added line #L520 was not covered by tests
# spec["variants"] is a set, so its order is undefined. Sort it.
spec["devel_hash"] += "/" + ",".join(sorted(spec["variants"]))

Check warning on line 522 in alibuild_helpers/build.py

View check run for this annotation

Codecov / codecov/patch

alibuild_helpers/build.py#L522

Added line #L522 was not covered by tests
out = git(("rev-parse", "--abbrev-ref", "HEAD"), directory=spec["source"])
if out == "HEAD":
out = git(("rev-parse", "HEAD"), directory=spec["source"])[:10]
Expand Down Expand Up @@ -1058,6 +1068,8 @@ def doBuild(args, parser):
("FULL_BUILD_REQUIRES", " ".join(spec["full_build_requires"])),
("FULL_REQUIRES", " ".join(spec["full_requires"])),
("WRITE_REPO", spec.get("write_repo", source)),
# spec["variants"] is a set, so its order is undefined. Sort it.
("ALIBUILD_BUILD_VARIANT", ",".join(sorted(spec.get("variants", ())))),
]
# Add the extra environment as passed from the command line.
buildEnvironment += [e.partition('=')[::2] for e in args.environment]
Expand Down
20 changes: 19 additions & 1 deletion alibuild_helpers/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,30 @@ def getPackageList(packages, specs, configDir, preferSystem, noSystem,
packages = packages[:]
validDefaults = [] # empty list: all OK; None: no valid default; non-empty list: list of valid ones
while packages:
p = packages.pop(0)
# Find requested variants of packages.
# We only apply variants to development packages (we always store
# requested variants here, but delete them from non-dev packages later).
# Variants allow building only a subset of a package (e.g. a specific
# CMake target), saving build time.
p, has_variants, variants = packages.pop(0).partition("#")
variants = {var.strip() for var in variants.split(",") if var}

if p in specs:
if not has_variants:
# If we now want to build without variants (i.e. the whole package),
# wipe out any previously-configured variants for this package.
specs[p].pop("variants", None)
elif specs[p].get("variants"):

Check warning on line 374 in alibuild_helpers/utilities.py

View check run for this annotation

Codecov / codecov/patch

alibuild_helpers/utilities.py#L374

Added line #L374 was not covered by tests
# The existing package has variants, and this repetition of it does
# too. Merge the variants lists.
specs[p]["variants"] |= variants

Check warning on line 377 in alibuild_helpers/utilities.py

View check run for this annotation

Codecov / codecov/patch

alibuild_helpers/utilities.py#L377

Added line #L377 was not covered by tests
continue

lowerPkg = p.lower()
filename = taps.get(lowerPkg, "%s/%s.sh" % (configDir, lowerPkg))
err, spec, recipe = parseRecipe(getRecipeReader(filename, configDir))
if has_variants and variants:
spec["variants"] = variants

Check warning on line 384 in alibuild_helpers/utilities.py

View check run for this annotation

Codecov / codecov/patch

alibuild_helpers/utilities.py#L384

Added line #L384 was not covered by tests
dieOnError(err, err)
dieOnError(spec["package"].lower() != lowerPkg,
"%s.sh has different package field: %s" % (p, spec["package"]))
Expand Down

0 comments on commit 145852e

Please sign in to comment.