yocto中SDK、eSDK、toolchain相关(一)

SDK、eSDK、toolchain之间的关系

toolchain 属于 sdk;sdk属于esdk(可以这样简单的描述)

toolchain

工具链,没啥说的。

sdk

在toolchain之上添加了一些库。

esdk

在sdk的基础上,添加了devtool。
相关信息可以看这里

预总结:文章目的是搞清楚toolchain、sdk、esdk是如何产生的。


bitbake image -c populate_sdk —— 从这里开始

从该命令看出,sdk跟rootfs是紧密相关的(官方文档也说明了这一点)。
populate_sdk代码在populate_sdk_base.bbclass中,至于rootfs如何继承的目前没有理清,暂时mark一下,以后再看。
这直接看代码:

109 def populate_sdk_common(d):
110     from oe.sdk import populate_sdk
111     from oe.manifest import create_manifest, Manifest
112 
113     # Handle package exclusions
114     excl_pkgs = (d.getVar("PACKAGE_EXCLUDE") or "").split()
115     inst_pkgs = (d.getVar("PACKAGE_INSTALL") or "").split()
116     inst_attempt_pkgs = (d.getVar("PACKAGE_INSTALL_ATTEMPTONLY") or "").split()
117 
118     d.setVar('PACKAGE_INSTALL_ORIG', ' '.join(inst_pkgs))
119     d.setVar('PACKAGE_INSTALL_ATTEMPTONLY', ' '.join(inst_attempt_pkgs))
120 
121     for pkg in excl_pkgs:
122     ¦   if pkg in inst_pkgs:
123     ¦   ¦   bb.warn("Package %s, set to be excluded, is in %s PACKAGE_INSTALL (%s).  It will be removed from the list." % (pkg, d.getVar('PN'), inst_pkgs))
124     ¦   ¦   inst_pkgs.remove(pkg)
125 
126     ¦   if pkg in inst_attempt_pkgs:
127     ¦   ¦   bb.warn("Package %s, set to be excluded, is in %s PACKAGE_INSTALL_ATTEMPTONLY (%s).  It will be removed from the list." % (pkg, d.getVar('PN'), inst_pkgs))
128     ¦   ¦   inst_attempt_pkgs.remove(pkg)
129 
130     d.setVar("PACKAGE_INSTALL", ' '.join(inst_pkgs))
131     d.setVar("PACKAGE_INSTALL_ATTEMPTONLY", ' '.join(inst_attempt_pkgs))
132 
133     pn = d.getVar('PN')
134     runtime_mapping_rename("TOOLCHAIN_TARGET_TASK", pn, d)
135     runtime_mapping_rename("TOOLCHAIN_TARGET_TASK_ATTEMPTONLY", pn, d)
136 
137     ld = bb.data.createCopy(d)
138     ld.setVar("PKGDATA_DIR", "${STAGING_DIR}/${SDK_ARCH}-${SDKPKGSUFFIX}${SDK_VENDOR}-${SDK_OS}/pkgdata")
139     runtime_mapping_rename("TOOLCHAIN_HOST_TASK", pn, ld)
140     runtime_mapping_rename("TOOLCHAIN_HOST_TASK_ATTEMPTONLY", pn, ld)
141     d.setVar("TOOLCHAIN_HOST_TASK", ld.getVar("TOOLCHAIN_HOST_TASK"))
142     d.setVar("TOOLCHAIN_HOST_TASK_ATTEMPTONLY", ld.getVar("TOOLCHAIN_HOST_TASK_ATTEMPTONLY"))
143     
144     # create target/host SDK manifests
145     create_manifest(d, manifest_dir=d.getVar('SDK_DIR'),
146     ¦   ¦   ¦   ¦   manifest_type=Manifest.MANIFEST_TYPE_SDK_HOST)
147     create_manifest(d, manifest_dir=d.getVar('SDK_DIR'),
148     ¦   ¦   ¦   ¦   manifest_type=Manifest.MANIFEST_TYPE_SDK_TARGET)
149 
150     populate_sdk(d)
151 
152 fakeroot python do_populate_sdk() {
153     populate_sdk_common(d)
154 }

