Table of contents
기본적으로 파이썬은 인터프리터에서 실행되는 언어이기에 컴파일이 안 됩니다. 소스를 수정하는 족족 인터프리터가 바로바로 해석할 수 있으니 개발 속도가 빠르다는 장점이 있습니다. 다만 그만큼 속도가 느리고 내 코드를 다른 이들이 마음대로 볼 수 있다는 단점이 있습니다. 오픈 소스라면야 상관없겠다만 상품을 만든다는 입장에서는 난감할 수밖에 없습니다. 또한 python과 모듈에 대한 버전 문제도 복잡하게 얽혀 있기에 배포할 시에 이들을 독립된 공간에 묶어서 한 번에 배포하니 프로그램 하나에 대한 크기가 너무 커진다는 단점도 존재합니다.
이러한 단점을 극복하기 위해서 PyInstaller라는 모듈이 만들어졌으나, 여러 파일들을 하나로 묶어 주는 역할만 할 뿐 프로그램의 속도와 크기에는 미미한 변화만이 있을 뿐이며 묶음을 풀어서 코드를 확인하기도 그다지 어려운 일이 아닙니다. 이를 해결하기 위해서는 바이너리 파일로 컴파일을 할 필요가 있습니다. 현재 이를 위에서 유명한 방법으로 2가지가 존재합니다.
1.
cython을 사용하여 python파일을 c 파일로 변환 후 직접 c 파일을 컴파일하는 방법이 있습니다.
2.
nuitka을 사용하여 python 파일을 실행 파일로 만들어줍니다.
cython을 사용하면 사용자가 직접 c 파일을 컴파일 해줘야 하니 어렵습니다. 따라서 nuitka를 사용해 보려고 합니다. 단, nuitka 는 python interpreter를 포함하기 때문에 크기가 더 크고 성능도 더 낮습니다. (크기의 경우 인터프리터의 크기는 고정되어 있으니 큰 프로젝트일 수록 크기의 차이는 무시할 수 있을 것입니다.)
Nuitka
우선 pip install kivy_examples로 demo를 설치 후에 프로젝트 경로에 복사해줍니다.
# python -m virtualenv kivy_project_first
# cd kivy_project_first
# source bin/activate
# mkdir app_build_binary
pip install kivy_examples
cp -r share/kivy_examples/demo/showcase/* app_build_binary
Bash
복사
Linux(ubuntu)
WSL도 똑같습니다.
prerequsite
sudo apt install g++ python3-dev patchelf
Bash
복사
installation
pip로 nuitka를 설치해줍니다.
pip install nuitka
Bash
복사
compile & execute
ccache를 설치하면, sudo apt install ccache 더 빠른 속도로 빌드할 수 있습니다.
# mkdir build_linux
nuitka --standalone --onefile --output-dir=build_linux main.py
Bash
복사
system DLL/SO를 포함하지 않는 실행 파일을 build_linux/에 생성합니다.
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libgcc_s.so.1'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libGL.so.1'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libXrender.so.1'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libX11.so.6'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libGLdispatch.so.0'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libGLX.so.0'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libxcb.so.1'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libXau.so.6'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libXdmcp.so.6'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libbsd.so.0'
Nuitka-Inclusion: Not including system DLL '/lib/x86_64-linux-gnu/libmd.so.0'
아래 명령어를 통해 binary가 명시적으로 의존하고 있는 동적 라이브러리를 확인할 수 있습니다.
ldd build_linux/main.bin
# linux-vdso.so.1 (0x00007ffc59880000)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff992960000)
# /lib64/ld-linux-x86-64.so.2 (0x00007ff992bd0000)
Bash
복사
이제 실행해보도록 합니다. 제 환경에서 실행한 결과는 다음과 같습니다.
└❯ ./build_linux/main.bin
[INFO ] [Logger ] Record log in /home/sunghee/.kivy/logs/kivy_24-12-15_12.txt
[INFO ] [Kivy ] v2.3.0
[INFO ] [Kivy ] Installed at "/tmp/onefile_71664_1734240235_10492/kivy/__init__.py"
[INFO ] [Python ] v3.12.8 (main, Dec 13 2024, 23:32:03) [GCC 11.4.0]
[INFO ] [Python ] Interpreter at "/tmp/onefile_71664_1734240235_10492/python"
[INFO ] [Logger ] Purge log fired. Processing...
[INFO ] [Logger ] Purge finished!
[INFO ] [Factory ] 195 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer ignored)
Traceback (most recent call last):
File "/tmp/onefile_71664_1734240235_10492/main.py", line 243, in <module>
File "/tmp/onefile_71664_1734240235_10492/kivy/app.py", line 955, in run
File "/tmp/onefile_71664_1734240235_10492/kivy/app.py", line 925, in _run_prepare
File "/tmp/onefile_71664_1734240235_10492/main.py", line 76, in build
File "/tmp/onefile_71664_1734240235_10492/main.py", line 97, in go_next_screen
File "/tmp/onefile_71664_1734240235_10492/main.py", line 121, in load_screen
File "/tmp/onefile_71664_1734240235_10492/kivy/lang/builder.py", line 308, in load_file
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/onefile_71664_1734240235_10492/data/screens/accordions.kv'
Bash
복사
에러가 발생했습니다. 오직 소스파일만 build하고 소스코드 외의 다른 resource들을 포함하지 않아서 발생한 에러입니다. 다행히도 nuitka의 두 옵션, --include-data-dir과 --include-data-files를 통해 이를 해결할 수 있습니다. 두 옵션을 사용하여 다시 빌드하여 실행해보겠습니다.
nuitka --standalone --onefile --output-dir=build_linux --include-data-dir=data=data --include-data-files=showcase.kv=showcase.kv main.py
Bash
복사
└❯ ./build_linux/main.bin
[INFO ] [Logger ] Record log in /home/sunghee/.kivy/logs/kivy_24-12-15_20.txt
[INFO ] [Kivy ] v2.3.0
[INFO ] [Kivy ] Installed at "/tmp/onefile_92266_1734244814_36857/kivy/__init__.py"
[INFO ] [Python ] v3.12.8 (main, Dec 13 2024, 23:32:03) [GCC 11.4.0]
[INFO ] [Python ] Interpreter at "/tmp/onefile_92266_1734244814_36857/python"
[INFO ] [Logger ] Purge log fired. Processing...
[INFO ] [Logger ] Purge finished!
[INFO ] [Factory ] 195 symbols loaded
[INFO ] [Image ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer ignored)
[ERROR ]
Traceback (most recent call last):
File "/tmp/onefile_92266_1734244814_36857/kivy/lang/parser.py", line 553, in execute_directives
File "<frozen importlib._bootstrap>", line 1466, in __import__
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1324, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'kivy.extras'
Bash
복사
ModuleNotFoundError가 발생했습니다. nuitka가 완벽하게 모듈을 다 찾아서 빌드해주진 못하는 것 같습니다. ( __import__(..), importlib(..) 등으로 동적 import하는 것들을 못 찾는 것으로 보입니다. ) 시간이 많이 걸려도 trial error를 통해 빌드 및 실행을 해보았습니다. 최종적으로 kivy.extras와 pygments라는 모듈을 같이 build하니 정상 동작하는 것을 확인할 수 있었습니다.
nuitka --standalone --onefile --output-dir=build_linux --include-data-dir=data=data --include-data-files=showcase.kv=showcase.kv --include-package=kivy.extras --include-package=pygments main.py
build_linux/main.bin
Bash
복사
Figure1 - Kivy demo binary build
Figure2 - Kivy demo binary build
android build 때도 그렇고 module을 제가 직접 적어줘야하는 것을 보니 바이너리 파일을 만드는 것은 아직 미흡한 부분이 많은 것 같습니다. 그래도 파이썬을 통해 여러 platform에서 동일한 framework로 GUI 프로그래밍을 할 수 있다는 점은 상당한 메리트인 거 같습니다.