소스에서 PyPy 빌드하기

RPython은 Python2 방언(dialect)이므로, PyPy 빌드에는 Python2 인터프리터가 필요합니다. PyPy를 빌드하려면 먼저 미리 빌드된 PyPy2.7을 설치하는 것을 권장합니다(PyPy 다운로드 및 설치 참조). CPython2.7으로 PyPy를 빌드하는 것도 가능하지만, 실행하는 데 훨씬 더 오래 걸립니다 – 아키텍처에 따라 2배에서 3배 정도 더 걸립니다.

PyPy2.7을 사용하여 PyPy를 빌드하는 경우에도, 변환에는 시간이 오래 걸리며 – 빠른 머신에서 20분 – 메모리도 많이 소모합니다. 32비트 머신에서는 최소 3GB, 64비트 머신에서는 6GB의 메모리가 필요합니다.

시작하기 전에

저희의 일반적인 개발 워크플로는 테스트 주도 개발을 사용함으로써 전체 변환을 피합니다. PyPy 개발 방법에 대한 자세한 내용은 here를 참고하시기 바라며, 최신 번역(translation)된 (바라건대 작동하는) 바이너리 패키지는 저희 buildbot의 nightly builds에서 확인하실 수 있습니다.

테스트를 실행하려면 아래의 빌드 의존성이 필요합니다.

저장소를 복제합니다

직접 PyPy를 컴파일하고 싶거나 수정하고 싶다면, 소스 코드 사본을 받아야 합니다. 이는 downloading them from the download page를 하거나, git을 사용하여 저장소에서 체크아웃하는 방법으로 가능합니다. 최신 개발 버전에 접근하고 싶다면 git 사용을 권장합니다.

명령줄, DOS 박스 또는 터미널에서 다음 명령을 실행해야 합니다:

git clone https://github.com/pypy/pypy.git

이것은 저장소를 클론하여 pypy라는 디렉터리에 배치하며, pypy/pypy에서 PyPy 소스를, pypy/pypy/doc에서 문서 파일을 얻게 됩니다. 저희는 tip이 항상 안정적으로 유지되도록 노력하지만, 가끔 깨질 수 있습니다. our nightly tests를 확인해 보는 것도 좋습니다: 예를 들어 “963e808156b3”처럼 최소한 {linux64} 테스트를 통과한(success 줄의 + 기호에 해당) 리비전 해시를 찾은 다음, 클론한 저장소에서 다음을 사용해 이 리비전으로 전환합니다:

git checkout XXXXX

여기서 XXXXX는 리비전 해시입니다.

빌드 타임 의존성 설치

Note

Windows에서 Python 인터프리터를 번역(translation)하는 방법에 대한 몇 가지 힌트는 Windows 문서를 참조하십시오.

호스트 Python2에는 CFFI가 설치되어 있어야 합니다. PyPy에서 번역(translation)하는 경우, CFFI는 이미 설치되어 있습니다. CPython에서 번역(translation)하는 경우, 예를 들어 python2.7 -mpip install cffi를 사용하여 설치해야 합니다.

C 변환 백엔드를 사용해 Unix에서 PyPy를 빌드하려면 최소한 C 컴파일러와 make가 설치되어 있어야 합니다. 또한, 일부 선택적 모듈은 추가 의존성을 가지고 있습니다:

cffi, ctypes
libffi, pkg-config
zlib
libz
bz2
libbz2
pyexpat
libexpat1
_vmprof
libunwind (선택 사항, 런타임에 동적으로 로드됨)

PyPy를 빌드하기 전에 이러한 라이브러리(개발 헤더 포함)가 설치되어 있는지 확인하십시오. 그렇지 않으면 결과 바이너리에 이 모듈들이 포함되지 않습니다. 또한, PyPy를 빌드한 후에는 다음 라이브러리들이 존재해야 합니다. 그렇지 않으면 해당 CFFI 모듈이 빌드되지 않습니다(이를 빌드하려면 lib_pypy/pypy_tools/build_cffi_imports.py를 실행하거나 다시 실행하면 됩니다. 전체 PyPy를 다시 번역(translation)할 필요는 없습니다):

sqlite3
libsqlite3
_ssl, _hashlib
libssl
curses
libncurses-dev (PyPy2용) libncursesw-dev (PyPy3용)
gdbm
libgdbm-dev
tk
tk-dev
lzma (PyPy3 전용)
liblzma 또는 libxz, 버전 5 이상

번역(translation)되지 않은 테스트를 실행하려면 Boehm 가비지 컬렉터인 libgc 버전 7.4 이상이 필요합니다.

Debian과 Ubuntu(16.04 이상)에서는 다음 명령으로 모든 빌드 타임 의존성을 설치할 수 있습니다:

apt-get install gcc make libffi-dev pkg-config zlib1g-dev libbz2-dev \
libsqlite3-dev libncurses5-dev libexpat1-dev libssl-dev libgdbm-dev \
tk-dev libgc-dev \
liblzma-dev libncursesw5-dev     # These two are only needed on PyPy3

Fedora에서:

dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
sqlite-devel ncurses-devel expat-devel openssl-devel tk-devel \
gdbm-devel gc-devel \
xz-devel  # For lzma on PyPy3.

SLES11에서:

zypper install gcc make python-devel pkg-config \
zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \
libexpat-devel libffi-devel \
xz-devel # For lzma on PyPy3.
(XXX plus the SLES11 version of libgdbm-dev and tk-dev)

Mac OS X에서:

현재 PyPy는 Apple Silicon(M1, Arm64)과 X86_64에서의 빌드를 모두 지원합니다. 빌드 시 arm64 또는 x86_64 중 하나의 적절한 툴체인을 사용해야 합니다. “Fat” universal2 빌드는 지원되지 않습니다.

빌드 시점 의존성 대부분은 Developer Tools와 함께 설치됩니다. libx11tkinter에 필요합니다. openssl은 테스트를 위해 설치되어야 하며, brew로 제공되는 pypy를 사용하면 변환 속도가 빨라집니다. 아키텍처에 맞는 x86_64 또는 arm64 brew 명령을 사용해야 한다는 점에 유의하십시오:

xcode-select --install
    brew install openssl pypy pkg-config libx11
# expose openssl in the cffi _ssl_build script
export CPPFLAGS=$(pkg-config openssl --cflags-only-I)
export LDFLAGS=$(pkg-config openssl --libs-only-L)

변환에 영향을 미칠 환경 변수를 설정하십시오

다음 환경 변수를 사용하여 결과를 조정할 수 있습니다:

결과
CC 사용할 컴파일러
PYPY_MULTIARCH pypy 3.7+: posix에서는 sys.platform._multiarch에 반영되며, 기본값은 x86_64-linux-gnu입니다.
PYPY_USESSION_DIR 임시 파일을 위한 기본 디렉터리이며, 보통 $TMP입니다
PYPY_USESSION_BASENAME from rpython.tools import udir를 호출할 때마다 $PYPY_USESSION_DIR/usession-$PYPY_USESSION_BASENAME-N 임시 디렉터리를 얻게 되며, 여기서 N은 호출할 때마다 증가합니다
PYPY_USESSION_KEEP 보관할 오래된 임시 디렉터리의 개수를 지정하며, 그보다 오래된 것은 삭제됩니다. 기본값은 3입니다.

변환을 실행하십시오

번역(translation) 대상 Python은 CFFI가 필요하므로, virtualenv를 만들고 그곳에서 pip install cffi를 실행하는 것이 가장 좋습니다.

저희는 보통 pypy/goal 디렉터리에서 번역(translation)을 수행하므로, 이어지는 모든 명령어는 $pwd가 그곳에 있다고 가정합니다.

JIT를 사용해 번역(translation)하기:

pypy2.7 ../../rpython/bin/rpython --opt=jit

JIT 없이 번역(translation):

pypy2.7 ../../rpython/bin/rpython --opt=2

참고로, 이는 targetpypystandalone.py 파일을 통해 pypy를 번역(translation)하는 것이며, 따라서 이것들은 다음의 축약형입니다:

pypy2.7 ../../rpython/bin/rpython <rpython options> targetpypystandalone.py <pypy options>

--help를 통해 두 옵션 위치 모두에서 더 많은 도움말을 확인할 수 있으며, 더 자세한 정보는 PyPy를위한 설정 옵션 섹션에서 찾을 수 있습니다.

(여기서 pypy2.7 대신 python2를 사용할 수도 있는데, 시간이 더 걸리지만 이 역시 동작합니다.)

모든 것이 올바르게 작동하면 다음과 같이 진행됩니다:

  1. RPython translation chain을 실행하여, PyPy 인터프리터 전체의 데이터베이스를 생성합니다. 현재 이 단계는 단일 스레드로 동작하며, RAM을 많이 사용합니다. 이 단계의 일부로, 체인은 PYPY_USESSION_DIR 환경 변수로 제어되는 디렉터리에 다수의 C 코드 파일과 이를 컴파일할 Makefile을 생성합니다.
  2. Makefile을 실행하여 실행 파일 pypy-cpypy3.XX-c를 생성합니다. 이 단계는 머신에서 사용 가능한 모든 코어를 활용할 수 있습니다.
  3. 필요한 바이너리를 현재 디렉터리로 복사합니다.
  4. cffi 기반 stdlib 모듈에 대해 c-확장 모듈을 생성합니다.

