Complete Yocto mirror with license table for TQMa6UL (2038-compliance)
- 264 license table entries with exact download URLs (224/264 resolved) - Complete sources/ directory with all BitBake recipes - Build configuration: tqma6ul-multi-mba6ulx, spaetzle (musl) - Full traceability for Softwarefreigabeantrag - GCC 13.4.0, Linux 6.6.102, U-Boot 2023.04, musl 1.2.4 - License distribution: GPL-2.0 (24), MIT (23), GPL-2.0+ (18), BSD-3 (16)
This commit is contained in:
211
sources/poky/meta/classes/go-vendor.bbclass
Normal file
211
sources/poky/meta/classes/go-vendor.bbclass
Normal file
@@ -0,0 +1,211 @@
|
||||
#
|
||||
# Copyright 2023 (C) Weidmueller GmbH & Co KG
|
||||
# Author: Lukas Funke <lukas.funke@weidmueller.com>
|
||||
#
|
||||
# Handle Go vendor support for offline builds
|
||||
#
|
||||
# When importing Go modules, Go downloads the imported modules using
|
||||
# a network (proxy) connection ahead of the compile stage. This contradicts
|
||||
# the yocto build concept of fetching every source ahead of build-time
|
||||
# and supporting offline builds.
|
||||
#
|
||||
# To support offline builds, we use Go 'vendoring': module dependencies are
|
||||
# downloaded during the fetch-phase and unpacked into the modules 'vendor'
|
||||
# folder. Additionally a manifest file is generated for the 'vendor' folder
|
||||
#
|
||||
|
||||
inherit go-mod
|
||||
|
||||
def go_src_uri(repo, version, path=None, subdir=None, \
|
||||
vcs='git', replaces=None, pathmajor=None):
|
||||
|
||||
destsuffix = "git/src/import/vendor.fetch"
|
||||
module_path = repo if not path else path
|
||||
|
||||
src_uri = "{}://{};name={}".format(vcs, repo, module_path.replace('/', '.'))
|
||||
src_uri += ";destsuffix={}/{}@{}".format(destsuffix, repo, version)
|
||||
|
||||
if vcs == "git":
|
||||
src_uri += ";nobranch=1;protocol=https"
|
||||
|
||||
src_uri += ";go_module_path={}".format(module_path)
|
||||
|
||||
if replaces:
|
||||
src_uri += ";go_module_replacement={}".format(replaces)
|
||||
if subdir:
|
||||
src_uri += ";go_subdir={}".format(subdir)
|
||||
if pathmajor:
|
||||
src_uri += ";go_pathmajor={}".format(pathmajor)
|
||||
src_uri += ";is_go_dependency=1"
|
||||
|
||||
return src_uri
|
||||
|
||||
python do_vendor_unlink() {
|
||||
go_import = d.getVar('GO_IMPORT')
|
||||
source_dir = d.getVar('S')
|
||||
linkname = os.path.join(source_dir, *['src', go_import, 'vendor'])
|
||||
|
||||
os.unlink(linkname)
|
||||
}
|
||||
|
||||
addtask vendor_unlink before do_package after do_install
|
||||
|
||||
python do_go_vendor() {
|
||||
import shutil
|
||||
|
||||
src_uri = (d.getVar('SRC_URI') or "").split()
|
||||
|
||||
if not src_uri:
|
||||
bb.fatal("SRC_URI is empty")
|
||||
|
||||
default_destsuffix = "git/src/import/vendor.fetch"
|
||||
fetcher = bb.fetch2.Fetch(src_uri, d)
|
||||
go_import = d.getVar('GO_IMPORT')
|
||||
source_dir = d.getVar('S')
|
||||
|
||||
linkname = os.path.join(source_dir, *['src', go_import, 'vendor'])
|
||||
vendor_dir = os.path.join(source_dir, *['src', 'import', 'vendor'])
|
||||
import_dir = os.path.join(source_dir, *['src', 'import', 'vendor.fetch'])
|
||||
|
||||
if os.path.exists(vendor_dir):
|
||||
# Nothing to do except re-establish link to actual vendor folder
|
||||
if not os.path.exists(linkname):
|
||||
os.symlink(vendor_dir, linkname)
|
||||
return
|
||||
|
||||
bb.utils.mkdirhier(vendor_dir)
|
||||
|
||||
modules = {}
|
||||
|
||||
for url in fetcher.urls:
|
||||
srcuri = fetcher.ud[url].host + fetcher.ud[url].path
|
||||
|
||||
# Skip non Go module src uris
|
||||
if not fetcher.ud[url].parm.get('is_go_dependency'):
|
||||
continue
|
||||
|
||||
destsuffix = fetcher.ud[url].parm.get('destsuffix')
|
||||
# We derive the module repo / version in the following manner (exmaple):
|
||||
#
|
||||
# destsuffix = git/src/import/vendor.fetch/github.com/foo/bar@v1.2.3
|
||||
# p = github.com/foo/bar@v1.2.3
|
||||
# repo = github.com/foo/bar
|
||||
# version = v1.2.3
|
||||
|
||||
p = destsuffix[len(default_destsuffix)+1:]
|
||||
repo, version = p.split('@')
|
||||
|
||||
module_path = fetcher.ud[url].parm.get('go_module_path')
|
||||
|
||||
subdir = fetcher.ud[url].parm.get('go_subdir')
|
||||
subdir = None if not subdir else subdir
|
||||
|
||||
pathMajor = fetcher.ud[url].parm.get('go_pathmajor')
|
||||
pathMajor = None if not pathMajor else pathMajor.strip('/')
|
||||
|
||||
if not (repo, version) in modules:
|
||||
modules[(repo, version)] = {
|
||||
"repo_path": os.path.join(import_dir, p),
|
||||
"module_path": module_path,
|
||||
"subdir": subdir,
|
||||
"pathMajor": pathMajor }
|
||||
|
||||
for module_key, module in modules.items():
|
||||
|
||||
# only take the version which is explicitly listed
|
||||
# as a dependency in the go.mod
|
||||
module_path = module['module_path']
|
||||
rootdir = module['repo_path']
|
||||
subdir = module['subdir']
|
||||
pathMajor = module['pathMajor']
|
||||
|
||||
src = rootdir
|
||||
|
||||
if subdir:
|
||||
src = os.path.join(rootdir, subdir)
|
||||
|
||||
# If the module is released at major version 2 or higher, the module
|
||||
# path must end with a major version suffix like /v2.
|
||||
# This may or may not be part of the subdirectory name
|
||||
#
|
||||
# https://go.dev/ref/mod#modules-overview
|
||||
if pathMajor:
|
||||
tmp = os.path.join(src, pathMajor)
|
||||
# source directory including major version path may or may not exist
|
||||
if os.path.exists(tmp):
|
||||
src = tmp
|
||||
|
||||
dst = os.path.join(vendor_dir, module_path)
|
||||
|
||||
bb.debug(1, "cp %s --> %s" % (src, dst))
|
||||
shutil.copytree(src, dst, symlinks=True, dirs_exist_ok=True, \
|
||||
ignore=shutil.ignore_patterns(".git", \
|
||||
"vendor", \
|
||||
"*._test.go"))
|
||||
|
||||
# If the root directory has a LICENSE file but not the subdir
|
||||
# we copy the root license to the sub module since the license
|
||||
# applies to all modules in the repository
|
||||
# see https://go.dev/ref/mod#vcs-license
|
||||
if subdir:
|
||||
rootdirLicese = os.path.join(rootdir, "LICENSE")
|
||||
subdirLicense = os.path.join(src, "LICENSE")
|
||||
|
||||
if not os.path.exists(subdir) and \
|
||||
os.path.exists(rootdirLicese):
|
||||
shutil.copy2(rootdirLicese, subdirLicense)
|
||||
|
||||
# Copy vendor manifest
|
||||
modules_txt_src = os.path.join(d.getVar('WORKDIR'), "modules.txt")
|
||||
bb.debug(1, "cp %s --> %s" % (modules_txt_src, vendor_dir))
|
||||
shutil.copy2(modules_txt_src, vendor_dir)
|
||||
|
||||
# Clean up vendor dir
|
||||
# We only require the modules in the modules_txt file
|
||||
fetched_paths = set([os.path.relpath(x[0], vendor_dir) for x in os.walk(vendor_dir)])
|
||||
|
||||
# Remove toplevel dir
|
||||
fetched_paths.remove('.')
|
||||
|
||||
vendored_paths = set()
|
||||
replaced_paths = dict()
|
||||
with open(modules_txt_src) as f:
|
||||
for line in f:
|
||||
if not line.startswith("#"):
|
||||
line = line.strip()
|
||||
vendored_paths.add(line)
|
||||
|
||||
# Add toplevel dirs into vendored dir, as we want to keep them
|
||||
topdir = os.path.dirname(line)
|
||||
while len(topdir):
|
||||
if not topdir in vendored_paths:
|
||||
vendored_paths.add(topdir)
|
||||
|
||||
topdir = os.path.dirname(topdir)
|
||||
else:
|
||||
replaced_module = line.split("=>")
|
||||
if len(replaced_module) > 1:
|
||||
# This module has been replaced, use a local path
|
||||
# we parse the line that has a pattern "# module-name [module-version] => local-path
|
||||
actual_path = replaced_module[1].strip()
|
||||
vendored_name = replaced_module[0].split()[1]
|
||||
bb.debug(1, "added vendored name %s for actual path %s" % (vendored_name, actual_path))
|
||||
replaced_paths[vendored_name] = actual_path
|
||||
|
||||
for path in fetched_paths:
|
||||
if path not in vendored_paths:
|
||||
realpath = os.path.join(vendor_dir, path)
|
||||
if os.path.exists(realpath):
|
||||
shutil.rmtree(realpath)
|
||||
|
||||
for vendored_name, replaced_path in replaced_paths.items():
|
||||
symlink_target = os.path.join(source_dir, *['src', go_import, replaced_path])
|
||||
symlink_name = os.path.join(vendor_dir, vendored_name)
|
||||
bb.debug(1, "vendored name %s, symlink name %s" % (vendored_name, symlink_name))
|
||||
os.symlink(symlink_target, symlink_name)
|
||||
|
||||
# Create a symlink to the actual directory
|
||||
os.symlink(vendor_dir, linkname)
|
||||
}
|
||||
|
||||
addtask go_vendor before do_patch after do_unpack
|
||||
Reference in New Issue
Block a user