23.6. 重新編譯 World

當本地的原始碼樹已與特定版本的 FreeBSD 如 FreeBSD-STABLE 或 FreeBSD-CURRENT 同步以後,便可使用原始碼樹來重新編譯系統。這個程序即為重新編譯 World。

在重新編譯 World 之前,請確定已完成以下工作:

過程 23.1. 編譯 World 之前 要完成的工作
  1. 備份所有重要的資料到另一個系統或可卸除的媒體,檢查備份的完整性並在手中保留一份可開機的安裝媒體。如何強調都不足夠說明在重新編譯系統 之前 備份系統的重要性。即便重新編譯 World 已變成簡單的一件事,也難免會有原始碼樹失誤導致系統無法開機的時候。您可能永遠都用不上備份,但最好確保安全而非後悔。

  2. 回顧最近 freebsd-stablefreebsd-current 中的項目,依您所追蹤的分支決定。注意任何已知的問題以及會被影響的系統。若已知的問題影響您已同步的原始碼版本,請等候表明問題已被解決的 全部解決 (all clear) 公告發佈,然後重新同步原始碼並確認本地的原始碼版本已含有所需的修正。

  3. 閱讀 /usr/src/UPDATING 了解該版本的原始碼是否有必要的額外步驟要完成。 這個檔案中會包含有關潛藏問題的重要資訊,並且可能會要求執行某些指令。大多升級需要完成指定的額外步驟,例如:在安裝新 World 前重新命名或刪除指定檔案,這些步驟會列在檔案最後,明確說明目前建議的升級順序。若 UPDATING 中有與本章相矛盾的步驟,請以 UPDATING 為準並應遵循其內容。

不要使用 make world:

部份舊版的文件建議使用 make world。然而該指令跳過了部份重要的步驟,應僅供專家使用。大多數的情況使用 make world 都是錯的,並應使用此處說明的程序。

23.6.1. 流程概述

編譯 World 流程會假設您是依照 節 23.5, “同步原始碼” 指示取得最近版本的原始碼來升級舊版的 FreeBSD。

在 FreeBSD,world 一詞包含了核心,核心系統 Binary,程式庫,原始碼以及內建的編譯器。這些元件編譯與安裝的順序非常重要。

舉例來說,舊的編譯器可能有問題而無法編譯新的核心。新的核心需使用新的編譯器來編譯,因此新的編譯器必需先編譯,但在新核心編譯前並不一定要安裝。

新的 World 可能需要使用新的核心功能,所以必須在新的 World 安裝之前先安裝新的核心。舊的 World 也可能在新的核心上無法正常執行,所以必須在新的核心安裝完之後 馬上安裝新的 World。

有一部份設定必須在新的 World 安裝前變更,但其他的部份在之前變更則可能會破壞舊的 World。因此會使用到兩種不同的設定升級步驟。大部份情況,更新程序只會取代或新增檔案,不會刪除已存在的舊檔案。當這可能會造成問題時 /usr/src/UPDATING 便會說明需要手動刪除的檔案以及操作的步驟。

這些問題會影響接下來的建議升級順序。

注意:

將執行 make 的輸出儲存到檔案是不錯的辦法,若發生錯誤時,便可複製錯誤訊息張貼到 FreeBSD 郵遞論壇。

最簡單的方式是使用 script 並透過參數指定要儲存所有輸出的檔案名稱。請不要儲存輸出到 /tmp,因這個目錄可能在下次重新開機後被清除。儲存檔案最好的地方是 /var/tmp。在重新編譯 World 之前執行這個指令,並在流程完成後輸入 exit

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out
過程 23.2. 編譯 World 流程概述

