我们在做openharmony的时候,关于lfs推送的时候,经常出现错误,本文提供解决办法
git push -u origin --all Locking support detected on remote "origin". Consider enabling it with: $ git config lfs.https://gitlab2.kylin.com/sh-product-Embedded/openharmony/device_soc_rockchip.git/info/lfs.locksverify true Locking support detected on remote "origin". Consider enabling it with: $ git config lfs.https://gitlab2.kylin.com/sh-product-Embedded/openharmony/device_soc_rockchip.git/info/lfs.locksverify true LFS upload failed:cts: 50% (4/8), 172 MB | 0 B/s (missing) rk3568/hardware/gpu/lib/libmali-bifrost-g52-g2p0-ohos.so (ad12817eb634607e114fa6fcf2b4fc18244b20172664f9f374ed1ef844df7cda) (missing) rk3568/hardware/gpu/lib64/libmali-bifrost-g52-g2p0-ohos.so (e7902e8a59cec7211f3ca2dcc53cb8a1e94b8328023025d7fcc2fb2dacf07e41) hint: Your push was rejected due to missing or corrupt local objects. hint: You can disable this check with: 'git config lfs.allowincompletepush true' error: 无法推送一些引用到 'git@gitlab2.kylin.com:sh-product-Embedded/openharmony/device_soc_rockchip.git'
此原因是推送git的时候,lfs 的object不完善,需要单独拉一下
git lfs fetch --all origin OpenHarmony-4.0-Release
这样再通过git push的仓库的lfs是完善的
git push -u origin --all
ftrace是内核的一套框架,它将内核多种trace整合在一起,之前我们提到的tracepoint,trace event,kprobe等等都是ftrace base的。ftrace 提供了一个tracefs基本框架。本文介绍ftrace的基本使用 一、ftrace 框架 为了了解ftrace框架,我们需要把其他几个trace都介绍进来,主要如下所示:

如上图所示
如果关系社区文档的,可以查看如下:
https://lwn.net/Articles/370423/
这样我们就对整个ftrace框架有了一个比较清晰的了解了,接下来介绍ftrace的使用
对于function trace,我们需要关注如下几个文件,目录是在:/sys/kernel/debug/tracing
set_ftrace_filter set_ftrace_notrace
这里以usbhid鼠标事件为例,开展一个示例。
我们知道,usb事件通过urb提交数据,对于usbhid而言,提交数据的函数是usb_submit_urb,我们此时跟踪usb_submit_urb函数,如下:
cd /sys/kernel/debug/tracing echo 0 > tracing_on echo usb_submit_urb > set_ftrace_filter echo function > current_tracer echo 1 > tracing_on cat trace_pipe
此时我们晃动鼠标,可以知道trace信息如下:
<idle>-0 [000] .Ns. 802.924876: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 802.928922: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 802.932923: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 802.936922: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 802.940922: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 802.944876: usb_submit_urb <-hid_irq_in
我们能够准确的抓到usb_submit_urb事件信息,其是hid_irq_in调用。但是缺点是我并不知道是如何传入的,所以我们还需要开一个特性,如下:
echo 1 > options/func_stack_trace
此时我们再晃动鼠标,可以看到信息如下:
<idle>-0 [000] .Ns. 879.322927: usb_submit_urb <-hid_irq_in <idle>-0 [000] .Ns. 879.322929: <stack trace> => usb_submit_urb => hid_irq_in => __usb_hcd_giveback_urb => usb_giveback_urb_bh => tasklet_action_common.isra.0 => tasklet_hi_action => __do_softirq => irq_exit => __handle_domain_irq => gic_handle_irq => el1_irq => cpuidle_enter_state => cpuidle_enter => call_cpuidle => do_idle => cpu_startup_entry => rest_init => arch_call_rest_init => start_kernel
这里我们就清楚的知道,系统idle进程在等待gic中断,也就是我鼠标晃动,然后在gic_handle_irq中根据注册的中断调用回调。我们关注hid_irq_in是谁注册的就知道整个代码调用过程了。
如果不用,则关闭即可。
echo 0 > tracing_on echo nop > current_tracer
function graph trace改进了function trace,可以将整个函数调用堆栈打印出来,并且按照括号给折叠查看,对于排查代码框架问题上比trace更好用
对于function graph trace,主要关注如下文件:
set_graph_function set_graph_notrace
这里还是以usbhid为例,开展示例:
cd /sys/kernel/debug/tracing echo 0 > tracing_on echo function_graph > current_tracer echo usb_submit_urb > set_graph_function echo 0 > max_graph_depth
晃动鼠标
echo 1 > tracing_on cp /sys/kernel/debug/tracing/trace ~/ echo 0 > tracing_on
我们可以拿到如下日志
# tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | ------------------------------------------ 0) ukui-po-2485 => <idle>-0 ------------------------------------------ 0) | usb_submit_urb() { 0) | usb_hcd_submit_urb() { 0) | usb_get_urb() { 0) 0.875 us | usb_get_urb.part.0(); 0) 2.625 us | } 0) 0.875 us | usb_hcd_map_urb_for_dma(); 0) | ehci_urb_enqueue() { 0) | qh_urb_transaction() { 0) | ehci_qtd_alloc() { 0) | dma_pool_alloc() { 0) | _raw_spin_lock_irqsave() { 0) 0.583 us | do_raw_spin_lock(); 0) 1.750 us | } 0) | _raw_spin_unlock_irqrestore() { 0) 0.584 us | do_raw_spin_unlock(); 0) 1.750 us | } 0) 5.541 us | } 0) 6.709 us | } 0) 0.583 us | qtd_fill.isra.0(); 0) 9.625 us | } 0) | _raw_spin_lock_irqsave() { 0) 0.583 us | do_raw_spin_lock(); 0) 1.750 us | } 0) | usb_hcd_link_urb_to_ep() { 0) | _raw_spin_lock() { 0) 0.584 us | do_raw_spin_lock(); 0) 1.458 us | } 0) | _raw_spin_unlock() { 0) 0.583 us | do_raw_spin_unlock(); 0) 1.459 us | } 0) 6.416 us | } 0) 0.875 us | qh_append_tds(); 0) 1.750 us | qh_append_tds(); 0) | _raw_spin_unlock_irqrestore() { 0) 0.583 us | do_raw_spin_unlock(); 0) 1.750 us | } 0) + 26.542 us | } 0) + 32.375 us | } 0) + 37.916 us | }
我们可以看到usb_submit_urb的调用流程了,便于分析解决usb_submit_urb函数内部存在的问题。
这里,我们发现能够直接追到usb_submit_urb后面所有的调用和运行的时间了,但是这些括号匹配起来很麻烦,所以我们应该打开如下:
echo 1 > options/funcgraph-tail
此时日志不一样了,如下:
0) | usb_submit_urb() { 0) | usb_hcd_submit_urb() { 0) | usb_get_urb() { 0) 0.583 us | usb_get_urb.part.0(); 0) 1.750 us | } /* usb_get_urb */ 0) 0.583 us | usb_hcd_map_urb_for_dma(); 0) | ehci_urb_enqueue() { 0) | qh_urb_transaction() { 0) | ehci_qtd_alloc() { 0) | dma_pool_alloc() { 0) | _raw_spin_lock_irqsave() { 0) 0.583 us | do_raw_spin_lock(); 0) 1.458 us | } /* _raw_spin_lock_irqsave */ 0) | _raw_spin_unlock_irqrestore() { 0) 0.583 us | do_raw_spin_unlock(); 0) 1.750 us | } /* _raw_spin_unlock_irqrestore */ 0) 4.666 us | } /* dma_pool_alloc */ 0) 5.834 us | } /* ehci_qtd_alloc */ 0) 0.583 us | qtd_fill.isra.0(); 0) 8.458 us | } /* qh_urb_transaction */ 0) | _raw_spin_lock_irqsave() { 0) 0.583 us | do_raw_spin_lock(); 0) 1.750 us | } /* _raw_spin_lock_irqsave */ 0) | usb_hcd_link_urb_to_ep() { 0) | _raw_spin_lock() { 0) 0.583 us | do_raw_spin_lock(); 0) 1.750 us | } /* _raw_spin_lock */ 0) | _raw_spin_unlock() { 0) 0.292 us | do_raw_spin_unlock(); 0) 2.625 us | } /* _raw_spin_unlock */ 0) 5.834 us | } /* usb_hcd_link_urb_to_ep */ 0) 0.583 us | qh_append_tds(); 0) 1.750 us | qh_append_tds(); 0) | _raw_spin_unlock_irqrestore() { 0) 0.583 us | do_raw_spin_unlock(); 0) 1.458 us | } /* _raw_spin_unlock_irqrestore */ 0) + 23.625 us | } /* ehci_urb_enqueue */ 0) + 28.292 us | } /* usb_hcd_submit_urb */
可以发现括号后面带注释了
但是这还不满足,我想要折叠function graph的信息。
内核有一个vim配置脚本,如下:
scp Documentation/trace/function-graph-fold.vim root@172.25.xx.xx:~
我们用vim打开trace文件的时候执行这个脚本如下:
vim -S function-graph-fold.vim trace
此时日志长这样了:
# tracer: function_graph # # CPU DURATION FUNCTION CALLS # | | | | | | | 6) $ 115370075 us | } /* schedule */ + 0) | usb_submit_urb() {-------------------------------------------------------------------------------------------------------------------------------------
我们在折叠的地方按下L即可展开。
ftrace是一个黑盒测试调试的很好的工具,基本上所有调试过内核的人都知道使用,本文作为普及的目的说了一下ftrace的使用。
我们可以使用ftrace来把内核调试,但是我们发现一个问题就是,我需要反复的echo这echo那,为了避免这类问题,linux提供了trace-cmd工具,其目的是方便ftrace的使用,仅此而已。
首先我们安装trace-cmd
apt install trace-cmd
然后我们可以看看trace-cmd可以获取哪些信息:
# trace-cmd list -h trace-cmd version 2.8.3 usage: trace-cmd list [-e [regex]][-t][-o][-f [regex]] -e list available events -F show event format -R show event triggers -l show event filters -t list available tracers -o list available options -f [regex] list available functions to filter on -P list loaded plugin files (by path) -O list plugin options -B list defined buffer instances -C list the defined clocks (and active one)
我们看看record支持哪些参数
# trace-cmd record -h trace-cmd version 2.8.3 usage: trace-cmd record [-v][-e event [-f filter]][-p plugin][-F][-d][-D][-o file] \ [-q][-s usecs][-O option ][-l func][-g func][-n func] \ [-P pid][-N host:port][-t][-r prio][-b size][-B buf][command ...] [-m max][-C clock] -e run command with event enabled -f filter for previous -e event -R trigger for previous -e event -p run command with plugin enabled -F filter only on the given process -P trace the given pid like -F for the command -c also trace the children of -F (or -P if kernel supports it) -C set the trace clock -T do a stacktrace on all events -l filter function name -g set graph function -n do not trace function -m max size per CPU in kilobytes -M set CPU mask to trace -v will negate all -e after it (disable those events) -d disable function tracer when running -D Full disable of function tracing (for all users) -o data output file [default trace.dat] -O option to enable (or disable) -r real time priority to run the capture threads -s sleep interval between recording (in usecs) [default: 1000] -S used with --profile, to enable only events in command line -N host:port to connect to (see listen) -t used with -N, forces use of tcp in live trace -b change kernel buffersize (in kilobytes per CPU) -B create sub buffer and following events will be enabled here -k do not reset the buffers after tracing. -i do not fail if an event is not found -q print no output to the screen --quiet print no output to the screen --module filter module name --by-comm used with --profile, merge events for related comms --profile enable tracing options needed for report --profile --func-stack perform a stack trace for function tracer (use with caution) --max-graph-depth limit function_graph depth --no-filter include trace-cmd threads in the trace
我相信对于了解ftrace的人来说,这些就无需解释了
我们可以把trace-cmd的使用习惯和perf对齐。如下讲解一下trace-cmd调试function trace和function graph trace,还是以usb_submit_urb为例。
trace-cmd record -p function -l usb_submit_urb --func-stack 此时我们会在本地记录trace.dat文件,我们通过report查看即可
# trace-cmd report | less CPU 1 is empty CPU 2 is empty CPU 3 is empty CPU 4 is empty CPU 5 is empty CPU 6 is empty CPU 7 is empty cpus=8 <idle>-0 [000] 569.464380: function: usb_submit_urb <idle>-0 [000] 569.464385: kernel_stack: <stack trace> => usb_submit_urb (ffffffc008d28b28) => hid_irq_in (ffffffc0090770e4) => __usb_hcd_giveback_urb (ffffffc008d26338) => usb_giveback_urb_bh (ffffffc008d264ac) => tasklet_action_common.isra.0 (ffffffc00808f020) => tasklet_hi_action (ffffffc00808f33c) => __do_softirq (ffffffc0080104b0) => irq_exit (ffffffc00808ee40) => __handle_domain_irq (ffffffc0080fea0c) => gic_handle_irq (ffffffc008010128) => el1_irq (ffffffc008011c08) => cpuidle_enter_state (ffffffc008ff95dc) => cpuidle_enter (ffffffc008ff9984) => call_cpuidle (ffffffc0080c9b18) => do_idle (ffffffc0080c9e18) => cpu_startup_entry (ffffffc0080ca040) => rest_init (ffffffc0095071d0) => arch_call_rest_init (ffffffc009ed0a34) => start_kernel (ffffffc009ed0f94) <idle>-0 [000] 569.468361: function: usb_submit_urb <idle>-0 [000] 569.468365: kernel_stack: <stack trace>
trace-cmd record -p function_graph -g usb_submit_urb 此时为了能够查看括号的注释,我们report如下:
# trace-cmd report -O tailprint CPU 1 is empty CPU 2 is empty CPU 3 is empty CPU 4 is empty CPU 5 is empty CPU 6 is empty CPU 7 is empty cpus=8 <idle>-0 [000] 1094.765032: funcgraph_entry: | finish_task_switch() { <idle>-0 [000] 1094.765034: funcgraph_entry: | _raw_spin_unlock_irq() { <idle>-0 [000] 1094.765035: funcgraph_entry: 0.584 us | do_raw_spin_unlock(); <idle>-0 [000] 1094.765037: funcgraph_exit: 2.334 us | } /* _raw_spin_unlock_irq */ <idle>-0 [000] 1094.765037: funcgraph_exit: 6.417 us | } /* finish_task_switch */ <idle>-0 [000] 1102.416579: funcgraph_entry: | usb_submit_urb() { <idle>-0 [000] 1102.416584: funcgraph_entry: | usb_hcd_submit_urb() { <idle>-0 [000] 1102.416585: funcgraph_entry: | usb_get_urb() { <idle>-0 [000] 1102.416586: funcgraph_entry: 0.875 us | usb_get_urb.part.0(); <idle>-0 [000] 1102.416587: funcgraph_exit: 2.917 us | } /* usb_get_urb */
根据上面的文章,我们知道了EulerMaker(一)功能简介和EulerMaker(二)界面介绍,从功能上,我们知道了它是改进了标准发行版的系统构建工具,取yocto的分层思想而诞生的一个系统构建平台,从界面上,我们可以简单的点点就能完成软件包的构建和操作系统镜像的定制。本文主要根据其日志步骤来分析其基本原理
系统构建有两条路,以自顶向下和自底向上,之前我解释过,如下:
自顶向下是描述操作系统默认是一个单独的发行版本,对于不同的需求,通过增加或移除软件包的方式来定制它。可以理解为减法 自底向上是描述一个操作系统版本,是根据其根本需求来从零逐步增加软件包来实现一个系统版本。可以理解为加法
可以知道,如果我们一味的选择自顶向下构建,那么我们需要具备一个全功能的操作系统,然后按照一个包一个包修改定制的方式来定制,类似于现在常见的发行版本,如debian,ubuntu,suse等。但它的缺点是定制能力不强,只能提供一个客户大而全的系统,而不是适用于客户业务场景的系统
而自底向上构建,我们需要针对每个源码,每个细节进行构建,然后整合成一个操作系统,类似于gentoo,yocto,buildroot等。它的缺点显而易见,从源码构建太慢,优点也十分突出,具备高定制能力,能够提供适用于客户场景的系统
目前来看,openeuler意识到了自顶向下的方式不太适用于当前市场,无论是服务器,桌面,手机,平板,电脑,车载还是嵌入式其他设备,都需要适合其场景的操作系统,而不是一个操作系统版本用在各个行业,所以openeuler提供了eulermaker来借鉴yocto的思维,实现自底向上构建,也就是俗称的:“搭积木的方式构建系统”
当前市场来看,所有受欢迎的电子设备产品,都是自底向上构建的,例如,安卓,苹果,特斯拉,鸿蒙,欧拉等,其因为良好的适配性,带来良好的用户体验,从而占领着各个软件行业市场。
根据构建日志,我们可以分析其构建的原理
2024-10-09 17:05:42 starting DOCKER
根据此,我们可以知道EulerMaker默认在docker中构建
2024-10-09 17:06:19 RESULT_ROOT=/result/rpmbuild/2024-10-09/dc-64g/openeuler-24.03-lts-aarch64/aarch64-common-gitee.com-src-openeuler-bi/cbs.6536572
根据此,我们可以知道EulerMaker使用rpmbuild来执行软件包的构建
2024-10-09 17:06:48 Running transaction check 2024-10-09 17:06:48 Transaction check succeeded. 2024-10-09 17:06:48 Running transaction test 2024-10-09 17:06:48 Transaction test succeeded. 2024-10-09 17:06:48 Running transaction
根据此,我们可以知道其调用了yum/dnf来进行依赖拉包解决
2024-10-09 17:07:07 Complete! 2024-10-09 17:07:07 Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.C1k8v5 2024-10-09 17:07:07 + umask 022 2024-10-09 17:07:07 + cd /home/lkp/rpmbuild/BUILD 2024-10-09 17:07:07 + cd /home/lkp/rpmbuild/BUILD 2024-10-09 17:07:07 + rm -rf binutils-2.41 2024-10-09 17:07:07 + /usr/lib/rpm/rpmuncompress -x /home/lkp/rpmbuild/SOURCES/binutils-2.41.tar.xz
根据此,我们可以大概率知道正在根据spec来运行构建操作,根据上面知道的,构建操作是通过rpmbuild来触发的。那么这个spec和文件如何获取呢?我们留意如下仓库:
https://gitee.com/src-openeuler/binutils
文件如下:
可以发现,这里存放了spec文件,源码tar.xz,补丁文件和服务于EulerMaker的binutils.yaml文件
至此,我们可以知道,EulerMaker的构建工程是通过创建了一个docker环境,docker环境内部根据https://gitee.com/src-openeuler指定软件名的yaml文件来触发,通过spec文件来实施rpmbuild构建rpm包的
根据构建日志,我们可以分析其构建的原理
2024-09-26 09:35:08 starting DOCKER
这里还是使用docker
2024-09-26 09:35:47 + . /lkp/lkp/src/lib/chroot_libs.sh 2024-09-26 09:35:47 + trap restore_local_repo EXIT 2024-09-26 09:35:47 + make_ebs_iso 2024-09-26 09:35:47 ++ uname -m 2024-09-26 09:35:47 + ARCH=aarch64 2024-09-26 09:35:47 + '[' aarch64 '!=' aarch64 ']' 2024-09-26 09:35:47 + '[' '!' -n iso_normal ']' 2024-09-26 09:35:47 + '[' iso_normal == iso ']' 2024-09-26 09:35:47 + '[' iso_normal == embedded ']' 2024-09-26 09:35:47 + '[' '!' -n 2203sp2iso ']' 2024-09-26 09:35:47 + '[' '!' -n 1 ']' 2024-09-26 09:35:47 + '[' '!' -n https://repo.huaweicloud.com/openeuler/openEuler-22.03-LTS-SP2/everything/aarch64/ ']' 2024-09-26 09:35:47 + yum install -y util-linux lsof
这里通过猜测可以发现和构建版本相关,make_ebs_iso是一个shell函数,描述iso的构建方式
2024-09-26 09:35:48 + backup_local_repo 2024-09-26 09:35:48 + '[' -d /etc/yum.repos.d ']' 2024-09-26 09:35:48 + rm -rf /etc/yum.repos.d.bak 2024-09-26 09:35:48 + mv /etc/yum.repos.d /etc/yum.repos.d.bak 2024-09-26 09:35:48 + config_ebs_repo 2024-09-26 09:35:48 + export yum_conf=/tmp/ebs-repo.conf 2024-09-26 09:35:48 + yum_conf=/tmp/ebs-repo.conf 2024-09-26 09:35:48 + rm -rf /tmp/ebs-repo.conf 2024-09-26 09:35:48 + touch /tmp/ebs-repo.conf 2024-09-26 09:35:48 + i=1 2024-09-26 09:35:48 + for repo in ${repo_url[@]} 2024-09-26 09:35:48 + cat 2024-09-26 09:35:48 + let i=i+1 2024-09-26 09:35:48 + '[' iso_normal == embedded ']' 2024-09-26 09:35:48 + '[' iso_normal == iso_normal ']' 2024-09-26 09:35:48 + chroot_run 'cd /lkp/lkp/src/tests/; bash make_iso_image.sh' 2024-09-26 09:35:48 + chroot_init 2024-09-26 09:35:48 + root_path=/usr1/openeuler
这里佐证了上面的猜测,在docker中实施了chroot命令,类似于运行chroot -c make_iso_image.sh
2024-09-26 09:36:33 Total 4.0 MB/s | 157 MB 00:38 2024-09-26 09:36:33 Running transaction check 2024-09-26 09:36:34 Transaction check succeeded. 2024-09-26 09:36:34 Running transaction test 2024-09-26 09:36:34 Transaction test succeeded. 2024-09-26 09:36:34 Running transaction
这里已经在chroot中通过yum安装二进制软件包了
2024-09-26 09:37:56 + pkgs='edk2-aarch64 2024-09-26 09:37:56 grub2-efi-aa64 2024-09-26 09:37:56 grub2-efi-aa64-modules 2024-09-26 09:37:56 kae-driver 2024-09-26 09:37:56 kae-openssl 2024-09-26 09:37:56 kae-zip 2024-09-26 09:37:56 uadk_engine 2024-09-26 09:37:56 libwd 2024-09-26 09:37:56 shim-aa64'
这里已经在制作grub2了
2024-09-26 09:48:46 + yumdownloader --resolve --installroot=/result/tmp/tmp --destdir=/result/tmp/iso/Packages/ yum.noarch xfsprogs.aarch64 wget.aarch64 vim-minimal.aarch64 util-linux.aarch64 uadk_engine.aarch64 tuned.noarch tmux.aarch64 systemd.aarch64 sysfsutils.aarch64 sudo.aarch64 sssd.aarch64 shim-aa64 shadow.aarch64 sg3_utils.aarch64 setup.noarch selinux-policy-targeted.noarch selinux-policy-mls.noarch security-tool.aarch64 rsyslog.aarch64 rpm.aarch64 rootfiles.noarch rng-tools.aarch64 realmd.aarch64 rdma-core.aarch64 procps-ng.aarch64 policycoreutils.aarch64 passwd.aarch64 parted.aarch64 openssh-server.aarch64 openssh-clients.aarch64 openssh.aarch64 openEuler-release.aarch64 openEuler-latest-release.aarch64 ncurses.aarch64 mdadm.aarch64 man-db.aarch64 lvm2.aarch64 lsscsi.aarch64 lshw.aarch64 lorax.aarch64 linux-firmware.noarch libwd.aarch64 libteam.aarch64 less.aarch64 kexec-tools.aarch64 kernel-tools.aarch64 kernel.aarch64 kdump-anaconda-addon.noarch kbd.aarch64 iscsi-initiator-utils irqbalance.aarch64 iputils.aarch64 iprutils.aarch64 iproute.aarch64 initscripts.aarch64 hostname.aarch64 grubby.aarch64 grub2-tools-extra.aarch64 grub2-tools.aarch64 grub2-efi-aa64-modules.noarch grub2-efi-aa64-cdboot.aarch64 grub2-efi-aa64.aarch64 glibc-all-langpacks.aarch64 glibc.aarch64 gfs2-utils.aarch64 firewalld.noarch filesystem.aarch64 fcoe-utils.aarch64 efibootmgr.aarch64 edk2-aarch64.noarch e2fsprogs.aarch64 dracut-network.aarch64 dracut-config-rescue.aarch64 dracut-config-generic.aarch64 dosfstools.aarch64 dnf-plugins-core.noarch dnf.noarch device-mapper-multipath curl.aarch64 cryptsetup.aarch64 cronie.aarch64 coreutils.aarch64 chrony.aarch64 bash.aarch64 basesystem.noarch authselect-compat.aarch64 authselect.aarch64 audit.aarch64 NetworkManager-config-server.noarch NetworkManager.aarch64 2024-09-26 09:48:47 Unable to detect release version (use '--releasever' to specify release version)
这里通过yumdownloader 批量拉包安装
2024-09-26 09:50:42 /opt/oemaker 2024-09-26 09:50:42 + cp /result/tmp/iso/GPG_tmp/etc/pki/rpm-gpg/RPM-GPG-KEY-openEuler /result/tmp/iso 2024-09-26 09:50:42 + rm -rf /result/tmp/iso/GPG_tmp 2024-09-26 09:50:42 + '[' 0 -ne 0 ']' 2024-09-26 09:50:42 + echo 'Waiting for lorax to finish...' 2024-09-26 09:50:42 + '[' standard == debug ']' 2024-09-26 09:50:42 + '[' standard == standard ']' 2024-09-26 09:50:42 + gen_standard_iso 2024-09-26 09:50:42 Waiting for lorax to finish... 2024-09-26 09:50:42 + '[' aarch64 == x86_64 ']' 2024-09-26 09:50:42 + '[' aarch64 == aarch64 ']' 2024-09-26 09:50:42 + mkisofs -R -J -T -r -l -d -joliet-long -allow-multidot -allow-leading-dots -no-bak -V 2203sp2iso-1-1-aarch64 -o /result/2203sp2iso-1-1-aarch64-dvd.iso -e images/efiboot.img -no-emul-boot /result/tmp/iso 2024-09-26 09:50:42 Warning: creating filesystem that does not conform to ISO-9660. 2024-09-26 09:50:42 Size of boot image is 14688 sectors -> No emulation
这里我们知道,通过oemaker封装了mkisofs来生成iso的镜像
至此,我们可以知道,EulerMaker的镜像定制是通过创建了一个docker环境,docker环境内部沿用了常用的构建工具例如livebuild/koji,创建了chroot环境,在chroot中进行yum安装软件包,然后通过oemaker来制作iso镜像文件
虽然我们上面可以发现EulerMaker好像和koji等其他构建平台相差无几,但是我们需要知道的是,分层是一种思想,也就意味着,在触发版本构建时,分层可以在网页中实施,所以我们日志分析不出来的。
不过我们需要明确知道的是,EulerMaker确实借鉴了yocto的分层思想,从而使得构建系统版本能够以搭积木的方式实施,而不是在原有的发行版本上增加和减少软件包。
根据上面通过日志分析原理来看,我们可以发现,eulermaker通过封装了rpmbuild来实现了源码构建工程,在网页上通过设置的方式实现了分层概念,对于镜像定制,底层使用了oemaker来制作iso。其设计思路等价于如下:
koji+yocto分层思想
这样的设计是基于原有构建方案的优化,极大的改善了系统的碎片化问题,同时也降低了使用者的使用门槛,是真正意义上的全场景OS制作工具。
对于eulermaker的使用方法,推荐可以参考:https://docs.openeuler.org/zh/docs/24.03_LTS/docs/EulerMaker/EulerMaker%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97.html,本文根据官方文章,对eulermaker进行了使用,提供使用说明
对于第一次使用eulermaker的同学,需要先进行注册,如下:
https://eulermaker.compass-ci.openeuler.openatom.cn
这里可以看到,右上角有名字是tangfeng的账号已经登录,而下面存在构建工程/镜像定制两大功能



这里需要设置软件包名字,描述,git地址,分支。这里注意的是,需要与https://gitee.com/organizations/src-openeuler/projects 的工程名字匹配,如下为示例

这里需要配置构建目标,软件源,分层url.








先进入软件包详情,点击构建历史
此时我们点击jobID 可以看到任务日志

等待构建完成之后,可以点击下载看到生成的rpm包


此时选择嵌入式场景

设置镜像定制,流水线,格式,架构,如下:


点击定制业务包,设置repo地址,rpm,驱动,命令,库,分区,参数等等


点击构建历史,点击查看日志

等等系统构建完成之后,点击下载镜像

至此,我们通过openeuler发布的eulermaker网页端完成了其构建工程和镜像定制的两大功能项。可以发现,相比于任何的livebuild/koji工具还是yocto,这种方式操作简单,只要用户懂得操作系统构建的基本知识就可以完成一个操作系统的构建,一个软件包工程的编译。