llm-agent-backend/build/compile.py
2026-06-06 19:29:23 +03:00

94 lines
4.3 KiB
Python

import os
import shutil
from setuptools import setup, Extension
from Cython.Build import cythonize
def build_project():
# 1. Сначала определяем все абсолютные пути, пока мы в исходной директории
build_dir = os.path.dirname(os.path.abspath(__file__)) # папка build/
project_root = os.path.abspath(os.path.join(build_dir, "..")) # корень проекта
source_app = os.path.join(project_root, "app")
dist_dir = os.path.join(project_root, "dist")
dist_app = os.path.join(dist_dir, "app")
build_main_file = os.path.join(build_dir, "main.py")
dist_main_file = os.path.join(dist_dir, "main.py")
print("🚀 Старт сборки проекта...")
# 2. Пересоздаем чистую папку dist/
if os.path.exists(dist_dir):
shutil.rmtree(dist_dir)
os.makedirs(dist_dir)
# 3. Копируем исходный код app/ в dist/app/
shutil.copytree(source_app, dist_app)
# Сохраняем текущую директорию корня, чтобы вернуться в неё в конце
original_cwd = os.getcwd()
# СИСТЕМНЫЙ СДВИГ: Переносим рабочую директорию процесса внутрь dist/app/
# Теперь для компилятора корнем является именно dist/app/
os.chdir(dist_app)
# 4. Собираем модули для компиляции (сканируем текущую папку, так как мы уже внутри dist/app)
extensions = []
for root, _, files in os.walk("."):
for file in files:
if file.endswith('.py') and not file.startswith('__'):
full_path = os.path.join(root, file)
# Вычисляем путь относительно dist/app
clean_path = os.path.relpath(full_path, ".")
# Формируем имя модуля для Python (например, workflows.graph_manager)
module_name = clean_path.replace(os.sep, '.').rstrip('.py')
if module_name == "run":
extensions.append(Extension("run", [clean_path]))
else:
extensions.append(Extension(module_name, [clean_path]))
# 5. Запускаем компиляцию (теперь --inplace положит бинарники строго в dist/app/)
setup(
name="AppBinary",
script_args=["build_ext", "--inplace"],
ext_modules=cythonize(
extensions,
language_level="3",
compiler_directives={
'annotation_typing': False, # Отключаем строгую типизацию (фиксит max_tokens)
'binding': True, # Сохраняем Python-совместимость методов
'always_allow_keywords': True # Разрешаем передачу None в именованные аргументы
}
),
)
# 6. Очищаем dist/app/ от исходного кода
print("\n🧹 Удаление исходного кода из папки dist/app/...")
for root, _, files in os.walk("."):
for file in files:
if (file.endswith('.py') and not file.startswith('__')) or file.endswith('.c'):
try:
os.remove(os.path.join(root, file))
except OSError:
pass
# Удаляем временную папку сборки компилятора C++
if os.path.exists("build"):
shutil.rmtree("build")
# Возвращаем рабочую директорию обратно в корень проекта
os.chdir(original_cwd)
# 7. Копируем файл build/main.py в dist/main.py
if os.path.exists(build_main_file):
shutil.copy(build_main_file, dist_main_file)
print("📄 Файл build/main.py успешно скопирован в dist/main.py")
else:
print("⚠️ Ошибка: Файл build/main.py не найден, нечего копировать!")
print("\n✅ Сборка успешно завершена! Папка dist/ готова к деплою.")
if __name__ == "__main__":
build_project()