关键步骤:

  • 设置PACKAGE_INSTALL
  • 设置PACKAGE_INSTALL_ATTEMPTONLY
  • 设置TOOLCHAIN_TARGET_TASK
  • 设置TOOLCHAIN_HOST_TASK
  • 设置TOOLCHAIN_HOST_TASK_ATTEMPTONLY
  • create_manifest for MANIFEST_TYPE_SDK_HOST
  • create_manifest for MANIFEST_TYPE_SDK_TARGET
  • populate_sdk

core-image-minimal为例

export PACKAGE_INSTALL="packagegroup-core-boot  run-postinsts "
PACKAGE_INSTALL_ATTEMPTONLY=""
TOOLCHAIN_TARGET_TASK="packagegroup-core-standalone-sdk-target target-sdk-provides-dummy packagegroup-core-boot  run-postinsts "
TOOLCHAIN_TARGET_TASK_ATTEMPTONLY=" "
TOOLCHAIN_HOST_TASK="nativesdk-packagegroup-sdk-host packagegroup-cross-canadian-qemux86"
TOOLCHAIN_HOST_TASK_ATTEMPTONLY=""

明显TOOLCHAIN_TARGET_TASK TOOLCHAIN_HOST_TASK是重点,所以

先看一下runtime_mapping_rename做了啥。

 520 def runtime_mapping_rename (varname, pkg, d):    
 521     #bb.note("%s before: %s" % (varname, d.getVar(varname)))
 522                                                                                                                  
 523     new_depends = {}                                                                                             
 524     deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "")                                               
 525     for depend in deps:                                                                                          
 526     ¦   new_depend = get_package_mapping(depend, pkg, d)                                                         
 527     ¦   new_depends[new_depend] = deps[depend]                                                                   
 528                                                                                                                  
 529     d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False))                                           
 530                                                                                                                  
 531     #bb.note("%s after: %s" % (varname, d.getVar(varname)))  

 494 def get_package_mapping (pkg, basepkg, d):                                                                                                                                                                                               
 495     import oe.packagedata
 496 
 497     data = oe.packagedata.read_subpkgdata(pkg, d)
 498     key = "PKG_%s" % pkg                    
 499                                                                                   
 500     if key in data:                                                                    
 501     ¦   # Have to avoid undoing the write_extra_pkgs(global_variants...)                  
 502     ¦   if bb.data.inherits_class('allarch', d) and not d.getVar('MULTILIB_VARIANTS') \
 503     ¦   ¦   and data[key] == basepkg:                                    
 504     ¦   ¦   return pkg                                                                 
 505     ¦   return data[key]             
 506                          
 507     return pkg

 185 def explode_dep_versions2(s, *, sort=True):   #这里看注释就够了
 186     """ 
 187     Take an RDEPENDS style string of format:      
 188     "DEPEND1 (optional version) DEPEND2 (optional version) ..."                   
 189     and return a dictionary of dependencies and versions.
 190     """ 

目前看懂这3个函数需要明白packagedata,先mark后续再看。


看create_manifest做了啥。

333 def create_manifest(d, final_manifest=False, manifest_dir=None,
334     ¦   ¦   ¦   ¦   manifest_type=Manifest.MANIFEST_TYPE_IMAGE):
335     manifest_map = {'rpm': RpmManifest,
336     ¦   ¦   ¦   ¦   'ipk': OpkgManifest,
337     ¦   ¦   ¦   ¦   'deb': DpkgManifest}
338 
339     manifest = manifest_map[d.getVar('IMAGE_PKGTYPE')](d, manifest_dir, manifest_type)
340 
341     if final_manifest:
342     ¦   manifest.create_final()
343     else:
344     ¦   manifest.create_initial()

