How Linux Works Chương 16 · Introduction to Compiling Software from C Source Code

Chương 16 · Biên dịch phần mềm từ mã nguồn C Chapter 16 · Introduction to Compiling Software from C Source Code

Bốn bước, một script, và quyền tự quyết về phần mềm trên máy bạn Tự nấu phần mềm từ “nguyên liệu” thay vì mua đồ hộp Four steps, one script, and the right to decide what runs on your machine

Phần lớn phần mềm Unix phi độc quyền của bên thứ ba đến tay bạn dưới dạng mã nguồn để bạn tự dựng và cài, và Brian Ward đưa ra hai lý do. Thứ nhất, Unix — và cả Linux — có quá nhiều biến thể và kiến trúc, nên phát hành gói nhị phân cho mọi tổ hợp nền tảng là việc rất khó. Thứ hai, quan trọng ít nhất là ngang thế: việc phân phối mã nguồn rộng khắp trong cộng đồng Unix khuyến khích người dùng đóng góp bản vá lỗi và tính năng mới, và chính điều đó mới làm cho cụm từ open source có ý nghĩa.1

Có hai cách để có phần mềm: lấy sẵn bản đã nấu chín, hoặc lấy “công thức và nguyên liệu” rồi tự nấu. Trên Linux, “nguyên liệu” đó gọi là mã nguồn. Người ta phát mã nguồn vì máy tính có quá nhiều loại khác nhau, và vì khi ai cũng xem được công thức thì ai cũng có thể sửa chỗ sai. Nhớ nhé: mã nguồn là công thức, bạn tự nấu được món của mình.

Most nonproprietary third-party Unix software packages arrive as source code that you build and install yourself, and Brian Ward gives two reasons. First, Unix — and Linux itself — has so many flavors and architectures that distributing binary packages for every possible platform combination would be difficult. Second, and at least as important: widespread source code distribution throughout the Unix community encourages users to contribute bug fixes and new features, which is what gives the term open source its meaning.1

Ward nói thẳng một điều mà nhiều hướng dẫn trên mạng né tránh: bạn có thể lấy gần như mọi thứ trên hệ thống Linux dưới dạng mã nguồn — từ nhân và thư viện C cho tới trình duyệt web — và thậm chí có thể cập nhật toàn bộ hệ thống bằng cách cài lại từ mã nguồn, nhưng bạn có lẽ không nên làm thế, trừ phi bạn thật sự thích quá trình đó hoặc có lý do riêng.1 Các bản phân phối vốn đã có cách dễ dàng để cập nhật phần lõi như các chương trình trong /bin, và một tính chất đặc biệt quan trọng của bản phân phối là chúng thường vá lỗi bảo mật rất nhanh.1 Chương này vì vậy không phải lời kêu gọi “tự biên dịch tất cả”, mà là bộ kỹ năng cho những lần bạn cần tự biên dịch.

Luận đề của chương: cài một gói từ mã nguồn C thường chỉ gồm bốn bước — giải nén kho lưu trữ, cấu hình gói, chạy make để dựng chương trình, rồi chạy make install — và việc học một hệ thống dựng duy nhất, các script cấu hình sinh ra từ bộ công cụ GNU autotools, là đủ để bạn chuyển kiến thức sang những hệ thống dựng khác, vì tất cả đều đặt trên nền make.1

Ý chính: tự cài phần mềm từ mã nguồn chỉ có bốn bước: mở gói ra, chỉnh cấu hình, dựng, rồi cài. Học kỹ một bộ công cụ là bạn dùng được các bộ khác. Nhớ nhé: mở gói — cấu hình — dựng — cài.

The chapter's thesis: installing a package from C source code usually involves just four steps — unpack the source archive, configure the package, run make to build the programs, then run make install — and learning one build system, the configuration scripts generated from the GNU autotools suite, is enough to transfer your knowledge to others, because they all sit on top of make.1

Cụm khái niệm 01 Concept cluster 01

Vì sao tự cài, và cách mở một gói mã nguồn cho an toàn Khi nào nên tự cài, và mở gói thế nào Why install it yourself, and how to open a source package safely

Ward không bảo bạn đừng dùng bản phân phối — ông bảo đừng trông đợi bản phân phối lo mọi thứ cho bạn. Ông liệt kê bốn lý do khiến bạn muốn tự cài một số gói: để kiểm soát các tuỳ chọn cấu hình; để cài phần mềm ở bất cứ đâu bạn thích, thậm chí cài nhiều phiên bản khác nhau của cùng một gói; để kiểm soát phiên bản mình chạy, vì bản phân phối không phải lúc nào cũng theo kịp bản mới nhất, đặc biệt với các phần bổ trợ như thư viện Python; và để hiểu rõ hơn một gói vận hành ra sao.1

Máy Linux đã có sẵn “cửa hàng” phần mềm của nó, và cửa hàng đó rất tiện. Nhưng có lúc bạn muốn món hơi khác: bản mới hơn, hoặc có thêm tuỳ chọn, hoặc bạn chỉ muốn nhìn xem nó được làm ra thế nào. Khi đó bạn tự nấu. Nhớ nhé: tự cài khi bạn cần khác đi, chứ không phải để cho oai.

Ward is not telling you to avoid your distribution — he is telling you not to expect it to provide everything. He lists four reasons you might install certain packages yourself: to control configuration options; to install the software anywhere you like, even several different versions of the same package; to control the version you install, since distributions don't always stay up to date with the latest versions, particularly add-ons such as Python libraries; and to better understand how a package works.1

Trước khi bước vào chương này. Ward đặt một chú ý rõ ràng: bạn nên nắm những điều cơ bản ở Chương 15 trước khi tiếp tục chương 16 — nghĩa là phân biệt được lỗi trình biên dịch, cảnh báo trình biên dịch, lỗi trình liên kết và vấn đề thư viện dùng chung.1 Và ở thời điểm bắt đầu thực hành, bạn phải có sẵn mọi công cụ dựng cần thiết trên máy: với Debian và Ubuntu, cách dễ nhất là cài gói build-essential; với các hệ kiểu Fedora, dùng groupinstall nhóm “Development Tools”.1

Định nghĩa. Một hệ thống dựng (build system) là bộ công cụ riêng của một môi trường lập trình dùng để dựng và cài các gói, nằm bên cạnh những công cụ mà bản phân phối cung cấp. Linux có nhiều môi trường lập trình — từ C truyền thống tới các ngôn ngữ script thông dịch như Python — và mỗi môi trường thường có ít nhất một hệ thống như vậy.1

Nói đơn giản. Hệ thống dựng là bộ “dụng cụ bếp” đi kèm công thức: nó biết phải nấu theo thứ tự nào. Mỗi loại bếp có bộ dụng cụ riêng. Nhớ nhé: công thức đi kèm dụng cụ, học một bộ là quen dần các bộ khác.

Definition. A build system is a programming environment's own set of tools for building and installing packages, alongside the ones your Linux distribution provides. Linux hosts many programming environments — from traditional C to interpreted scripting languages such as Python — and each typically has at least one such system.1

1. tar xzf package-1.23.tar.gz
2. ./configure
3. make
4. make install

1. mở gói
2. cấu hình
3. dựng
4. cài