編譯 World 流程中使用的指令應依此處指定的順序執行。本節將摘要各指令的功能。

  1. 若編譯 World 流程先前已在系統執行過,先前編譯的結果可能遺留在 /usr/obj。要加速新的編譯 World 流程及節省處理相依問題的時間,若此目錄存在,請移除此目錄:

    # chflags -R noschg /usr/obj/*
    # rm -rf /usr/obj
  2. 編譯新的編譯器及一些相關工具,然後使用新的編譯器編譯新的 World。編譯的結果會儲存到 /usr/obj

    # cd /usr/src
    # make buildworld
  3. 使用在 /usr/obj 中的新編譯器來編譯新的核心,來確保不會發生編譯器與核心不相容的問題。因某些記憶體結構可能有修改,這個步驟是必要的,若核心與原始碼的版本不同,pstop 這類的程式會無法運作。

    # make buildkernel
  4. 安裝新的核心與新的核心模組,讓開機時可以使用新的核心。這個指令可在多使用者模式執行,除非 kern.securelevel 設定在 1 以上 在核心 Binary 有設定 noschg 或類似的旗標 (Flag),請先讓系統進入單使用者模式。請參考 init(8) 取得有關 kern.securelevel 的詳細資訊以及 chflags(1) 取得有關各種檔案旗標的詳細資訊。

    # make installkernel
  5. 讓系統進入單使用者模組來減少升級任何已在執行中的 Binary 所產生的問題,同樣也可減少在新核心上執行舊 World 的問題。

    # shutdown now

    進入單使用者模式後,若系統磁碟格式為 UFS 請執行以下指令:

    # mount -u /
    # mount -a -t ufs
    # swapon -a

    若系統磁碟格式為 ZFS,則需執行以下兩個指令。此範例假設 zpool 名稱為 zroot

    # zfs set readonly=off zroot
    # zfs mount -a
  6. 選用:若想要使用 US 英文以外的鍵盤對應表,可以使用 kbdmap(1) 來變更:

    # kbdmap
  7. 接著,不論那一種檔案系統,若 CMOS 時鐘設定為本地時間 (若 date(1) 顯示不正確的時間與時區),請執行:

    # adjkerntz -i
  8. 重新編譯 World 不會直接更新某些目錄中的設定檔,如 /etc, /var 以及 /usr。接下來的步驟是更新一部份的設定檔到 /etc 來準備安裝新的 World。以下指令只會比對影響 installworld 是否成功執行的必要檔案。例如,這個步驟會可能會加入新版 FreeBSD 的新群組、系統帳號或啟動 Script。為了讓 installworld 步驟可以使用任何新的系統帳號、群組與 Script,這是個必要的步驟。請參考 節 23.6.4, “合併設定檔” 來取得更多有關此指令的詳細操作說明:

    # mergemaster -p
  9. /usr/obj 安裝新 World 與系統 Binary。

    # cd /usr/src
    # make installworld
  10. 更新任何剩下的設定檔。

    # mergemaster -iF
  11. 刪除任何過時的檔案。這很重要,因為若檔案遺留在磁碟上可能會造成問題。

    # make delete-old
  12. 現在需要完整重新啟動來載入新的核心、新的 World 與新的設定檔。

    # reboot
  13. 確認所有已安裝的 Port 在舊的程式庫移除前已依照 節 4.5.3, “升級 Port” 的說明重新編譯。當重新編譯完成後,移除過時的程式庫來避免與新的程式庫發生衝突。有關此步驟更詳細的說明請參考 節 23.6.5, “刪除過時的檔案及程式庫”

    # make delete-old-libs

若系統允許停機一小段時間,請考慮以單使用者模式編譯系統來替代在多使用者模組編譯系統,然後進入單使用者模式來完成安裝。重新安裝系統會觸及到很多重要的系統檔案,所有的標準系統 Binary、程式庫以及引用檔。在執行中的系統更換這些檔案,特別是有使用者在使用時,是自找麻煩。

23.6.2. 設定檔

This build world process uses several configuration files.

The Makefile located in /usr/src describes how the programs that comprise FreeBSD should be built and the order in which they should be built.

The options available to make are described in make.conf(5) and some common examples are included in /usr/share/examples/etc/make.conf. Any options which are added to /etc/make.conf will control the how make runs and builds programs. These options take effect every time make is used, including compiling applications from the Ports Collection, compiling custom C programs, or building the FreeBSD operating system. Changes to some settings can have far-reaching and potentially surprising effects. Read the comments in both locations and keep in mind that the defaults have been chosen for a combination of performance and safety.

How the operating system is built from source code is controlled by /etc/src.conf. Unlike /etc/make.conf, the contents of /etc/src.conf only take effect when the FreeBSD operating system itself is being built. Descriptions of the many options available for this file are shown in src.conf(5). Be cautious about disabling seemingly unneeded kernel modules and build options. Sometimes there are unexpected or subtle interactions.

23.6.3. 變數與目標

The general format for using make is as follows:

# make -x -DVARIABLE target

In this example, -x is an option passed to make. Refer to make(1) for examples of the available options.

To pass a variable, specify the variable name with -DVARIABLE. The behavior of the Makefile is controlled by variables. These can either be set in /etc/make.conf or they can be specified when using make. For example, this variable specifies that profiled libraries should not be built:

# make -DNO_PROFILE target

It corresponds with this setting in /etc/make.conf:

NO_PROFILE=    true     #    Avoid compiling profiled libraries

The target tells make what to do and the Makefile defines the available targets. Some targets are used by the build process to break out the steps necessary to rebuild the system into a number of sub-steps.

