Resolve dependencies from POMs; add deps:/coordinate_map wiring
Soong needs every transitive edge spelled out as static_libs — the old generator emitted bare imports, so consumers compiled but failed at dex/runtime (this bit coil). Now each artifact's POM is parsed: compile/runtime deps become static_libs; in-group deps are auto-downloaded into the same repo (KMP -android variants probed); out-of-group deps map to in-tree module names via coordinate_map (null = ignore), with warnings for anything unmapped. Explicit deps: lists merge in; pom_deps: false or --no-pom opts out. Config: coil pinned at 3.5.0 with the full six-artifact graph, splashscreen 1.0.1 added, accompanist gains drawablepainter.
This commit is contained in:
+79
-8
@@ -5,6 +5,18 @@
|
||||
# python maven-to-lib.py --lib coil # single lib
|
||||
# python maven-to-lib.py --git-init # also commit on version branch
|
||||
# python maven-to-lib.py --output /path/to/repos # custom base output dir
|
||||
# python maven-to-lib.py --no-pom # skip POM dep resolution
|
||||
#
|
||||
# Dependency wiring — Soong has no Maven resolution, so every dependency an
|
||||
# artifact needs must appear as a static_libs edge on its import module:
|
||||
# * By default each artifact's POM is parsed. In-group deps (same Maven
|
||||
# group as the lib) are downloaded into the same repo automatically
|
||||
# (KMP "-android" variants are probed). Out-of-group deps are translated
|
||||
# to in-tree Soong module names through coordinate_map below; anything
|
||||
# unmapped prints a warning.
|
||||
# * `deps: [module, ...]` on an artifact adds manual edges (merged with
|
||||
# POM-derived ones; also the only source of edges with pom_deps: false
|
||||
# on the lib or --no-pom on the command line).
|
||||
|
||||
# Applied to every lib unless the lib overrides them.
|
||||
defaults:
|
||||
@@ -17,17 +29,67 @@ maven_repos:
|
||||
- https://repo1.maven.org/maven2
|
||||
- https://dl.google.com/dl/android/maven2
|
||||
|
||||
# Maven coordinate (group:artifact) -> Soong module name, used to wire
|
||||
# POM dependencies that live OUTSIDE the lib being generated (AOSP prebuilts,
|
||||
# external/ projects, or other prebuilt_libs repos). Map a coordinate to null
|
||||
# to acknowledge-and-ignore it (no warning, no edge). Artifact names may be
|
||||
# written without the KMP -android suffix — both spellings match.
|
||||
coordinate_map:
|
||||
# other prebuilt_libs repos
|
||||
com.squareup.okio:okio: okio
|
||||
com.squareup.okio:okio-jvm: okio
|
||||
com.squareup.okhttp3:okhttp: okhttp3
|
||||
com.google.accompanist:accompanist-drawablepainter: accompanist-drawablepainter
|
||||
# AOSP external/
|
||||
org.jetbrains.kotlin:kotlin-stdlib: kotlin-stdlib
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8: kotlin-stdlib-jdk8
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core: kotlinx-coroutines-core
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm: kotlinx-coroutines-core-jvm
|
||||
org.jetbrains.kotlinx:kotlinx-coroutines-android: kotlinx-coroutines-android
|
||||
com.google.code.gson:gson: gson
|
||||
# AOSP prebuilts/sdk androidx
|
||||
androidx.annotation:annotation: androidx.annotation_annotation
|
||||
androidx.annotation:annotation-jvm: androidx.annotation_annotation
|
||||
androidx.activity:activity: androidx.activity_activity
|
||||
androidx.activity:activity-compose: androidx.activity_activity-compose
|
||||
androidx.appcompat:appcompat: androidx.appcompat_appcompat
|
||||
androidx.appcompat:appcompat-resources: androidx.appcompat_appcompat-resources
|
||||
androidx.core:core: androidx.core_core
|
||||
androidx.core:core-ktx: androidx.core_core-ktx
|
||||
androidx.collection:collection: androidx.collection_collection
|
||||
androidx.collection:collection-ktx: androidx.collection_collection-ktx
|
||||
androidx.lifecycle:lifecycle-runtime: androidx.lifecycle_lifecycle-runtime
|
||||
androidx.lifecycle:lifecycle-runtime-ktx: androidx.lifecycle_lifecycle-runtime-ktx
|
||||
androidx.exifinterface:exifinterface: androidx.exifinterface_exifinterface
|
||||
androidx.profileinstaller:profileinstaller: androidx.profileinstaller_profileinstaller
|
||||
androidx.compose.foundation:foundation: androidx.compose.foundation_foundation
|
||||
androidx.compose.ui:ui: androidx.compose.ui_ui
|
||||
androidx.compose.runtime:runtime: androidx.compose.runtime_runtime
|
||||
# JetBrains' KMP compose coordinates = the androidx artifacts on Android
|
||||
org.jetbrains.compose.foundation:foundation: androidx.compose.foundation_foundation
|
||||
org.jetbrains.compose.ui:ui: androidx.compose.ui_ui
|
||||
org.jetbrains.compose.runtime:runtime: androidx.compose.runtime_runtime
|
||||
# annotation-only / compile-time-only artifacts: no runtime payload to bundle
|
||||
org.jetbrains:annotations: null
|
||||
|
||||
libs:
|
||||
|
||||
# ── Image loading ──────────────────────────────────────────────────────────
|
||||
# Coil 3.x is Kotlin Multiplatform — the Android-specific artifacts use the
|
||||
# -android suffix. bp_name keeps the module names stable for apps that depend
|
||||
# on "coil-base" and "coil-compose" in their Android.bp static_libs.
|
||||
# Coil 3.x is Kotlin Multiplatform — the Android payloads use the -android
|
||||
# artifact suffix, and module names drop it (coil-core, coil-compose, ...).
|
||||
# Version is PINNED: the manifest revision (prebuilt_libs_coil @ 3.5.0) and
|
||||
# app code (coil3.* imports) move together, never via 'latest'.
|
||||
# Consumers need "coil-compose" + "coil-network-okhttp" (Coil 3 core ships
|
||||
# no network fetcher; the okhttp one self-registers via ServiceLoader).
|
||||
- name: coil
|
||||
version: latest
|
||||
version: "3.5.0"
|
||||
artifacts:
|
||||
- { group: io.coil-kt.coil3, artifact: coil-android, bp_name: coil-base }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-compose-android, bp_name: coil-compose }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-core-android, bp_name: coil-core }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-android, bp_name: coil }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-compose-core-android, bp_name: coil-compose-core }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-compose-android, bp_name: coil-compose }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-network-core-android, bp_name: coil-network-core }
|
||||
- { group: io.coil-kt.coil3, artifact: coil-network-okhttp-android, bp_name: coil-network-okhttp }
|
||||
|
||||
- name: glide
|
||||
version: latest
|
||||
@@ -44,6 +106,7 @@ libs:
|
||||
- name: okhttp
|
||||
version: latest
|
||||
artifacts:
|
||||
# bp_name okhttp3: "okhttp" collides with the ART module SDK
|
||||
- { group: com.squareup.okhttp3, artifact: okhttp, bp_name: okhttp3 }
|
||||
- { group: com.squareup.okhttp3, artifact: logging-interceptor, bp_name: okhttp-logging-interceptor }
|
||||
|
||||
@@ -86,6 +149,13 @@ libs:
|
||||
version: latest
|
||||
artifacts:
|
||||
- { group: com.google.accompanist, artifact: accompanist-permissions, bp_name: accompanist-permissions }
|
||||
# runtime dep of coil-compose-core
|
||||
- { group: com.google.accompanist, artifact: accompanist-drawablepainter, bp_name: accompanist-drawablepainter }
|
||||
|
||||
- name: splashscreen # androidx core-splashscreen is NOT in AOSP prebuilts/sdk
|
||||
version: "1.0.1"
|
||||
artifacts:
|
||||
- { group: androidx.core, artifact: core-splashscreen, bp_name: androidx.core_core-splashscreen }
|
||||
|
||||
# ── Utilities ──────────────────────────────────────────────────────────────
|
||||
- name: timber
|
||||
@@ -117,10 +187,11 @@ libs:
|
||||
- { group: io.ktor, artifact: ktor-client-content-negotiation, bp_name: ktor-client-content-negotiation }
|
||||
- { group: io.ktor, artifact: ktor-serialization-kotlinx-json, bp_name: ktor-serialization-kotlinx-json }
|
||||
|
||||
# ── Custom Maven repo example ──────────────────────────────────────────────
|
||||
# ── Custom Maven repo / manual deps example ────────────────────────────────
|
||||
# - name: mylib
|
||||
# version: "1.2.0"
|
||||
# pom_deps: false # opt out of POM parsing for this lib
|
||||
# maven_repos:
|
||||
# - https://maven.example.com/releases
|
||||
# artifacts:
|
||||
# - { group: com.example, artifact: mylib }
|
||||
# - { group: com.example, artifact: mylib, deps: [okhttp3, gson] }
|
||||
|
||||
+197
-15
@@ -5,12 +5,27 @@ maven-to-lib — Download Maven artifacts and generate Android.bp prebuilt lib r
|
||||
Each lib defined in config.yml becomes a directory containing its AAR(s)/JAR(s)
|
||||
plus a generated Android.bp with android_library_import / java_import modules.
|
||||
|
||||
Dependency wiring (Soong has no POM resolution — every edge must be a
|
||||
static_libs entry on the import module):
|
||||
|
||||
* POM mode (default): each downloaded artifact's .pom is parsed.
|
||||
- compile/runtime, non-optional dependencies become static_libs edges
|
||||
- deps whose group belongs to this lib are auto-downloaded into the same
|
||||
repo (KMP "-android" variants are probed automatically)
|
||||
- deps outside the lib are mapped to in-tree Soong module names via the
|
||||
top-level `coordinate_map` (map a coordinate to null to ignore it);
|
||||
unmapped coordinates produce a warning so the wiring is never silently
|
||||
incomplete
|
||||
- disable per lib with `pom_deps: false`, or globally with --no-pom
|
||||
* Manual mode: give any artifact an explicit `deps: [module, ...]` list;
|
||||
these merge with (and work without) POM-derived edges.
|
||||
|
||||
Run with --git-init to have each output directory committed on a version-named
|
||||
branch, ready to push as a prebuilt lib repo for AOSP local manifest inclusion:
|
||||
|
||||
<project path="prebuilts/application_libs/coil"
|
||||
name="PawletOS/prebuilt_libs_coil"
|
||||
revision="3.1.4" />
|
||||
revision="3.5.0" />
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -23,6 +38,11 @@ from pathlib import Path
|
||||
import requests
|
||||
import yaml
|
||||
|
||||
# Windows consoles default to a legacy codepage that can't print arrows etc.
|
||||
if hasattr(sys.stdout, "reconfigure"):
|
||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||||
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
||||
|
||||
|
||||
DEFAULT_MAVEN_REPOS = [
|
||||
"https://repo1.maven.org/maven2",
|
||||
@@ -47,6 +67,11 @@ def _group_path(group: str) -> str:
|
||||
return group.replace(".", "/")
|
||||
|
||||
|
||||
def _strip_android(artifact: str) -> str:
|
||||
"""KMP android artifacts are '<name>-android'; module names drop the suffix."""
|
||||
return artifact[:-8] if artifact.endswith("-android") else artifact
|
||||
|
||||
|
||||
def resolve_version(group: str, artifact: str, version: str, repos: list) -> str:
|
||||
"""Return the concrete version string, resolving 'latest' via Maven metadata."""
|
||||
if version != "latest":
|
||||
@@ -102,6 +127,90 @@ def download_artifact(group: str, artifact: str, version: str, ext: str, repos:
|
||||
raise RuntimeError(f"Could not download {group}:{artifact}:{version} (.aar or .jar)")
|
||||
|
||||
|
||||
def artifact_exists(group: str, artifact: str, version: str, repos: list) -> bool:
|
||||
gp = _group_path(group)
|
||||
for ext in ("aar", "jar"):
|
||||
filename = f"{artifact}-{version}.{ext}"
|
||||
for repo in repos:
|
||||
url = f"{repo.rstrip('/')}/{gp}/{artifact}/{version}/{filename}"
|
||||
try:
|
||||
r = requests.head(url, timeout=10, allow_redirects=True)
|
||||
if r.status_code == 200:
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def resolve_kmp_variant(group: str, artifact: str, version: str, repos: list) -> str:
|
||||
"""
|
||||
POMs of KMP libraries reference the root artifact (e.g. coil-core), but the
|
||||
Android payload lives in the '-android' variant. Prefer it when published.
|
||||
"""
|
||||
if not artifact.endswith("-android"):
|
||||
candidate = f"{artifact}-android"
|
||||
if artifact_exists(group, candidate, version, repos):
|
||||
return candidate
|
||||
return artifact
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# POM parsing
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _local_tag(tag: str) -> str:
|
||||
"""Strip any XML namespace: '{http://...}artifactId' -> 'artifactId'."""
|
||||
return tag.rsplit("}", 1)[-1]
|
||||
|
||||
|
||||
def fetch_pom(group: str, artifact: str, version: str, repos: list):
|
||||
gp = _group_path(group)
|
||||
filename = f"{artifact}-{version}.pom"
|
||||
for repo in repos:
|
||||
url = f"{repo.rstrip('/')}/{gp}/{artifact}/{version}/{filename}"
|
||||
try:
|
||||
r = requests.get(url, timeout=15)
|
||||
if r.status_code == 200:
|
||||
return ET.fromstring(r.content)
|
||||
except Exception as e:
|
||||
print(f" warn: pom fetch failed ({url}): {e}")
|
||||
return None
|
||||
|
||||
|
||||
def parse_pom_deps(pom_root) -> list:
|
||||
"""
|
||||
Return [(group, artifact, version-or-None), ...] for the POM's direct
|
||||
compile/runtime, non-optional dependencies.
|
||||
|
||||
Only <dependencies> that is a direct child of <project> is read —
|
||||
<dependencyManagement> pins versions but declares no actual dependencies.
|
||||
"""
|
||||
deps = []
|
||||
for child in pom_root:
|
||||
if _local_tag(child.tag) != "dependencies":
|
||||
continue
|
||||
for dep in child:
|
||||
if _local_tag(dep.tag) != "dependency":
|
||||
continue
|
||||
fields = {_local_tag(f.tag): (f.text or "").strip() for f in dep}
|
||||
scope = fields.get("scope") or "compile"
|
||||
if scope not in ("compile", "runtime"):
|
||||
continue
|
||||
if fields.get("optional") == "true":
|
||||
continue
|
||||
group = fields.get("groupId")
|
||||
artifact = fields.get("artifactId")
|
||||
if not group or not artifact:
|
||||
continue
|
||||
version = fields.get("version") or None
|
||||
# Property references (${...}) can't be resolved without the parent
|
||||
# POM chain; the caller falls back to the depending artifact's version.
|
||||
if version and version.startswith("${"):
|
||||
version = None
|
||||
deps.append((group, artifact, version))
|
||||
return deps
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Android.bp generation
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -110,11 +219,12 @@ def _bp_module_name(artifact_cfg: dict) -> str:
|
||||
return artifact_cfg.get("bp_name", artifact_cfg["artifact"])
|
||||
|
||||
|
||||
def generate_android_bp(lib: dict, resolved: list, defaults: dict) -> str:
|
||||
def generate_android_bp(lib: dict, resolved: list, defaults: dict, dep_edges: dict) -> str:
|
||||
"""
|
||||
Generate an Android.bp string.
|
||||
|
||||
resolved: list of (artifact_cfg, output_filename, resolved_version, actual_ext)
|
||||
resolved: list of (artifact_cfg, output_filename, resolved_version, actual_ext)
|
||||
dep_edges: bp module name -> set of static_libs module names
|
||||
"""
|
||||
sdk_version = str(lib.get("sdk_version", defaults.get("sdk_version", "current")))
|
||||
min_sdk = str(lib.get("min_sdk_version", defaults.get("min_sdk_version", "36")))
|
||||
@@ -124,11 +234,18 @@ def generate_android_bp(lib: dict, resolved: list, defaults: dict) -> str:
|
||||
ext = actual_ext # use what was actually downloaded, not what was requested
|
||||
name = _bp_module_name(artifact_cfg)
|
||||
|
||||
deps = sorted(dep_edges.get(name, ()))
|
||||
static_libs = ""
|
||||
if deps:
|
||||
entries = "".join(f' "{d}",\n' for d in deps)
|
||||
static_libs = f" static_libs: [\n{entries} ],\n"
|
||||
|
||||
if ext == "aar":
|
||||
block = (
|
||||
f'android_library_import {{\n'
|
||||
f' name: "{name}",\n'
|
||||
f' aars: ["{out_name}"],\n'
|
||||
f'{static_libs}'
|
||||
f' sdk_version: "{sdk_version}",\n'
|
||||
f' min_sdk_version: "{min_sdk}",\n'
|
||||
f' visibility: ["//visibility:public"],\n'
|
||||
@@ -139,6 +256,7 @@ def generate_android_bp(lib: dict, resolved: list, defaults: dict) -> str:
|
||||
f'java_import {{\n'
|
||||
f' name: "{name}",\n'
|
||||
f' jars: ["{out_name}"],\n'
|
||||
f'{static_libs}'
|
||||
f' sdk_version: "{sdk_version}",\n'
|
||||
f' visibility: ["//visibility:public"],\n'
|
||||
f'}}'
|
||||
@@ -191,7 +309,15 @@ def git_commit(output_dir: Path, lib_name: str, version: str) -> None:
|
||||
# Core processing
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def process_lib(lib: dict, defaults: dict, global_repos: list, git_init: bool, base_output: Path) -> None:
|
||||
def process_lib(
|
||||
lib: dict,
|
||||
defaults: dict,
|
||||
global_repos: list,
|
||||
git_init: bool,
|
||||
base_output: Path,
|
||||
coordinate_map: dict,
|
||||
use_poms: bool,
|
||||
) -> None:
|
||||
name = lib["name"]
|
||||
print(f"\n[{name}]")
|
||||
|
||||
@@ -200,9 +326,20 @@ def process_lib(lib: dict, defaults: dict, global_repos: list, git_init: bool, b
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
lib_version = lib.get("version") # default version for all artifacts in this lib
|
||||
resolved = []
|
||||
lib_groups = {a["group"] for a in lib["artifacts"]}
|
||||
pom_enabled = use_poms and lib.get("pom_deps", True)
|
||||
|
||||
for artifact_cfg in lib["artifacts"]:
|
||||
# Worklist: explicit artifacts first, POM-discovered in-group transitives
|
||||
# appended behind them. Keyed on (group, suffix-stripped artifact) so a POM
|
||||
# reference to "coil-core" dedups against a configured "coil-core-android".
|
||||
queue = [dict(a) for a in lib["artifacts"]]
|
||||
index = {(a["group"], _strip_android(a["artifact"])): a for a in queue}
|
||||
|
||||
resolved = []
|
||||
dep_edges = {} # bp module name -> set of static_libs names
|
||||
|
||||
while queue:
|
||||
artifact_cfg = queue.pop(0)
|
||||
group = artifact_cfg["group"]
|
||||
artifact = artifact_cfg["artifact"]
|
||||
ext = artifact_cfg.get("type", "aar")
|
||||
@@ -211,7 +348,7 @@ def process_lib(lib: dict, defaults: dict, global_repos: list, git_init: bool, b
|
||||
if version is None:
|
||||
raise ValueError(f"No version for {group}:{artifact} — set it on the artifact or the lib")
|
||||
|
||||
ver = resolve_version(group, artifact, version, repos)
|
||||
ver = resolve_version(group, artifact, version, repos)
|
||||
data, actual_ext = download_artifact(group, artifact, ver, ext, repos)
|
||||
|
||||
# Output filename: explicit output_name, or "{artifact}.{actual_ext}"
|
||||
@@ -221,8 +358,47 @@ def process_lib(lib: dict, defaults: dict, global_repos: list, git_init: bool, b
|
||||
|
||||
resolved.append((artifact_cfg, out_name, ver, actual_ext))
|
||||
|
||||
mod_name = _bp_module_name(artifact_cfg)
|
||||
edges = set(artifact_cfg.get("deps", []))
|
||||
|
||||
if pom_enabled:
|
||||
pom = fetch_pom(group, artifact, ver, repos)
|
||||
if pom is None:
|
||||
print(f" warn: no POM for {group}:{artifact}:{ver} — POM deps skipped")
|
||||
else:
|
||||
for dg, da, dv in parse_pom_deps(pom):
|
||||
key = (dg, _strip_android(da))
|
||||
if dg in lib_groups:
|
||||
dep_cfg = index.get(key)
|
||||
if dep_cfg is None:
|
||||
dver = dv or ver
|
||||
actual_da = resolve_kmp_variant(dg, da, dver, repos)
|
||||
dep_cfg = {
|
||||
"group": dg,
|
||||
"artifact": actual_da,
|
||||
"bp_name": _strip_android(actual_da),
|
||||
"version": dver,
|
||||
}
|
||||
index[key] = dep_cfg
|
||||
queue.append(dep_cfg)
|
||||
print(f" + transitive {dg}:{actual_da}:{dver} (from {artifact} POM)")
|
||||
edges.add(_bp_module_name(dep_cfg))
|
||||
else:
|
||||
for coord in (f"{dg}:{da}", f"{dg}:{_strip_android(da)}"):
|
||||
if coord in coordinate_map:
|
||||
mapped = coordinate_map[coord]
|
||||
if mapped: # null/empty mapping = deliberately ignored
|
||||
edges.add(mapped)
|
||||
break
|
||||
else:
|
||||
print(f" warn: unmapped dep {dg}:{da} (of {artifact}) — "
|
||||
f"add it to coordinate_map (or map it to null to ignore)")
|
||||
|
||||
edges.discard(mod_name)
|
||||
dep_edges[mod_name] = edges
|
||||
|
||||
# Android.bp
|
||||
bp = generate_android_bp(lib, resolved, defaults)
|
||||
bp = generate_android_bp(lib, resolved, defaults, dep_edges)
|
||||
(output_dir / "Android.bp").write_text(bp, encoding="utf-8")
|
||||
print(f" wrote Android.bp")
|
||||
|
||||
@@ -261,21 +437,27 @@ def main() -> None:
|
||||
"--output", default="./output",
|
||||
help="Base output directory when lib has no output_dir set (default: ./output)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-pom", action="store_true",
|
||||
help="Skip POM parsing entirely; only explicit deps: lists are emitted",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
config = load_config(args.config)
|
||||
defaults = config.get("defaults", {})
|
||||
global_repos = config.get("maven_repos", DEFAULT_MAVEN_REPOS)
|
||||
libs = config.get("libs", [])
|
||||
base_output = Path(args.output)
|
||||
filter_libs = set(args.lib) if args.lib else None
|
||||
config = load_config(args.config)
|
||||
defaults = config.get("defaults", {})
|
||||
global_repos = config.get("maven_repos", DEFAULT_MAVEN_REPOS)
|
||||
coordinate_map = config.get("coordinate_map", {}) or {}
|
||||
libs = config.get("libs", [])
|
||||
base_output = Path(args.output)
|
||||
filter_libs = set(args.lib) if args.lib else None
|
||||
|
||||
failed = []
|
||||
for lib in libs:
|
||||
if filter_libs and lib["name"] not in filter_libs:
|
||||
continue
|
||||
try:
|
||||
process_lib(lib, defaults, global_repos, args.git_init, base_output)
|
||||
process_lib(lib, defaults, global_repos, args.git_init, base_output,
|
||||
coordinate_map, not args.no_pom)
|
||||
except Exception as e:
|
||||
print(f" ERROR: {e}", file=sys.stderr)
|
||||
failed.append(lib["name"])
|
||||
|
||||
Reference in New Issue
Block a user