1. tar xzf package-1.23.tar.gz
2. ./configure
3. make
4. make install

  1. tar tvf

    Xem mục lục trước khi giải nén — thói quen nhỏ, hậu quả lớn Ngó vào gói trước khi mở List before you extract — a small habit with large consequences

    Bản phân phối mã nguồn của một gói thường đến dưới dạng tệp .tar.gz, .tar.bz2 hoặc .tar.xz. Trước khi giải nén, Ward yêu cầu bạn kiểm tra nội dung kho lưu trữ bằng tar tvf hoặc tar ztvf, bởi một số gói không tự tạo thư mục con trong thư mục nơi bạn giải nén.1 Kết xuất kiểu package-1.23/Makefile.in, package-1.23/README, package-1.23/main.c — tức mọi thứ nằm dưới một thư mục chung — là dấu hiệu gói có lẽ mở được an toàn.1

    Trước khi mở một gói nén, hãy liệt kê xem bên trong có gì. Nếu mọi thứ nằm gọn trong một thư mục thì tốt. Nếu không, mở ra sẽ vãi tung toé khắp nơi. Nhớ nhé: ngó trước, mở sau.

    A package's source distribution usually arrives as a .tar.gz, .tar.bz2 or .tar.xz file. Before unpacking, Ward wants you to verify the archive's contents with tar tvf or tar ztvf, because some packages don't create their own subdirectory in the directory where you extract them.1 Output like package-1.23/Makefile.in, package-1.23/README, package-1.23/main.c — everything under one common directory — means the package is probably okay to unpack.1

    Bạn gặp nó ở đâuWhere you meet it Nếu mục lục hiện ra Makefile, README, main.c mà không có thư mục chung, hãy tạo một thư mục mới và cd vào đó trước khi giải nén.1 Khi gói không có thư mục riêng — thì bạn tự tạo một thư mục rồi mới mở. If the listing shows Makefile, README, main.c with no common directory, create a new directory and cd there before extracting.1

    Đường dẫn tuyệt đối là cờ đỏ

    Ward cảnh báo phải dè chừng những gói chứa tệp có đường dẫn tuyệt đối, ví dụ /etc/passwd hay /etc/inetd.conf. Ông viết rằng bạn có lẽ sẽ không gặp thứ như vậy, nhưng nếu gặp thì hãy gỡ kho lưu trữ đó khỏi hệ thống: nó nhiều khả năng chứa ngựa thành Troy hoặc mã độc khác.1 Đây chính là lý do kỹ thuật cho thói quen liệt kê trước: tar tự nó chỉ làm theo những gì kho lưu trữ nói.2

    Đọc README trước, luôn luôn

    Sau khi giải nén, Ward khuyên hãy tìm những tệp tên đại loại README và INSTALL. Luôn xem README trước vì nó thường chứa mô tả gói, một cuốn hướng dẫn ngắn, các gợi ý cài đặt và thông tin hữu ích khác; nhiều gói cũng kèm tệp INSTALL với hướng dẫn biên dịch và cài đặt. Hãy đặc biệt chú ý tới các tuỳ chọn và định nghĩa đặc biệt của trình biên dịch.1

  2. package layout

    Ba nhóm tệp trong một gói mã nguồn Trong gói có những loại tệp nào The three families of files inside a source package

    Ngoài README và INSTALL, Ward xếp các tệp còn lại vào ba nhóm. Một: tệp liên quan tới hệ thống make — Makefile, Makefile.in, configure, CMakeLists.txt; vài gói rất cũ đi kèm một Makefile mà bạn có thể phải tự sửa, nhưng phần lớn dùng một tiện ích cấu hình như GNU autoconf hay CMake, kèm script hoặc tệp cấu hình để sinh Makefile từ Makefile.in dựa trên thiết lập hệ thống của bạn.1 Hai: tệp mã nguồn kết thúc bằng .c, .h hoặc .cc; tệp C có thể nằm gần như bất cứ đâu trong thư mục gói, còn tệp C++ thường mang đuôi .cc, .C hoặc .cxx.1 Ba: tệp đối tượng đuôi .o hoặc tệp nhị phân.1

    Trong gói có ba loại tệp: loại chỉ cách dựng (Makefile, configure), loại là mã nguồn thật (.c, .h), và loại đã dựng sẵn (.o). Loại thứ ba bình thường không nên có. Nhớ nhé: công thức, nguyên liệu, và đồ đã nấu sẵn — loại thứ ba là đáng ngờ.

    Beyond README and INSTALL, Ward sorts the remaining files into three categories. One: files relating to the make system — Makefile, Makefile.in, configure, CMakeLists.txt; some very old packages ship a Makefile you might need to modify, but most use a configuration utility such as GNU autoconf or CMake, with a script or configuration file that generates Makefile from Makefile.in based on your system settings.1 Two: source files ending in .c, .h or .cc; C files may appear just about anywhere in a package directory, while C++ files usually carry .cc, .C or .cxx suffixes.1 Three: object files ending in .o, or binaries.1

    Bạn gặp nó ở đâuWhere you meet it Thấy tệp .o trong một bản phân phối mã nguồn thì trong phần lớn trường hợp nghĩa là gói được đóng gói không tốt — hãy chạy make clean để chắc chắn bạn có một lần biên dịch mới hoàn toàn.1 Thấy đồ nấu sẵn lẫn trong nguyên liệu thì bỏ đi, nấu lại từ đầu. Object files in a source distribution mostly mean the package wasn't put together well — run make clean to make sure you get a fresh compile.1

    Ngoại lệ hiếm cho tệp .o

    Ward ghi chú rằng bình thường không có tệp đối tượng nào trong bản phân phối mã nguồn, nhưng trong vài trường hợp hiếm bạn có thể gặp — khi người bảo trì gói không được phép phát hành một phần mã nguồn nào đó và bạn phải làm điều gì đó đặc biệt để dùng được các tệp đối tượng ấy.1

    Vì sao cần Makefile.in

    Các tệp .in là khuôn mẫu; ý tưởng là chạy script configure để phát hiện đặc tính hệ thống của bạn, rồi thay thế vào các tệp .in để tạo ra tệp dựng thật.1 Tài liệu Autoconf mô tả đúng cơ chế đó: configure đoán giá trị đúng cho các biến phụ thuộc hệ thống và dùng chúng để tạo một Makefile trong mỗi thư mục của gói.3

  3. portability

    Vì sao không thể có một Makefile duy nhất Vì sao mỗi máy cần một bản hướng dẫn riêng Why one Makefile can never be enough

    Mã nguồn C nhìn chung khá khả chuyển, nhưng Ward chỉ ra rằng khác biệt giữa các nền tảng khiến việc biên dịch phần lớn gói bằng một Makefile duy nhất là bất khả thi. Các giải pháp thời kỳ đầu là cung cấp Makefile riêng cho từng hệ điều hành, hoặc một Makefile dễ sửa. Cách tiếp cận ấy tiến hoá thành các script sinh ra Makefile dựa trên phân tích chính hệ thống dùng để dựng gói.1

    Mỗi máy một khác: chỗ để thư viện khác nhau, tên công cụ khác nhau. Một bản hướng dẫn chung không dùng được cho mọi máy. Thế nên người ta viết một script tự dò máy rồi viết bản hướng dẫn riêng. Nhớ nhé: máy nào cũng khác nhau một chút, nên phải dò rồi mới dựng.

    C source code is usually fairly portable, but Ward points out that differences on each platform make it impossible to compile most packages with a single Makefile. Early solutions provided individual Makefiles per operating system, or one Makefile that was easy to modify. That approach evolved into scripts that generate Makefiles based on an analysis of the system used to build the package.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi dòng checking for… mà configure in ra chính là một lần kiểm tra khác biệt nền tảng đang diễn ra trước mắt bạn.3 Những dòng “checking…” chạy vèo vèo chính là lúc máy đang tự dò. Every checking for… line configure prints is one platform difference being tested in front of you.3

    Vì sao Ward chọn autotools cho chương này

    Ward xem xét biên dịch và cài đặt mã nguồn C với chỉ một trong số các hệ thống dựng: các script cấu hình sinh ra từ bộ GNU autotools. Lý do ông đưa ra: hệ thống này nhìn chung được coi là ổn định, nhiều tiện ích Linux cơ bản dùng nó, và vì nó đặt trên nền các công cụ sẵn có như make, sau khi thấy nó hoạt động bạn sẽ chuyển được kiến thức sang các hệ thống dựng khác.1

    Điều Autoconf hứa với người dùng cuối

    Tài liệu Autoconf nói rõ điều làm nên giá trị của cách tiếp cận này: các script cấu hình do Autoconf sinh ra độc lập với Autoconf khi chạy, nên người dùng không cần cài Autoconf; và chúng không cần sự can thiệp thủ công, thường cũng không cần tham số chỉ định loại hệ thống, mà tự kiểm tra sự hiện diện của từng tính năng.4

Cụm khái niệm 02 Concept cluster 02

GNU autoconf: một script dò máy, rồi viết Makefile cho bạn Script configure: máy tự dò rồi tự viết hướng dẫn GNU autoconf: a script that inspects your machine, then writes the Makefile

GNU autoconf là một hệ thống phổ biến để sinh Makefile tự động. Gói dùng hệ thống này đi kèm các tệp tên configure, Makefile.in và config.h.in. Các tệp .in là khuôn mẫu; ý tưởng là chạy script configure để khám phá đặc tính hệ thống của bạn, rồi thay thế vào các tệp .in để tạo ra tệp dựng thật.1 Với người dùng cuối thì việc này rất dễ: để sinh Makefile từ Makefile.in, chỉ cần chạy ./configure.1

Có một script tên là configure. Bạn chạy nó, nó tự đi xem máy bạn có gì — có trình biên dịch không, thư viện nằm ở đâu — rồi nó viết ra bản hướng dẫn dựng hợp với máy bạn. Bạn chỉ cần gõ đúng một dòng. Nhớ nhé: gõ ./configure, rồi để máy tự lo phần dò.

GNU autoconf is a popular system for automatic Makefile generation. Packages using it come with files named configure, Makefile.in and config.h.in. The .in files are templates; the idea is to run the configure script to discover the characteristics of your system, then make substitutions in the .in files to create the real build files.1 For the end user it's easy: to generate a Makefile from Makefile.in, run ./configure.1

Điều configure để lại sau lưng. Nếu mọi việc trôi chảy, Ward mô tả rằng configure tạo ra một hoặc nhiều Makefile và một tệp config.h, cùng một tệp đệm config.cache để khỏi phải chạy lại một số kiểm tra.1 Tài liệu Autoconf bổ sung một chi tiết đáng lưu ý: tệp đệm — thường tên config.cache, bật bằng --cache-file=config.cache hoặc gọn hơn là -C — mặc định bị tắt ở các phiên bản Autoconf hiện đại, chính để tránh những rắc rối do vô tình dùng lại tệp đệm cũ.3 Trang này giữ cách mô tả của sách trong phần thân và ghi chú khác biệt ở đây thay vì lặng lẽ chọn một bên.

Chuỗi lệnh chuẩn. Tài liệu Autoconf tóm gọn toàn bộ quy trình vào ba dòng cho người dựng từ bản phát hành: ./configure, make, make install. Trong đó make check là bước tuỳ chọn chạy các bài tự kiểm tra bằng chính các tệp nhị phân vừa dựng mà chưa cài.3

Nói đơn giản. Ba dòng lệnh thôi: cấu hình, dựng, cài. Giữa chừng có thể thử make check để xem món có ổn không trước khi dọn lên bàn. Nhớ nhé: configure — make — make install.

The standard sequence. The Autoconf manual compresses the whole procedure into three lines for someone building from a distribution tarball: ./configure, make, make install. make check is the optional step in between, running any self-tests with the just-built, not-yet-installed binaries.3

configure.ac → autoconf → configure
configure + Makefile.in → Makefile
configure + config.h.in → config.h
configure → config.status, config.log

khuôn mẫu + máy của bạn
  → bản hướng dẫn riêng
  → nhật ký để tra khi hỏng

