Skip to content
Merged
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
14 changes: 12 additions & 2 deletions conda_forge_tick/migrators/arch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import os
from textwrap import dedent
from typing import Any, Collection, Literal, Optional, Sequence

Expand Down Expand Up @@ -68,6 +69,7 @@ def _filter_stubby_and_ignored_nodes(graph, ignored_packages):
class ArchRebuild(GraphMigrator):
"""A Migrator that adds aarch64 and ppc64le builds to feedstocks."""

allowed_schema_versions = {0, 1}
migrator_version = 1
rerender = True
# We purposefully don't want to bump build number for this migrator
Expand Down Expand Up @@ -155,7 +157,10 @@ def migrate(
self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any
) -> MigrationUidTypedDict | Literal[False]:
with pushd(recipe_dir + "/.."):
self.set_build_number("recipe/meta.yaml")
recipe_file = next(
filter(os.path.exists, ("recipe/recipe.yaml", "recipe/meta.yaml"))
)
self.set_build_number(recipe_file)

with open("conda-forge.yml") as f:
y = yaml_safe_load(f)
Expand Down Expand Up @@ -311,7 +316,10 @@ def migrate(
self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any
) -> MigrationUidTypedDict | Literal[False]:
with pushd(recipe_dir + "/.."):
self.set_build_number("recipe/meta.yaml")
recipe_file = next(
filter(os.path.exists, ("recipe/recipe.yaml", "recipe/meta.yaml"))
)
self.set_build_number(recipe_file)

