diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2025-12-04 22:19:59 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2025-12-08 20:57:44 -0500 |
| commit | 9f40ce9b277a677ad3cddd8bf1c1d15fbd035251 (patch) | |
| tree | 109cdd94bb9fdbb5437240cc15fa9bc5371f0874 /classes/go-mod-discovery.bbclass | |
| parent | 44c4e44db7300f241e6740b389489e84ef7c1f65 (diff) | |
| download | meta-virtualization-9f40ce9b277a677ad3cddd8bf1c1d15fbd035251.tar.gz | |
classes: add go-mod-vcs and go-mod-discovery for Go module builds
Add two new bbclass files that enable building Go applications using
git-based module resolution instead of network proxy fetches:
go-mod-vcs.bbclass:
- Provides do_create_module_cache task to build GOMODCACHE from git sources
- Implements pure Python h1: hash calculation with go-dirhash-native fallback
- Creates properly structured module zip files and hash files
- Handles module path transformations and case encoding
go-mod-discovery.bbclass:
- Runs module discovery using the oe-go-mod-fetcher tool
- Generates go-mod-git.inc and go-mod-cache.inc files
- Supports bootstrap mode for initial recipe conversion
Together these classes enable fully offline, reproducible Go builds
by fetching module sources via git and constructing the module cache
during the build rather than relying on network access to module proxies.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'classes/go-mod-discovery.bbclass')
| -rw-r--r-- | classes/go-mod-discovery.bbclass | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/classes/go-mod-discovery.bbclass b/classes/go-mod-discovery.bbclass new file mode 100644 index 00000000..0d703d0a --- /dev/null +++ b/classes/go-mod-discovery.bbclass | |||
| @@ -0,0 +1,441 @@ | |||
| 1 | # | ||
| 2 | # Copyright OpenEmbedded Contributors | ||
| 3 | # | ||
| 4 | # SPDX-License-Identifier: MIT | ||
| 5 | # | ||
| 6 | |||
| 7 | # go-mod-discovery.bbclass | ||
| 8 | # | ||
| 9 | # Provides a do_discover_modules task for Go projects that downloads complete | ||
| 10 | # module metadata from proxy.golang.org for use with the bootstrap strategy. | ||
| 11 | # | ||
| 12 | # USAGE: | ||
| 13 | # 1. Add to recipe: inherit go-mod-discovery | ||
| 14 | # 2. Set required variables (see CONFIGURATION below) | ||
| 15 | # 3. Run discovery: bitbake <recipe> -c discover_modules | ||
| 16 | # (This automatically: downloads modules, extracts metadata, regenerates recipe) | ||
| 17 | # 4. Build normally: bitbake <recipe> | ||
| 18 | # | ||
| 19 | # CONFIGURATION: | ||
| 20 | # | ||
| 21 | # Required (must be set by recipe): | ||
| 22 | # | ||
| 23 | # GO_MOD_DISCOVERY_BUILD_TARGET - Build target for go build | ||
| 24 | # Example: "./cmd/server" or "./..." | ||
| 25 | # | ||
| 26 | # Optional (have sensible defaults): | ||
| 27 | # | ||
| 28 | # GO_MOD_DISCOVERY_SRCDIR - Directory containing go.mod | ||
| 29 | # Default: "${S}/src/import" (standard Go recipe layout) | ||
| 30 | # | ||
| 31 | # GO_MOD_DISCOVERY_BUILD_TAGS - Build tags for go build | ||
| 32 | # Default: "${TAGS}" (uses recipe's TAGS variable if set) | ||
| 33 | # Example: "netcgo osusergo static_build" | ||
| 34 | # | ||
| 35 | # GO_MOD_DISCOVERY_LDFLAGS - Linker flags for go build | ||
| 36 | # Default: "-w -s" | ||
| 37 | # Example: "-X main.version=${PV} -w -s" | ||
| 38 | # | ||
| 39 | # GO_MOD_DISCOVERY_GOPATH - GOPATH for discovery build | ||
| 40 | # Default: "${S}/src/import/.gopath:${S}/src/import/vendor" | ||
| 41 | # | ||
| 42 | # GO_MOD_DISCOVERY_OUTPUT - Output binary path | ||
| 43 | # Default: "${WORKDIR}/discovery-build-output" | ||
| 44 | # | ||
| 45 | # GO_MOD_DISCOVERY_DIR - Persistent cache location | ||
| 46 | # Default: "${TOPDIR}/go-mod-discovery/${PN}/${PV}" | ||
| 47 | # | ||
| 48 | # GO_MOD_DISCOVERY_MODULES_JSON - Output path for extracted module metadata | ||
| 49 | # Default: "${GO_MOD_DISCOVERY_DIR}/modules.json" | ||
| 50 | # | ||
| 51 | # GO_MOD_DISCOVERY_SKIP_EXTRACT - Set to "1" to skip automatic extraction | ||
| 52 | # Default: "0" (extraction runs automatically) | ||
| 53 | # | ||
| 54 | # GO_MOD_DISCOVERY_SKIP_GENERATE - Set to "1" to skip automatic recipe generation | ||
| 55 | # Default: "0" (generation runs automatically) | ||
| 56 | # | ||
| 57 | # GO_MOD_DISCOVERY_GIT_REPO - Git repository URL for recipe generation | ||
| 58 | # Example: "https://github.com/rancher/k3s.git" | ||
| 59 | # Required for automatic generation | ||
| 60 | # | ||
| 61 | # GO_MOD_DISCOVERY_GIT_REF - Git ref (commit/tag) for recipe generation | ||
| 62 | # Default: "${SRCREV}" (uses recipe's SRCREV) | ||
| 63 | # | ||
| 64 | # GO_MOD_DISCOVERY_RECIPEDIR - Output directory for generated .inc files | ||
| 65 | # Default: "${FILE_DIRNAME}" (recipe's directory) | ||
| 66 | # | ||
| 67 | # MINIMAL EXAMPLE (manual generation - no GIT_REPO set): | ||
| 68 | # | ||
| 69 | # TAGS = "netcgo osusergo" | ||
| 70 | # GO_MOD_DISCOVERY_BUILD_TARGET = "./cmd/myapp" | ||
| 71 | # inherit go-mod-discovery | ||
| 72 | # # Run: bitbake myapp -c discover_modules | ||
| 73 | # # Then manually: oe-go-mod-fetcher.py --discovered-modules ... --git-repo ... | ||
| 74 | # | ||
| 75 | # FULL AUTOMATIC EXAMPLE (all-in-one discovery + generation): | ||
| 76 | # | ||
| 77 | # TAGS = "netcgo osusergo" | ||
| 78 | # GO_MOD_DISCOVERY_BUILD_TARGET = "./cmd/myapp" | ||
| 79 | # GO_MOD_DISCOVERY_GIT_REPO = "https://github.com/example/myapp.git" | ||
| 80 | # inherit go-mod-discovery | ||
| 81 | # # Run: bitbake myapp -c discover_modules | ||
| 82 | # # Recipe files are automatically regenerated! | ||
| 83 | # | ||
| 84 | # See: meta-virtualization/scripts/BOOTSTRAP-STRATEGY.md (Approach B) | ||
| 85 | # | ||
| 86 | # This task is NOT part of the normal build - it must be explicitly invoked | ||
| 87 | # via bitbake <recipe> -c discover_modules | ||
| 88 | # | ||
| 89 | # PERSISTENT CACHE: The discovery cache is stored in ${TOPDIR}/go-mod-discovery/${PN}/${PV}/ | ||
| 90 | # instead of ${WORKDIR}. This ensures the cache survives `bitbake <recipe> -c cleanall` | ||
| 91 | # since TOPDIR is the build directory root (e.g., /path/to/build/). | ||
| 92 | # To clean the discovery cache, run: rm -rf ${TOPDIR}/go-mod-discovery/${PN}/${PV}/ | ||
| 93 | |||
| 94 | # Required variable (must be set by recipe) | ||
| 95 | GO_MOD_DISCOVERY_BUILD_TARGET ?= "" | ||
| 96 | |||
| 97 | # Optional variables with sensible defaults for standard Go recipe layout | ||
| 98 | GO_MOD_DISCOVERY_SRCDIR ?= "${S}/src/import" | ||
| 99 | GO_MOD_DISCOVERY_BUILD_TAGS ?= "${TAGS}" | ||
| 100 | GO_MOD_DISCOVERY_LDFLAGS ?= "-w -s" | ||
| 101 | GO_MOD_DISCOVERY_GOPATH ?= "${S}/src/import/.gopath:${S}/src/import/vendor" | ||
| 102 | GO_MOD_DISCOVERY_OUTPUT ?= "${WORKDIR}/discovery-build-output" | ||
| 103 | |||
| 104 | # Persistent discovery cache location - survives cleanall | ||
| 105 | GO_MOD_DISCOVERY_DIR ?= "${TOPDIR}/go-mod-discovery/${PN}/${PV}" | ||
| 106 | |||
| 107 | # Output JSON file for discovered modules (used by oe-go-mod-fetcher.py --discovered-modules) | ||
| 108 | GO_MOD_DISCOVERY_MODULES_JSON ?= "${GO_MOD_DISCOVERY_DIR}/modules.json" | ||
| 109 | |||
| 110 | # Set to "1" to skip automatic extraction (only download modules, don't extract metadata) | ||
| 111 | GO_MOD_DISCOVERY_SKIP_EXTRACT ?= "0" | ||
| 112 | |||
| 113 | # Set to "1" to skip automatic recipe regeneration (only discover and extract) | ||
| 114 | GO_MOD_DISCOVERY_SKIP_GENERATE ?= "0" | ||
| 115 | |||
| 116 | # Git repository URL for recipe generation (required if SKIP_GENERATE != "1") | ||
| 117 | # Example: "https://github.com/rancher/k3s.git" | ||
| 118 | GO_MOD_DISCOVERY_GIT_REPO ?= "" | ||
| 119 | |||
| 120 | # Git ref (commit/tag) for recipe generation - defaults to recipe's SRCREV | ||
| 121 | GO_MOD_DISCOVERY_GIT_REF ?= "${SRCREV}" | ||
| 122 | |||
| 123 | # Recipe directory for generated .inc files - defaults to recipe's directory | ||
| 124 | GO_MOD_DISCOVERY_RECIPEDIR ?= "${FILE_DIRNAME}" | ||
| 125 | |||
| 126 | # Empty default for TAGS if not set by recipe (avoids undefined variable errors) | ||
| 127 | TAGS ?= "" | ||
| 128 | |||
| 129 | # Shell task that mirrors do_compile but with network access and discovery GOMODCACHE | ||
| 130 | do_discover_modules() { | ||
| 131 | # Validate required variable | ||
| 132 | if [ -z "${GO_MOD_DISCOVERY_BUILD_TARGET}" ]; then | ||
| 133 | bbfatal "GO_MOD_DISCOVERY_BUILD_TARGET must be set (e.g., './cmd/server' or './...')" | ||
| 134 | fi | ||
| 135 | |||
| 136 | # Validate source directory exists and contains go.mod | ||
| 137 | if [ ! -d "${GO_MOD_DISCOVERY_SRCDIR}" ]; then | ||
| 138 | bbfatal "GO_MOD_DISCOVERY_SRCDIR does not exist: ${GO_MOD_DISCOVERY_SRCDIR} | ||
| 139 | Hint: Set GO_MOD_DISCOVERY_SRCDIR in your recipe if go.mod is not in \${S}/src/import" | ||
| 140 | fi | ||
| 141 | if [ ! -f "${GO_MOD_DISCOVERY_SRCDIR}/go.mod" ]; then | ||
| 142 | bbfatal "go.mod not found in GO_MOD_DISCOVERY_SRCDIR: ${GO_MOD_DISCOVERY_SRCDIR} | ||
| 143 | Hint: Set GO_MOD_DISCOVERY_SRCDIR to the directory containing go.mod" | ||
| 144 | fi | ||
| 145 | |||
| 146 | # Use PERSISTENT cache location outside WORKDIR to survive cleanall | ||
| 147 | # This is stored in ${TOPDIR}/go-mod-discovery/${PN}/${PV}/ so it persists | ||
| 148 | DISCOVERY_CACHE="${GO_MOD_DISCOVERY_DIR}/cache" | ||
| 149 | |||
| 150 | # Create required directories first | ||
| 151 | mkdir -p "${DISCOVERY_CACHE}" | ||
| 152 | mkdir -p "${WORKDIR}/go-tmp" | ||
| 153 | mkdir -p "$(dirname "${GO_MOD_DISCOVERY_OUTPUT}")" | ||
| 154 | |||
| 155 | # Use discovery-cache instead of the normal GOMODCACHE | ||
| 156 | export GOMODCACHE="${DISCOVERY_CACHE}" | ||
| 157 | |||
| 158 | # Enable network access to proxy.golang.org | ||
| 159 | export GOPROXY="https://proxy.golang.org,direct" | ||
| 160 | export GOSUMDB="sum.golang.org" | ||
| 161 | |||
| 162 | # Standard Go environment - use recipe-provided GOPATH or default | ||
| 163 | export GOPATH="${GO_MOD_DISCOVERY_GOPATH}:${STAGING_DIR_TARGET}/${prefix}/local/go" | ||
| 164 | export CGO_ENABLED="1" | ||
| 165 | export GOTOOLCHAIN="local" | ||
| 166 | |||
| 167 | # Use system temp directory for Go's work files | ||
| 168 | export GOTMPDIR="${WORKDIR}/go-tmp" | ||
| 169 | |||
| 170 | # Disable excessive debug output from BitBake environment | ||
| 171 | unset GODEBUG | ||
| 172 | |||
| 173 | # Build tags from recipe configuration | ||
| 174 | TAGS="${GO_MOD_DISCOVERY_BUILD_TAGS}" | ||
| 175 | |||
| 176 | # Change to source directory | ||
| 177 | cd "${GO_MOD_DISCOVERY_SRCDIR}" | ||
| 178 | |||
| 179 | echo "======================================================================" | ||
| 180 | echo "MODULE DISCOVERY: ${PN} ${PV}" | ||
| 181 | echo "======================================================================" | ||
| 182 | echo "GOMODCACHE: ${GOMODCACHE}" | ||
| 183 | echo "GOPROXY: ${GOPROXY}" | ||
| 184 | echo "Source dir: ${GO_MOD_DISCOVERY_SRCDIR}" | ||
| 185 | echo "Build target: ${GO_MOD_DISCOVERY_BUILD_TARGET}" | ||
| 186 | echo "Build tags: ${TAGS:-<none>}" | ||
| 187 | echo "LDFLAGS: ${GO_MOD_DISCOVERY_LDFLAGS}" | ||
| 188 | echo "" | ||
| 189 | |||
| 190 | # Use native go binary (not cross-compiler) | ||
| 191 | GO_NATIVE="${STAGING_DIR_NATIVE}${bindir_native}/go" | ||
| 192 | |||
| 193 | # NOTE: Do NOT run go mod tidy during discovery - it can upgrade versions in go.mod | ||
| 194 | # without adding checksums to go.sum, causing version mismatches. | ||
| 195 | # The source's go.mod/go.sum should already be correct for the commit. | ||
| 196 | # echo "Running: go mod tidy" | ||
| 197 | # ${GO_NATIVE} mod tidy | ||
| 198 | # ${GO_NATIVE} mod download # If tidy is re-enabled, this ensures go.sum gets all checksums | ||
| 199 | |||
| 200 | echo "" | ||
| 201 | echo "Running: go build (to discover all modules)..." | ||
| 202 | |||
| 203 | # Build to discover ALL modules that would be used at compile time | ||
| 204 | # This is better than 'go mod download' because it handles build tags correctly | ||
| 205 | BUILD_CMD="${GO_NATIVE} build -v -trimpath" | ||
| 206 | if [ -n "${TAGS}" ]; then | ||
| 207 | BUILD_CMD="${BUILD_CMD} -tags \"${TAGS}\"" | ||
| 208 | fi | ||
| 209 | BUILD_CMD="${BUILD_CMD} -ldflags \"${GO_MOD_DISCOVERY_LDFLAGS}\"" | ||
| 210 | BUILD_CMD="${BUILD_CMD} -o \"${GO_MOD_DISCOVERY_OUTPUT}\" ${GO_MOD_DISCOVERY_BUILD_TARGET}" | ||
| 211 | |||
| 212 | echo "Executing: ${BUILD_CMD}" | ||
| 213 | eval ${BUILD_CMD} | ||
| 214 | |||
| 215 | echo "" | ||
| 216 | echo "Fetching ALL modules referenced in go.sum..." | ||
| 217 | # go build downloads .zip files but not always .info files | ||
| 218 | # We need .info files for VCS metadata (Origin.URL, Origin.Hash) | ||
| 219 | # Extract unique module@version pairs from go.sum and download each | ||
| 220 | # go.sum format: "module version/go.mod hash" or "module version hash" | ||
| 221 | # | ||
| 222 | # IMPORTANT: We must download ALL versions, including /go.mod-only entries! | ||
| 223 | # When GOPROXY=off during compile, Go may need these for dependency resolution. | ||
| 224 | # Strip the /go.mod suffix to get the base version, then download it. | ||
| 225 | awk '{gsub(/\/go\.mod$/, "", $2); print $1 "@" $2}' go.sum | sort -u | while read modver; do | ||
| 226 | ${GO_NATIVE} mod download "$modver" 2>/dev/null || true | ||
| 227 | done | ||
| 228 | |||
| 229 | # Download ALL modules in the complete dependency graph. | ||
| 230 | # The go.sum loop above only gets direct dependencies. Replace directives | ||
| 231 | # can introduce transitive deps that aren't in go.sum but are needed at | ||
| 232 | # compile time when GOPROXY=off. `go mod download all` resolves and | ||
| 233 | # downloads the entire module graph, including transitive dependencies. | ||
| 234 | echo "" | ||
| 235 | echo "Downloading complete module graph (including transitive deps)..." | ||
| 236 | ${GO_NATIVE} mod download all 2>&1 || echo "Warning: some modules may have failed to download" | ||
| 237 | |||
| 238 | # Additionally scan for any modules that go build downloaded but don't have .info | ||
| 239 | # This ensures we capture everything that was fetched dynamically | ||
| 240 | echo "" | ||
| 241 | echo "Ensuring .info files for all cached modules..." | ||
| 242 | find "${GOMODCACHE}/cache/download" -name "*.zip" 2>/dev/null | while read zipfile; do | ||
| 243 | # Extract module@version from path like: .../module/@v/version.zip | ||
| 244 | version=$(basename "$zipfile" .zip) | ||
| 245 | moddir=$(dirname "$zipfile") | ||
| 246 | infofile="${moddir}/${version}.info" | ||
| 247 | if [ ! -f "$infofile" ]; then | ||
| 248 | # Reconstruct module path from directory structure | ||
| 249 | # cache/download/github.com/foo/bar/@v/v1.0.0.zip -> github.com/foo/bar@v1.0.0 | ||
| 250 | modpath=$(echo "$moddir" | sed "s|${GOMODCACHE}/cache/download/||" | sed 's|/@v$||') | ||
| 251 | echo " Fetching .info for: ${modpath}@${version}" | ||
| 252 | ${GO_NATIVE} mod download "${modpath}@${version}" 2>/dev/null || true | ||
| 253 | fi | ||
| 254 | done | ||
| 255 | |||
| 256 | # Download transitive deps of REPLACED modules. | ||
| 257 | # Replace directives can point to older versions whose deps aren't in the MVS | ||
| 258 | # graph. At compile time with GOPROXY=off, Go validates the replaced version's | ||
| 259 | # go.mod. We parse replace directives and download each replacement version, | ||
| 260 | # which fetches all its transitive dependencies. | ||
| 261 | echo "" | ||
| 262 | echo "Downloading dependencies of replaced modules..." | ||
| 263 | |||
| 264 | # Extract replace directives: "old_module => new_module new_version" | ||
| 265 | awk '/^replace \($/,/^\)$/ {if ($0 !~ /^replace|^\)/) print}' go.mod | \ | ||
| 266 | grep "=>" | while read line; do | ||
| 267 | # Parse: github.com/foo/bar => github.com/baz/qux v1.2.3 | ||
| 268 | new_module=$(echo "$line" | awk '{print $(NF-1)}') | ||
| 269 | new_version=$(echo "$line" | awk '{print $NF}') | ||
| 270 | |||
| 271 | if [ -n "$new_module" ] && [ -n "$new_version" ] && [ "$new_version" != "=>" ]; then | ||
| 272 | echo " Replace target: ${new_module}@${new_version}" | ||
| 273 | # Download this specific version - Go will fetch all its dependencies | ||
| 274 | ${GO_NATIVE} mod download "${new_module}@${new_version}" 2>/dev/null || true | ||
| 275 | fi | ||
| 276 | done | ||
| 277 | |||
| 278 | # Count modules discovered | ||
| 279 | MODULE_COUNT=$(find "${GOMODCACHE}/cache/download" -name "*.info" 2>/dev/null | wc -l) | ||
| 280 | |||
| 281 | echo "" | ||
| 282 | echo "======================================================================" | ||
| 283 | echo "DISCOVERY COMPLETE" | ||
| 284 | echo "======================================================================" | ||
| 285 | echo "Modules discovered: ${MODULE_COUNT}" | ||
| 286 | echo "Cache location: ${GOMODCACHE}" | ||
| 287 | |||
| 288 | # Extract module metadata automatically (unless skipped) | ||
| 289 | if [ "${GO_MOD_DISCOVERY_SKIP_EXTRACT}" != "1" ]; then | ||
| 290 | echo "" | ||
| 291 | echo "Extracting module metadata..." | ||
| 292 | |||
| 293 | # Find the extraction script relative to this class file | ||
| 294 | EXTRACT_SCRIPT="${COREBASE}/../meta-virtualization/scripts/extract-discovered-modules.py" | ||
| 295 | if [ ! -f "${EXTRACT_SCRIPT}" ]; then | ||
| 296 | # Try alternate location | ||
| 297 | EXTRACT_SCRIPT="$(dirname "${COREBASE}")/meta-virtualization/scripts/extract-discovered-modules.py" | ||
| 298 | fi | ||
| 299 | if [ ! -f "${EXTRACT_SCRIPT}" ]; then | ||
| 300 | # Last resort - search in layer path | ||
| 301 | for layer in ${BBLAYERS}; do | ||
| 302 | if [ -f "${layer}/scripts/extract-discovered-modules.py" ]; then | ||
| 303 | EXTRACT_SCRIPT="${layer}/scripts/extract-discovered-modules.py" | ||
| 304 | break | ||
| 305 | fi | ||
| 306 | done | ||
| 307 | fi | ||
| 308 | |||
| 309 | if [ -f "${EXTRACT_SCRIPT}" ]; then | ||
| 310 | python3 "${EXTRACT_SCRIPT}" \ | ||
| 311 | --gomodcache "${GOMODCACHE}" \ | ||
| 312 | --output "${GO_MOD_DISCOVERY_MODULES_JSON}" | ||
| 313 | EXTRACT_RC=$? | ||
| 314 | if [ $EXTRACT_RC -eq 0 ]; then | ||
| 315 | echo "" | ||
| 316 | echo "✓ Module metadata extracted to: ${GO_MOD_DISCOVERY_MODULES_JSON}" | ||
| 317 | else | ||
| 318 | bbwarn "Module extraction failed (exit code $EXTRACT_RC)" | ||
| 319 | bbwarn "You can run manually: python3 ${EXTRACT_SCRIPT} --gomodcache ${GOMODCACHE} --output ${GO_MOD_DISCOVERY_MODULES_JSON}" | ||
| 320 | EXTRACT_RC=1 # Mark as failed for generation check | ||
| 321 | fi | ||
| 322 | else | ||
| 323 | bbwarn "Could not find extract-discovered-modules.py script" | ||
| 324 | bbwarn "Run manually: extract-discovered-modules.py --gomodcache ${GOMODCACHE} --output ${GO_MOD_DISCOVERY_MODULES_JSON}" | ||
| 325 | EXTRACT_RC=1 # Mark as failed for generation check | ||
| 326 | fi | ||
| 327 | else | ||
| 328 | echo "" | ||
| 329 | echo "Skipping automatic extraction (GO_MOD_DISCOVERY_SKIP_EXTRACT=1)" | ||
| 330 | EXTRACT_RC=1 # Skip generation too if extraction skipped | ||
| 331 | fi | ||
| 332 | |||
| 333 | # Step 3: Generate recipe .inc files (unless skipped or extraction failed) | ||
| 334 | if [ "${GO_MOD_DISCOVERY_SKIP_GENERATE}" != "1" ] && [ "${EXTRACT_RC:-0}" = "0" ]; then | ||
| 335 | # Validate required git repo | ||
| 336 | if [ -z "${GO_MOD_DISCOVERY_GIT_REPO}" ]; then | ||
| 337 | bbwarn "GO_MOD_DISCOVERY_GIT_REPO not set - skipping recipe generation" | ||
| 338 | bbwarn "Set GO_MOD_DISCOVERY_GIT_REPO in your recipe to enable automatic generation" | ||
| 339 | echo "" | ||
| 340 | echo "NEXT STEP: Regenerate recipe manually:" | ||
| 341 | echo "" | ||
| 342 | echo " ./meta-virtualization/scripts/oe-go-mod-fetcher.py \\" | ||
| 343 | echo " --discovered-modules ${GO_MOD_DISCOVERY_MODULES_JSON} \\" | ||
| 344 | echo " --git-repo <your-git-repo-url> \\" | ||
| 345 | echo " --git-ref ${GO_MOD_DISCOVERY_GIT_REF} \\" | ||
| 346 | echo " --recipedir ${GO_MOD_DISCOVERY_RECIPEDIR}" | ||
| 347 | else | ||
| 348 | echo "" | ||
| 349 | echo "Generating recipe .inc files..." | ||
| 350 | |||
| 351 | # Find the fetcher script (same search as extraction script) | ||
| 352 | FETCHER_SCRIPT="${COREBASE}/../meta-virtualization/scripts/oe-go-mod-fetcher.py" | ||
| 353 | if [ ! -f "${FETCHER_SCRIPT}" ]; then | ||
| 354 | FETCHER_SCRIPT="$(dirname "${COREBASE}")/meta-virtualization/scripts/oe-go-mod-fetcher.py" | ||
| 355 | fi | ||
| 356 | if [ ! -f "${FETCHER_SCRIPT}" ]; then | ||
| 357 | for layer in ${BBLAYERS}; do | ||
| 358 | if [ -f "${layer}/scripts/oe-go-mod-fetcher.py" ]; then | ||
| 359 | FETCHER_SCRIPT="${layer}/scripts/oe-go-mod-fetcher.py" | ||
| 360 | break | ||
| 361 | fi | ||
| 362 | done | ||
| 363 | fi | ||
| 364 | |||
| 365 | if [ -f "${FETCHER_SCRIPT}" ]; then | ||
| 366 | python3 "${FETCHER_SCRIPT}" \ | ||
| 367 | --discovered-modules "${GO_MOD_DISCOVERY_MODULES_JSON}" \ | ||
| 368 | --git-repo "${GO_MOD_DISCOVERY_GIT_REPO}" \ | ||
| 369 | --git-ref "${GO_MOD_DISCOVERY_GIT_REF}" \ | ||
| 370 | --recipedir "${GO_MOD_DISCOVERY_RECIPEDIR}" | ||
| 371 | GENERATE_RC=$? | ||
| 372 | if [ $GENERATE_RC -eq 0 ]; then | ||
| 373 | echo "" | ||
| 374 | echo "✓ Recipe files regenerated in: ${GO_MOD_DISCOVERY_RECIPEDIR}" | ||
| 375 | else | ||
| 376 | bbwarn "Recipe generation failed (exit code $GENERATE_RC)" | ||
| 377 | bbwarn "Check the output above for errors" | ||
| 378 | fi | ||
| 379 | else | ||
| 380 | bbwarn "Could not find oe-go-mod-fetcher.py script" | ||
| 381 | bbwarn "Run manually: oe-go-mod-fetcher.py --discovered-modules ${GO_MOD_DISCOVERY_MODULES_JSON} --git-repo ${GO_MOD_DISCOVERY_GIT_REPO} --git-ref ${GO_MOD_DISCOVERY_GIT_REF} --recipedir ${GO_MOD_DISCOVERY_RECIPEDIR}" | ||
| 382 | fi | ||
| 383 | fi | ||
| 384 | elif [ "${GO_MOD_DISCOVERY_SKIP_GENERATE}" = "1" ]; then | ||
| 385 | echo "" | ||
| 386 | echo "Skipping automatic generation (GO_MOD_DISCOVERY_SKIP_GENERATE=1)" | ||
| 387 | echo "" | ||
| 388 | echo "NEXT STEP: Regenerate recipe manually:" | ||
| 389 | echo "" | ||
| 390 | echo " ./meta-virtualization/scripts/oe-go-mod-fetcher.py \\" | ||
| 391 | echo " --discovered-modules ${GO_MOD_DISCOVERY_MODULES_JSON} \\" | ||
| 392 | echo " --git-repo <your-git-repo-url> \\" | ||
| 393 | echo " --git-ref <your-git-ref> \\" | ||
| 394 | echo " --recipedir ${GO_MOD_DISCOVERY_RECIPEDIR}" | ||
| 395 | fi | ||
| 396 | |||
| 397 | echo "" | ||
| 398 | echo "NOTE: Cache is stored OUTSIDE WORKDIR in a persistent location." | ||
| 399 | echo " This cache survives 'bitbake ${PN} -c cleanall'!" | ||
| 400 | echo " To clean: rm -rf ${GO_MOD_DISCOVERY_DIR}" | ||
| 401 | echo "" | ||
| 402 | echo "======================================================================" | ||
| 403 | } | ||
| 404 | |||
| 405 | # Make this task manually runnable (not part of default build) | ||
| 406 | # Run after unpack and patch so source is available | ||
| 407 | addtask discover_modules after do_patch | ||
| 408 | |||
| 409 | # Task dependencies - need source unpacked and full toolchain available | ||
| 410 | # Depend on do_prepare_recipe_sysroot to get cross-compiler for CGO | ||
| 411 | do_discover_modules[depends] = "${PN}:do_prepare_recipe_sysroot" | ||
| 412 | |||
| 413 | # Enable network access for this task ONLY | ||
| 414 | do_discover_modules[network] = "1" | ||
| 415 | |||
| 416 | # Don't create stamp file - allow running multiple times | ||
| 417 | do_discover_modules[nostamp] = "1" | ||
| 418 | |||
| 419 | # Track all configuration variables for proper task hashing | ||
| 420 | do_discover_modules[vardeps] += "GO_MOD_DISCOVERY_DIR GO_MOD_DISCOVERY_SRCDIR \ | ||
| 421 | GO_MOD_DISCOVERY_BUILD_TARGET GO_MOD_DISCOVERY_BUILD_TAGS \ | ||
| 422 | GO_MOD_DISCOVERY_LDFLAGS GO_MOD_DISCOVERY_GOPATH GO_MOD_DISCOVERY_OUTPUT \ | ||
| 423 | GO_MOD_DISCOVERY_MODULES_JSON GO_MOD_DISCOVERY_SKIP_EXTRACT \ | ||
| 424 | GO_MOD_DISCOVERY_SKIP_GENERATE GO_MOD_DISCOVERY_GIT_REPO \ | ||
| 425 | GO_MOD_DISCOVERY_GIT_REF GO_MOD_DISCOVERY_RECIPEDIR" | ||
| 426 | |||
| 427 | # Task to clean the persistent discovery cache | ||
| 428 | # Usage: bitbake <recipe> -c clean_discovery | ||
| 429 | do_clean_discovery() { | ||
| 430 | if [ -d "${GO_MOD_DISCOVERY_DIR}" ]; then | ||
| 431 | echo "Removing discovery cache: ${GO_MOD_DISCOVERY_DIR}" | ||
| 432 | rm -rf "${GO_MOD_DISCOVERY_DIR}" | ||
| 433 | echo "Discovery cache removed." | ||
| 434 | else | ||
| 435 | echo "Discovery cache not found: ${GO_MOD_DISCOVERY_DIR}" | ||
| 436 | fi | ||
| 437 | } | ||
| 438 | |||
| 439 | addtask clean_discovery | ||
| 440 | do_clean_discovery[nostamp] = "1" | ||
| 441 | do_clean_discovery[vardeps] += "GO_MOD_DISCOVERY_DIR" | ||