configure.ac → autoconf → configure
configure + Makefile.in → Makefile
configure + config.h.in → config.h
configure → config.status, config.log

  1. --prefix

    --prefix — tuỳ chọn hữu ích nhất của configure --prefix — chọn chỗ để cài --prefix — the most useful configure option

    Ward gọi --prefix là một trong những tuỳ chọn hữu ích nhất: nó chỉ định thư mục cài đặt. Mặc định, đích install của một Makefile do autoconf sinh ra dùng tiền tố /usr/local — nghĩa là chương trình nhị phân vào /usr/local/bin, thư viện vào /usr/local/lib, và cứ thế.1 Bạn sẽ thường muốn đổi tiền tố ấy bằng ./configure --prefix=new_prefix.1

    Mặc định, phần mềm bạn tự dựng sẽ được cài vào /usr/local. Nhưng bạn có thể bảo nó cài vào bất kỳ đâu — kể cả một thư mục trong nhà bạn. Như thế gỡ đi cũng dễ. Nhớ nhé: --prefix là chỗ bạn chọn nơi cài.

    Ward calls --prefix one of the most useful options: it specifies the installation directory. By default the install target of an autoconf-generated Makefile uses a prefix of /usr/local — binaries go in /usr/local/bin, libraries in /usr/local/lib, and so on.1 You will often want to change that with ./configure --prefix=new_prefix.1

    Bạn gặp nó ở đâuWhere you meet it Trong ví dụ thực hành của Ward, ./configure --prefix=$HOME/mycoreutils đặt toàn bộ gói GNU coreutils vào thư mục nhà, để bạn không làm hỏng hệ thống.1 Ví dụ trong sách: cài vào thư mục riêng trong nhà bạn, xong xoá đi cũng chẳng sao. In Ward's hands-on example, ./configure --prefix=$HOME/mycoreutils puts the whole GNU coreutils package in your home directory, so you can't mess up your system.1

    Tiền tố này là một quy ước của GNU, không phải của autoconf

    GNU Coding Standards quy định rằng giá trị mặc định của prefix phải là /usr/local, và mọi thư mục cài đặt khác đều là thư mục con của prefix hoặc exec_prefix, chứ không có gì được cài thẳng vào hai thư mục gốc ấy.5 exec_prefix mặc định bằng $(prefix) và dành cho những thư mục chứa tệp phụ thuộc kiến trúc máy — chương trình thực thi và thư viện — trong khi $(prefix) dùng trực tiếp cho các thư mục còn lại.5

    Đổi tiền tố không nên bắt biên dịch lại

    Cũng trong tài liệu đó có một câu đáng nhớ khi bạn nghi ngờ một gói cư xử lạ: chạy make install với giá trị prefix khác với giá trị lúc dựng không nên biên dịch lại chương trình.5 Tài liệu Autoconf nói thêm rằng cách khả chuyển nhất vẫn là truyền đúng vị trí cho configure; các cách ghi đè lúc make install chỉ là lối tắt và có nền tảng gặp hạn chế với ngữ nghĩa thư viện dùng chung.6

  2. configure options

    Những tuỳ chọn thiết yếu khác — khi --help quá dài để đọc Vài tuỳ chọn đáng nhớ The other essential options — when --help is too long to read

    Phần lớn phiên bản configure có tuỳ chọn --help liệt kê các lựa chọn cấu hình khác. Ward nhận xét thẳng: đáng tiếc là danh sách ấy thường dài tới mức khó biết cái nào quan trọng. Ông chắt ra một nhóm thiết yếu: --bindir=directory cài tệp thực thi vào directory; --sbindir=directory cài tệp thực thi hệ thống; --libdir=directory cài thư viện; --disable-shared ngăn gói dựng thư viện dùng chung, điều mà tuỳ thư viện có thể tránh được phiền phức về sau; và --with-package=directory cho configure biết package nằm ở directory, rất tiện khi một thư viện cần thiết nằm ở vị trí phi tiêu chuẩn.1

    Có vài công tắc hay dùng: chọn chỗ để chương trình, chọn chỗ để thư viện, và bảo nó “thư viện tôi cần nằm ở đây này”. Danh sách đầy đủ thì rất dài, nên chỉ cần nhớ mấy cái hay dùng. Nhớ nhé: --prefix là chính, còn lại là chỉnh lặt vặt.

    Most versions of configure have a --help option listing other configuration options. Ward is blunt: the list is usually so long that it's hard to work out what might be important. He distils an essential set: --bindir=directory installs executables there; --sbindir=directory installs system executables; --libdir=directory installs libraries; --disable-shared prevents the package from building shared libraries, which depending on the library can save hassles later; and --with-package=directory tells configure that package is in directory, handy when a needed library sits in a nonstandard location.1

    Bạn gặp nó ở đâuWhere you meet it Ward cảnh báo rằng không phải mọi script configure đều nhận dạng tuỳ chọn --with-…, và có thể khó xác định cú pháp chính xác.1 Không phải gói nào cũng hiểu mọi công tắc — nên đọc --help của chính gói đó. Ward warns that not all configure scripts recognise the --with-… form, and the exact syntax can be hard to determine.1

    Các biến thư mục chuẩn, theo nguồn gốc của chúng

    Những tuỳ chọn --bindir, --sbindir, --libdir ánh xạ một-một vào các biến thư mục của GNU Coding Standards: bindir là $(exec_prefix)/bin cho chương trình người dùng chạy được; sbindir là $(exec_prefix)/sbin cho chương trình chỉ hữu ích với quản trị viên; libexecdir là $(exec_prefix)/libexec cho chương trình được chương trình khác gọi chứ không phải người dùng gọi; datarootdir là $(prefix)/share; sysconfdir là $(prefix)/etc; còn localstatedir là $(prefix)/var cho dữ liệu chương trình sửa đổi trong lúc chạy.5

    Vì sao mặc định được viết theo ${prefix}

    Tài liệu Autoconf giải thích: mặc định của các tuỳ chọn thư mục nhìn chung được biểu đạt theo ${prefix}, nên chỉ cần chỉ định --prefix là ảnh hưởng tới mọi thư mục khác chưa được nêu tường minh.6 Đó là lý do một dòng --prefix duy nhất đủ để di dời cả gói.

  3. CPPFLAGS / CFLAGS / LDFLAGS

    Biến môi trường — nơi configure rất khó tính Ba biến hay dùng, và một dấu gạch dễ quên Environment variables — where configure is very picky

    Bạn có thể tác động tới configure bằng các biến môi trường mà nó đưa vào biến của make. Ward nêu ba biến quan trọng nhất: CPPFLAGS, CFLAGS và LDFLAGS — nhưng cảnh báo rằng configure có thể rất khó tính với biến môi trường. Ví dụ, bạn thường nên dùng CPPFLAGS thay vì CFLAGS cho thư mục tệp tiêu đề, vì configure hay chạy bộ tiền xử lý độc lập với trình biên dịch.1

    Ba cái “hộp” bạn có thể nhét chỉ dẫn vào: một cho chỗ tìm tệp tiêu đề, một cho trình biên dịch, một cho bước nối các mảnh lại. Chọn nhầm hộp là hỏng. Nhớ nhé: tìm tệp .h thì dùng CPPFLAGS, đừng dùng CFLAGS.

    You can influence configure with environment variables that it feeds into make variables. Ward names the three most important: CPPFLAGS, CFLAGS and LDFLAGS — but warns that configure can be very picky about them. For instance, you should normally use CPPFLAGS rather than CFLAGS for header file directories, because configure often runs the preprocessor independently of the compiler.1

    Bạn gặp nó ở đâuWhere you meet it Trong bash, cách dễ nhất là đặt phép gán ngay trước ./configure: CPPFLAGS=-DDEBUG ./configure. Bạn cũng có thể truyền biến như một tuỳ chọn: ./configure CPPFLAGS=-DDEBUG.1 Gõ biến ngay trước lệnh, hoặc gõ nó như một tham số phía sau — cả hai đều được. In bash the easiest way is to put the assignment in front of ./configure: CPPFLAGS=-DDEBUG ./configure. You can also pass a variable as an option: ./configure CPPFLAGS=-DDEBUG.1

    Tìm tệp tiêu đề và thư viện ở nơi phi tiêu chuẩn

    Ward cho hai công thức cụ thể: để bộ tiền xử lý tìm trong include_dir, chạy CPPFLAGS=-Iinclude_dir ./configure; để trình liên kết tìm trong lib_dir, chạy LDFLAGS=-Llib_dir ./configure.1 Nếu lib_dir chứa thư viện dùng chung, lệnh trên có lẽ không đặt đường dẫn cho trình liên kết động lúc chạy; khi đó dùng thêm tuỳ chọn -rpath: LDFLAGS="-Llib_dir -Wl,-rpath=lib_dir" ./configure.17

    Một dấu gạch thiếu, một lỗi khó hiểu

    Ward dựng sẵn cái bẫy: quên dấu - trong -I, tức gõ CPPFLAGS=Iinclude_dir ./configure, sẽ sinh ra lỗi configure: error: C compiler cannot create executables kèm dòng See 'config.log' for more details.1 Đào vào config.log mới thấy nguyên nhân thật: gcc: error: Iinclude_dir: No such file or directory.1 Thông điệp lớn hơn: lỗi mà configure in ra thường không phải lỗi thật.

    Vì sao nên truyền biến trên dòng lệnh

    Tài liệu Autoconf đưa một lý do kỹ thuật cho lối viết ./configure VAR=value: một số gói có thể chạy lại configure trong lúc dựng, và khi đó giá trị tuỳ chỉnh đặt trong môi trường có thể bị mất; đặt biến ngay trên dòng lệnh configure tránh được vấn đề này.8

  4. make targets

    Bốn đích make mà autoconf tặng thêm Bốn lệnh make hay dùng The four extra make targets autoconf gives you

    Khi configure đã chạy được, Ward chỉ ra rằng Makefile nó sinh ra có một số đích hữu ích ngoài all và install tiêu chuẩn. make clean xoá mọi tệp đối tượng, tệp thực thi và thư viện. make distclean giống clean nhưng xoá mọi tệp được sinh tự động, gồm cả các Makefile, config.h, config.log — ý tưởng là sau khi chạy, cây mã nguồn trông như một bản phân phối vừa mới giải nén. make check chạy bộ bài kiểm tra mà một số gói kèm theo. Và make install-strip giống install nhưng lược bỏ bảng ký hiệu cùng thông tin gỡ lỗi khỏi tệp thực thi và thư viện khi cài; tệp nhị phân đã lược bỏ chiếm ít không gian hơn nhiều.1

    Ngoài “dựng” và “cài”, còn bốn lệnh nữa: dọn dẹp, dọn sạch về như lúc mới mở gói, chạy thử, và cài bản gọn nhẹ. Nhớ nhé: clean là quét nhà, distclean là trả lại nguyên trạng.

    Once configure works, Ward points out that the generated Makefile has several useful targets beyond the standard all and install. make clean removes all object files, executables and libraries. make distclean is like clean but also removes all automatically generated files, including Makefiles, config.h and config.log — the idea being that after it runs, the source tree should look like a newly unpacked distribution. make check runs the battery of tests some packages ship. And make install-strip is like install except it strips the symbol table and other debugging information from executables and libraries when installing; stripped binaries require much less space.1

    Bạn gặp nó ở đâuWhere you meet it Khi bạn muốn cấu hình lại gói cho một hệ thống khác, make distclean là bước đưa cây mã nguồn về trạng thái sạch trước khi chạy lại configure.6 Muốn làm lại từ đầu thì gõ make distclean trước. When you want to reconfigure the package for another system, make distclean is the step that returns the source tree to a clean state before running configure again.6

    Vì sao install cố tình không lược bỏ ký hiệu

    GNU Coding Standards nêu lý do đằng sau cặp install / install-strip: đừng lược bỏ tệp thực thi khi cài, vì điều đó giúp cho việc gỡ lỗi có thể cần về sau, và ngày nay không gian đĩa rẻ trong khi bộ nạp động thường bảo đảm các phần gỡ lỗi không được nạp trong lúc chạy bình thường; người cần bản nhị phân đã lược bỏ có thể gọi đích install-strip.9 Công cụ thực hiện việc lược bỏ là strip, vốn loại bỏ ký hiệu khỏi tệp đối tượng.10

    clean và distclean theo đúng định nghĩa chuẩn

    Cùng tài liệu ấy định nghĩa: clean xoá mọi tệp trong thư mục hiện tại thường được tạo ra khi dựng chương trình, nhưng không xoá những tệp ghi lại cấu hình; còn distclean xoá mọi tệp được tạo ra bởi việc cấu hình hoặc dựng, sao cho nếu bạn chỉ giải nén và dựng thì sau make distclean chỉ còn lại những tệp vốn có trong bản phân phối.9 Đó chính là ranh giới giữa hai lệnh mà Ward mô tả.

    check: thử trước khi cài

    Định nghĩa chuẩn của check là thực hiện các bài tự kiểm tra, nếu có: người dùng phải dựng chương trình trước khi chạy kiểm tra nhưng không cần cài, và tác giả gói phải viết bài kiểm tra sao cho chúng chạy được khi chương trình đã dựng mà chưa cài.9 Đây là lý do make check nằm giữa make và make install chứ không phải sau cùng.

  5. config.log

    Đọc config.log từ dưới lên — nhưng đừng đọc ngay cuối Khi configure hỏng thì tra nhật ký ở đâu Reading config.log backwards — but not from the very end

    Nếu có gì sai trong quá trình configure mà nguyên nhân không hiển nhiên, bạn có thể xem config.log. Đáng tiếc, Ward lưu ý, config.log thường là một tệp khổng lồ, khiến việc định vị nguồn gốc chính xác của vấn đề trở nên khó.1 Cách tiếp cận chung là đi tới tận cuối tệp — chẳng hạn gõ G viết hoa trong less — rồi lật ngược lên cho tới khi thấy vấn đề.1

    Khi bước cấu hình hỏng, có một tệp nhật ký ghi lại mọi thứ. Nó rất dài. Mẹo là nhảy xuống cuối rồi tìm ngược lên, chứ không đọc từ đầu. Nhớ nhé: lỗi thật thường nằm ngay phía trên chỗ bạn tìm thấy.

    If something goes wrong during configure and the cause isn't obvious, you can examine config.log. Unfortunately, Ward notes, config.log is often a gigantic file, which makes pinpointing the exact source difficult.1 The general approach is to go to the very end of the file — for example by typing a capital G in less — and then page back up until you see the problem.1

    Bạn gặp nó ở đâuWhere you meet it Ward tinh chỉnh mẹo này: vẫn còn rất nhiều thứ ở cuối vì configure đổ toàn bộ môi trường của nó ra đó — biến kết xuất, biến đệm và các định nghĩa khác — nên thay vì lật ngược, hãy tìm ngược một chuỗi như for more details.1 Đừng lật từng trang: hãy tìm ngược một cụm chữ quen thuộc. Ward refines the trick: there's still a lot at the end because configure dumps its entire environment there — output variables, cache variables and other definitions — so rather than paging up, search backward for a string such as for more details.1

    Cú pháp tìm ngược trong less

    Ward nhắc rằng bạn khởi tạo một lần tìm ngược trong less bằng lệnh ?; và có khả năng cao lỗi sẽ nằm ngay phía trên chỗ lần tìm của bạn dừng lại.1 Trong ví dụ về dấu gạch bị thiếu, phần config.log đáng giá gồm bốn dòng đánh số dòng của chính script — configure:5037: checking whether the C compiler works cho tới configure:5101: result: no — với dòng gcc: error: nằm chính giữa.1

    config.log là gì theo tài liệu gốc

    Tài liệu Autoconf mô tả config.log đúng bằng một câu: configure tạo ra script config.status để bạn tái lập cấu hình hiện tại trong tương lai, và một tệp config.log chứa kết xuất hữu ích cho việc gỡ lỗi chính configure.3 Nói cách khác, nó không phải nhật ký của chương trình bạn dựng — nó là nhật ký của bước dò.