with open("conda-forge.yml") as f:
y = yaml_safe_load(f)
Expand Down Expand Up @@ -344,6 +352,7 @@ def migrate(
class OSXArm(_CrossCompileRebuild):
"""A Migrator that adds osx-arm64 builds to feedstocks."""

allowed_schema_versions = {0, 1}
migrator_version = 1
build_platform = {"osx_arm64": "osx_64"}
pkg_list_filename = "osx_arm64.txt"
Expand Down Expand Up @@ -378,6 +387,7 @@ def remote_branch(self, feedstock_ctx: FeedstockContext) -> str:
class WinArm64(_CrossCompileRebuild):
"""A Migrator that adds win-arm64 builds to feedstocks."""

allowed_schema_versions = {0, 1}
migrator_version = 1
build_platform = {"win_arm64": "win_64"}
pkg_list_filename = "win_arm64.txt"
Expand Down
124 changes: 79 additions & 45 deletions conda_forge_tick/migrators/cross_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:


class UpdateConfigSubGuessMigrator(CrossCompilationMigratorBase):
allowed_schema_versions = {0, 1}

def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> None:
if (
attrs["feedstock_name"] == "libtool"
Expand Down Expand Up @@ -97,22 +99,40 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No
with open("build.sh", "w") as f:
f.write("".join(lines))

with open("meta.yaml") as f:
recipe_file = next(
filter(os.path.exists, ("recipe.yaml", "meta.yaml"))
)
with open(recipe_file) as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.strip().startswith("- {{ compiler"):
if recipe_file == "meta.yaml" and line.strip().startswith(
"- {{ compiler"
):
new_line = " " * (len(line) - len(line.lstrip()))
new_line += "- gnuconfig # [unix]\n"
lines.insert(i, new_line)
break

with open("meta.yaml", "w") as f:
if recipe_file == "recipe.yaml" and line.strip().startswith(
"- ${{ compiler"
):
new_line = " " * (len(line) - len(line.lstrip()))
new_line += "- if: unix\n"
lines.insert(i, new_line)
new_line = " " * (len(line) - len(line.lstrip()))
new_line += " then: gnuconfig\n"
lines.insert(i + 1, new_line)
break

with open(recipe_file, "w") as f:
f.write("".join(lines))
except RuntimeError:
return


class GuardTestingMigrator(CrossCompilationMigratorBase):
allowed_schema_versions = {0, 1}

def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> None:
with pushd(recipe_dir):
if not os.path.exists("build.sh"):
Expand Down Expand Up @@ -149,35 +169,41 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No


class GuardTestingWinMigrator(CrossCompilationMigratorBase):
allowed_schema_versions = {0, 1}

def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> None:
with pushd(recipe_dir):
if not os.path.exists("bld.bat"):
return
with open("bld.bat") as f:
lines = list(f.readlines())
for batch_file in ("bld.bat", "build.bat"):
if not os.path.exists(batch_file):
continue
with open(batch_file) as f:
lines = list(f.readlines())

for i, line in enumerate(lines):
if "CONDA_BUILD_CROSS_COMPILATION" in line:
return
if (
line.strip().startswith("make check")
or line.strip().startswith("ctest")
or line.strip().startswith("make test")
):
lines.insert(i, 'if not "%CONDA_BUILD_SKIP_TESTS%"=="1" (\n')
insert_after = i + 1
while len(lines) > insert_after and lines[insert_after].endswith(
"\\\n",
for i, line in enumerate(lines):
if "CONDA_BUILD_CROSS_COMPILATION" in line:
return
if (
line.strip().startswith("make check")
or line.strip().startswith("ctest")
or line.strip().startswith("make test")
):
insert_after += 1
if lines[insert_after][-1] != "\n":
lines[insert_after] += "\n"
lines.insert(insert_after + 1, ")\n")
break
else:
return
with open("bld.bat", "w") as f:
f.write("".join(lines))
lines.insert(i, 'if not "%CONDA_BUILD_SKIP_TESTS%"=="1" (\n')
insert_after = i + 1
while len(lines) > insert_after and lines[
insert_after
].endswith(
"\\\n",
):
insert_after += 1
if lines[insert_after][-1] != "\n":
lines[insert_after] += "\n"
lines.insert(insert_after + 1, ")\n")
break
else:
return
with open(batch_file, "w") as f:
f.write("".join(lines))
break


class CrossPythonMigrator(MiniMigrator):
Expand Down Expand Up @@ -265,6 +291,8 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No


class UpdateCMakeArgsMigrator(CrossCompilationMigratorBase):
allowed_schema_versions = {0, 1}

def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:
build_reqs = attrs.get("requirements", {}).get("build", set())
return "cmake" not in build_reqs or skip_migrator_due_to_schema(
Expand Down Expand Up @@ -294,6 +322,8 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No


class UpdateCMakeArgsWinMigrator(CrossCompilationMigratorBase):
allowed_schema_versions = {0, 1}

def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:
build_reqs = attrs.get("requirements", {}).get("build", set())
return "cmake" not in build_reqs or skip_migrator_due_to_schema(
Expand All @@ -302,24 +332,26 @@ def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:

def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> None:
with pushd(recipe_dir):
if not os.path.exists("bld.bat"):
return
with open("bld.bat") as f:
lines = list(f.readlines())
for batch_file in ("bld.bat", "build.bat"):
if not os.path.exists(batch_file):
continue
with open(batch_file) as f:
lines = list(f.readlines())

for i, line in enumerate(lines):
if "%CMAKE_ARGS%" in line:
return
for i, line in enumerate(lines):
if "%CMAKE_ARGS%" in line:
return

for i, line in enumerate(lines):
if line.startswith("cmake "):
lines[i] = "cmake %CMAKE_ARGS% " + line[len("cmake ") :]
break
else:
return
for i, line in enumerate(lines):
if line.startswith("cmake "):
lines[i] = "cmake %CMAKE_ARGS% " + line[len("cmake ") :]
break
else:
return

with open("bld.bat", "w") as f:
f.write("".join(lines))
with open(batch_file, "w") as f:
f.write("".join(lines))
break


class Build2HostMigrator(MiniMigrator):
Expand Down Expand Up @@ -374,6 +406,7 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No


class NoCondaInspectMigrator(MiniMigrator):
allowed_schema_versions = {0, 1}
post_migration = True

def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:
Expand All @@ -385,7 +418,8 @@ def filter(self, attrs: "AttrsTypedDict", not_bad_str_start: str = "") -> bool:

def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> None:
with pushd(recipe_dir):
with open("meta.yaml") as fp:
recipe_file = next(filter(os.path.exists, ("recipe.yaml", "meta.yaml")))
with open(recipe_file) as fp:
meta_yaml = fp.readlines()

new_lines = []
Expand All @@ -394,7 +428,7 @@ def migrate(self, recipe_dir: str, attrs: "AttrsTypedDict", **kwargs: Any) -> No
continue
new_lines.append(line)

with open("meta.yaml", "w") as f:
with open(recipe_file, "w") as f:
f.write("".join(new_lines))


Expand Down
2 changes: 2 additions & 0 deletions conda_forge_tick/migrators/mpi_pin_run_as_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def _parse_cbc_mpi(lines):


class MPIPinRunAsBuildCleanup(MiniMigrator):
allowed_schema_versions = {0, 1}

def filter(self, attrs, not_bad_str_start=""):
host_req = (attrs.get("requirements", {}) or {}).get("host", set()) or set()

Expand Down
101 changes: 78 additions & 23 deletions conda_forge_tick/provide_source_code.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import glob
import json
import logging
import os
import shutil
import subprocess
import sys
import tempfile
from contextlib import contextmanager

import wurlitzer
import yaml
from conda_forge_feedstock_ops.container_utils import (
get_default_log_level_args,
run_container_operation,
Expand Down Expand Up @@ -149,38 +152,90 @@ def _print_out():

try:
with wurlitzer.pipes(stderr=wurlitzer.STDOUT) as (out, _):
from conda_build.api import render
from conda_build.config import get_or_merge_config
from conda_build.source import provide

# Use conda build to do all the downloading/extracting bits
config = get_or_merge_config(None)
ci_support_files = sorted(
glob.glob(os.path.join(recipe_dir, "../.ci_support/*.yaml"))
)
if ci_support_files:
config.variant_config_files = [ci_support_files[0]]
variant_config_file = ci_support_files[0]
else:
config.variant_config_files = [
# try global pinnings
os.path.join(os.environ["CONDA_PREFIX"], "conda_build_config.yaml")
]

md = render(
recipe_dir,
config=config,
finalize=False,
bypass_env_check=True,
)
if not md:
return None
md = md[0][0]
# try global pinnings
variant_config_file = os.path.join(
os.environ["CONDA_PREFIX"], "conda_build_config.yaml"
)
if os.path.exists(os.path.join(recipe_dir, "recipe.yaml")):
result = _provide_source_code_v1(recipe_dir, variant_config_file)
if result is not None:
yield result
else:
from conda_build.api import render
from conda_build.config import get_or_merge_config
from conda_build.source import provide

# Use conda build to do all the downloading/extracting bits
config = get_or_merge_config(None)
config.variant_config_files = [variant_config_file]
md = render(
recipe_dir,
config=config,
finalize=False,
bypass_env_check=True,
)
if not md:
return None
md = md[0][0]

yield provide(md)

# provide source dir
yield provide(md)
except (SystemExit, Exception) as e:
_print_out()
logger.error("Error in getting conda build src!", exc_info=e)
raise RuntimeError("conda build src exception: " + str(e))

_print_out()


def _provide_source_code_v1(recipe_dir, variant_config_file):
recipe_json = subprocess.check_output(
[
"rattler-build",
"build",
"--render-only",
"-r",
f"{recipe_dir}/recipe.yaml",
"-m",
variant_config_file,
]
)
recipe_meta = json.loads(recipe_json)[0]
recipe = recipe_meta["recipe"]
minimal_recipe = {
"context": recipe.get("context", {}),
"package": recipe.get("package", {}),
"source": recipe["source"],
"build": {
"script": {
"content": "exit 1",
},
},
}
with open(f"{recipe_dir}/minimal_recipe.yaml", "w") as f:
yaml.dump(minimal_recipe, f)
try:
out = subprocess.run(
[
"rattler-build",
"build",
"-r",
f"{recipe_dir}/minimal_recipe.yaml",
"-m",
variant_config_file,
],
check=False,
capture_output=True,
)
for line in out.stderr.decode("utf-8").splitlines():
text_to_search = "Work directory: "
if text_to_search in line:
return line[(line.index(text_to_search) + len(text_to_search)) :]
finally:
os.remove(f"{recipe_dir}/minimal_recipe.yaml")
Loading