Chương 3. Sửa đổi mã nguồn

Mục lục

3.1. Cài đặt quilt
3.2. Sửa lỗi ở thượng nguồn
3.3. Cài đặt các tệp tin đến đích của chúng
3.4. Thư viện khác

Xin lưu ý rằng không có nhiều thời gian để đi vào tất cả các chi tiết để khắc phục tất cả thượng nguồn, nhưng đây sẽ là một số bước cơ bản và vài vấn đề mà mọi người thường xuyên gặp phải.

Chương trình quilt cung cấp phương pháp cơ bản để ghi lại các sửa đổi đối với mã nguồn thượng nguồn cho gói Debian. Rất hữu ích khi có một mặc định hơi tùy chỉnh, vì vậy hãy tạo một alias dquilt cho gói Debian bằng cách thêm các dòng sau vào ~/.bashrc. Dòng thứ hai là tính năng bash-completion gợi ý của của lệnh quilt vào lệnh dquilt:

alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"
complete -F _quilt_completion -o filenames dquilt

Sau đó hãy tạo tệp ~/.quiltrc-dpkg như sau:

d=. ; while [ ! -d $d/debian -a $(readlink -e $d) != / ]; do d=$d/..; done
if [ -d $d/debian ] && [ -z $QUILT_PATCHES ]; then
    # if in Debian packaging tree with unset $QUILT_PATCHES
    QUILT_PATCHES="debian/patches"
    QUILT_PATCH_OPTS="--reject-format=unified"
    QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto"
    QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index"
    QUILT_COLORS="diff_hdr=1;32:diff_add=1;34:diff_rem=1;31:diff_hunk=1;33:diff_ctx=35:diff_cctx=33"
    if ! [ -d $d/debian/patches ]; then mkdir $d/debian/patches; fi
fi

Xem quilt(1)/usr/share/doc/quilt/quilt.pdf.gz để biết cách sử dụng quilt.

Hãy giả sử bạn đã tìm thấy một lỗi trong thượng nguồn Makefile như sau, dòng install: gentoo nên được sửa lại thành install: gentoo-target.

install: gentoo
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Hãy sửa và ghi lại nó bằng lệnh dquilt với bản vá mới là fix-gentoo-target.patch: [22]

$ mkdir debian/patches
$ dquilt new fix-gentoo-target.patch
$ dquilt add Makefile

Bạn thay đổi tệp tin Makefile như sau

install: gentoo-target
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Lệnh dquilt sẽ tạo ra bản vá debian/patches/fix-gentoo-target.patch và thêm mô tả của nó như sau DEP-3: Patch Tagging Guidelines:

$ dquilt refresh
$ dquilt header -e
... mô tả bản vá

Hầu hết các phần mềm của bên thứ ba cài đặt chính nó vào hệ thống phân cấp thư mục /usr/local. Với Debian, người quản trị hệ thống nên dành riêng cho việc sử dụng cá nhân, vì vậy các gói không được sử dụng các thư mục như /usr/local/bin nhưng nên sử dụng thư mục hệ thống như /usr/bin, tuân theo Tiêu chuẩn Phân cấp Hệ thống Tập tin(Filesystem Hierarchy Standard) (FHS).

Thông thường, make(1) được sử dụng để tự động xây dựng chương trình và thực hiện make install để cài đặt các chương trình trực tiếp tới đích mong muốn (sau phần install là target trong Makefile). Để Debian tạo ra các gói trước khi cài đặt, nó sẽ sửa đổi hệ thống xây dựng để cài đặt các chương trình vào cây thư mục giả định dưới một thư mục tạm thay vì một đích thực.

Hai khác biệt giữa cài đặt chương trình bình thường và hệ thống đóng gói Debian có thể được hiểu rõ bởi gói debhelperqua lệnh dh_auto_configuredh_auto_install nếu đáp ứng các điều kiện sau:

  • Tệp Makefile phải tuân theo các quy ước GNU và hỗ trợ biến $(DESTDIR) . [23]

  • Mã nguồn phải tuân theo Filesystem Hierarchy Standard (FHS)

Các chương trình sử dụng GNU autoconf tuân theo các quy ước của GNU một cách tự động, do đó chúng rất dễ đóng gói. Trên cơ sở điều này cùng các phương pháp chẩn đoán khác, người ta ước tính rằng debhelper sẽ hoạt động với khoảng 90% gói mà không làm thay đổi gì đối hệ thống xây dựng của thượng nguồn. Vì vậy, việc đóng gói không phải là phức tạp như bạn thấy