Cụm khái niệm 03 Concept cluster 03

Cài ở đâu, cài bằng gì, và giữ cho hệ thống khỏi thành mớ hỗn độn Cài vào chỗ nào cho gọn gàng Where to install, with what, and how to keep the system from becoming a mess

Ward đảo ngược trọng tâm ở đây: biết cách dựng và cài phần mềm là tốt, nhưng biết khi nào và ở đâu nên cài gói của riêng mình còn hữu ích hơn. Vì các bản phân phối cố nhồi càng nhiều phần mềm càng tốt lúc cài đặt, bạn nên luôn kiểm tra xem tự cài một gói có tốt hơn không.1

Biết nấu là một chuyện. Biết nên nấu món nào, và để món đó vào ngăn nào trong tủ, mới là chuyện quan trọng hơn. Nhớ nhé: cài đúng chỗ thì sau này dọn mới dễ.

Ward flips the emphasis here: knowing how to build and install software is good, but knowing when and where to install your own packages is even more useful. Because distributions try to cram in as much software as possible at installation, you should always check whether installing a package yourself would be better.1

Danh sách hai chiều của Ward. Ông không bán ý tưởng một chiều. Lợi thế của việc tự cài: bạn tuỳ biến được mặc định của gói; bạn thường hiểu rõ hơn cách dùng nó; bạn kiểm soát bản phát hành mình chạy; sao lưu một gói tự cài dễ hơn; và phân phối gói tự cài qua mạng cũng dễ hơn, miễn kiến trúc nhất quán và vị trí cài tương đối biệt lập.1 Bất lợi: nếu gói đã có sẵn trên hệ thống, bạn có thể ghi đè các tệp quan trọng và gây rắc rối — tránh điều đó bằng tiền tố /usr/local; việc này tốn thời gian; gói tuỳ chỉnh không tự nâng cấp, một mối lo đặc biệt với các gói tương tác qua mạng vì bạn muốn luôn có bản vá bảo mật mới nhất; nếu bạn không thật sự dùng gói đó thì bạn đang phí thời gian; và luôn có nguy cơ cấu hình sai.1

Định nghĩa. Tiền tố (prefix) là thư mục gốc mà toàn bộ cây cài đặt của một gói treo bên dưới. Tiền tố mặc định trong GNU autoconf và nhiều gói khác là /usr/local, thư mục truyền thống cho phần mềm cài tại chỗ; việc nâng cấp hệ điều hành bỏ qua /usr/local, nên bạn sẽ không mất thứ gì đã cài ở đó khi nâng cấp hệ điều hành.1

Nói đơn giản. Tiền tố là cái ngăn tủ bạn chọn để cất phần mềm tự cài. Ngăn tiêu chuẩn tên là /usr/local, và khi hệ điều hành nâng cấp thì nó không đụng vào ngăn này. Nhớ nhé: /usr/local là ngăn của riêng bạn.

Definition. The prefix is the root directory under which a package's entire installed tree hangs. The default prefix in GNU autoconf and many other packages is /usr/local, the traditional directory for locally installed software; operating system upgrades ignore /usr/local, so you won't lose anything installed there during an OS upgrade.1

prefix = /usr/local
  bindir  = $(exec_prefix)/bin
  libdir  = $(exec_prefix)/lib
  sysconfdir = $(prefix)/etc

