2. Xây dựng CPython từ nguồn

Xây dựng CPython từ nguồn cung cấp cho bạn một trình thông dịch cục bộ mà bạn có thể kiểm tra, sửa đổi, gỡ lỗi và kiểm tra. Đây là bước thực tế đầu tiên trước khi đọc nội bộ một cách nghiêm túc.

Bản dựng nguồn cho phép bạn thực hiện những việc mà bản cài đặt Python đóng gói thường ẩn:```text change interpreter code add debug prints inspect object layout run CPython tests use debug-only assertions trace reference counts debug crashes in C compare bytecode across builds


CPython sng trong kho Git. Thanh toán cc b bình thường trông như thế này:```bash
git clone https://github.com/python/cpython.git
cd cpython
```Kho lưu tr cha trình thông dch, thư vin chun, bài kim tra, tài liu, tp xây dng và mã h tr nn tng.

Mt cái nhìn đơn gin hóa:```text
cpython/
    Include/        public and internal C headers
    Objects/        core object implementations
    Python/         compiler, runtime, interpreter loop
    Parser/         tokenizer and parser support
    Modules/        built-in and extension modules
    Lib/            Python standard library
    Lib/test/       regression test suite
    Programs/       executable entry points
    Tools/          developer tools
    Doc/            documentation source
```Các thư mc quan trng nht cho công vic ni b là`Objects`, `Python`, `Include`, `Modules`, Và`Lib/test`.

## 2.2 Chọn Chế độ xây dựng

Có hai cách xây dng ph biến:

| Xây dng | Mc đích |
| ------------- | ------------------------------------ |
| Phát hành bn dng | Tương t như Python được cài đặt bình thường |
| Bn dng g li | Tt hơn cho công vic ni b |

Đối vi nghiên cu ni b, trước tiên hãy s dng bn dng g li. Nó cho phép xác nhn b sung, trình tr giúp g li, h tr theo dõi tham chiếu và các chế độ li an toàn hơn.

Quá trình xây dng g li chm hơn nhưng d kim tra hơn.

## 2.3 Xây dựng trên Linux hoặc macOS

Trên các h thng ging Unix, CPython s dng cu hình và to lung thông thường.```bash
./configure --with-pydebug
make -j
```Điu này to ra mt tp thc thi trong cây ngun, thường có tên như sau:```bash
./python
```Chy nó:```bash
./python -V
./python -c "print('hello from local CPython')"
```các`--with-pydebug`tùy chn to bn dng g li. Điu này thay đổi th ABI và cho phép hot động g li.

Lnh cu hình phát trin ph biến là:```bash
./configure --with-pydebug --with-trace-refs
make -j
```S dng`--with-trace-refs`ch khi bn cn theo dõi tài liu tham kho sâu hơn. Nó thay đổi b cc đối tượng và có th làm chm trình thông dch hơn na.

## 2.4 Xây dựng phụ thuộc

Bn dng ti thiu có th thành công mà không cn mi ph thuc tùy chn, nhưng nhiu mô-đun thư vin tiêu chun cn có thư vin h thng.

Các ph thuc ph biến bao gm:

| Tính năng | S ph thuc đin hình |
| ---------------------- | -------------------------- |
| SSL và HTTPS | OpenSSL |
| Nén | zlib, bzip2, xz |
| SQLite | Tiêu đề phát trin SQLite |
| H tr v Readline | readline hoc libedit |
| Li nguyn | ncurses |
| Tkinter | Tcl/Tk |
| H tr UUID | libuuid |
| H tr FFI | libfi |

Nếu thiếu phn ph thuc, CPython vn có th được xây dng nhưng mt s mô-đun m rng s b b qua.

Bn có th kim tra đầu ra ca bn dng để tìm thông báo v các mô-đun b thiếu.

## 2.5 Bản dựng ngoài cây

Bn có th xây dng CPython bên ngoài thư mc ngun. Điu này gi cho các tp tin được to riêng bit.```bash
mkdir ../cpython-build-debug
cd ../cpython-build-debug
../cpython/configure --with-pydebug
make -j
```Kết qu thc thi được nm trong thư mc bn dng:```bash
./python
```Các bn dng ngoài cây rt hu ích khi bn mun có nhiu cu hình t mt ngun kim tra:```text
cpython/
cpython-build-debug/
cpython-build-release/
cpython-build-asan/
```## 2.6 Xây dựng trên Windows

Trên Windows, CPython s dng tp xây dng Visual Studio.

T Du nhc lnh ca nhà phát trin:```bat
PCbuild\build.bat -d
```các`-d`flag xây dng trình thông dch g li.

Tp thc thi thường  dưới:```text
PCbuild\amd64\python_d.exe
```Bn dng phát hành s dng:```bat
PCbuild\build.bat
```Các bn dng Windows có tp d án, mã nn tng và quy tc xây dng tin ích m rng riêng. B cc khác vi các bn dng Unix, nhưng ngun trình thông dch có cùng mã lõi.

## 2.7 Xác minh bản dựng

Sau khi xây dng, hãy kim tra tp thc thi:```bash
./python -V
./python -m sysconfig
```Kim tra xem trình thông dch cho rng nó được cài đặt  đâu:```bash
./python - <<'PY'
import sys
print(sys.executable)
print(sys.prefix)
print(sys.path)
PY
```Để phát trin cây ngun,`sys.path`nên bao gm địa phương`Lib`thư mc.

## 2.8 Chạy bộ thử nghiệm

B th nghim ca CPython được chy vi:```bash
./python -m test
```Để kim tra ln đầu nhanh hơn:```bash
./python -m test test_sys test_gc test_dict test_compile
```Chy th nghim song song:```bash
./python -m test -j8
```Chy li các bài kim tra tht bi:```bash
./python -m test --fail-env-changed
```Chy mt tp th nghim:```bash
./python -m test test_dict
```Chy mt trường hp th nghim vi`unittest`cú pháp:```bash
./python -m unittest Lib.test.test_dict.DictTest.test_constructor
```B th nghim là mt phn ca quy trình làm vic ni b. Khi bn thay đổi CPython, các bài kim tra là bin pháp bo v đầu tiên chng li hành vi vi phm ngôn ng.

## 2.9 Hành vi xây dựng gỡ lỗi

Bn dng g li thay đổi cách CPython hot động ni b.

Nó cho phép kim tra b sung như:```text
assertions in C code
debug memory allocator checks
extra object consistency checks
reference leak tools
debug ABI marker
stricter failure behavior
```Bn dng g li thường phát hin li sm hơn. Vic s dng sai b nh có v vô hi trong bn phát hành có th b hy b nhanh chóng trong bn dng g li.

Điu này rt hu ích. Công vic ni b s tht bi nng n.

## 2.10 Kiểm tra cấu hình bản dựng

CPython hin th cu hình xây dng thông qua`sysconfig`.

```python
import sysconfig

