rpmbuild時為什麼會出現空的debugsourcefiles.list?

2023-02-17 18:02:06
錯誤: 空 %file 檔案 /home/user/rpmbuild/BUILD/xxxx-0.1/debugsourcefiles.list

你看錯誤的裡邊有一個%file,這是使用spec檔案構建時的一個命令階段,用於列出檔案以生成對應的rpm包。
我們查詢rpm的宏定義,發現了一行程式碼%files debugsource -f debugsourcefiles.list,debugsource包要使用debugsourcefiles.list檔案,而debugsourcefiles.list是空的,所以出現了相應的錯誤。

原始碼包經過構建後,除了生成spec中指定的包外,還會生成額外的debuginfo和debugsource包,noarch架構除外。

  • 那麼debugsourcefiles.list檔案是怎麼生成的?為什麼是空的?

debugsourcefiles.list是由find-debuginfo生成的。
生成的檔案內容為空有以下幾個原因:
1 編譯的目標並未生成任何動態庫和可執行檔案。
2 編譯時未給編譯器加可偵錯選項,比如gcc的-g選項。
3 有些開發者在構建檔案的install階段執行了strip,剝除了偵錯資訊。

如果不想生成額外的debuginfo和debugsource包,可以在rpmbuild命令列指定--nodebuginfo,也可以在spec檔案的開頭加上%define debug_package %{nil}

如果只是不想生成debugsource,還繼續生成debuginfo,可以在spec檔案的開頭加上%define _debugsource_template %{nil}
如果不想生成debuginfo,還繼續生成debugsource?別折騰了,這樣做沒意義。

但是如果本意是想生成的,卻遇到了以上的問題,那就往下看,瞭解一下find-debuginfo的原理。

find-debuginfo

建立臨時目錄 /tmp/find-debuginfo.XXXXXX,XXXXXX為亂數。

然後在$RPM_BUILD_ROOT查詢檔案屬性中有not stripped標誌的檔案,將結果寫到臨時目錄的primary檔案內。使用了下邊的一段程式碼。
可以看到查詢條件,只要檔案許可權中owner、group、other任意一個可執行,並且屬性中有not stripped就滿足要求。

touch "$temp/primary"
find "$RPM_BUILD_ROOT" ! -path "${debugdir}/*.debug" -type f \
                     \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \
                     -print | LC_ALL=C sort |
file -N -f - | sed -n -e 's/^\(.*\):[   ]*.*ELF.*, not stripped.*/\1/p' |
xargs --no-run-if-empty stat -c '%h %D_%i %n' |
while read nlinks inum f; do
  if [ $nlinks -gt 1 ]; then
    var=seen_$inum
    if test -n "${!var}"; then
      echo "$inum $f" >>"$temp/linked"
      continue
    else
      read "$var" < <(echo 1)
    fi
  fi
  echo "$nlinks $inum $f" >>"$temp/primary"
done

對所有寫入primary的檔案,逐個進行處理,這裡使用了多執行緒,指令碼中每個執行緒是一個run_job函數,ran_job其本質執行的是do_file函數。
比如使用了8個執行緒,執行緒0是run_job0,run_job0將自己處理過的檔案寫入elfbins.0,將提取的資訊寫入debugsources.0,將處理結果寫入res.0。

然後再將多個執行緒處理產生的多個elfbins和debugsources檔案進行合併,顧名思義,debugsources裡邊記錄著偵錯原始檔的名稱和型別。

debugsourcefiles.list debugsource包的列表檔案。記錄所有偵錯原始檔(就是程式碼檔案)將要被安裝到系統的路徑,一般是/usr/src/debug/%{packagename}-%{version}-%{release}.%{dist}.%{arch}
debugfiles.list debuginfo包的列表檔案。記錄所有的偵錯檔案將要被安裝的路徑,就是未被stripped的檔案,每個檔案一條記錄。
debuglinks.list
debugsources.list 記錄所有偵錯用原始碼檔案的名稱和型別。原始碼檔案的偵錯型別可以是<internal><built-in><__thread_local_inner macros>等。
elfbins.list 記錄所有的可偵錯的可執行程式,不包括動態庫,每個檔案一條記錄。

我們再來看看run_job執行緒內都做了些什麼?

run_job執行緒內呼叫了do_file函數,do_file函數使用了debugedit命令對單個檔案進行偵錯資訊處理。