ngăn gốc = /usr/local
  chương trình → bin
  thư viện → lib
  cấu hình → etc

prefix = /usr/local
  bindir  = $(exec_prefix)/bin
  libdir  = $(exec_prefix)/lib
  sysconfdir = $(prefix)/etc

  1. make -n install

    Chạy thử trước khi cài thật Diễn tập trước khi làm thật Rehearse the install before you do it

    Trong ví dụ coreutils, trước khi cài Ward yêu cầu làm một lần chạy khan bằng make -n install, để thấy make install sẽ làm gì mà không thật sự cài. Hãy duyệt qua kết xuất, và nếu không có gì lạ — chẳng hạn gói định cài vào chỗ nào khác ngoài thư mục mycoreutils của bạn — thì mới cài thật bằng make install.1

    Trước khi cài thật, bảo máy “diễn thử” đi: nó sẽ kể ra định chép những gì đi đâu, mà chưa chép gì cả. Đọc xong thấy ổn thì mới làm thật. Nhớ nhé: diễn thử một lần, đỡ hối hận một lần.

    In the coreutils example, Ward asks you to do a dry run with make -n install first, to see what make install does without actually doing it. Browse the output, and if nothing seems strange — such as the package installing anywhere other than your mycoreutils directory — then do the real install with make install.1

    Bạn gặp nó ở đâuWhere you meet it Sau khi cài, bạn sẽ có thư mục con mycoreutils trong thư mục nhà, chứa bin, share và các thư mục con khác — và vì nó độc lập với phần còn lại của hệ thống, bạn có thể xoá sạch mà không lo gây hỏng.1 Cài xong, muốn bỏ thì xoá cả thư mục đó là xong — không ảnh hưởng gì tới máy. After installing you'll have a mycoreutils subdirectory in your home directory containing bin, share and others — and because it's independent of the rest of your system, you can remove it completely without worrying about causing damage.1

    Bài tập đầy đủ của Ward

    Ví dụ thực hành trong sách là cài gói GNU coreutils vào thư mục nhà của chính bạn để chắc chắn không làm hỏng hệ thống: lấy gói từ ftp.gnu.org/gnu/coreutils/ (bản mới nhất thường là tốt nhất), giải nén, chuyển vào thư mục của nó, rồi ./configure --prefix=$HOME/mycoreutils, sau đó make.111 Tiếp đó hãy thử chạy một trong các tệp thực thi vừa tạo, chẳng hạn ./src/ls, và chạy make check để thực hiện một loạt bài kiểm tra trên gói — việc này có thể mất một lúc, nhưng thú vị.1

    Bạn vừa dựng lại chính những công cụ mình dùng

    Ward chốt bài tập bằng một nhận xét có chủ ý: hãy xem qua các chương trình trong bin, vì bạn vừa dựng nhiều công cụ cơ bản mà bạn đã học ở Chương 2.1 Ông cũng nói thẳng ở mục sau: chẳng có mấy ý nghĩa khi cài những gói như coreutils — ls, cat và tương tự — trừ phi bạn đang dựng một hệ thống rất tuỳ biến; ngược lại, nếu bạn quan tâm sống còn tới máy chủ mạng như Apache thì cách tốt nhất để kiểm soát hoàn toàn là tự cài lấy.1

  2. checkinstall

    Cài bằng công cụ đóng gói, để còn gỡ được về sau Cài kiểu có “phiếu bảo hành” Installing through a packaging tool, so you can remove it later

    Trên phần lớn bản phân phối, bạn có thể cài phần mềm mới như một gói mà sau này vẫn bảo trì được bằng công cụ đóng gói của bản phân phối. Ward nói các bản phân phối dựa trên Debian, như Ubuntu, có lẽ là dễ nhất: thay vì chạy make install trơn, bạn cài bằng tiện ích checkinstall, dạng # checkinstall make install.1

    Có một cách cài thông minh hơn: thay vì chép tệp lung tung, bạn bảo máy ghi lại danh sách mọi thứ đã chép, rồi gói danh sách đó lại. Sau này muốn gỡ, chỉ cần nói “gỡ gói này”. Nhớ nhé: cài có ghi sổ thì gỡ mới sạch.

    On most distributions you can install new software as a package that you can maintain later with your distribution's packaging tools. Ward says Debian-based distributions such as Ubuntu are perhaps the easiest: rather than running a plain make install, you install with the checkinstall utility, as # checkinstall make install.1

    Bạn gặp nó ở đâuWhere you meet it Chạy lệnh này sẽ hiện các thiết lập liên quan tới gói sắp dựng và cho bạn cơ hội thay đổi; khi bạn tiếp tục, checkinstall theo dõi mọi tệp sẽ được cài lên hệ thống và đặt chúng vào một tệp .deb — sau đó bạn dùng dpkg để cài và gỡ gói mới.112 Nó hỏi bạn vài câu, rồi tạo ra một “hộp” gói đúng chuẩn để cài và gỡ như mọi gói khác. Running it shows the settings for the package you're about to build and lets you change them; when you proceed, checkinstall tracks all the files to be installed and puts them into a .deb file — you then use dpkg to install and remove the new package.112

    Phía RPM thì rườm rà hơn

    Ward nói rõ rằng tạo một gói RPM phức tạp hơn một chút, vì trước hết bạn phải tạo một cây thư mục cho gói của mình. Việc này làm được bằng lệnh rpmdev-setuptree; xong xuôi thì dùng tiện ích rpmbuild để đi qua các bước còn lại. Ông khuyên nên theo một hướng dẫn trực tuyến cho quy trình này.113

    Khi /usr/local bắt đầu mất kiểm soát

    Ward thừa nhận nhược điểm của tiền tố truyền thống: nếu bạn cài nhiều phần mềm tuỳ chỉnh, /usr/local có thể biến thành một mớ hỗn độn khủng khiếp — hàng nghìn tệp nhỏ lạ lẫm lọt vào cây thư mục ấy, và bạn có thể chẳng biết chúng từ đâu ra.1 Lời khuyên của ông khi mọi thứ thật sự trở nên khó bảo: hãy tự tạo gói của mình, tức quay lại đúng kỹ thuật checkinstall/rpmbuild ở trên.1

  3. pkg-config

    pkg-config — hỏi thư viện xem nó cần cờ gì Hỏi thẳng thư viện xem nó ở đâu pkg-config — asking a library which flags it needs

    Có vô số thư viện bên thứ ba trên một hệ thống, nên giữ hết chúng ở một chỗ chung thì lộn xộn; nhưng cài mỗi thư viện với một tiền tố riêng lại gây rắc rối khi dựng các gói cần tới chúng. Ward nêu ví dụ cụ thể: muốn biên dịch OpenSSH thì bạn cần thư viện OpenSSL — làm sao cho quy trình cấu hình của OpenSSH biết OpenSSL nằm đâu và cần những thư viện nào?1 Nhiều thư viện nay dùng chương trình pkg-config không chỉ để quảng bá vị trí tệp tiêu đề và thư viện, mà còn để chỉ định chính xác các cờ bạn cần để biên dịch và liên kết.1

    Thư viện nằm rải rác khắp máy. Thay vì bạn phải đi tìm, có một chương trình nhỏ hỏi hộ: “thư viện này ở đâu, cần khai báo gì?” Nó trả lời gọn một dòng. Nhớ nhé: đừng đoán chỗ thư viện — hỏi pkg-config.

    The multitude of third-party libraries makes keeping them all in one common location messy, yet installing each under a separate prefix causes problems when building packages that need them. Ward's concrete example: to compile OpenSSH you need the OpenSSL library — how do you tell the OpenSSH configuration process where the OpenSSL libraries are and which ones are required?1 Many libraries now use the pkg-config program not only to advertise the locations of their include files and libraries but also to specify the exact flags you need to compile and link.1

    Bạn gặp nó ở đâuWhere you meet it Cú pháp là pkg-config options package1 package2 …; ví dụ pkg-config --libs zlib cho kết quả -lz, còn pkg-config --list-all hiện mọi thư viện mà nó biết kèm mô tả ngắn.114 Ví dụ: hỏi về thư viện nén zlib, nó trả lời đúng một chữ -lz. The syntax is pkg-config options package1 package2 …; for example pkg-config --libs zlib outputs -lz, while pkg-config --list-all shows every library it knows about with a brief description.114

    Các tệp .pc — dữ liệu đằng sau câu trả lời

    Nhìn sau hậu trường, pkg-config tìm thông tin gói bằng cách đọc các tệp cấu hình kết thúc bằng .pc. Ward trưng ra openssl.pc của thư viện OpenSSL trên một hệ Ubuntu, nằm ở /usr/lib/x86_64-linux-gnu/pkgconfig, với các dòng như prefix=/usr, libdir=${exec_prefix}/lib/x86_64-linux-gnu, Libs: -L${libdir} -lssl -lcrypto và Libs.private: -ldl -lz.1 Ông lưu ý bạn có thể sửa tệp này, chẳng hạn thêm -Wl,-rpath=${libdir} vào cờ thư viện để đặt đường dẫn tìm thư viện lúc chạy.1

    Nó tìm .pc ở đâu — và vì sao bạn thường không thấy

    Mặc định, pkg-config tìm trong thư mục lib/pkgconfig thuộc tiền tố cài đặt của chính nó: một pkg-config cài với tiền tố /usr/local sẽ tìm trong /usr/local/lib/pkgconfig.1 Ward kèm một chú ý rất thực tế: bạn sẽ không thấy tệp .pc cho nhiều gói trừ phi cài các gói phát triển — ví dụ để có openssl.pc trên Ubuntu, bạn phải cài gói libssl-dev.1

    Hai cách đưa .pc ở nơi phi tiêu chuẩn vào tầm với

    Vì mặc định pkg-config không đọc tệp .pc nào ngoài tiền tố cài đặt của nó, một tệp ở chỗ như /opt/openssl/lib/pkgconfig/openssl.pc sẽ nằm ngoài tầm với. Ward nêu hai cách: tạo liên kết tượng trưng (hoặc bản sao) từ các tệp .pc thật tới thư mục pkgconfig trung tâm; hoặc đặt biến môi trường PKG_CONFIG_PATH để bao gồm các thư mục pkgconfig phụ — nhưng ông nói thẳng rằng chiến lược thứ hai không hoạt động tốt trên phạm vi toàn hệ thống.114

  4. separate build directory

    Thư mục dựng riêng — giữ cây mã nguồn nguyên vẹn Dựng ở một chỗ khác, đừng bày bừa lên nguyên liệu A separate build directory — keeping the source tree pristine

    Nếu bạn muốn thí nghiệm với các tuỳ chọn, Ward chỉ cách tạo thư mục dựng riêng: tạo một thư mục mới ở bất cứ đâu trên hệ thống, rồi từ thư mục đó chạy script configure nằm trong thư mục mã nguồn gốc của gói. Bạn sẽ thấy configure tạo một rừng liên kết tượng trưng trong thư mục dựng mới, nơi mọi liên kết trỏ ngược về cây mã nguồn trong thư mục gói ban đầu.1

    Thay vì nấu ngay trên đống nguyên liệu, bạn bày một cái bàn khác rồi nấu ở đó. Nguyên liệu vẫn sạch, và bạn có thể nấu nhiều kiểu cùng lúc. Nhớ nhé: dựng ở bàn riêng, nguyên liệu giữ nguyên.

    If you want to experiment with options, Ward shows how to use a separate build directory: create a new directory anywhere on the system and, from there, run the configure script in the original package source directory. You'll find configure makes a symbolic link farm in your new build directory, where all the links point back to the source tree in the original package directory.1

    Bạn gặp nó ở đâuWhere you meet it Một số nhà phát triển thích bạn dựng gói theo lối này vì cây mã nguồn gốc không bao giờ bị sửa đổi; cách này cũng hữu ích khi bạn muốn dựng cho nhiều nền tảng hoặc nhiều bộ tuỳ chọn cấu hình từ cùng một gói mã nguồn.1 Hữu ích khi bạn muốn thử nhiều kiểu dựng khác nhau từ cùng một bộ nguyên liệu. Some developers prefer that you build this way because the original source tree is never modified; it's also useful when you want to build for more than one platform or option set from the same source package.1

    Tên chính thức của kỹ thuật này

    Tài liệu Autoconf gọi đây là VPATH build và mô tả cơ chế: bạn cd tới thư mục nơi bạn muốn đặt tệp đối tượng và tệp thực thi, rồi chạy script configure; configure tự động tìm mã nguồn trong thư mục chứa chính nó và trong ...15 Tài liệu cũng cảnh báo: với một make không phải GNU, an toàn hơn là biên dịch gói cho một hệ thống tại một thời điểm ngay trong thư mục mã nguồn, và dùng make distclean trước khi cấu hình lại cho hệ thống khác.15

    Họ hàng gần: cài theo giai đoạn với DESTDIR

    Chương 16 không bàn tới DESTDIR, nhưng nó là công cụ đứng ngay cạnh --prefix khi bạn đóng gói, nên đáng phân biệt cho rõ. DESTDIR là một biến được thêm vào trước mỗi tệp đích khi cài, do người dùng chỉ định trên dòng lệnh make dưới dạng tên tệp tuyệt đối, ví dụ make DESTDIR=/tmp/stage install: một bước cài lẽ ra đặt /usr/local/bin/foo sẽ đặt /tmp/stage/usr/local/bin/foo.16 Khác biệt cốt lõi: --prefix thay đổi nơi chương trình nghĩ rằng nó được cài, còn DESTDIR chỉ dời nơi tệp được chép tới lần này — tài liệu nói rõ rằng việc chỉ định DESTDIR không được thay đổi hoạt động của phần mềm theo bất kỳ cách nào, nên giá trị của nó không được nhúng vào nội dung tệp nào cả.16 Nó chỉ nên được hỗ trợ trong các đích install* và uninstall*, và thường dùng nhất khi tạo gói.16

