Skip to content
This repository was archived by the owner on Dec 5, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@

- [boa] fix multi-output
- [boa] fix keep run_export and existing spec when existing spec is not simple
- [mambabuild] allow testing multiple recipes (thanks @gabm)
- [mambabuild] allow testing multiple recipes (thanks @gabm)
92 changes: 92 additions & 0 deletions boa/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from pathlib import Path

from boa.core.render import render as core_render
from boa.core.utils import get_config
from boa.core.run_build import to_build_tree, get_dependency_variants
from boa.core.metadata import MetaData

# os.path.join(forge_dir, forge_config["recipe_dir"]),
# platform=platform,
# arch=arch,
# ignore_system_variants=True,
# variants=migrated_combined_variant_spec,
# permit_undefined_jinja=True,
# finalize=False,
# bypass_env_check=True,
# channel_urls=forge_config.get("channels", {}).get(
# "sources", []
# ),


def render(
recipe_dir,
platform,
arch,
ignore_system_variants=True,
variants=None,
permit_undefined_jinja=True,
finalize=False,
bypass_env_check=True,
channel_urls=None,
selected_features=None,
):

if not channel_urls:
channel_urls = []
if not selected_features:
selected_features = dict()

variant = {"target_platform": platform}
# cbc_file = Path(recipe_dir) / "conda_build_config.yaml"
cbc, config = get_config(recipe_dir, variant, [])
cbc["target_platform"] = [variant["target_platform"]]

recipe_path = Path(recipe_dir) / "recipe.yaml"
ydoc = core_render(recipe_path, config)

# this takes in all variants and outputs, builds a dependency tree and returns
# the final metadata

assembled_variants = {}
# if we have a outputs section, use that order the outputs
if ydoc.get("outputs"):
for o in ydoc["outputs"]:
# inherit from global package
pkg_meta = {}
pkg_meta.update(ydoc["package"])
pkg_meta.update(o["package"])
o["package"] = pkg_meta

build_meta = {}
build_meta.update(ydoc.get("build"))
build_meta.update(o.get("build") or {})
o["build"] = build_meta

o["selected_features"] = selected_features

assembled_variants[o["package"]["name"]] = get_dependency_variants(
o.get("requirements", {}), variants, config
)
else:
# we only have one output
assembled_variants[ydoc["package"]["name"]] = get_dependency_variants(
ydoc.get("requirements", {}), variants, config
)

print("Selected variants: ", assembled_variants)

sorted_outputs = to_build_tree(
ydoc, assembled_variants, config, variants, selected_features
)

metas = []
for output in sorted_outputs:
meta = MetaData(recipe_path, output)
print(output)
meta.config.variants = {}
meta.config.input_variants = variants
# meta.config.variants =
metas.append((meta, None, None))
print(metas)
return metas
# o.set_final_build_id(meta)
14 changes: 11 additions & 3 deletions boa/cli/boa.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def main(config=None):
"-i",
"--interactive",
action="store_true",
help="Use interactive mode if build fails",
help="Use (experimental) interactive mode if build fails",
)
build_parser.add_argument(
"--skip-existing", nargs="?", default="default", const="yes",
Expand All @@ -75,11 +75,19 @@ def main(config=None):
action="store_true",
help="Continue building remaining recipes if a recipe fails.",
)

build_parser.add_argument(
"--suppress-variables",
action="store_true",
help="CURRENTLY IGNORED! Do not display value of environment variables specified in build.script_env",
)
build_parser.add_argument(
"--clobber-file",
help="CURRENTLY IGNORED! Clobber data in meta.yaml with fields from this file. Jinja2 is not done on clobbered fields",
)
subparsers.add_parser(
"build",
parents=[parent_parser, build_parser, variant_parser],
help="build a recipe",
help="Build a recipe",
)