Nếu bạn cần thực hiện thay đổi tệp Makefile, bạn nên cẩn thận hỗ trợ biến $(DESTDIR). Mặc dù nó bị bỏ bởi mặc định, biến $(DESTDIR) được thêm vào cho mỗi đường dẫn tập tin dể cài đặt chương trình. Kịch bản đóng gói sẽ đặt $(DESTDIR) là thư mục tạm thời.

Đối với một gói nguồn tạo ra một gói nhị phân duy nhất, thư mục tạm thời được sử dụng bởi lệnh dh_auto_install sẽ được cài đặt vào debian/package. [24] Tất cả mọi thứ có trong thư mục tạm thời sẽ được cài đặt trên hệ thống của người dùng khi họ cài đặt gói của bạn; Khác biệt duy nhất là dpkg sẽ cài đặt các tập tin vào đường dẫn liên quan đến thư mục gốc thay vì thư mục làm việc của bạn.

Lưu ý rằng ngay cả khi chương trình của bạn cài đặt trong debian/package, nó vẫn cần phải hoạt động chính xác khi cài đặt từ tệp .deb vào thư mục gốc. Vì vâỵ bạn không được tạo hệ thống xây dựng cài đặt vào như đường dẫn tuyệt đối như /home/me/deb/package-version/usr/share/package ở các tệp tin trong gói.

Đây là một phần tệp tin Makefile của gentoo[25]:

# Where to put executable commands on 'make install'?
BIN     = /usr/local/bin
# Where to put icons on 'make install'?
ICONS   = /usr/local/share/gentoo

Chúng ta thấy rằng các tệp được cài đặt vào /usr/local. Như đã giải thích ở trên, cây thư mục đó được dành riêng cho việc sử dụng cục bộ trên Debian, do đó cần thay đổi những đường dẫn đó như sau:

# Where to put executable commands on 'make install'?
BIN     = $(DESTDIR)/usr/bin
# Where to put icons on 'make install'?
ICONS   = $(DESTDIR)/usr/share/gentoo

Vị trí chính xác cần được sử dụng cho các tệp nhị phân, icons, tài liệu, v.v. được xác định trong Filesystem Hierarchy Standard (FHS). Bạn nên đọc qua nó và các phần có liên quan đến gói của bạn.

Vậy, chúng ta nên cài đặt chương trình vào /usr/bin thay vì /usr/local/bin, trang hướng dẫn vào /usr/share/man/man1 thay vì /usr/local/man/man1, và vân vân. Chú ý là không có trang hướng dẫn trong Makefile của gentoo, nhưng vì Debian Policy đòi hỏi mọi chương trình phải có, chúng ta sẽ làm sau và sẽ cài đặt nó trong /usr/share/man/man1.

Một số chương trình không sử dụng biến trong Makefile để xác định các đường dẫn như vậy. Điều này có nghĩa là bạn có thể phải chỉnh sửa một số mã nguồn C để khắc phục chúng giúp sử dụng đúng vị trí. Nhưng tìm kiếm ở đâu, và chính xác những gì? Bạn có thể tìm ra điều này bằng cách thực hiện:

$ grep -nr --include='*.[c|h]' -e 'usr/local/lib' .

lệnh grep này sẽ tìm đệ quy trong cây mã nguồn và cho bạn tên tập tin và vị trí dòng chứa cụm từ usr/local/lib.

Sửa đổi các tệp và thay thế usr/local/lib bằng usr/lib. Điều này có thể thực hiện tự động như sau:

$ sed -i -e 's#usr/local/lib#usr/lib#g' \
        $(find . -type f -name '*.[c|h]')

Nếu bạn muốn xác nhận của mỗi lần thay thế thay, điều này có thể được thực hiện như sau:

$ vim '+argdo %s#usr/local/lib#usr/lib#gce|update' +q \
        $(find . -type f -name '*.[c|h]')

Tiếp theo, bạn nên tìm mục install (tìm kiếm dòng bắt đầu bằng install: thường sẽ có) và đổi tên tất cả các tham chiếu tới các thư mục khác. Được xác định ở trên cùng của Makefile.

Bản gốc ban đầu, mục install của gentoo như sau:

install: gentoo-target
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Hãy sửa lỗi thượng nguồn này và ghi lại nó bằng lệnh dquilt dưới dạng debian/patches/install.patch.

$ dquilt new install.patch
$ dquilt add Makefile

Trong trình soạn thảo của bạn, thay đổi này cho gói Debian như sau:

install: gentoo-target
        install -d $(BIN) $(ICONS) $(DESTDIR)/etc
        install ./gentoo $(BIN)
        install -m644 icons/* $(ICONS)
        install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc

Bạn sẽ nhận thấy rằng hiện có một lệnh install -d trước các lệnh khác trong quy tắc. Tệp Makefile ban đầu không có nó bởi vì thường thư mục /usr/local/bin và các thư mục khác đã tồn tại trên hệ thống mà bạn đang chạy make install. Tuy nhiên, khi chúng ta sẽ cài đặt vào một cây thư mục cá nhân mới, chúng ta sẽ phải tạo ra một trong những thư mục đó.

Chúng ta cũng có thể thêm vào những thứ khác ở cuối quy tắc, như việc cài đặt các tài liệu bổ sung mà các tác giả thượng nguồn đôi khi bỏ qua:

        install -d $(DESTDIR)/usr/share/doc/gentoo/html
        cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html

Kiểm tra cẩn thận, và nếu mọi thứ đều ổn, hãy yêu cầu dquilt tạo ra bản vá vào debian/patches/install.patch và thêm mô tả cho nó:

$ dquilt refresh
$ dquilt header -e
... mô tả bản vá

Bây giờ bạn có một loạt các bản vá.

  1. Bản vá thượng nguồn: debian/patches/fix-gentoo-target.patch

  2. Bản vá việc đóng gói riêng cho Debian: debian/patches/install.patch

Bất cứ khi nào bạn thực hiện các thay đổi không phải đặc trưng cho gói Debian như debian/patches/fix-gentoo-target.patch, hãy chắc chắn gửi chúng đến người bảo trì thượng nguồn để có thể được áp dụng vào trong phiên bản kế tiếp của chương trình, sẽ là hữu ích cho mọi người khác. Đồng thời nhớ tránh tạo các bản sửa lỗi cụ thể cứng nhắc cho Debian hoặc Linux — hoặc thậm chí là Unix! Hãy làm cho chúng di động. Điều này sẽ làm cho các bản sửa lỗi của bạn dễ dàng hơn để áp dụng.

Nhớ rằng bạn không phải gửi toàn bộ tệp debian/* tới thượng nguồn.

Có một vấn đề phổ biến khác: các thư viện thường khác nhau từ nền tảng này đến nền tảng khác. Ví dụ, một tệp Makefile có thể chứa một tham chiếu đến thư viện không tồn tại trên hệ thống Debian. Trong trường hợp đó, chúng ta cần thay đổi nó thành một thư viện tồn tại trong Debian nhưng phục vụ cùng một mục đích.

Hãy giả sử một dòng trong Makefile của chương trình của bạn (hoặc Makefile.in) như sau.

LIBS = -lfoo -lbar

Nếu chương trình không biên dịch được khi thư viện foo không tồn tại và nó tương đương với thư viện foo2 được cung cấp trên hệ thống Debian , bạn có thể sửa vấn đề này với debian/patches/foo2.patch bằng cách thay đổi từ foo sang foo2:[26]

$ dquilt new foo2.patch
$ dquilt add Makefile
$ sed -i -e 's/-lfoo/-lfoo2/g' Makefile
$ dquilt refresh
$ dquilt header -e
... mô tả bản vá


[22] Thư mục debian/patches sẽ tồn tại nếu bạn đã chạy dh_make như đã mô tả trước. Thao tác ví dụ này cũng tạo ra nhưng chỉ trong trường hợp bạn đang cập nhật một gói hiện có.

[24] Với một gói mã nguồn tạo ra nhiều gói nhị phân, lệnh dh_auto_install sử dụng thư mục debian/tmp như là thư mục tạm thời trong khi lệnh dh_install sẽ tạo ra các kịch bản debian/package-1.installdebian/package-2.install sẽ chia nội dung của debian/tmp vào thư mục tạm thời là debian/package-1debian/package-2, để tạo gói nhị phân package-1_*.debpackage-2_*.deb.

[25] Đây chỉ là một ví dụ để xem Makefile trông như thế nào. Nếu Makefile được tạo bởi lệnh ./configure, cách chính xác để sửa lỗi trên Makefile là thực thi ./configure từ lệnh dh_auto_configure với các tùy chọn mặc định bao gồm --prefix =/usr .

[26] Nếu có sự thay đổi API từ thư viện foo sang thư viện foo2, yêu cầu thay đổi mã nguồn để khớp với API mới.