diff --git a/alibuild_helpers/build.py b/alibuild_helpers/build.py index 1a6a9b0c..d5a4bd9d 100644 --- a/alibuild_helpers/build.py +++ b/alibuild_helpers/build.py @@ -463,6 +463,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"]) @@ -522,6 +529,9 @@ def doBuild(args, parser): local_hash, untracked = hash_local_changes(spec) untrackedFilesDirectories.extend(untracked) spec["devel_hash"] = spec["commit_hash"] + local_hash + if spec.get("variants", ()): + # spec["variants"] is a set, so its order is undefined. Sort it. + spec["devel_hash"] += "/" + ",".join(sorted(spec["variants"])) out = spec["scm"].branchOrRef(directory=spec["source"]) develPackageBranch = out.replace("/", "-") spec["tag"] = args.develPrefix if "develPrefix" in args else develPackageBranch @@ -1068,6 +1078,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] diff --git a/alibuild_helpers/utilities.py b/alibuild_helpers/utilities.py index cd694dfa..b1982139 100644 --- a/alibuild_helpers/utilities.py +++ b/alibuild_helpers/utilities.py @@ -365,12 +365,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"): + # The existing package has variants, and this repetition of it does + # too. Merge the variants lists. + specs[p]["variants"] |= variants 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 dieOnError(err, err) dieOnError(spec["package"].lower() != lowerPkg, "%s.sh has different package field: %s" % (p, spec["package"]))