Having separate options is useful for two reasons. First, it allows for a build that does not affect any components of a running system. Because of this, buildworld can be safely run on a machine running in multi-user mode. It is still recommended that installworld be run in part in single-user mode, though.

Secondly, it allows NFS mounts to be used to upgrade multiple machines on a network, as described in 節 23.7, “多部機器追蹤”.

It is possible to specify -j which will cause make to spawn several simultaneous processes. Since much of the compiling process is I/O-bound rather than CPU-bound, this is useful on both single CPU and multi-CPU machines.

On a single-CPU machine, run the following command to have up to 4 processes running at any one time. Empirical evidence posted to the mailing lists shows this generally gives the best performance benefit.

# make -j4 buildworld

On a multi-CPU machine, try values between 6 and 10 to see how they speed things up.

注意:

If any variables were specified to make buildworld, specify the same variables to make installworld. However, -j must never be used with installworld.

For example, if this command was used:

# make -DNO_PROFILE buildworld

Install the results with:

# make -DNO_PROFILE installworld

Otherwise, the second command will try to install profiled libraries that were not built during the make buildworld phase.

23.6.4. 合併設定檔

Contributed by Tom Rhodes.

FreeBSD provides the mergemaster(8) Bourne script to aid in determining the differences between the configuration files in /etc, and the configuration files in /usr/src/etc. This is the recommended solution for keeping the system configuration files up to date with those located in the source tree.

Before using mergemaster, it is recommended to first copy the existing /etc somewhere safe. Include -R which does a recursive copy and -p which preserves times and the ownerships on files:

# cp -Rp /etc /etc.old

When run, mergemaster builds a temporary root environment, from / down, and populates it with various system configuration files. Those files are then compared to the ones currently installed in the system. Files that differ will be shown in diff(1) format, with the + sign representing added or modified lines, and - representing lines that will be either removed completely or replaced with a new file. Refer to diff(1) for more information about how file differences are shown.

Next, mergemaster will display each file that differs, and present options to: delete the new file, referred to as the temporary file, install the temporary file in its unmodified state, merge the temporary file with the currently installed file, or view the results again.

Choosing to delete the temporary file will tell mergemaster to keep the current file unchanged and to delete the new version. This option is not recommended. To get help at any time, type ? at the mergemaster prompt. If the user chooses to skip a file, it will be presented again after all other files have been dealt with.

Choosing to install the unmodified temporary file will replace the current file with the new one. For most unmodified files, this is the best option.

Choosing to merge the file will present a text editor, and the contents of both files. The files can be merged by reviewing both files side by side on the screen, and choosing parts from both to create a finished product. When the files are compared side by side, l selects the left contents and r selects contents from the right. The final output will be a file consisting of both parts, which can then be installed. This option is customarily used for files where settings have been modified by the user.

Choosing to view the results again will redisplay the file differences.

After mergemaster is done with the system files, it will prompt for other options. It may prompt to rebuild the password file and will finish up with an option to remove left-over temporary files.

23.6.5. 刪除過時的檔案及程式庫

Based on notes provided by Anton Shterenlikht.

As a part of the FreeBSD development lifecycle, files and their contents occasionally become obsolete. This may be because functionality is implemented elsewhere, the version number of the library has changed, or it was removed from the system entirely. These obsoleted files, libraries, and directories should be removed when updating the system. This ensures that the system is not cluttered with old files which take up unnecessary space on the storage and backup media. Additionally, if the old library has a security or stability issue, the system should be updated to the newer library to keep it safe and to prevent crashes caused by the old library. Files, directories, and libraries which are considered obsolete are listed in /usr/src/ObsoleteFiles.inc. The following instructions should be used to remove obsolete files during the system upgrade process.

After the make installworld and the subsequent mergemaster have finished successfully, check for obsolete files and libraries:

# cd /usr/src
# make check-old

If any obsolete files are found, they can be deleted using the following command:

# make delete-old

A prompt is displayed before deleting each obsolete file. To skip the prompt and let the system remove these files automatically, use BATCH_DELETE_OLD_FILES:

# make -DBATCH_DELETE_OLD_FILES delete-old

The same goal can be achieved by piping these commands through yes:

# yes|make delete-old

Warning:

Deleting obsolete files will break applications that still depend on those obsolete files. This is especially true for old libraries. In most cases, the programs, ports, or libraries that used the old library need to be recompiled before make delete-old-libs is executed.

Utilities for checking shared library dependencies include sysutils/libchk and sysutils/bsdadminscripts.

Obsolete shared libraries can conflict with newer libraries, causing messages like these:

/usr/bin/ld: warning: libz.so.4, needed by /usr/local/lib/libtiff.so, may conflict with libz.so.5
/usr/bin/ld: warning: librpcsvc.so.4, needed by /usr/local/lib/libXext.so, may conflict with librpcsvc.so.5