311 class DpkgManifest(Manifest):
312     def create_initial(self):
313     ¦   with open(self.initial_manifest, "w+") as manifest:
314     ¦   ¦   manifest.write(self.initial_manifest_file_header)
315 
316     ¦   ¦   for var in self.var_maps[self.manifest_type]:
317     ¦   ¦   ¦   pkg_list = self.d.getVar(var)
318 
319     ¦   ¦   ¦   if pkg_list is None:
320     ¦   ¦   ¦   ¦   continue
321 
322     ¦   ¦   ¦   for pkg in pkg_list.split():
323     ¦   ¦   ¦   ¦   manifest.write("%s,%s\n" %
324     ¦   ¦   ¦   ¦   ¦   ¦   ¦   ¦  (self.var_maps[self.manifest_type][var], pkg))

 25     var_maps = {                                                                                                                                                                                                                          
 26     ¦   MANIFEST_TYPE_IMAGE: {
 27     ¦   ¦   "PACKAGE_INSTALL": PKG_TYPE_MUST_INSTALL,
 28     ¦   ¦   "PACKAGE_INSTALL_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY,
 29     ¦   ¦   "LINGUAS_INSTALL": PKG_TYPE_LANGUAGE
 30     ¦   },  
 31     ¦   MANIFEST_TYPE_SDK_HOST: {
 32     ¦   ¦   "TOOLCHAIN_HOST_TASK": PKG_TYPE_MUST_INSTALL,
 33     ¦   ¦   "TOOLCHAIN_HOST_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
 34     ¦   },
 35     ¦   MANIFEST_TYPE_SDK_TARGET: {
 36     ¦   ¦   "TOOLCHAIN_TARGET_TASK": PKG_TYPE_MUST_INSTALL,
 37     ¦   ¦   "TOOLCHAIN_TARGET_TASK_ATTEMPTONLY": PKG_TYPE_ATTEMPT_ONLY
 38     ¦   }
 39     }

 80     ¦   self.vars_to_split = ["PACKAGE_INSTALL",                                                                                                                                                                                          
 81     ¦   ¦   ¦   ¦   ¦   ¦   ¦ "TOOLCHAIN_HOST_TASK",
 82     ¦   ¦   ¦   ¦   ¦   ¦   ¦ "TOOLCHAIN_TARGET_TASK"]

简单的说, 就是在SDK_DIR下创建manifest文件,分别写入TOOLCHAIN_HOST_TASK TOOLCHAIN_TARGET_TASK的值。


看populate_sdk做了啥

408 def 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)

 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'))

304 class 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)

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])

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)

代码略微有些长,简单来说,就是创建2个PM——self.target_pm self.host_pm,分别管理target_sysroot 和 host_sysroot,然后分别使用2个manifest,将manifest中记录的包安装进去。
需要安装的包看上面。

那么,这些被安装的包首先需要编译出来的,在哪编译的?

310 do_populate_sdk[depends] += "${@' '.join([x + ':do_populate_sysroot' for x in d.getVar('SDK_DEPENDS').split()])}  ${@d.getVarFlag('do_rootfs', 'depends', False)}"                                                                        
311 do_populate_sdk[rdepends] = "${@' '.join([x + ':do_package_write_${IMAGE_PKGTYPE} ' + x + ':do_packagedata' for x in d.getVar('SDK_RDEPENDS').split()])}"

 48 SDK_RDEPENDS = "${TOOLCHAIN_TARGET_TASK} ${TOOLCHAIN_HOST_TASK}"
 49 SDK_DEPENDS = "virtual/fakeroot-native xz-native cross-localedef-native nativesdk-qemuwrapper-cross ${@' '.join(["%s-qemuwrapper-cross" % m for m in d.getVar("MULTILIB_VARIANTS").split()])} qemuwrapper-cross" 

这下完全清楚了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容