transmute_parser = subparsers.add_parser(
Expand Down
74 changes: 67 additions & 7 deletions boa/core/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import json
import copy

from boa.core.config import boa_config

console = boa_config.console


def get_package_version_pin(specs, name):
for s in specs:
Expand Down Expand Up @@ -347,12 +351,10 @@ def get_hash_contents(self):
"""

# trim_build_only_deps(self, dependencies)
dependencies = (
self.get_dependencies("build")
+ self.get_dependencies("host")
# self.output.requirements["build"] + self.output.requirements["host"]
raw_dependencies = self.get_dependencies("build") + self.get_dependencies(
"host"
)
dependencies = {x.name for x in dependencies}
dependencies = {x.name for x in raw_dependencies}
# filter out ignored versions
build_string_excludes = ["python", "r_base", "perl", "lua", "target_platform"]
build_string_excludes.extend(
Expand Down Expand Up @@ -380,12 +382,35 @@ def get_hash_contents(self):
continue
filtered_deps.append(req)

take_keys = set(self.config.variant.keys())
take_keys = set(k for k in self.config.variant.keys() if k in dependencies)
if "python" in take_keys and "python" not in dependencies:
take_keys.remove("python")

# Add <lang>_compiler and <lang>_compiler_version if it was used
for dep in raw_dependencies:
if dep.is_compiler:
if f"{dep.splitted[1]}_compiler" in self.config.variant:
take_keys.add(f"{dep.splitted[1]}_compiler")
if f"{dep.splitted[1]}_compiler_version" in self.config.variant:
take_keys.add(f"{dep.splitted[1]}_compiler_version")

if "CONDA_BUILD_SYSROOT" in self.config.variant:
for dep in raw_dependencies:
if dep.is_compiler and dep.splitted[1] in ["c", "cxx"]:
take_keys.add("CONDA_BUILD_SYSROOT")

# always add target_platform and channel_targets to hash
if ("target_platform" in self.config.variant) and not self.noarch:
take_keys.add("target_platform")
if "channel_targets" in self.config.variant:
take_keys.add("channel_targets")

console.print(self.config.variant)

# retrieve values - this dictionary is what makes up the hash.
return {key: self.config.variant[key] for key in take_keys}
hash_dict = {key: self.config.variant[key] for key in take_keys}
console.print("[bold]Hash dictionary:\n", hash_dict)
return hash_dict

def info_index(self):
arch = (
Expand Down Expand Up @@ -460,6 +485,41 @@ def copy(self):
new = copy.deepcopy(self)
return new

def get_used_vars(self, force_top_level=False):

raw_dependencies = self.get_dependencies("build") + self.get_dependencies(
"host"
)
dependencies = {x.name for x in raw_dependencies}

take_keys = set(k for k in self.config.variant.keys() if k in dependencies)
if "python" in take_keys and "python" not in dependencies:
take_keys.remove("python")

# Add <lang>_compiler and <lang>_compiler_version if it was used
for dep in raw_dependencies:
if dep.is_compiler:
if f"{dep.splitted[1]}_compiler" in self.config.variant:
take_keys.add(f"{dep.splitted[1]}_compiler")
if f"{dep.splitted[1]}_compiler_version" in self.config.variant:
take_keys.add(f"{dep.splitted[1]}_compiler_version")

if "CONDA_BUILD_SYSROOT" in self.config.variant:
for dep in raw_dependencies:
if dep.is_compiler and dep.splitted[1] in ["c", "cxx"]:
take_keys.add("CONDA_BUILD_SYSROOT")

# always add target_platform and channel_targets to hash
if ("target_platform" in self.config.variant) and not self.noarch:
take_keys.add("target_platform")
if "channel_targets" in self.config.variant:
take_keys.add("channel_targets")

return take_keys

def get_used_loop_vars(self, force_top_level=False):
return set()

def get_test_deps(self, py_files, pl_files, lua_files, r_files):
specs = ["%s %s %s" % (self.name(), self.version(), self.build_id())]

Expand Down
9 changes: 9 additions & 0 deletions boa/core/recipe_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ def __init__(
parent = {}
if selected_features is None:
selected_features = {}

self.data = d
self.data["source"] = d.get("source", parent.get("source", {}))
self.config = config
Expand All @@ -182,7 +183,13 @@ def set_section(sname):
set_section("build")
set_section("package")
set_section("app")

# TODO this is a hack ...
set_section("extra")
set_section("about")
self.data["extra"] = self.sections["extra"]
self.data["about"] = self.sections["about"]

set_section("test")

self.sections["files"] = d.get("files")
Expand Down Expand Up @@ -278,6 +285,8 @@ def apply_variant(self, variant, differentiating_keys=()):
copied = copy.deepcopy(self)

copied.variant = variant
# copied.variants = [variant]
# copied.config.variants = [variant]
for idx, r in enumerate(self.requirements["build"]):
vname = r.name.replace("-", "_")
if vname in variant:
Expand Down
5 changes: 3 additions & 2 deletions boa/core/run_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import itertools
import json
import pathlib
import copy

from libmambapy import PrefixData
from libmambapy import Context as MambaContext
Expand Down Expand Up @@ -280,10 +281,9 @@ def to_build_tree(ydoc, variants, config, cbc, selected_features):

# zip keys need to be contracted
zipped_keys = cbc.get("zip_keys", [])

print(f"Variant for {variant_name} ", variants.get(variant_name))
if variants.get(variant_name):
v = variants[variant_name]
import copy

vzipped = copy.copy(v)
zippers = {}
Expand Down Expand Up @@ -344,6 +344,7 @@ def to_build_tree(ydoc, variants, config, cbc, selected_features):

unzipped_combinations.append(unz_combo)

print("Applying variant! ", c, differentiating_keys)
for c in unzipped_combinations:
x = output.apply_variant(c, differentiating_keys)
final_outputs.append(x)
Expand Down