To solve these problems, determine which port installed the library:

# pkg which /usr/local/lib/libtiff.so
  /usr/local/lib/libtiff.so was installed by package tiff-3.9.4
# pkg which /usr/local/lib/libXext.so
  /usr/local/lib/libXext.so was installed by package libXext-1.1.1,1

Then deinstall, rebuild, and reinstall the port. To automate this process, ports-mgmt/portmaster can be used. After all ports are rebuilt and no longer use the old libraries, delete the old libraries using the following command:

# make delete-old-libs

If something goes wrong, it is easy to rebuild a particular piece of the system. For example, if /etc/magic was accidentally deleted as part of the upgrade or merge of /etc, file will stop working. To fix this, run:

# cd /usr/src/usr.bin/file
# make all install

23.6.6. 常見問題

每個變更是否都需要重新編譯 World?

It depends upon the nature of the change. For example, if svn only shows the following files as being updated:

src/games/cribbage/instr.c
src/games/sail/pl_main.c
src/release/sysinstall/config.c
src/release/sysinstall/media.c
src/share/mk/bsd.port.mk

it probably is not worth rebuilding the entire world. Instead, go into the appropriate sub-directories and run make all install. But if something major changes, such as src/lib/libc/stdlib, consider rebuilding world.

Some users rebuild world every fortnight and let changes accumulate over that fortnight. Others only re-make those things that have changed and are careful to spot all the dependencies. It all depends on how often a user wants to upgrade and whether they are tracking FreeBSD-STABLE or FreeBSD-CURRENT.

什麼會造成有很多信號 11 (或其他信號) 錯誤的編譯失敗?

This normally indicates a hardware problem. Building world is an effective way to stress test hardware, especially memory. A sure indicator of a hardware issue is when make is restarted and it dies at a different point in the process.

To resolve this error, swap out the components in the machine, starting with RAM, to determine which component is failing.

完成編譯後是可否移除 /usr/obj?

This directory contains all the object files that were produced during the compilation phase. Normally, one of the first steps in the make buildworld process is to remove this directory and start afresh. Keeping /usr/obj around when finished makes little sense, and its removal frees up a approximately 2GB of disk space.

是否能繼續中斷的編譯?

This depends on how far into the process the problem occurs. In general, make buildworld builds new copies of essential tools and the system libraries. These tools and libraries are then installed, used to rebuild themselves, and are installed again. The rest of the system is then rebuilt with the new system tools.

During the last stage, it is fairly safe to run these commands as they will not undo the work of the previous make buildworld:

# cd /usr/src
# make -DNO_CLEAN all

If this message appears:

--------------------------------------------------------------
Building everything..
--------------------------------------------------------------

in the make buildworld output, it is probably fairly safe to do so.

If that message is not displayed, it is always better to be safe than sorry and to restart the build from scratch.

有可能加速編譯 World 的速度嗎?

Several actions can speed up the build world process. For example, the entire process can be run from single-user mode. However, this will prevent users from having access to the system until the process is complete.

Careful file system design or the use of ZFS datasets can make a difference. Consider putting /usr/src and /usr/obj on separate file systems. If possible, place the file systems on separate disks on separate disk controllers. When mounting /usr/src, use noatime which prevents the file system from recording the file access time. If /usr/src is not on its own file system, consider remounting /usr with noatime.

The file system holding /usr/obj can be mounted or remounted with async so that disk writes happen asynchronously. The write completes immediately, and the data is written to the disk a few seconds later. This allows writes to be clustered together, and can provide a dramatic performance boost.

警告:

Keep in mind that this option makes the file system more fragile. With this option, there is an increased chance that, should power fail, the file system will be in an unrecoverable state when the machine restarts.

If /usr/obj is the only directory on this file system, this is not a problem. If you have other, valuable data on the same file system, ensure that there are verified backups before enabling this option.

Turn off profiling by setting NO_PROFILE=true in /etc/make.conf.

Pass -jn to make(1) to run multiple processes in parallel. This usually helps on both single- and multi-processor machines.

若發生錯誤時該怎麼辦?

First, make absolutely sure that the environment has no extraneous cruft from earlier builds:

# chflags -R noschg /usr/obj/usr
# rm -rf /usr/obj/usr
# cd /usr/src
# make cleandir
# make cleandir

Yes, make cleandir really should be run twice.

Then, restart the whole process, starting with make buildworld.

If problems persist, send the error and the output of uname -a to FreeBSD general questions mailing list. Be prepared to answer other questions about the setup!

本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。

關於本文件的問題,請洽詢 <doc@FreeBSD.org>。