Cụm khái niệm 04 Concept cluster 04

Vá mã nguồn, và đọc lỗi biên dịch cho đúng chỗ Vá mã nguồn và đọc thông báo lỗi Applying patches, and reading build errors in the right place

Phần lớn thay đổi với mã nguồn phần mềm ngày nay xuất hiện dưới dạng nhánh trong bản mã nguồn trực tuyến của nhà phát triển, chẳng hạn một kho Git. Nhưng thỉnh thoảng bạn vẫn nhận được một bản vá cần áp vào mã nguồn để sửa lỗi hoặc thêm tính năng. Ward ghi chú rằng bạn cũng có thể thấy từ diff được dùng như từ đồng nghĩa của patch, vì chương trình diff chính là thứ tạo ra bản vá.1

Bản vá là một tờ giấy ghi “ở dòng này, bỏ chữ cũ, thêm chữ mới”. Có một chương trình đọc tờ giấy đó và sửa hộ bạn. Nhớ nhé: bản vá là danh sách những chỗ cần sửa, không phải bản mã nguồn mới.

Most changes to software source code now arrive as branches of the developer's online source, such as a Git repository. But every now and then you get a patch that you need to apply against source code to fix bugs or add features. Ward notes you may also see the term diff used as a synonym for patch, because the diff program is what produces the patch.1

Trước khi gỡ rối, hãy đọc được kết xuất make. Ward đặt một điều kiện tiên quyết: nếu bạn hiểu khác biệt giữa lỗi trình biên dịch, cảnh báo trình biên dịch, lỗi trình liên kết và vấn đề thư viện dùng chung như mô tả ở Chương 15, bạn sẽ không quá chật vật với phần lớn trục trặc khi dựng phần mềm.1 Ông cũng nói thẳng rằng bạn khó có khả năng gặp những vấn đề trong mục này khi dựng bằng autoconf — nhưng biết chúng trông thế nào thì chẳng bao giờ thừa.1

Định nghĩa. Phần đầu một bản vá trông như --- src/file.c.orig theo sau là +++ src/file.c và một dòng phạm vi dạng @@ -2,16 +2,12 @@. Bản vá thường chứa thay đổi cho nhiều hơn một tệp: hãy tìm ba dấu gạch liên tiếp (---) trong bản vá để thấy những tệp nào bị sửa.1

Nói đơn giản. Nhìn mấy dòng đầu là biết bản vá đụng vào tệp nào. Dấu ba gạch mở đầu mỗi tệp mới. Nhớ nhé: đọc đầu bản vá trước khi áp nó.

Definition. The beginning of a patch looks like --- src/file.c.orig followed by +++ src/file.c and a range line such as @@ -2,16 +2,12 @@. Patches usually contain alterations to more than one file: search the patch for three dashes in a row (---) to see which files have alterations.1

--- src/file.c.orig
+++ src/file.c
@@ -2,16 +2,12 @@

$ patch -p0 < patch_file

tệp cũ → tệp mới
vị trí cần sửa

rồi chạy: patch -p0

--- src/file.c.orig
+++ src/file.c
@@ -2,16 +2,12 @@

