1# 2# SPDX-License-Identifier: GPL-2.0-only 3# 4 5from abc import ABCMeta, abstractmethod 6from oe.utils import execute_pre_post_process 7from oe.manifest import * 8from oe.package_manager import * 9import os 10import shutil 11import glob 12import traceback 13 14class Sdk(object, metaclass=ABCMeta): 15 def __init__(self, d, manifest_dir): 16 self.d = d 17 self.sdk_output = self.d.getVar('SDK_OUTPUT') 18 self.sdk_native_path = self.d.getVar('SDKPATHNATIVE').strip('/') 19 self.target_path = self.d.getVar('SDKTARGETSYSROOT').strip('/') 20 self.sysconfdir = self.d.getVar('sysconfdir').strip('/') 21 22 self.sdk_target_sysroot = os.path.join(self.sdk_output, self.target_path) 23 self.sdk_host_sysroot = self.sdk_output 24 25 if manifest_dir is None: 26 self.manifest_dir = self.d.getVar("SDK_DIR") 27 else: 28 self.manifest_dir = manifest_dir 29 30 self.remove(self.sdk_output, True) 31 32 self.install_order = Manifest.INSTALL_ORDER 33 34 @abstractmethod 35 def _populate(self): 36 pass 37 38 def populate(self): 39 self.mkdirhier(self.sdk_output) 40 41 # call backend dependent implementation 42 self._populate() 43 44 # Don't ship any libGL in the SDK 45 self.remove(os.path.join(self.sdk_output, self.sdk_native_path, 46 self.d.getVar('libdir_nativesdk').strip('/'), 47 "libGL*")) 48 49 # Fix or remove broken .la files 50 self.remove(os.path.join(self.sdk_output, self.sdk_native_path, 51 self.d.getVar('libdir_nativesdk').strip('/'), 52 "*.la")) 53 54 # Link the ld.so.cache file into the hosts filesystem 55 link_name = os.path.join(self.sdk_output, self.sdk_native_path, 56 self.sysconfdir, "ld.so.cache") 57 self.mkdirhier(os.path.dirname(link_name)) 58 os.symlink("/etc/ld.so.cache", link_name) 59 60 execute_pre_post_process(self.d, self.d.getVar('SDK_POSTPROCESS_COMMAND')) 61 62 def movefile(self, sourcefile, destdir): 63 try: 64 # FIXME: this check of movefile's return code to None should be 65 # fixed within the function to use only exceptions to signal when 66 # something goes wrong 67 if (bb.utils.movefile(sourcefile, destdir) == None): 68 raise OSError("moving %s to %s failed" 69 %(sourcefile, destdir)) 70 #FIXME: using umbrella exc catching because bb.utils method raises it 71 except Exception as e: 72 bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc()) 73 bb.error("unable to place %s in final SDK location" % sourcefile) 74 75 def mkdirhier(self, dirpath): 76 try: 77 bb.utils.mkdirhier(dirpath) 78 except OSError as e: 79 bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc()) 80 bb.fatal("cannot make dir for SDK: %s" % dirpath) 81 82 def remove(self, path, recurse=False): 83 try: 84 bb.utils.remove(path, recurse) 85 #FIXME: using umbrella exc catching because bb.utils method raises it 86 except Exception as e: 87 bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc()) 88 bb.warn("cannot remove SDK dir: %s" % path) 89 90 def install_locales(self, pm): 91 linguas = self.d.getVar("SDKIMAGE_LINGUAS") 92 if linguas: 93 import fnmatch 94 # Install the binary locales 95 if linguas == "all": 96 pm.install_glob("nativesdk-glibc-binary-localedata-*.utf-8", sdk=True) 97 else: 98 pm.install(["nativesdk-glibc-binary-localedata-%s.utf-8" % \ 99 lang for lang in linguas.split()]) 100 # Generate a locale archive of them 101 target_arch = self.d.getVar('SDK_ARCH') 102 rootfs = oe.path.join(self.sdk_host_sysroot, self.sdk_native_path) 103 localedir = oe.path.join(rootfs, self.d.getVar("libdir_nativesdk"), "locale") 104 generate_locale_archive(self.d, rootfs, target_arch, localedir) 105 # And now delete the binary locales 106 pkgs = fnmatch.filter(pm.list_installed(), "nativesdk-glibc-binary-localedata-*.utf-8") 107 pm.remove(pkgs) 108 else: 109 # No linguas so do nothing 110 pass 111 112 113class RpmSdk(Sdk): 114 def __init__(self, d, manifest_dir=None, rpm_workdir="oe-sdk-repo"): 115 super(RpmSdk, self).__init__(d, manifest_dir) 116 117 self.target_manifest = RpmManifest(d, self.manifest_dir, 118 Manifest.MANIFEST_TYPE_SDK_TARGET) 119 self.host_manifest = RpmManifest(d, self.manifest_dir, 120 Manifest.MANIFEST_TYPE_SDK_HOST) 121 122 rpm_repo_workdir = "oe-sdk-repo" 123 if "sdk_ext" in d.getVar("BB_RUNTASK"): 124 rpm_repo_workdir = "oe-sdk-ext-repo" 125 126 self.target_pm = RpmPM(d, 127 self.sdk_target_sysroot, 128 self.d.getVar('TARGET_VENDOR'), 129 'target', 130 rpm_repo_workdir=rpm_repo_workdir 131 ) 132 133 self.host_pm = RpmPM(d, 134 self.sdk_host_sysroot, 135 self.d.getVar('SDK_VENDOR'), 136 'host', 137 "SDK_PACKAGE_ARCHS", 138 "SDK_OS", 139 rpm_repo_workdir=rpm_repo_workdir 140 ) 141 142 def _populate_sysroot(self, pm, manifest): 143 pkgs_to_install = manifest.parse_initial_manifest() 144 145 pm.create_configs() 146 pm.write_index() 147 pm.update() 148 149 pkgs = [] 150 pkgs_attempt = [] 151 for pkg_type in pkgs_to_install: 152 if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY: 153 pkgs_attempt += pkgs_to_install[pkg_type] 154 else: 155 pkgs += pkgs_to_install[pkg_type] 156 157 pm.install(pkgs) 158 159 pm.install(pkgs_attempt, True) 160 161 def _populate(self): 162 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND")) 163 164 bb.note("Installing TARGET packages") 165 self._populate_sysroot(self.target_pm, self.target_manifest) 166 167 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 168 169 self.target_pm.run_intercepts(populate_sdk='target') 170 171 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 172 173 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 174 self.target_pm.remove_packaging_data() 175 176 bb.note("Installing NATIVESDK packages") 177 self._populate_sysroot(self.host_pm, self.host_manifest) 178 self.install_locales(self.host_pm) 179 180 self.host_pm.run_intercepts(populate_sdk='host') 181 182 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) 183 184 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 185 self.host_pm.remove_packaging_data() 186 187 # Move host RPM library data 188 native_rpm_state_dir = os.path.join(self.sdk_output, 189 self.sdk_native_path, 190 self.d.getVar('localstatedir_nativesdk').strip('/'), 191 "lib", 192 "rpm" 193 ) 194 self.mkdirhier(native_rpm_state_dir) 195 for f in glob.glob(os.path.join(self.sdk_output, 196 "var", 197 "lib", 198 "rpm", 199 "*")): 200 self.movefile(f, native_rpm_state_dir) 201 202 self.remove(os.path.join(self.sdk_output, "var"), True) 203 204 # Move host sysconfig data 205 native_sysconf_dir = os.path.join(self.sdk_output, 206 self.sdk_native_path, 207 self.d.getVar('sysconfdir', 208 True).strip('/'), 209 ) 210 self.mkdirhier(native_sysconf_dir) 211 for f in glob.glob(os.path.join(self.sdk_output, "etc", "rpm*")): 212 self.movefile(f, native_sysconf_dir) 213 for f in glob.glob(os.path.join(self.sdk_output, "etc", "dnf", "*")): 214 self.movefile(f, native_sysconf_dir) 215 self.remove(os.path.join(self.sdk_output, "etc"), True) 216 217 218class OpkgSdk(Sdk): 219 def __init__(self, d, manifest_dir=None): 220 super(OpkgSdk, self).__init__(d, manifest_dir) 221 222 self.target_conf = self.d.getVar("IPKGCONF_TARGET") 223 self.host_conf = self.d.getVar("IPKGCONF_SDK") 224 225 self.target_manifest = OpkgManifest(d, self.manifest_dir, 226 Manifest.MANIFEST_TYPE_SDK_TARGET) 227 self.host_manifest = OpkgManifest(d, self.manifest_dir, 228 Manifest.MANIFEST_TYPE_SDK_HOST) 229 230 ipk_repo_workdir = "oe-sdk-repo" 231 if "sdk_ext" in d.getVar("BB_RUNTASK"): 232 ipk_repo_workdir = "oe-sdk-ext-repo" 233 234 self.target_pm = OpkgPM(d, self.sdk_target_sysroot, self.target_conf, 235 self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS"), 236 ipk_repo_workdir=ipk_repo_workdir) 237 238 self.host_pm = OpkgPM(d, self.sdk_host_sysroot, self.host_conf, 239 self.d.getVar("SDK_PACKAGE_ARCHS"), 240 ipk_repo_workdir=ipk_repo_workdir) 241 242 def _populate_sysroot(self, pm, manifest): 243 pkgs_to_install = manifest.parse_initial_manifest() 244 245 if (self.d.getVar('BUILD_IMAGES_FROM_FEEDS') or "") != "1": 246 pm.write_index() 247 248 pm.update() 249 250 for pkg_type in self.install_order: 251 if pkg_type in pkgs_to_install: 252 pm.install(pkgs_to_install[pkg_type], 253 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY]) 254 255 def _populate(self): 256 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND")) 257 258 bb.note("Installing TARGET packages") 259 self._populate_sysroot(self.target_pm, self.target_manifest) 260 261 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 262 263 self.target_pm.run_intercepts(populate_sdk='target') 264 265 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 266 267 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 268 self.target_pm.remove_packaging_data() 269 270 bb.note("Installing NATIVESDK packages") 271 self._populate_sysroot(self.host_pm, self.host_manifest) 272 self.install_locales(self.host_pm) 273 274 self.host_pm.run_intercepts(populate_sdk='host') 275 276 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) 277 278 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 279 self.host_pm.remove_packaging_data() 280 281 target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir) 282 host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir) 283 284 self.mkdirhier(target_sysconfdir) 285 shutil.copy(self.target_conf, target_sysconfdir) 286 os.chmod(os.path.join(target_sysconfdir, 287 os.path.basename(self.target_conf)), 0o644) 288 289 self.mkdirhier(host_sysconfdir) 290 shutil.copy(self.host_conf, host_sysconfdir) 291 os.chmod(os.path.join(host_sysconfdir, 292 os.path.basename(self.host_conf)), 0o644) 293 294 native_opkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path, 295 self.d.getVar('localstatedir_nativesdk').strip('/'), 296 "lib", "opkg") 297 self.mkdirhier(native_opkg_state_dir) 298 for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "opkg", "*")): 299 self.movefile(f, native_opkg_state_dir) 300 301 self.remove(os.path.join(self.sdk_output, "var"), True) 302 303 304class DpkgSdk(Sdk): 305 def __init__(self, d, manifest_dir=None): 306 super(DpkgSdk, self).__init__(d, manifest_dir) 307 308 self.target_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt") 309 self.host_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt-sdk") 310 311 self.target_manifest = DpkgManifest(d, self.manifest_dir, 312 Manifest.MANIFEST_TYPE_SDK_TARGET) 313 self.host_manifest = DpkgManifest(d, self.manifest_dir, 314 Manifest.MANIFEST_TYPE_SDK_HOST) 315 316 deb_repo_workdir = "oe-sdk-repo" 317 if "sdk_ext" in d.getVar("BB_RUNTASK"): 318 deb_repo_workdir = "oe-sdk-ext-repo" 319 320 self.target_pm = DpkgPM(d, self.sdk_target_sysroot, 321 self.d.getVar("PACKAGE_ARCHS"), 322 self.d.getVar("DPKG_ARCH"), 323 self.target_conf_dir, 324 deb_repo_workdir=deb_repo_workdir) 325 326 self.host_pm = DpkgPM(d, self.sdk_host_sysroot, 327 self.d.getVar("SDK_PACKAGE_ARCHS"), 328 self.d.getVar("DEB_SDK_ARCH"), 329 self.host_conf_dir, 330 deb_repo_workdir=deb_repo_workdir) 331 332 def _copy_apt_dir_to(self, dst_dir): 333 staging_etcdir_native = self.d.getVar("STAGING_ETCDIR_NATIVE") 334 335 self.remove(dst_dir, True) 336 337 shutil.copytree(os.path.join(staging_etcdir_native, "apt"), dst_dir) 338 339 def _populate_sysroot(self, pm, manifest): 340 pkgs_to_install = manifest.parse_initial_manifest() 341 342 pm.write_index() 343 pm.update() 344 345 for pkg_type in self.install_order: 346 if pkg_type in pkgs_to_install: 347 pm.install(pkgs_to_install[pkg_type], 348 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY]) 349 350 def _populate(self): 351 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND")) 352 353 bb.note("Installing TARGET packages") 354 self._populate_sysroot(self.target_pm, self.target_manifest) 355 356 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 357 358 self.target_pm.run_intercepts(populate_sdk='target') 359 360 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 361 362 self._copy_apt_dir_to(os.path.join(self.sdk_target_sysroot, "etc", "apt")) 363 364 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 365 self.target_pm.remove_packaging_data() 366 367 bb.note("Installing NATIVESDK packages") 368 self._populate_sysroot(self.host_pm, self.host_manifest) 369 self.install_locales(self.host_pm) 370 371 self.host_pm.run_intercepts(populate_sdk='host') 372 373 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) 374 375 self._copy_apt_dir_to(os.path.join(self.sdk_output, self.sdk_native_path, 376 "etc", "apt")) 377 378 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 379 self.host_pm.remove_packaging_data() 380 381 native_dpkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path, 382 "var", "lib", "dpkg") 383 self.mkdirhier(native_dpkg_state_dir) 384 for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "dpkg", "*")): 385 self.movefile(f, native_dpkg_state_dir) 386 self.remove(os.path.join(self.sdk_output, "var"), True) 387 388 389 390def sdk_list_installed_packages(d, target, rootfs_dir=None): 391 if rootfs_dir is None: 392 sdk_output = d.getVar('SDK_OUTPUT') 393 target_path = d.getVar('SDKTARGETSYSROOT').strip('/') 394 395 rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True] 396 397 img_type = d.getVar('IMAGE_PKGTYPE') 398 if img_type == "rpm": 399 arch_var = ["SDK_PACKAGE_ARCHS", None][target is True] 400 os_var = ["SDK_OS", None][target is True] 401 return RpmPkgsList(d, rootfs_dir).list_pkgs() 402 elif img_type == "ipk": 403 conf_file_var = ["IPKGCONF_SDK", "IPKGCONF_TARGET"][target is True] 404 return OpkgPkgsList(d, rootfs_dir, d.getVar(conf_file_var)).list_pkgs() 405 elif img_type == "deb": 406 return DpkgPkgsList(d, rootfs_dir).list_pkgs() 407 408def populate_sdk(d, manifest_dir=None): 409 env_bkp = os.environ.copy() 410 411 img_type = d.getVar('IMAGE_PKGTYPE') 412 if img_type == "rpm": 413 RpmSdk(d, manifest_dir).populate() 414 elif img_type == "ipk": 415 OpkgSdk(d, manifest_dir).populate() 416 elif img_type == "deb": 417 DpkgSdk(d, manifest_dir).populate() 418 419 os.environ.clear() 420 os.environ.update(env_bkp) 421 422def get_extra_sdkinfo(sstate_dir): 423 """ 424 This function is going to be used for generating the target and host manifest files packages of eSDK. 425 """ 426 import math 427 428 extra_info = {} 429 extra_info['tasksizes'] = {} 430 extra_info['filesizes'] = {} 431 for root, _, files in os.walk(sstate_dir): 432 for fn in files: 433 if fn.endswith('.tgz'): 434 fsize = int(math.ceil(float(os.path.getsize(os.path.join(root, fn))) / 1024)) 435 task = fn.rsplit(':',1)[1].split('_',1)[1].split(',')[0] 436 origtotal = extra_info['tasksizes'].get(task, 0) 437 extra_info['tasksizes'][task] = origtotal + fsize 438 extra_info['filesizes'][fn] = fsize 439 return extra_info 440 441if __name__ == "__main__": 442 pass 443