print(sysconfig.get_config_var("Py_DEBUG"))
print(sysconfig.get_config_var("WITH_PYMALLOC"))
print(sysconfig.get_config_var("Py_GIL_DISABLED"))
print(sysconfig.get_config_var("CONFIG_ARGS"))
```Chy nó trc tiếp:```bash
./python - <<'PY'
import sysconfig
for name in ["Py_DEBUG", "WITH_PYMALLOC", "Py_GIL_DISABLED", "CONFIG_ARGS"]:
    print(name, "=", sysconfig.get_config_var(name))
PY
```Điu này cho bn biết tính năng thi gian biên dch nào đang hot động.

## 2.11 Mục tiêu xây dựng hữu ích

chung`make`mc tiêu:

| Mc tiêu | Mc đích |
| ------------------ | -------------------------------------- |
|`make`| Xây dng trình thông dch |
|`make -j`| Xây dng song song |
|`make clean`| Xóa nhiu tp được to |
|`make distclean`| Loi b đầu ra cu hình quá |
|`make test`| Chy th nghim |
|`make regen-all`| Tái to các tp tin đã to |
|`make profile-opt`| Xây dng bng cách ti ưu hóa theo hướng dn h sơ |

Đối vi công vic ni b thông thường, hãy s dng:```bash
make -j
./python -m test test_name
```Đối vi các tp được to, ch s dng mc tiêu tái to khi bn thay đổi thông tin đầu vào như ng pháp, định nghĩa phòng khám hoc siêu d liu opcode.

## 2.12 Tệp được tạo

Mt s tp CPython được to. Đừng chnh sa chúng mt cách mù quáng.

Các to phm được to ra có th đến t:```text
Grammar definitions
Argument Clinic input
opcode metadata
frozen modules
configuration scripts
documentation tools
```Argument Clinic đặc bit ph biến trong phn m rng C và các định nghĩa phương thc tích hp. Nó to ra mã phân tích cú pháp và trình bao bc t các nhn xét có cu trúc.

Tp C có th cha các khi như:```c
/*[clinic input]
module.function

    arg: object

Description here.
[clinic start generated code]*/
```Phn được to phi được to li thông qua công c chính xác thay vì chnh sa th công.

## 2.13 Xây dựng lại sau khi thay đổi

Mt vòng chnh sa bình thường:```bash
vim Objects/listobject.c
make -j
./python -m test test_list
```Đối vi mt thay đổi nh trong mã C, vic xây dng li tăng dn thường nhanh chóng.

Để thay đổi thư vin chun Python:```bash
vim Lib/pathlib/__init__.py
./python -m test test_pathlib
```Không cn xây dng li C cho các thay đổi Python thun túy.

Đối vi các thay đổi v trình phân tích cú pháp, mã opcode hoc mã được to, bn có th cn to li trước khi xây dng.

## 2.14 Thêm bản in gỡ lỗi

Mt cách đơn gin để xác nhn rng bn đang chy trình thông dch ca riêng mình là thêm bn in g li tm thi.

Ví d: trong hàm C:```c
fprintf(stderr, "debug: list append called\n");
```Sau đó xây dng li:```bash
make -j
```Chy mt chương trình nh:```bash
./python - <<'PY'
x = []
x.append(1)
PY
```Các bn in tm thi thô sơ nhưng hiu qu. Loi b chúng trước khi cam kết.

## 2.15 Sử dụng`gdb`hoặc`lldb`Bản dựng gỡ lỗi hoạt động tốt với trình gỡ lỗi gốc.

Vi`gdb`:

```bash
gdb --args ./python script.py
```Bên trong`gdb`:

```gdb
break PyEval_EvalFrameDefault
run
bt
```Vi`lldb`:

```bash
lldb -- ./python script.py
```Bên trong`lldb`:

```lldb
breakpoint set --name PyEval_EvalFrameDefault
run
bt
```Đim dng hu ích:```text
Py_Initialize
PyEval_EvalFrameDefault
_PyEval_EvalFrameDefault
PyObject_Malloc
PyObject_Free
PyErr_SetString
_Py_Dealloc
```Tên biu tượng chính xác có th thay đổi theo phiên bn và cu hình bn dng.

## 2.16 Sử dụng Kiểm tra cấp độ Python

Không phi mi câu hi ni b đều cn trình g li C.

Các mô-đun hu ích:

| Mô-đun | S dng |
| ------------- | -------------------------------------- |
|`dis`| Kim tra mã byte |
|`sys`| Trng thái thi gian chy và cài đặt trình thông dch |
|`gc`| Kim tra người thu gom rác |
|`inspect`| Khung, chc năng, ngun, ch ký |
|`types`| Đối tượng loi thi gian chy |
|`sysconfig`| Xây dng cu hình |
|`tracemalloc`| Theo dõi phân b Python |

Ví d:```python
import dis
import gc
import sys