$ patch -p0 < patch_file

  1. patch -p0

    Đứng đúng thư mục — điều kiện thật sự của patch Đứng đúng chỗ rồi mới vá Standing in the right directory — what patch really requires

    Ward nhấn mạnh: hãy luôn xem phần đầu bản vá để xác định thư mục làm việc cần thiết. Trong ví dụ của ông, bản vá nhắc tới src/file.c; do đó bạn phải chuyển tới thư mục chứa src, chứ không phải vào chính thư mục src.1 Áp bản vá bằng lệnh patch -p0 < patch_file; nếu mọi việc trôi chảy, patch thoát mà không làm ồn, để lại cho bạn một bộ tệp đã cập nhật.1

    Bản vá ghi đường đi tới tệp cần sửa. Bạn phải đứng đúng chỗ để đường đi đó khớp. Đứng sai một bậc là hỏng. Nhớ nhé: nhìn đường dẫn trong bản vá rồi đứng cho khớp.

    Ward stresses that you should always look at the beginning of a patch to determine the required working directory. In his example the patch refers to src/file.c; therefore you should change to the directory that contains src, not to the src directory itself.1 Apply it with patch -p0 < patch_file; if all goes well, patch exits without a fuss, leaving you with an updated set of files.1

    Bạn gặp nó ở đâuWhere you meet it Nếu patch hỏi bạn File to patch: thì thường là bạn không ở đúng thư mục — nhưng cũng có thể mã nguồn của bạn không khớp với mã nguồn trong bản vá.1 Nếu nó hỏi “vá tệp nào?” thì gần như chắc là bạn đứng sai chỗ. If patch asks you File to patch:, it usually means you're not in the correct directory — but it could also mean your source code doesn't match the source in the patch.1

    Khi mã nguồn không khớp, hãy dừng lại

    Ward không khuyến khích cố chữa: trong trường hợp mã nguồn không khớp bản vá, bạn có lẽ hết cách. Kể cả nếu bạn nhận ra được một số tệp cần vá, những tệp khác vẫn sẽ không được cập nhật đúng, để lại cho bạn một cây mã nguồn không biên dịch nổi.1

    -p làm gì, theo trang hướng dẫn

    Trang patch(1) định nghĩa -pnum (hay --strip=num) là: lược bỏ tiền tố ngắn nhất chứa num dấu gạch chéo dẫn đầu khỏi mỗi tên tệp tìm thấy trong tệp vá; một chuỗi nhiều dấu gạch chéo liền nhau được tính là một. Ví dụ trong trang đó: với tên /u/howard/src/blurfl/blurfl.c, -p0 giữ nguyên toàn bộ tên, -p1 cho u/howard/src/blurfl/blurfl.c, còn -p4 cho blurfl/blurfl.c.17

  2. patch -p1

    Khi bản vá mang theo số phiên bản gói Khi tên thư mục trong bản vá không khớp When the patch carries a package version in its paths

    Đôi khi bạn gặp một bản vá tham chiếu tới phiên bản gói, kiểu --- package-3.42/src/file.c.orig và +++ package-3.42/src/file.c. Nếu số phiên bản của bạn hơi khác — hoặc bạn chỉ vừa đổi tên thư mục — bạn có thể bảo patch lược bỏ các thành phần đường dẫn dẫn đầu. Đứng ở thư mục chứa src như trước, để patch bỏ qua phần package-3.42/, tức lược một thành phần, hãy dùng patch -p1 < patch_file.1

    Nếu bản vá viết “package-3.42/src/file.c” mà thư mục của bạn tên khác, bạn bảo nó “bỏ giúp tôi bậc đầu tiên” — đó chính là con số sau chữ -p. Nhớ nhé: -p là số bậc thư mục cần bỏ.

    Sometimes you come across a patch that refers to a package version, like --- package-3.42/src/file.c.orig and +++ package-3.42/src/file.c. If you have a slightly different version number — or you just renamed the directory — you can tell patch to strip leading path components. Standing in the directory containing src as before, to make patch ignore the package-3.42/ part, that is strip one leading component, use patch -p1 < patch_file.1

    Bạn gặp nó ở đâuWhere you meet it Bản vá sinh từ một kho Git thường mang tiền tố a/ và b/ — tiền tố nguồn và đích mặc định của git diff — nên -p1 là con số bạn dùng thường xuyên nhất trong thực tế.2417 Trong thực tế bạn sẽ dùng -p1 nhiều hơn -p0. Patches generated from a Git repository usually carry a/ and b/ prefixes — git diff’s default source and destination prefixes — which is why -p1 is the number you reach for most often in practice.2417

    patch chọn tên tệp thế nào

    Trang hướng dẫn mô tả một quy trình có thứ tự: patch lập một danh sách tên tệp ứng viên theo thứ tự (cũ, mới, Index:), và một cái tên bị bỏ qua nếu nó không có đủ số dấu gạch chéo để thoả mãn tuỳ chọn -pnum; tên /dev/null cũng bị bỏ qua.17 Nếu không tên nào từ các quy tắc này cho kết quả, bạn sẽ được hỏi tên tệp cần vá — chính là câu File to patch: mà Ward cảnh báo.17

    Một cái bẫy có sẵn trong trang patch(1)

    Trang hướng dẫn liệt kê một hành vi đáng nhớ trong mục BUGS: nếu bạn áp một bản vá đã áp rồi, patch tưởng đó là bản vá ngược và đề nghị gỡ bản vá ra.17 Trang này ghi chú đó là quan sát từ tài liệu patch, không phải từ sách của Ward.

  3. make error

    Lỗi thật, lỗi bị bỏ qua, và lỗi vọng lại Dòng lỗi nào mới đáng đọc Real errors, ignored errors, and echoes

    Trước khi bàn chi tiết, Ward yêu cầu bạn phải đọc được vài kiểu kết xuất make, và quan trọng nhất là biết phân biệt lỗi với lỗi đã bị bỏ qua. Dòng make: *** [target] Error 1 là một lỗi thật mà bạn cần điều tra. Nhưng một số Makefile nghi ngờ rằng một điều kiện lỗi có thể xảy ra trong khi biết rằng lỗi ấy vô hại: bạn thường có thể bỏ qua thông báo dạng make: *** [target] Error 1 (ignored).1

    Máy in ra rất nhiều dòng đỏ, nhưng không phải dòng nào cũng là lỗi thật. Có dòng ghi rõ “(ignored)” — nghĩa là “không sao đâu”. Nhớ nhé: đọc kỹ chữ trong ngoặc trước khi hoảng.

    Before the specifics, Ward wants you to be able to read certain kinds of make output, and above all to know the difference between an error and an ignored error. The line make: *** [target] Error 1 is a real error you need to investigate. But some Makefiles suspect an error condition might occur while knowing it's harmless: you can usually disregard messages like make: *** [target] Error 1 (ignored).1

    Bạn gặp nó ở đâuWhere you meet it GNU make thường tự gọi chính nó nhiều lần trong các gói lớn, mỗi lần được đánh dấu [N] trong thông báo lỗi, với N là một con số; bạn thường tìm ra lỗi nhanh bằng cách nhìn vào lỗi make đứng ngay sau thông báo lỗi của trình biên dịch.1 Nhìn dòng lỗi đầu tiên, đừng nhìn dòng cuối cùng. GNU make often calls itself many times in large packages, each instance marked [N] in the error message, where N is a number; you can often find the error quickly by looking at the make error that comes directly after the compiler error message.1

    Đọc một chồng lỗi lồng nhau

    Ward trưng ra một chồng điển hình: thông báo lỗi trình biên dịch liên quan tới file.c, rồi make[3]: *** [file.o] Error 1, rồi make[3]: Leaving directory '/home/src/package-5.0/src', và tiếp tục vọng lên qua make[2], make[1] cho tới make: *** [all] Error 2.1 Ông chỉ rõ: ba dòng đầu tiên mới cho bạn thông tin cần thiết — rắc rối nằm quanh file.c, đặt tại /home/src/package-5.0/src.1 Học cách lọc bỏ các lỗi make phía sau giúp ích rất nhiều cho việc đào ra nguyên nhân thật.1

    Dấu *** nghĩa là gì

    Tài liệu GNU make giải thích phần mà Ward mô tả bằng ví dụ: nếu không có *** kèm theo thông báo, thì tiến trình con đã thất bại nhưng quy tắc trong makefile được đặt tiền tố bằng ký tự đặc biệt -, nên make đã bỏ qua lỗi ấy.18 Đó chính là cơ chế đằng sau hậu tố (ignored).

  4. missing header

    Bốn lỗi cụ thể, và cách lần ra tệp tiêu đề bị thiếu Bốn lỗi hay gặp và cách chữa Four specific errors, and how to track down a missing header

    Ward liệt kê bốn lỗi dựng thường gặp. Một: src.c:22: conflicting types for 'item' kèm /usr/include/file.h:47: previous declaration of 'item' — lập trình viên đã khai báo lại item một cách sai lầm ở dòng 22 của src.c; bạn thường sửa được bằng cách gỡ dòng gây lỗi, bằng chú thích, #ifdef, hoặc cách nào khác hiệu quả.1 Hai: src.c:37: 'time_t' undeclared (first use this function) rồi src.c:37: parse error before '...' — lập trình viên quên một tệp tiêu đề then chốt.1

    Bốn lỗi quen thuộc: khai báo hai lần, quên khai báo, thiếu tệp tiêu đề, và thiếu công cụ. Cách chữa cũng quen: đọc số dòng, tra sách hướng dẫn, thêm dòng khai báo hoặc cài thêm gói. Nhớ nhé: lỗi bao giờ cũng ghi rõ tệp nào, dòng nào.

    Ward lists four common build errors. One: src.c:22: conflicting types for 'item' with /usr/include/file.h:47: previous declaration of 'item' — the programmer made an erroneous redeclaration of item on line 22 of src.c; you can usually fix it by removing the offending line, with a comment, an #ifdef, or whatever works.1 Two: src.c:37: 'time_t' undeclared (first use this function) followed by src.c:37: parse error before '...' — the programmer forgot a critical header file.1

    Bạn gặp nó ở đâuWhere you meet it Ward gọi các trang hướng dẫn là cách tốt nhất để tìm tệp tiêu đề bị thiếu: nhìn dòng gây lỗi, tìm xuôi chỗ dùng biến quanh một lời gọi hàm, rồi tra trang hướng dẫn của hàm đó.1 Tra sách hướng dẫn của hàm đó, phần SYNOPSIS ghi sẵn dòng include cần thêm. Ward calls the manual pages the best way to find a missing header file: look at the offending line, search forward for the variable's use around a function call, then read that function's manual page.1

    Lần theo time_t, từng bước một

    Ward đi hết ví dụ: dòng 37 của src.c có lẽ là một khai báo biến như time_t v1;; tìm xuôi v1 trong chương trình sẽ thấy nó dùng quanh một lời gọi hàm, ví dụ v1 = time(NULL);. Giờ chạy man 2 time hoặc man 3 time để tìm các lời gọi hệ thống và thư viện tên time(); trong trường hợp này trang hướng dẫn mục 2 có thứ bạn cần, với phần SYNOPSIS ghi #include <time.h> và time_t time(time_t *t);.119 Nghĩa là time() cần time.h: đặt #include <time.h> ở đầu src.c rồi thử lại.1

    Lỗi ba: tệp tiêu đề không tìm thấy

    src.c:4: pkg.h: No such file or directory theo sau là một danh sách lỗi dài nghĩa là trình biên dịch đã chạy bộ tiền xử lý C trên src.c nhưng không tìm thấy tệp pkg.h. Mã nguồn có lẽ phụ thuộc vào một thư viện bạn cần cài, hoặc bạn chỉ cần cung cấp đường dẫn include phi tiêu chuẩn — thường là thêm một tuỳ chọn -I vào CPPFLAGS, và hãy nhớ có thể bạn cũng cần một cờ -L đi kèm cho trình liên kết.1 Nếu có vẻ không phải do thiếu thư viện, có khả năng nhỏ là bạn đang biên dịch cho một hệ điều hành mà mã nguồn này không hỗ trợ; hãy kiểm tra Makefile và các tệp README về nền tảng.1

    Tìm gói chứa tệp tiêu đề

    Ward đưa hai công cụ cụ thể theo họ bản phân phối: trên hệ dựa trên Debian, thử apt-file search pkg.h — lệnh này có thể tìm ra gói phát triển bạn cần; với các bản phân phối dùng yum, thử yum provides */pkg.h.120

    Lỗi bốn: thiếu chính công cụ

    Thông báo make: prog: Command not found nghĩa là để dựng gói, bạn cần prog trên hệ thống. Ward phân hai nhánh: nếu prog là thứ như cc, gcc hay ld thì bạn chưa cài các tiện ích phát triển; còn nếu bạn nghĩ prog đã có trên máy, hãy thử sửa Makefile để chỉ định đường dẫn đầy đủ của prog.1 Trong vài trường hợp hiếm với mã nguồn cấu hình kém, make dựng prog rồi dùng ngay, giả định rằng thư mục hiện tại (.) nằm trong đường dẫn lệnh của bạn; nếu $PATH của bạn không có thư mục hiện tại, bạn có thể sửa Makefile đổi prog thành ./prog, hoặc tạm thời nối . vào đường dẫn.1

