diff options
Diffstat (limited to 'meta/classes-recipe')
-rw-r--r-- | meta/classes-recipe/go-mod-update-modules.bbclass | 152 | ||||
-rw-r--r-- | meta/classes-recipe/go-mod.bbclass | 2 | ||||
-rw-r--r-- | meta/classes-recipe/image-live.bbclass | 5 | ||||
-rw-r--r-- | meta/classes-recipe/image_types_wic.bbclass | 12 | ||||
-rw-r--r-- | meta/classes-recipe/rust-target-config.bbclass | 2 | ||||
-rw-r--r-- | meta/classes-recipe/testsdk.bbclass | 1 | ||||
-rw-r--r-- | meta/classes-recipe/uboot-config.bbclass | 15 |
7 files changed, 180 insertions, 9 deletions
diff --git a/meta/classes-recipe/go-mod-update-modules.bbclass b/meta/classes-recipe/go-mod-update-modules.bbclass new file mode 100644 index 0000000000..5fccd0bb0d --- /dev/null +++ b/meta/classes-recipe/go-mod-update-modules.bbclass | |||
@@ -0,0 +1,152 @@ | |||
1 | addtask do_update_modules after do_configure | ||
2 | do_update_modules[nostamp] = "1" | ||
3 | do_update_modules[network] = "1" | ||
4 | |||
5 | # This class maintains two files, BPN-go-mods.inc and BPN-licenses.inc. | ||
6 | # | ||
7 | # -go-mods.inc will append SRC_URI with all of the Go modules that are | ||
8 | # dependencies of this recipe. | ||
9 | # | ||
10 | # -licenses.inc will append LICENSE and LIC_FILES_CHKSUM with the found licenses | ||
11 | # in the modules. | ||
12 | # | ||
13 | # These files are machine-generated and should not be modified. | ||
14 | |||
15 | python do_update_modules() { | ||
16 | import subprocess, tempfile, json, re, urllib.parse | ||
17 | from oe.license import tidy_licenses | ||
18 | from oe.license_finder import find_licenses | ||
19 | |||
20 | def unescape_path(path): | ||
21 | """Unescape capital letters using exclamation points.""" | ||
22 | return re.sub(r'!([a-z])', lambda m: m.group(1).upper(), path) | ||
23 | |||
24 | def fold_uri(uri): | ||
25 | """Fold URI for sorting shorter module paths before longer.""" | ||
26 | return uri.replace(';', ' ').replace('/', '!') | ||
27 | |||
28 | def parse_existing_licenses(): | ||
29 | hashes = {} | ||
30 | for url in d.getVar("LIC_FILES_CHKSUM").split(): | ||
31 | (method, host, path, user, pswd, parm) = bb.fetch.decodeurl(url) | ||
32 | if "spdx" in parm and parm["spdx"] != "Unknown": | ||
33 | hashes[parm["md5"]] = urllib.parse.unquote_plus(parm["spdx"]) | ||
34 | return hashes | ||
35 | |||
36 | bpn = d.getVar("BPN") | ||
37 | thisdir = d.getVar("THISDIR") | ||
38 | s_dir = d.getVar("S") | ||
39 | |||
40 | with tempfile.TemporaryDirectory(prefix='go-mod-') as mod_cache_dir: | ||
41 | notice = """ | ||
42 | # This file has been generated by go-mod-update-modules.bbclass | ||
43 | # | ||
44 | # Do not modify it by hand, as the contents will be replaced when | ||
45 | # running the update-modules task. | ||
46 | |||
47 | """ | ||
48 | |||
49 | env = dict(os.environ, GOMODCACHE=mod_cache_dir) | ||
50 | |||
51 | source = d.expand("${UNPACKDIR}/${GO_SRCURI_DESTSUFFIX}") | ||
52 | output = subprocess.check_output(("go", "mod", "edit", "-json"), cwd=source, env=env, text=True) | ||
53 | go_mod = json.loads(output) | ||
54 | |||
55 | output = subprocess.check_output(("go", "list", "-json=Dir,Module", "-deps", f"{go_mod['Module']['Path']}/..."), cwd=source, env=env, text=True) | ||
56 | |||
57 | # | ||
58 | # Licenses | ||
59 | # | ||
60 | |||
61 | # load hashes from the existing licenses.inc | ||
62 | extra_hashes = parse_existing_licenses() | ||
63 | |||
64 | # The output of this isn't actually valid JSON, but a series of dicts. | ||
65 | # Wrap in [] and join the dicts with , | ||
66 | # Very frustrating that the json parser in python can't repeatedly | ||
67 | # parse from a stream. | ||
68 | pkgs = json.loads('[' + output.replace('}\n{', '},\n{') + ']') | ||
69 | # Collect licenses for the dependencies. | ||
70 | licenses = set() | ||
71 | lic_files_chksum = [] | ||
72 | lic_files = {} | ||
73 | |||
74 | for pkg in pkgs: | ||
75 | mod = pkg.get('Module', None) | ||
76 | if not mod or mod.get('Main', False): | ||
77 | continue | ||
78 | |||
79 | mod_dir = mod['Dir'] | ||
80 | |||
81 | if not mod_dir.startswith(mod_cache_dir): | ||
82 | continue | ||
83 | |||
84 | path = os.path.relpath(mod_dir, mod_cache_dir) | ||
85 | |||
86 | for license_name, license_file, license_md5 in find_licenses(mod['Dir'], d, first_only=True, extra_hashes=extra_hashes): | ||
87 | lic_files[os.path.join(path, license_file)] = (license_name, license_md5) | ||
88 | |||
89 | for lic_file in lic_files: | ||
90 | license_name, license_md5 = lic_files[lic_file] | ||
91 | if license_name == "Unknown": | ||
92 | bb.warn(f"Unknown license: {lic_file} {license_md5}") | ||
93 | |||
94 | licenses.add(lic_files[lic_file][0]) | ||
95 | lic_files_chksum.append( | ||
96 | f'file://pkg/mod/{lic_file};md5={license_md5};spdx={urllib.parse.quote_plus(license_name)}') | ||
97 | |||
98 | licenses_filename = os.path.join(thisdir, f"{bpn}-licenses.inc") | ||
99 | with open(licenses_filename, "w") as f: | ||
100 | f.write(notice) | ||
101 | f.write(f'LICENSE += "& {" & ".join(tidy_licenses(licenses))}"\n\n') | ||
102 | f.write('LIC_FILES_CHKSUM += "\\\n') | ||
103 | for lic in sorted(lic_files_chksum, key=fold_uri): | ||
104 | f.write(' ' + lic + ' \\\n') | ||
105 | f.write('"\n') | ||
106 | |||
107 | # | ||
108 | # Sources | ||
109 | # | ||
110 | |||
111 | # Collect the module cache files downloaded by the go list command as | ||
112 | # the go list command knows best what the go list command needs and it | ||
113 | # needs more files in the module cache than the go install command as | ||
114 | # it doesn't do the dependency pruning mentioned in the Go module | ||
115 | # reference, https://go.dev/ref/mod, for go 1.17 or higher. | ||
116 | src_uris = [] | ||
117 | downloaddir = os.path.join(mod_cache_dir, 'cache', 'download') | ||
118 | for dirpath, _, filenames in os.walk(downloaddir): | ||
119 | # We want to process files under @v directories | ||
120 | path, base = os.path.split(os.path.relpath(dirpath, downloaddir)) | ||
121 | if base != '@v': | ||
122 | continue | ||
123 | |||
124 | path = unescape_path(path) | ||
125 | zipver = None | ||
126 | for name in filenames: | ||
127 | ver, ext = os.path.splitext(name) | ||
128 | if ext == '.zip': | ||
129 | chksum = bb.utils.sha256_file(os.path.join(dirpath, name)) | ||
130 | src_uris.append(f'gomod://{path};version={ver};sha256sum={chksum}') | ||
131 | zipver = ver | ||
132 | break | ||
133 | for name in filenames: | ||
134 | ver, ext = os.path.splitext(name) | ||
135 | if ext == '.mod' and ver != zipver: | ||
136 | chksum = bb.utils.sha256_file(os.path.join(dirpath, name)) | ||
137 | src_uris.append(f'gomod://{path};version={ver};mod=1;sha256sum={chksum}') | ||
138 | |||
139 | |||
140 | go_mods_filename = os.path.join(thisdir, f"{bpn}-go-mods.inc") | ||
141 | with open(go_mods_filename, "w") as f: | ||
142 | f.write(notice) | ||
143 | f.write('SRC_URI += "\\\n') | ||
144 | for uri in sorted(src_uris, key=fold_uri): | ||
145 | f.write(' ' + uri + ' \\\n') | ||
146 | f.write('"\n') | ||
147 | |||
148 | subprocess.check_output(("go", "clean", "-modcache"), cwd=source, env=env, text=True) | ||
149 | } | ||
150 | |||
151 | # This doesn't work as we need to wipe the inc files first so we don't try looking for LICENSE files that don't yet exist | ||
152 | # RECIPE_UPGRADE_EXTRA_TASKS += "do_update_modules" | ||
diff --git a/meta/classes-recipe/go-mod.bbclass b/meta/classes-recipe/go-mod.bbclass index 93ae72235f..a15dda8f0e 100644 --- a/meta/classes-recipe/go-mod.bbclass +++ b/meta/classes-recipe/go-mod.bbclass | |||
@@ -23,7 +23,7 @@ GOBUILDFLAGS:append = " -modcacherw" | |||
23 | inherit go | 23 | inherit go |
24 | 24 | ||
25 | export GOMODCACHE = "${S}/pkg/mod" | 25 | export GOMODCACHE = "${S}/pkg/mod" |
26 | GO_MOD_CACHE_DIR = "${@os.path.relpath(d.getVar('GOMODCACHE'), d.getVar('WORKDIR'))}" | 26 | GO_MOD_CACHE_DIR = "${@os.path.relpath(d.getVar('GOMODCACHE'), d.getVar('UNPACKDIR'))}" |
27 | do_unpack[cleandirs] += "${GOMODCACHE}" | 27 | do_unpack[cleandirs] += "${GOMODCACHE}" |
28 | 28 | ||
29 | GO_WORKDIR ?= "${GO_IMPORT}" | 29 | GO_WORKDIR ?= "${GO_IMPORT}" |
diff --git a/meta/classes-recipe/image-live.bbclass b/meta/classes-recipe/image-live.bbclass index d2e95ef51c..c3054be630 100644 --- a/meta/classes-recipe/image-live.bbclass +++ b/meta/classes-recipe/image-live.bbclass | |||
@@ -147,7 +147,10 @@ build_iso() { | |||
147 | isohybrid_args="-u" | 147 | isohybrid_args="-u" |
148 | fi | 148 | fi |
149 | 149 | ||
150 | isohybrid $isohybrid_args ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso | 150 | # EFI only does not need isohybrid |
151 | if [ "${PCBIOS}" = "1" ] || [ "${EFI}" != "1" ]; then | ||
152 | isohybrid $isohybrid_args ${IMGDEPLOYDIR}/${IMAGE_NAME}.iso | ||
153 | fi | ||
151 | } | 154 | } |
152 | 155 | ||
153 | build_fat_img() { | 156 | build_fat_img() { |
diff --git a/meta/classes-recipe/image_types_wic.bbclass b/meta/classes-recipe/image_types_wic.bbclass index 740ed946f8..6180874a4c 100644 --- a/meta/classes-recipe/image_types_wic.bbclass +++ b/meta/classes-recipe/image_types_wic.bbclass | |||
@@ -57,6 +57,16 @@ def wks_search(files, search_path): | |||
57 | if searched: | 57 | if searched: |
58 | return searched | 58 | return searched |
59 | 59 | ||
60 | def wks_checksums(files, search_path): | ||
61 | ret = "" | ||
62 | for f in files: | ||
63 | found, hist = bb.utils.which(search_path, f, history=True) | ||
64 | ret = ret + " " + " ".join(h + ":False" for h in hist[:-1]) | ||
65 | if found: | ||
66 | ret = ret + " " + found + ":True" | ||
67 | return ret | ||
68 | |||
69 | |||
60 | WIC_CREATE_EXTRA_ARGS ?= "" | 70 | WIC_CREATE_EXTRA_ARGS ?= "" |
61 | 71 | ||
62 | IMAGE_CMD:wic () { | 72 | IMAGE_CMD:wic () { |
@@ -98,7 +108,7 @@ do_image_wic[cleandirs] = "${WORKDIR}/build-wic" | |||
98 | 108 | ||
99 | # Rebuild when the wks file or vars in WICVARS change | 109 | # Rebuild when the wks file or vars in WICVARS change |
100 | USING_WIC = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic ' + ' '.join('wic.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}" | 110 | USING_WIC = "${@bb.utils.contains_any('IMAGE_FSTYPES', 'wic ' + ' '.join('wic.%s' % c for c in '${CONVERSIONTYPES}'.split()), '1', '', d)}" |
101 | WKS_FILE_CHECKSUM = "${@'${WKS_FULL_PATH}:%s' % os.path.exists('${WKS_FULL_PATH}') if '${USING_WIC}' else ''}" | 111 | WKS_FILE_CHECKSUM = "${@wks_checksums(d.getVar('WKS_FILES').split(), d.getVar('WKS_SEARCH_PATH')) if '${USING_WIC}' else ''}" |
102 | do_image_wic[file-checksums] += "${WKS_FILE_CHECKSUM}" | 112 | do_image_wic[file-checksums] += "${WKS_FILE_CHECKSUM}" |
103 | do_image_wic[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}" | 113 | do_image_wic[depends] += "${@' '.join('%s-native:do_populate_sysroot' % r for r in ('parted', 'gptfdisk', 'dosfstools', 'mtools'))}" |
104 | 114 | ||
diff --git a/meta/classes-recipe/rust-target-config.bbclass b/meta/classes-recipe/rust-target-config.bbclass index 906a5083d7..cac6e90a9e 100644 --- a/meta/classes-recipe/rust-target-config.bbclass +++ b/meta/classes-recipe/rust-target-config.bbclass | |||
@@ -171,7 +171,7 @@ MAX_ATOMIC_WIDTH[armv7-eabi] = "64" | |||
171 | FEATURES[armv7-eabi] = "+v7,+vfp2,+thumb2" | 171 | FEATURES[armv7-eabi] = "+v7,+vfp2,+thumb2" |
172 | 172 | ||
173 | ## aarch64-unknown-linux-{gnu, musl} | 173 | ## aarch64-unknown-linux-{gnu, musl} |
174 | DATA_LAYOUT[aarch64] = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" | 174 | DATA_LAYOUT[aarch64] = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32" |
175 | TARGET_ENDIAN[aarch64] = "little" | 175 | TARGET_ENDIAN[aarch64] = "little" |
176 | TARGET_POINTER_WIDTH[aarch64] = "64" | 176 | TARGET_POINTER_WIDTH[aarch64] = "64" |
177 | TARGET_C_INT_WIDTH[aarch64] = "32" | 177 | TARGET_C_INT_WIDTH[aarch64] = "32" |
diff --git a/meta/classes-recipe/testsdk.bbclass b/meta/classes-recipe/testsdk.bbclass index 59d2834c99..b1c4fa67e6 100644 --- a/meta/classes-recipe/testsdk.bbclass +++ b/meta/classes-recipe/testsdk.bbclass | |||
@@ -19,6 +19,7 @@ TESTSDK_SUITES ?= "" | |||
19 | 19 | ||
20 | TESTSDK_CLASS_NAME ?= "oeqa.sdk.testsdk.TestSDK" | 20 | TESTSDK_CLASS_NAME ?= "oeqa.sdk.testsdk.TestSDK" |
21 | TESTSDKEXT_CLASS_NAME ?= "oeqa.sdkext.testsdk.TestSDKExt" | 21 | TESTSDKEXT_CLASS_NAME ?= "oeqa.sdkext.testsdk.TestSDKExt" |
22 | TESTSDK_CASE_DIRS ?= "sdk" | ||
22 | 23 | ||
23 | def import_and_run(name, d): | 24 | def import_and_run(name, d): |
24 | import importlib | 25 | import importlib |
diff --git a/meta/classes-recipe/uboot-config.bbclass b/meta/classes-recipe/uboot-config.bbclass index f44605cb6a..bc20913f73 100644 --- a/meta/classes-recipe/uboot-config.bbclass +++ b/meta/classes-recipe/uboot-config.bbclass | |||
@@ -22,12 +22,17 @@ def removesuffix(s, suffix): | |||
22 | UBOOT_ENTRYPOINT ?= "0x20008000" | 22 | UBOOT_ENTRYPOINT ?= "0x20008000" |
23 | UBOOT_LOADADDRESS ?= "${UBOOT_ENTRYPOINT}" | 23 | UBOOT_LOADADDRESS ?= "${UBOOT_ENTRYPOINT}" |
24 | 24 | ||
25 | # When naming the files we install/deploy, the package version and revision | ||
26 | # are part of the filename. Create a single variable to represent this and | ||
27 | # allow it to be customized if desired. | ||
28 | UBOOT_VERSION ?= "${PV}-${PR}" | ||
29 | |||
25 | # Some versions of u-boot use .bin and others use .img. By default use .bin | 30 | # Some versions of u-boot use .bin and others use .img. By default use .bin |
26 | # but enable individual recipes to change this value. | 31 | # but enable individual recipes to change this value. |
27 | UBOOT_SUFFIX ??= "bin" | 32 | UBOOT_SUFFIX ??= "bin" |
28 | UBOOT_BINARY ?= "u-boot.${UBOOT_SUFFIX}" | 33 | UBOOT_BINARY ?= "u-boot.${UBOOT_SUFFIX}" |
29 | UBOOT_BINARYNAME ?= "${@os.path.splitext(d.getVar("UBOOT_BINARY"))[0]}" | 34 | UBOOT_BINARYNAME ?= "${@os.path.splitext(d.getVar("UBOOT_BINARY"))[0]}" |
30 | UBOOT_IMAGE ?= "${UBOOT_BINARYNAME}-${MACHINE}-${PV}-${PR}.${UBOOT_SUFFIX}" | 35 | UBOOT_IMAGE ?= "${UBOOT_BINARYNAME}-${MACHINE}-${UBOOT_VERSION}.${UBOOT_SUFFIX}" |
31 | UBOOT_SYMLINK ?= "${UBOOT_BINARYNAME}-${MACHINE}.${UBOOT_SUFFIX}" | 36 | UBOOT_SYMLINK ?= "${UBOOT_BINARYNAME}-${MACHINE}.${UBOOT_SUFFIX}" |
32 | UBOOT_MAKE_TARGET ?= "all" | 37 | UBOOT_MAKE_TARGET ?= "all" |
33 | 38 | ||
@@ -36,7 +41,7 @@ UBOOT_MAKE_TARGET ?= "all" | |||
36 | # purposes. | 41 | # purposes. |
37 | UBOOT_ELF ?= "" | 42 | UBOOT_ELF ?= "" |
38 | UBOOT_ELF_SUFFIX ?= "elf" | 43 | UBOOT_ELF_SUFFIX ?= "elf" |
39 | UBOOT_ELF_IMAGE ?= "u-boot-${MACHINE}-${PV}-${PR}.${UBOOT_ELF_SUFFIX}" | 44 | UBOOT_ELF_IMAGE ?= "u-boot-${MACHINE}-${UBOOT_VERSION}.${UBOOT_ELF_SUFFIX}" |
40 | UBOOT_ELF_BINARY ?= "u-boot.${UBOOT_ELF_SUFFIX}" | 45 | UBOOT_ELF_BINARY ?= "u-boot.${UBOOT_ELF_SUFFIX}" |
41 | UBOOT_ELF_SYMLINK ?= "u-boot-${MACHINE}.${UBOOT_ELF_SUFFIX}" | 46 | UBOOT_ELF_SYMLINK ?= "u-boot-${MACHINE}.${UBOOT_ELF_SUFFIX}" |
42 | 47 | ||
@@ -49,7 +54,7 @@ SPL_BINARY ?= "" | |||
49 | SPL_DELIMITER ?= "${@'.' if d.getVar("SPL_SUFFIX") else ''}" | 54 | SPL_DELIMITER ?= "${@'.' if d.getVar("SPL_SUFFIX") else ''}" |
50 | SPL_BINARYFILE ?= "${@os.path.basename(d.getVar("SPL_BINARY"))}" | 55 | SPL_BINARYFILE ?= "${@os.path.basename(d.getVar("SPL_BINARY"))}" |
51 | SPL_BINARYNAME ?= "${@removesuffix(d.getVar("SPL_BINARYFILE"), "." + d.getVar("SPL_SUFFIX"))}" | 56 | SPL_BINARYNAME ?= "${@removesuffix(d.getVar("SPL_BINARYFILE"), "." + d.getVar("SPL_SUFFIX"))}" |
52 | SPL_IMAGE ?= "${SPL_BINARYNAME}-${MACHINE}-${PV}-${PR}${SPL_DELIMITER}${SPL_SUFFIX}" | 57 | SPL_IMAGE ?= "${SPL_BINARYNAME}-${MACHINE}-${UBOOT_VERSION}${SPL_DELIMITER}${SPL_SUFFIX}" |
53 | SPL_SYMLINK ?= "${SPL_BINARYNAME}-${MACHINE}${SPL_DELIMITER}${SPL_SUFFIX}" | 58 | SPL_SYMLINK ?= "${SPL_BINARYNAME}-${MACHINE}${SPL_DELIMITER}${SPL_SUFFIX}" |
54 | 59 | ||
55 | # Additional environment variables or a script can be installed alongside | 60 | # Additional environment variables or a script can be installed alongside |
@@ -62,14 +67,14 @@ UBOOT_ENV ?= "" | |||
62 | UBOOT_ENV_SRC_SUFFIX ?= "cmd" | 67 | UBOOT_ENV_SRC_SUFFIX ?= "cmd" |
63 | UBOOT_ENV_SRC ?= "${UBOOT_ENV}.${UBOOT_ENV_SRC_SUFFIX}" | 68 | UBOOT_ENV_SRC ?= "${UBOOT_ENV}.${UBOOT_ENV_SRC_SUFFIX}" |
64 | UBOOT_ENV_BINARY ?= "${UBOOT_ENV}.${UBOOT_ENV_SUFFIX}" | 69 | UBOOT_ENV_BINARY ?= "${UBOOT_ENV}.${UBOOT_ENV_SUFFIX}" |
65 | UBOOT_ENV_IMAGE ?= "${UBOOT_ENV}-${MACHINE}-${PV}-${PR}.${UBOOT_ENV_SUFFIX}" | 70 | UBOOT_ENV_IMAGE ?= "${UBOOT_ENV}-${MACHINE}-${UBOOT_VERSION}.${UBOOT_ENV_SUFFIX}" |
66 | UBOOT_ENV_SYMLINK ?= "${UBOOT_ENV}-${MACHINE}.${UBOOT_ENV_SUFFIX}" | 71 | UBOOT_ENV_SYMLINK ?= "${UBOOT_ENV}-${MACHINE}.${UBOOT_ENV_SUFFIX}" |
67 | 72 | ||
68 | # U-Boot EXTLINUX variables. U-Boot searches for /boot/extlinux/extlinux.conf | 73 | # U-Boot EXTLINUX variables. U-Boot searches for /boot/extlinux/extlinux.conf |
69 | # to find EXTLINUX conf file. | 74 | # to find EXTLINUX conf file. |
70 | UBOOT_EXTLINUX_INSTALL_DIR ?= "/boot/extlinux" | 75 | UBOOT_EXTLINUX_INSTALL_DIR ?= "/boot/extlinux" |
71 | UBOOT_EXTLINUX_CONF_NAME ?= "extlinux.conf" | 76 | UBOOT_EXTLINUX_CONF_NAME ?= "extlinux.conf" |
72 | UBOOT_EXTLINUX_SYMLINK ?= "${UBOOT_EXTLINUX_CONF_NAME}-${MACHINE}-${PR}" | 77 | UBOOT_EXTLINUX_SYMLINK ?= "${UBOOT_EXTLINUX_CONF_NAME}-${MACHINE}-${UBOOT_VERSION}" |
73 | 78 | ||
74 | # Options for the device tree compiler passed to mkimage '-D' feature: | 79 | # Options for the device tree compiler passed to mkimage '-D' feature: |
75 | UBOOT_MKIMAGE_DTCOPTS ??= "" | 80 | UBOOT_MKIMAGE_DTCOPTS ??= "" |