def f(x):
    return x + 1

dis.dis(f)
print(f.__code__)
print(sys.getrefcount(f))
print(gc.is_tracked(f))
```Phong cách này rt hu ích trước khi rơi vào C.

## 2.17 Phân bổ bộ nhớ gỡ lỗi

CPython có móc g li cho b cp phát b nh.

Chy vi:```bash
PYTHONMALLOC=debug ./python script.py
```Điu này cho phép kim tra thêm xung quanh vic phân b b nh. Nó có th phát hin vic s dng sai API, li tràn b đệm, tràn b đệm và mt s mu không s dng sau này.

Để theo dõi phân b:```bash
./python -X tracemalloc script.py
```Hoc bên trong Python:```python
import tracemalloc

tracemalloc.start()

data = [bytearray(1024) for _ in range(1000)]

current, peak = tracemalloc.get_traced_memory()
print(current, peak)

tracemalloctheo dõi các đường dẫn phân bổ bộ nhớ cấp độ Python. Gỡ lỗi heap gốc vẫn cần các công cụ cấp thấp hơn.

Bản dựng công cụ vệ sinh 2.18

Đối với công việc cấp độ C nghiêm túc, hãy xây dựng bằng chất khử trùng.

addressSanitizer có thể phát hiện lỗi bộ nhớ:bash ./configure --with-pydebug --with-address-sanitizer make -j Und xác địnhBehaviorSanitizer có thể phát hiện hành vi C không xác định:```bash ./configure --with-pydebug --with-undefined-behavior-sanitizer make -j


## 2.19 Bản phát hành có hướng dẫn hồ sơ

Bn dng bn phát hành CPython được ti ưu hóa thông thường có th s dng tính năng ti ưu hóa theo hướng dn h sơ.```bash
make profile-opt
```Điu này xây dng CPython, chy khi lượng công vic đào to và xây dng li bng cách s dng d liu h sơ.

S dng điu này khi đo lường hiu sut. Không so sánh bn dng g li vi bn phát hành Python và coi các con s là có ý nghĩa.

Đối vi nghiên cu ni b:```text
debug build for correctness and inspection
release build for speed comparison
PGO build for performance-sensitive measurement
```## 2.20 Các sự cố thường gặp khi xây dựng

| Triu chng | Nguyên nhân có th |
| ---------------------------- | ---------------------------------------------- |
|`_ssl`mt tích | Tiêu đề hoc thư vin OpenSSL không có sn |
|`_sqlite3`mt tích | Gói phát trin SQLite không có sn |
|`readline`mt tích | tiêu đề readline hoc libedit không có sn |
| kim tra tht bi xung quanh min địa phương | ngôn ng môi trường không phù hp |
| kim tra li xung quanh mng | kim tra mng bên ngoài hoc gii hn nn tng |
| g li quá trình nhp bn dng không khp | chy sai file thc thi hoc sai`PYTHONPATH`|
| tp tin được to cũ | cn tái sinh |
| li liên kết | thư vin h thng b thiếu hoc không tương thích |

Trước khi g li CPython, hãy xác nhn rng bn đang chy trình thông dch bn va to:```bash
./python - <<'PY'
import sys
print(sys.executable)
print(sys.version)
PY
```## 2.21 Giữ nhiều bản dựng

Mt thiết lp thc tế:```text
cpython/
cpython-build-debug/
cpython-build-release/
cpython-build-asan/
```S dng mi bn dng cho mt công vic khác nhau:

| Xây dng | S dng |
| ------- | -------------------------------- |
| G li | Đọc và xác nhn ni b |
| Phát hành | So sánh hành vi |
| ASAN | Phát hin li b nh |
| PGO | Đo lường hiu sut |

Điu này tránh vic liên tc cu hình li mt thư mc bn dng.

## 2.22 Quy trình làm việc nội bộ tối thiểu

Mt quy trình làm vic đầu tiên tt:```bash
git clone https://github.com/python/cpython.git
cd cpython
./configure --with-pydebug
make -j
./python -V
./python -m test test_sys test_gc test_dict
```Sau đó kim tra mã byte:```bash
./python - <<'PY'
import dis

def f(x):
    return x + 1

dis.dis(f)
PY
```Sau đó thay đổi mt tp nh, xây dng li và chy th nghim được nhm mc tiêu.

## 2.23 Bản dựng này kích hoạt những gì

Sau chương này, bn s có mt tp thc thi CPython cc b mà bn có th s dng cho phn còn li ca cun sách.

Bây gi bn có th kim tra:```text
how source becomes bytecode
how frames execute
how objects are laid out
how reference counts change
how the garbage collector tracks containers
how built-in types are implemented
how tests protect behavior
how C-level bugs surface
```Bn dng ngun biến CPython t mt hp đen thành mt h thng mà bn có th bước qua, s dng công c và sa đổi.