Đính chính Corrections

Ba ngộ nhận mà người đọc lần đầu hay mắc Ba chỗ hay hiểu nhầm Three misconceptions first readers hit

Phần này thuộc mức đọc Đầy đủ: nó đối chiếu điều người đọc thường nghĩ với điều bản văn thật sự nói.

Phần này hơi khó, bạn có thể bỏ qua và quay lại sau. Nhớ nhé: hiểu chậm mà chắc vẫn hơn.

This block belongs to the Đầy đủ (full) reading level: it sets what readers usually assume against what the text actually says.

“Người dùng Linux giỏi thì cài mọi thứ từ mã nguồn” "A good Linux user installs everything from source"

Ngộ nhận: dùng trình quản lý gói là dấu hiệu của người mới; tự biên dịch mới là cách làm “đúng”.

Bản văn nói: Ward viết rằng bạn có thể cập nhật và bổ sung toàn bộ hệ thống bằng cách cài lại từ mã nguồn, nhưng bạn có lẽ không nên làm thế trừ phi bạn thật sự thích quá trình đó hoặc có lý do khác.1 Ông nhấn mạnh rằng các bản phân phối cung cấp cách dễ dàng để cập nhật phần lõi và thường sửa lỗi bảo mật rất nhanh, còn gói tự cài thì không tự nâng cấp — một mối lo đặc biệt với phần mềm tương tác qua mạng.1

Misconception: using a package manager marks you as a beginner; compiling yourself is the "proper" way.

The text says: Ward writes that you can update and augment your entire system by reinstalling parts from source, but you probably shouldn't, unless you really enjoy the process or have some other reason.1 He stresses that distributions provide easy ways to update core parts and usually fix security problems very quickly, while custom packages do not automatically upgrade themselves — a particular concern for software that interacts with the network.1

“configure chạy xong sạch nghĩa là make sẽ chạy được” "A clean configure means make will work"

Ngộ nhận: bước cấu hình là cửa kiểm tra đầy đủ; qua được nó thì phần còn lại chỉ là hình thức.

Bản văn nói: Ward viết rõ rằng một bước configure thành công không nhất thiết có nghĩa là bước make sẽ chạy được, dù khả năng là khá cao.1 Và khi lỗi xảy ra ở bước cấu hình, thông báo bề mặt cũng thường không phải nguyên nhân: ví dụ dấu gạch bị thiếu cho ra C compiler cannot create executables, trong khi nguyên nhân thật — gcc: error: Iinclude_dir: No such file or directory — chỉ lộ ra trong config.log.1

Misconception: the configure step is a complete gate; pass it and the rest is a formality.

The text says: Ward writes plainly that a successful configure step doesn't necessarily mean the make step will work, though the chances are pretty good.1 And when configure itself fails, the surface message is often not the cause: a missing dash yields C compiler cannot create executables, while the real cause — gcc: error: Iinclude_dir: No such file or directory — appears only inside config.log.1

“Giải nén một kho lưu trữ thì có gì mà phải kiểm tra” "Extracting an archive is harmless, so why check it"

Ngộ nhận: tar chỉ mở gói, nên cùng lắm là bày bừa vài tệp.

Bản văn nói: hậu quả nhẹ đúng là bừa bộn — một kho lưu trữ không có thư mục chung sẽ để lại một đống lộn xộn lớn trong thư mục hiện tại.1 Nhưng Ward nêu cả trường hợp nặng: nếu bạn thấy tệp mang đường dẫn tuyệt đối như /etc/passwd hay /etc/inetd.conf, hãy gỡ kho lưu trữ khỏi hệ thống, vì nó nhiều khả năng chứa ngựa thành Troy hoặc mã độc khác.1 Đó là lý do tar tvf đứng trước tar xvf.2

Misconception: tar only unpacks things, so the worst case is a few stray files.

The text says: the mild consequence is indeed mess — an archive with no common directory leaves a big mess in your current directory.1 But Ward also names the severe case: if you see files with absolute pathnames such as /etc/passwd or /etc/inetd.conf, remove the archive from your system, because it probably contains a Trojan horse or other malicious code.1 That is why tar tvf comes before tar xvf.2

Tự kiểm tra Self-check

Bạn đã tự dựng được một gói chưa? Thử trả lời xem nào Could you build a package yourself now?

Trả lời bằng lời của bạn, không tra sách. Nếu một câu khiến bạn ngập ngừng, đó chính là mục bạn nên đọc lại.

Thử trả lời miệng thôi, không cần giở lại. Câu nào bí thì quay lại đọc phần đó nhé. Nhớ nhé: chỗ bí chính là chỗ cần học.

Answer in your own words, without looking back. Whichever question makes you hesitate points at the section you should reread.

  1. Bốn bước để cài một gói từ mã nguồn C là gì, theo đúng thứ tự?

    Gợi ý sâu hơn: bước nào là bước duy nhất phụ thuộc vào đặc tính máy của bạn?

  2. Vì sao nên chạy tar tvf trước khi giải nén, và hai dấu hiệu xấu bạn đang tìm là gì?

    Gợi ý sâu hơn: dấu hiệu nào chỉ gây bừa bộn, dấu hiệu nào buộc bạn phải xoá kho lưu trữ?

  3. configure làm gì với các tệp .in, và nó để lại những tệp nào sau khi chạy?

    Gợi ý sâu hơn: tệp nào là nhật ký để tra khi hỏng, và mẹo tìm trong tệp đó là gì?

  4. Tiền tố mặc định của một Makefile do autoconf sinh ra là gì, và vì sao lại là thư mục đó?

    Gợi ý sâu hơn: bindir và libdir mặc định được viết theo biến nào?

  5. Khi nào bạn dùng CPPFLAGS thay vì CFLAGS, và vì sao?

    Gợi ý sâu hơn: thêm gì vào LDFLAGS nếu thư viện ở nơi phi tiêu chuẩn là thư viện dùng chung?

  6. make clean và make distclean khác nhau ở điểm nào?

    Gợi ý sâu hơn: sau distclean thì cây mã nguồn trông như thế nào?

  7. Con số sau -p trong patch -p1 có ý nghĩa gì?

    Gợi ý sâu hơn: câu hỏi File to patch: thường có nghĩa gì?

  8. Trong một chồng lỗi make[3], make[2], make[1], bạn đọc dòng nào trước?

    Gợi ý sâu hơn: hậu tố (ignored) nói với bạn điều gì?

  1. Cài phần mềm từ mã nguồn có mấy bước? Kể theo thứ tự.

  2. Vì sao nên ngó vào gói nén trước khi mở nó ra?

  3. Script configure làm gì cho bạn?

  4. --prefix dùng để làm gì?

  5. Muốn thử xem make install sẽ làm gì mà chưa cài thật thì gõ gì?

  6. Bản vá (patch) là gì?

  7. Thấy dòng lỗi có chữ (ignored) thì bạn có cần lo không?

  1. What are the four steps of installing a package from C source code, in order?

  2. Why run tar tvf before extracting, and what two bad signs are you looking for?

  3. What does configure do with the .in files, and which files does it leave behind?

  4. What is the default prefix of an autoconf-generated Makefile, and why that directory?

  5. When do you use CPPFLAGS rather than CFLAGS, and why?

  6. How do make clean and make distclean differ?

  7. What does the number after -p in patch -p1 mean?

  8. In a stack of make[3], make[2], make[1] errors, which line do you read first?

Khép lại chương Closing the chapter

Dựng phần mềm thường là bước đệm để học về lập trình và phát triển phần mềm. Các công cụ trong chương này và chương trước gỡ bỏ sự bí ẩn về nơi phần mềm hệ thống của bạn đến từ đâu. Và không khó để đi tiếp những bước sau: nhìn vào bên trong mã nguồn, thực hiện thay đổi, và tạo ra phần mềm của chính bạn.1

Biết tự dựng phần mềm là bước đầu để hiểu phần mềm được làm ra thế nào. Khi bạn đã mở được “hộp”, chẳng còn gì bí ẩn nữa — bước sau chỉ là sửa thử một dòng. Nhớ nhé: mở hộp ra xem, rồi sửa thử một dòng.

Building software is often a stepping stone to learning about programming and software development. The tools in this chapter and the previous one take the mystery out of where your system software came from. And it's not difficult to take the next steps: looking inside the source code, making changes, and creating your own software.1