From 20fb9876dc9ba19609f456c93c0fafc43e399329 Mon Sep 17 00:00:00 2001 From: sapetnioc Date: Tue, 18 Jun 2024 15:26:54 +0200 Subject: [PATCH] #7 --- recipes/soma-forge/src/recipes/anatomist.yaml | 19 +- .../soma-forge/src/recipes/bioprocessing.yaml | 16 +- recipes/soma-forge/src/recipes/brainrat.yaml | 17 +- recipes/soma-forge/src/recipes/brainvisa.yaml | 15 +- recipes/soma-forge/src/recipes/capsul.yaml | 11 +- .../src/recipes/cati-deidentification.yaml | 13 +- .../src/recipes/cati-longitudinal.yaml | 15 +- .../soma-forge/src/recipes/cati-rsfmri.yaml | 13 +- .../soma-forge/src/recipes/cati-sacha.yaml | 15 +- .../soma-forge/src/recipes/cati-whasa.yaml | 17 +- recipes/soma-forge/src/recipes/cati.yaml | 21 +- recipes/soma-forge/src/recipes/catidb.yaml | 11 +- .../soma-forge/src/recipes/constellation.yaml | 15 +- .../src/recipes/cortical-surface.yaml | 17 +- recipes/soma-forge/src/recipes/disco.yaml | 17 +- .../src/recipes/highres-cortex.yaml | 15 +- .../src/recipes/morphologist-baby.yaml | 13 +- .../soma-forge/src/recipes/morphologist.yaml | 31 +- .../src/recipes/nuclear-imaging.yaml | 17 +- .../soma-forge/src/recipes/populse-db.yaml | 21 +- .../soma-forge/src/recipes/primatologist.yaml | 17 +- recipes/soma-forge/src/recipes/qualicati.yaml | 16 +- .../src/recipes/soma-freesurfer.yaml | 13 +- .../soma-forge/src/recipes/soma-python.yaml | 13 +- recipes/soma-forge/src/recipes/soma-spm.yaml | 7 +- recipes/soma-forge/src/recipes/soma.yaml | 40 +-- recipes/soma-forge/src/soma_forge.py | 335 +++++++++++------- 27 files changed, 422 insertions(+), 348 deletions(-) diff --git a/recipes/soma-forge/src/recipes/anatomist.yaml b/recipes/soma-forge/src/recipes/anatomist.yaml index 2a1bae1..a3bda6c 100644 --- a/recipes/soma-forge/src/recipes/anatomist.yaml +++ b/recipes/soma-forge/src/recipes/anatomist.yaml @@ -1,20 +1,17 @@ package: name: anatomist -components: - - anatomist-free - - anatomist-gpl +soma-forge: + components: + - anatomist-free + - anatomist-gpl -internal-dependencies: - - soma + internal-dependencies: + - soma + + type: compiled requirements: - build: - - ${{ compiler('cxx') }} - - libstdcxx-devel_linux-64 - - cmake - - make - run: - qwt - matplotlib diff --git a/recipes/soma-forge/src/recipes/bioprocessing.yaml b/recipes/soma-forge/src/recipes/bioprocessing.yaml index ca04d11..ef1dfef 100644 --- a/recipes/soma-forge/src/recipes/bioprocessing.yaml +++ b/recipes/soma-forge/src/recipes/bioprocessing.yaml @@ -1,16 +1,16 @@ package: name: bioprocessing -components: - - bioprocessing +soma-forge: + components: + - bioprocessing -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled +requirements: run: - scikit-learn diff --git a/recipes/soma-forge/src/recipes/brainrat.yaml b/recipes/soma-forge/src/recipes/brainrat.yaml index 44432aa..4bb608b 100644 --- a/recipes/soma-forge/src/recipes/brainrat.yaml +++ b/recipes/soma-forge/src/recipes/brainrat.yaml @@ -1,14 +1,13 @@ package: name: brainrat -components: - - brainrat-private - - brainrat-gpl +soma-forge: + components: + - brainrat-private + - brainrat-gpl -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/brainvisa.yaml b/recipes/soma-forge/src/recipes/brainvisa.yaml index bb197b8..5d356ee 100644 --- a/recipes/soma-forge/src/recipes/brainvisa.yaml +++ b/recipes/soma-forge/src/recipes/brainvisa.yaml @@ -1,9 +1,12 @@ package: name: brainvisa -internal-dependencies: - - brainrat - - disco - - highres-cortex - - morphologist - - primatologist +soma-forge: + internal-dependencies: + - brainrat + - disco + - highres-cortex + - morphologist + - primatologist + + type: virtual diff --git a/recipes/soma-forge/src/recipes/capsul.yaml b/recipes/soma-forge/src/recipes/capsul.yaml index d2850c8..76230e6 100644 --- a/recipes/soma-forge/src/recipes/capsul.yaml +++ b/recipes/soma-forge/src/recipes/capsul.yaml @@ -1,11 +1,14 @@ package: name: capsul -components: - - capsul +soma-forge: + components: + - capsul -internal-dependencies: - - soma-python + internal-dependencies: + - soma-python + + type: interpreted requirements: run: diff --git a/recipes/soma-forge/src/recipes/cati-deidentification.yaml b/recipes/soma-forge/src/recipes/cati-deidentification.yaml index f024582..704c3a8 100644 --- a/recipes/soma-forge/src/recipes/cati-deidentification.yaml +++ b/recipes/soma-forge/src/recipes/cati-deidentification.yaml @@ -1,9 +1,12 @@ package: name: cati-deidentification -components: - - deidentification +soma-forge: + components: + - deidentification -internal-dependencies: - - soma - - anatomist + type: interpreted + + internal-dependencies: + - soma + - anatomist diff --git a/recipes/soma-forge/src/recipes/cati-longitudinal.yaml b/recipes/soma-forge/src/recipes/cati-longitudinal.yaml index d6b6010..a31be51 100644 --- a/recipes/soma-forge/src/recipes/cati-longitudinal.yaml +++ b/recipes/soma-forge/src/recipes/cati-longitudinal.yaml @@ -1,13 +1,12 @@ package: name: cati-longitudinal -components: - - longitudinal_pipelines +soma-forge: + components: + - longitudinal_pipelines -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/cati-rsfmri.yaml b/recipes/soma-forge/src/recipes/cati-rsfmri.yaml index 08fb3a7..5ec7e33 100644 --- a/recipes/soma-forge/src/recipes/cati-rsfmri.yaml +++ b/recipes/soma-forge/src/recipes/cati-rsfmri.yaml @@ -1,9 +1,12 @@ package: name: cati-rsfmri -components: - - rsfmri +soma-forge: + components: + - rsfmri -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist + + type: interpreted diff --git a/recipes/soma-forge/src/recipes/cati-sacha.yaml b/recipes/soma-forge/src/recipes/cati-sacha.yaml index f4442af..88862b9 100644 --- a/recipes/soma-forge/src/recipes/cati-sacha.yaml +++ b/recipes/soma-forge/src/recipes/cati-sacha.yaml @@ -1,13 +1,12 @@ package: name: cati-sacha -components: - - sacha-nonfree sacha-gpl +soma-forge: + components: + - sacha-nonfree sacha-gpl -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/cati-whasa.yaml b/recipes/soma-forge/src/recipes/cati-whasa.yaml index cd1fa6b..b36cab4 100644 --- a/recipes/soma-forge/src/recipes/cati-whasa.yaml +++ b/recipes/soma-forge/src/recipes/cati-whasa.yaml @@ -1,14 +1,13 @@ package: name: cati-whasa -components: - - whasa-nonfree - - whasa-gpl +soma-forge: + components: + - whasa-nonfree + - whasa-gpl -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/cati.yaml b/recipes/soma-forge/src/recipes/cati.yaml index fe715cc..30fd7ee 100644 --- a/recipes/soma-forge/src/recipes/cati.yaml +++ b/recipes/soma-forge/src/recipes/cati.yaml @@ -1,12 +1,15 @@ package: name: cati -internal-dependencies: - - qualicati - - cati-longitudinal - - cati-rsfmri - - cati-sacha - - cati-whasa - - cati-deidentification - - catidb - - nuclear-imaging +soma-forge: + internal-dependencies: + - qualicati + - cati-longitudinal + - cati-rsfmri + - cati-sacha + - cati-whasa + - cati-deidentification + - catidb + - nuclear-imaging + + type: virtual diff --git a/recipes/soma-forge/src/recipes/catidb.yaml b/recipes/soma-forge/src/recipes/catidb.yaml index 925a50d..f6fd157 100644 --- a/recipes/soma-forge/src/recipes/catidb.yaml +++ b/recipes/soma-forge/src/recipes/catidb.yaml @@ -1,8 +1,11 @@ package: name: catidb -components: - - catidb-client +soma-forge: + components: + - catidb-client -internal-dependencies: - - soma + internal-dependencies: + - soma + + type: interpreted diff --git a/recipes/soma-forge/src/recipes/constellation.yaml b/recipes/soma-forge/src/recipes/constellation.yaml index f2d286a..1192235 100644 --- a/recipes/soma-forge/src/recipes/constellation.yaml +++ b/recipes/soma-forge/src/recipes/constellation.yaml @@ -1,13 +1,12 @@ package: name: constellation -components: - - constellation-gpl - - constellation-nonfree +soma-forge: + components: + - constellation-gpl + - constellation-nonfree -internal-dependencies: - - morphologist + internal-dependencies: + - morphologist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/cortical-surface.yaml b/recipes/soma-forge/src/recipes/cortical-surface.yaml index b13abe5..50ab92b 100644 --- a/recipes/soma-forge/src/recipes/cortical-surface.yaml +++ b/recipes/soma-forge/src/recipes/cortical-surface.yaml @@ -1,14 +1,13 @@ package: name: cortical-surface -components: - - cortical_surface-gpl - - cortical_surface-nonfree +soma-forge: + components: + - cortical_surface-gpl + - cortical_surface-nonfree -internal-dependencies: - - morphologist - - soma-freesurfer + internal-dependencies: + - morphologist + - soma-freesurfer -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/disco.yaml b/recipes/soma-forge/src/recipes/disco.yaml index c3b8b50..2dacd30 100644 --- a/recipes/soma-forge/src/recipes/disco.yaml +++ b/recipes/soma-forge/src/recipes/disco.yaml @@ -1,14 +1,13 @@ package: name: disco -components: - - disco +soma-forge: + components: + - disco -internal-dependencies: - - soma - - anatomist - - soma-spm + internal-dependencies: + - soma + - anatomist + - soma-spm -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/highres-cortex.yaml b/recipes/soma-forge/src/recipes/highres-cortex.yaml index 34e15af..b49a8af 100644 --- a/recipes/soma-forge/src/recipes/highres-cortex.yaml +++ b/recipes/soma-forge/src/recipes/highres-cortex.yaml @@ -1,13 +1,12 @@ package: name: highres-cortex -components: - - highres-cortex +soma-forge: + components: + - highres-cortex -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/morphologist-baby.yaml b/recipes/soma-forge/src/recipes/morphologist-baby.yaml index 616fab4..d3dae68 100644 --- a/recipes/soma-forge/src/recipes/morphologist-baby.yaml +++ b/recipes/soma-forge/src/recipes/morphologist-baby.yaml @@ -1,12 +1,11 @@ package: name: morphologist-baby -components: - - morphologist-baby +soma-forge: + components: + - morphologist-baby -internal-dependencies: - - morphologist + internal-dependencies: + - morphologist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/morphologist.yaml b/recipes/soma-forge/src/recipes/morphologist.yaml index 26a8623..a4fe995 100644 --- a/recipes/soma-forge/src/recipes/morphologist.yaml +++ b/recipes/soma-forge/src/recipes/morphologist.yaml @@ -1,27 +1,24 @@ package: name: morphologist -components: - - morphologist-nonfree - - morphologist-gpl - - morphologist-ui - - sulci-nonfree - - morpho-deepsulci +soma-forge: + components: + - morphologist-nonfree + - morphologist-gpl + - morphologist-ui + - sulci-nonfree + - morpho-deepsulci -internal-dependencies: - - soma - - anatomist - - soma-spm - - capsul + internal-dependencies: + - soma + - anatomist + - soma-spm + - capsul + type: compiled -requirements: - build: - - ${{ compiler('cxx') }} - - libstdcxx-devel_linux-64 - - cmake - - make +requirements: run: - pytorch - torchvision diff --git a/recipes/soma-forge/src/recipes/nuclear-imaging.yaml b/recipes/soma-forge/src/recipes/nuclear-imaging.yaml index 016f8ce..90e610e 100644 --- a/recipes/soma-forge/src/recipes/nuclear-imaging.yaml +++ b/recipes/soma-forge/src/recipes/nuclear-imaging.yaml @@ -1,14 +1,13 @@ package: name: nuclear-imaging -components: - - nuclear_imaging-nonfree - - nuclear_imaging-gpl +soma-forge: + components: + - nuclear_imaging-nonfree + - nuclear_imaging-gpl -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/populse-db.yaml b/recipes/soma-forge/src/recipes/populse-db.yaml index 2a381ed..f4da095 100644 --- a/recipes/soma-forge/src/recipes/populse-db.yaml +++ b/recipes/soma-forge/src/recipes/populse-db.yaml @@ -1,16 +1,19 @@ package: name: populse-db -components: - - populse-db +soma-forge: + components: + - populse-db -requirements: - run: - - python >3.9 - - lark-parser >0.7.0 - - python-dateutil - - requests - - cryptography + requirements: + run: + - python >3.9 + - lark-parser >0.7.0 + - python-dateutil + - requests + - cryptography + + type: interpreted tests: - script: "python -m populse_db.test" diff --git a/recipes/soma-forge/src/recipes/primatologist.yaml b/recipes/soma-forge/src/recipes/primatologist.yaml index 1cd96e1..a5b615f 100644 --- a/recipes/soma-forge/src/recipes/primatologist.yaml +++ b/recipes/soma-forge/src/recipes/primatologist.yaml @@ -1,14 +1,13 @@ package: name: primatologist -components: - - primatologist-gpl +soma-forge: + components: + - primatologist-gpl -internal-dependencies: - - soma - - anatomist - - soma-freesurfer + internal-dependencies: + - soma + - anatomist + - soma-freesurfer -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled diff --git a/recipes/soma-forge/src/recipes/qualicati.yaml b/recipes/soma-forge/src/recipes/qualicati.yaml index ee7810e..a641f76 100644 --- a/recipes/soma-forge/src/recipes/qualicati.yaml +++ b/recipes/soma-forge/src/recipes/qualicati.yaml @@ -1,17 +1,17 @@ package: name: qualicati -components: - - qualicati +soma-forge: + components: + - qualicati -internal-dependencies: - - soma - - anatomist + internal-dependencies: + - soma + - anatomist -requirements: - build: - - ${{ compiler('cxx') }} + type: compiled +requirements: run: - nibabel - pydicom diff --git a/recipes/soma-forge/src/recipes/soma-freesurfer.yaml b/recipes/soma-forge/src/recipes/soma-freesurfer.yaml index e3c2368..d637449 100644 --- a/recipes/soma-forge/src/recipes/soma-freesurfer.yaml +++ b/recipes/soma-forge/src/recipes/soma-freesurfer.yaml @@ -1,9 +1,12 @@ package: name: soma-freesurfer -components: - - brainvisa_freesurfer +soma-forge: + components: + - brainvisa_freesurfer -internal-dependencies: - - soma - - morphologist + internal-dependencies: + - soma + - morphologist + + type: interpreted diff --git a/recipes/soma-forge/src/recipes/soma-python.yaml b/recipes/soma-forge/src/recipes/soma-python.yaml index ac14fa1..24065cd 100644 --- a/recipes/soma-forge/src/recipes/soma-python.yaml +++ b/recipes/soma-forge/src/recipes/soma-python.yaml @@ -1,12 +1,15 @@ package: name: soma-python -components: - - soma-base - - soma-workflow +soma-forge: + components: + - soma-base + - soma-workflow -internal-dependencies: - - populse-db + internal-dependencies: + - populse-db + + type: interpreted requirements: run: diff --git a/recipes/soma-forge/src/recipes/soma-spm.yaml b/recipes/soma-forge/src/recipes/soma-spm.yaml index 430d895..d25d60d 100644 --- a/recipes/soma-forge/src/recipes/soma-spm.yaml +++ b/recipes/soma-forge/src/recipes/soma-spm.yaml @@ -1,8 +1,11 @@ package: name: soma-spm -components: - - brainvisa-spm +soma-forge: + components: + - brainvisa-spm + + type: interpreted internal-dependencies: - soma diff --git a/recipes/soma-forge/src/recipes/soma.yaml b/recipes/soma-forge/src/recipes/soma.yaml index b4539e7..b1b4cc1 100644 --- a/recipes/soma-forge/src/recipes/soma.yaml +++ b/recipes/soma-forge/src/recipes/soma.yaml @@ -1,37 +1,21 @@ package: name: soma -components: - - soma-io - - aims-free - - aims-gpl - - brainvisa-share - - axon +soma-forge: + components: + - soma-io + - aims-free + - aims-gpl + - brainvisa-share + - axon -# build: -# number: 0 -# script: | -# cd "$PIXI_PROJECT_ROOT" -# pixi run bash << END -# cd "$CASA_BUILD" -# export BRAINVISA_INSTALL_PREFIX="$PREFIX" -# for component in soma-io aims-free aims-gpl brainvisa-share axon; do -# make install-\${component} -# make install-\${component}-dev -# make install-\${component}-usrdoc -# make install-\${component}-devdoc -# done -# END + internal-dependencies: + - soma-python -internal-dependencies: - - soma-python + type: compiled requirements: build: - - ${{ compiler('cxx') }} - - libstdcxx-devel_linux-64 - - cmake - - make - libsigcpp <3 - libblitz - boost-cpp @@ -55,10 +39,6 @@ requirements: - openjpeg - pywebp - #run_constrained: - #- pygltflib - #- DracoPy - tests: - script: | python -m soma_forge test soma diff --git a/recipes/soma-forge/src/soma_forge.py b/recipes/soma-forge/src/soma_forge.py index ebe49eb..fbb3de5 100644 --- a/recipes/soma-forge/src/soma_forge.py +++ b/recipes/soma-forge/src/soma_forge.py @@ -92,11 +92,8 @@ def cli(): @click.argument("packages", type=str, nargs=-1) def init(directory, packages, python, capsul, qt, force): """Create or reconfigure a full BrainVISA development directory""" - if not packages: - packages = ["all"] - neuro_forge_url = "https://brainvisa.info/neuro-forge" - pixi_root = pathlib.Path(directory) + pixi_root = pathlib.Path(directory).absolute() if not (pixi_root / "pixi.toml").exists(): pixi_root.mkdir(exist_ok=True) subprocess.check_call( @@ -119,48 +116,56 @@ def init(directory, packages, python, capsul, qt, force): conf_dir = pixi_root / "conf" conf_dir.mkdir(exist_ok=True) - build_options_file = conf_dir / "build_options.json" - build_options = { - "packages": packages, + build_info_file = conf_dir / "build_info.json" + build_info = { + "packages": packages or ["all"], + "options": { + "python": default_python, + "qt": default_qt, + "capsul": default_capsul, + }, } - if build_options_file.exists(): - with open(build_options_file) as f: - current_build_options = json.load(f) - build_options = current_build_options.copy() - for name, default in ( - ("python", default_python), - ("capsul", default_capsul), - ("qt", default_qt), + if build_info_file.exists() and not force: + with open(build_info_file) as f: + current_build_info = json.load(f) + build_info = current_build_info.copy() + for name in ( + "python", + "capsul", + "qt", ): - build_options[name] = locals()[name] or default + v = locals().get(name) + if v: + build_info["options"][name] = v - if force or not build_options_file.exists(): - with open(build_options_file, "w") as f: - json.dump(build_options, f, indent=4) + if force or not build_info_file.exists(): + with open(build_info_file, "w") as f: + json.dump(build_info, f, indent=4) else: - with open(build_options_file) as f: - current_build_options = json.load(f) - if current_build_options != build_options and build_dir.exists(): + with open(build_info_file) as f: + current_build_info = json.load(f) + if current_build_info != build_info and build_dir.exists(): console.print( - f"[red]Existing build options in [bold]{build_options_file}[/bold] differs from the selected ones[/red]" + f"[red]Existing build options in [bold]{build_info_file}[/bold] differs from the selected ones[/red]" ) table = Table() table.add_column("existing options") table.add_column("selected options") - table.add_row(Pretty(current_build_options), Pretty(build_options)) + table.add_row(Pretty(current_build_info), Pretty(build_info)) console.print(table) console.print( "Either remove the directory [code]{build_dir}[/code] or use [code]--force[/code] option." ) sys.exit(1) - with open(build_options_file, "w") as f: - json.dump(build_options, f, indent=4) + with open(build_info_file, "w") as f: + json.dump(build_info, f, indent=4) + packages = build_info["packages"] pixi_config = read_pixi_config(pixi_root) pixi_project_name = ( - f"{'-'.join(packages)}-py{build_options['python']}" - f"-cap{build_options['capsul']}" - f"-qt{build_options['qt']}" + f"{'-'.join(packages)}-py{build_info['options']['python']}" + f"-cap{build_info['options']['capsul']}" + f"-qt{build_info['options']['qt']}" ) modified = False if pixi_config["project"]["name"] != pixi_project_name: @@ -178,9 +183,10 @@ def init(directory, packages, python, capsul, qt, force): components = {} for recipe in selected_recipes(packages or ["all"]): package = recipe["package"]["name"] + print(package) print(package, recipe["soma-forge"]["type"]) - for component in recipe.get("components", []): - branch = components_branch.get(build_options["capsul"], {}).get( + for component in recipe["soma-forge"].get("components", []): + branch = components_branch.get(build_info["options"]["capsul"], {}).get( component, "master" ) components.setdefault(package, {})[component] = branch @@ -225,11 +231,13 @@ def init(directory, packages, python, capsul, qt, force): ) ) soma_forge_dependencies = { - "python": {f"={build_options['python']}"}, - "cmake": "*", + "python": {f"={build_info['options']['python']}"}, "gcc": "*", - "git": "*", "gxx": "*", + "libstdcxx-devel_linux-64": "*", + "cmake": "*", + "make": "*", + "git": "*", "pytest": "*", "pip": "*", "pyaml": "*", @@ -291,6 +299,16 @@ def init(directory, packages, python, capsul, qt, force): ) +def read_recipe(package): + """ + Read a single recip given its package name + """ + recipe_file = Pathlib.Path(__file__).parent / "recipes" / f"{package}.yaml" + with open(recipe_file) as f: + recipe = yaml.safe_load(f) + return recipe + + def read_recipes(): """ Iterate over all recipes files defined in soma-forge. @@ -308,19 +326,6 @@ def selected_recipes(selection=None): # Read recipes recipes = {r["package"]["name"]: r for r in read_recipes()} - # Parse direct dependencies - for package, recipe in recipes.items(): - if recipe.get("components"): - build_requirements = recipe.get("requirements", {}).get("build", []) - if any( - i for i in build_requirements if i.startswith("${{") and "compiler" in i - ): - recipe["soma-forge"] = {"type": "compiled"} - else: - recipe["soma-forge"] = {"type": "interpreted"} - else: - recipe["soma-forge"] = {"type": "virtual"} - all_packages = set(recipes) metapackages = { @@ -355,7 +360,7 @@ def selected_recipes(selection=None): recipe = recipes[package] yield recipe done.add(package) - dependencies = recipe.get("internal-dependencies", []) + dependencies = recipe["soma-forge"].get("internal-dependencies", []) stack.extend(i for i in dependencies if i not in done) @@ -368,14 +373,7 @@ def sorted_recipies(): ready = set() inverted_dependencies = {} for package, recipe in recipes.items(): - dependencies = ( - recipe["soma-forge"] - .get("requirements", {}) - .get("brainvisa-cmake", set()) - .union( - recipe["soma-forge"].get("requirements", {}).get("soma-forge", set()) - ) - ) + dependencies = recipe["soma-forge"].get("internal-dependencies", []) if not dependencies: ready.add(package) for dependency in dependencies: @@ -387,21 +385,12 @@ def sorted_recipies(): yield recipes[package] done.add(package) for dependent in inverted_dependencies.get(package, []): - dependencies = ( - recipes[dependent]["soma-forge"] - .get("requirements", {}) - .get("brainvisa-cmake", set()) - .union( - recipes[dependent]["soma-forge"] - .get("requirements", {}) - .get("soma-forge", set()) - ) - ) + dependencies = recipe.get("internal-dependencies", []) if all(d in done for d in dependencies): ready.add(dependent) -def forged_packages(name_re): +def forged_packages(pixi_root, name_re): """ Iterate over name of packages that exists in local forge """ @@ -498,77 +487,169 @@ def get_test_commands(log_lines=None): return tests -def build(): - (pixi_root / "build" / "success").unlink(missing_ok=True) - # Do not take into account failure on bv_maker sources as long as - # unstandard branches are used. - bv_maker = str(pixi_root / "src" / "brainvisa-cmake" / "bin" / "bv_maker") - subprocess.call([bv_maker, "sources"]) - subprocess.check_call([bv_maker, "configure", "build", "doc"]) - with open(pixi_root / "build" / "success", "w"): - pass +def brainvisa_cmake_component_version(src): + # Check pyproject.toml + pyproject_toml = src / "pyproject.toml" + if pyproject_toml.exists(): + with open(pyproject_toml) as f: + p = toml.load(f) + version = p.get("project", {}).get("version") + if version is None: + raise ValueError(f"Cannot find version in {pyproject_toml}") + + # Check info.py + info_py = list( + itertools.chain( + src.glob("info.py"), src.glob("*/info.py"), src.glob("python/*/info.py") + ) + ) + if info_py: + if len(info_py) > 1: + raise ValueError( + f"Cannot choose info.py among: {', '.join(str(i) for i in info_py)}" + ) + + info_py = info_py[0] + d = {} + with open(info_py) as f: + exec(compile(f.read(), info_py, "exec"), d, d) + return f"{d['version_major']}.{d['version_minor']}.{d['version_micro']}" + + # Check project_info.cmake + project_info = src / "project_info.cmake" + if not project_info.exists(): + project_info = src / "cmake" / "project_info.cmake" + if project_info.exists(): + v = [None, None, None] + with open(project_info) as f: + p = re.compile(r"\s*set\(\s*([^ \t]*)\s*(.*[^ \t])\s*\)") + for line in f: + match = p.match(line) + if match: + variable, value = match.groups() + if variable == "BRAINVISA_PACKAGE_VERSION_MAJOR": + v[0] = value + elif variable == "BRAINVISA_PACKAGE_VERSION_MINOR": + v[1] = value + elif variable == "BRAINVISA_PACKAGE_VERSION_PATCH": + v[2] = value + return ".".join(v) + + raise ValueError(f"Cannot find brainvisa-cmake component version in {pyproject_toml}") + +@cli.command() +@click.argument("directory", type=click.Path()) +def debug(directory): + pixi_root = pathlib.Path(directory) + for src in (pixi_root / "src").iterdir(): + if src.is_dir(): + print(src.name, "==", brainvisa_cmake_component_version(src)) -def forge(packages, force, show, test=True, check_build=True, verbose=None): + +@cli.command() +@click.option("-v", "--verbose", is_flag=True) +@click.option("--show", is_flag=True) +@click.option("--force", is_flag=True) +@click.option("--test", type=bool, default=True) +@click.argument("directory", type=click.Path()) +@click.argument("packages", type=str, nargs=-1) +def release_dev(directory, packages, force, show, test=True, verbose=None): if show and verbose is None: verbose = True if verbose is True: verbose = sys.stdout if not packages: packages = ["*"] + pixi_root = pathlib.Path(directory).absolute() selector = re.compile("|".join(f"(?:{fnmatch.translate(i)})" for i in packages)) - if check_build and not (pixi_root / "build" / "success").exists(): - build() - channels = read_pixi_config()["project"]["channels"] + channels = read_pixi_config(pixi_root)["project"]["channels"] + forge = pixi_root / "forge" for recipe in sorted_recipies(): package = recipe["package"]["name"] - recipe_dir = recipe["soma-forge"]["recipe_dir"] - if selector.match(package): - if not force: - # Check for the package exsitence - if any(forged_packages(f"^{re.escape(package)}$")): - if verbose: - print( - f"Skip existing package {package}", - file=verbose, - flush=True, - ) - continue - if verbose: - print( - f"Build {package}", - file=verbose, - flush=True, - ) - if not show: - build_dir = pixi_root / "forge" / "bld" / f"rattler-build_{package}" - if build_dir.exists(): - shutil.rmtree(build_dir) - forge = pixi_root / "forge" - command = [ - "rattler-build", - "build", - "--experimental", - "--no-build-id", - "-r", - recipe_dir, - "--output-dir", - str(forge), - ] - if not test: - command.append("--no-test") - for i in channels + [f"file://{str(forge)}"]: - command.extend(["-c", i]) - try: - subprocess.check_call(command) - except subprocess.CalledProcessError: - print( - "ERROR command failed:", - " ".join(f"'{i}'" for i in command), - file=sys.stderr, - flush=True, - ) - return 1 + print(package) + if not selector.match(package): + continue + components = recipe["soma-forge"].get("components", []) + if components: + # Check that build tree is clean + version = None + for component in components: + src = pixi_root / "src" / component + if version is None: + version = brainvisa_cmake_component_version(src) + repo = git.Repo(src) + if not force and repo.is_dirty(): + raise Exception(f"Repository {src} contains uncomited files") + if not force and repo.untracked_files: + raise Exception(f"Repository {src} has local modifications") + recipe["package"]["version"] = version + elif recipe["soma-forge"]["type"] == "virtual": + #TODO + pass + else: + raise Exception(f"No internal dependencies defined in {package} recipe") + + internal_dependencies = recipe["soma-forge"].get("internal-dependencies", []) + if internal_dependencies: + recipe.setdefault("requirements", {}).setdefault("run", []).extend( + internal_dependencies + ) + + # Remove soma-forge specific data + recipe.pop("soma-forge", None) + + recipe.setdefault("build", {})["script"] = "\n".join( + ( + 'cd "$PIXI_PROJECT_ROOT"', + "pixi run bash << END", + 'cd "$CASA_BUILD"', + 'export BRAINVISA_INSTALL_PREFIX="$PREFIX"', + f"for component in {' '.join(components)}; do", + " make install-\${component}", + " make install-\${component}-dev", + " make install-\${component}-usrdoc", + " make install-\${component}-devdoc", + "done", + "END", + ) + ) + + (forge / "recipes" / package).mkdir(exist_ok=True, parents=True) + + with open(forge / "recipes" / package / "recipe.yaml", "w") as f: + yaml.safe_dump(recipe, f) + + # if not show: + # build_dir = forge / "bld" / f"rattler-build_{package}" + # if build_dir.exists(): + # shutil.rmtree(build_dir) + # internal_recipe = read_recipe(package) + # internal_recipe.pop("internal-dependencies", None) + # command = [ + # "rattler-build", + # "build", + # "--experimental", + # "--no-build-id", + # "-r", + # recipe_dir, + # "--output-dir", + # str(forge), + # ] + # if not test: + # command.append("--no-test") + # for i in channels + [f"file://{str(forge)}"]: + # command.extend(["-c", i]) + # try: + # subprocess.check_call(command) + # except subprocess.CalledProcessError: + # print( + # "ERROR command failed:", + # " ".join(f"'{i}'" for i in command), + # file=sys.stderr, + # flush=True, + # ) + # return 1 def test_ref():