생성된 실행 파일은 대부분 일반 Python 인터프리터처럼 동작하며(PyPy와 CPython의 차이점 참조), 테스트하거나, 새 virtualenv의 기본 인터프리터로 사용하거나, 빌드 머신과 동일한 OS를 실행하는 다른 머신에 설치할 수 있는 바이너리로 패키징하는 데 바로 사용할 수 있습니다.

4단계는 단순히 편의를 위해 수행되는 것이며, 어떤 단계든 이전 단계를 다시 실행하지 않고도 재실행할 수 있습니다.

PyPy의 디버그 빌드 만들기

Makefilemake lldebug 또는 make lldebug0 타겟으로 다시 실행하십시오. 그러면 디버거에서 실행하는 것이 의미 있는 방식으로 빌드됩니다. 디버그 정보를 추가하기 위해 적절한 컴파일 플래그가 추가되며, lldebug0의 경우 컴파일러 최적화가 완전히 비활성화됩니다. 디버거에서 멈추면 rpython 변환 단계에서 기계적으로 생성된 매우 장황한 C 코드를 보게 되며, 이를 rpython 코드와 연관지으려면 조금 읽어봐야 합니다.

표준 라이브러리를 위한 cffi 임포트 라이브러리 빌드

다양한 표준 라이브러리 모듈은 out-of-line API mode에서 cffi 임포트 라이브러리를 생성하기 위해 별도의 빌드 단계가 필요합니다. 이는 다음 명령으로 수행됩니다.:

cd pypy/goal
PYTHONPATH=../.. ./pypy-c ../../lib_pypy/pypy_tools/build_cffi_imports.py

패키징(설치 준비)

PyPy를 시스템 전역에 설치하려면, 같은 머신에 설치하는 경우라도 패키징이 필요합니다. 그 이유는 패키징 과정에서 여러 추가 기능을 미리 준비해 두는데, 이는 root로 설치된 PyPy에서는 지연 처리될 수 없기 때문입니다. 일반 사용자에게는 쓰기 권한이 없기 때문입니다. 이는 주로 처음 임포트될 때 컴파일되는 라이브러리들과 관련이 있습니다.

python pypy/tool/release/package.py --archive-name=pypy-VER-PLATFORM

이는 정리되고 준비된 계층 구조와, 동일한 내용을 담은 .tar.bz2를 생성합니다. 이들을 찾을 수 있는 디렉터리가 출력됩니다. 그런 다음 파일 계층 구조를 옮기거나 .tar.bz2를 올바른 위치에 압축 해제하면 됩니다.

커스텀 스크립트는 항상 오래된 상태가 되기 마련이므로 package.py를 사용하는 것이 권장됩니다. 그래도 커스텀 스크립트를 작성하고 싶다면, 놓치기 쉬운 부분을 하나 짚어 두겠습니다: 일부 모듈은 CFFI로 작성되어 있어 어느 정도의 컴파일이 필요합니다. 이를 미리 컴파일하지 않은 채 root 권한으로 PyPy를 설치하면, 일반 사용자는 오류를 겪게 됩니다.

설치

PyPy는 실행 파일의 위치에 따라 라이브러리의 위치를 동적으로 찾습니다. 일반적인 PyPy2 설치의 디렉터리 계층 구조는 다음과 같습니다:

./bin/pypy
./include/
./lib_pypy/
./lib-python/2.7
./site-packages/

PyPy3.8+설치는 CPython 레이아웃과 일치합니다.:

./bin/
./include/pypy3.8/include
./lib/pypy3.8

위에 표시된 계층 구조는 PREFIX 디렉터리를 기준으로 합니다. PREFIX는 실행 파일이 있는 디렉터리에서 시작하여, lib_pypylib-python/2.7을 포함하는 디렉터리를 찾을 때까지 파일 시스템을 “거슬러 올라가며” 계산됩니다(pypy2 기준).

유닉스 계열 시스템에 PyPy를 시스템 전역에 설치하려면, 전체 계층 구조를 별도로 두고(예: /opt/pypy) pypy 실행 파일에 대한 심볼릭 링크를 /usr/bin 또는 /usr/local/bin에 두는 것이 권장됩니다.

실행 파일이 적절한 라이브러리를 찾지 못하면 debug: WARNING: library path not found, using compiled-in sys.path를 보고한 다음 정상적으로 계속 진행을 시도합니다. 기본 경로를 사용할 수 있다면 대부분의 코드는 문제없이 동작합니다. 하지만 sys.prefix는 설정되지 않으며, 일부 기존 라이브러리는 이런 경우가 절대 없다고 가정합니다.