|
|
@@ -1,66 +1,192 @@
|
|
|
-from setuptools import setup, find_packages
|
|
|
-from setuptools.command.build_py import build_py
|
|
|
-from setuptools.command.install import install
|
|
|
-import compileall
|
|
|
import os
|
|
|
import sys
|
|
|
+import re
|
|
|
import shutil
|
|
|
-from pathlib import Path
|
|
|
+import subprocess
|
|
|
+from setuptools import setup, find_packages
|
|
|
+from setuptools.command.build_py import build_py
|
|
|
+from setuptools.command.bdist_wheel import bdist_wheel
|
|
|
+
|
|
|
+# ========== 配置 ==========
|
|
|
+PACKAGE_NAME = "repositoryZN"
|
|
|
+COMPILE_DIRS = ["utils"] # 编译 utils 目录和根目录下的 .py
|
|
|
+INSTALL_REQUIRES = [] # 无内部依赖
|
|
|
+CLEAN_COMPILED_AFTER_BUILD = True
|
|
|
+# =========================
|
|
|
+
|
|
|
+def log(msg):
|
|
|
+ print(f"[SETUP] {msg}")
|
|
|
+
|
|
|
+def compile_with_nuitka(py_files):
|
|
|
+ for py_file in py_files:
|
|
|
+ if os.path.basename(py_file) == "__init__.py":
|
|
|
+ continue
|
|
|
+ log(f"编译: {py_file}")
|
|
|
+
|
|
|
+ output_dir = os.path.dirname(py_file)
|
|
|
+ cmd = [
|
|
|
+ sys.executable, "-m", "nuitka",
|
|
|
+ "--module",
|
|
|
+ "--no-pyi-file",
|
|
|
+ "--remove-output",
|
|
|
+ f"--output-dir={output_dir}",
|
|
|
+ py_file
|
|
|
+ ]
|
|
|
+ if sys.platform == "win32":
|
|
|
+ cmd.append("--mingw64")
|
|
|
+ result = subprocess.run(cmd, capture_output=True, text=True)
|
|
|
+ if result.returncode != 0:
|
|
|
+ log(f"编译失败: {py_file}\n{result.stderr}")
|
|
|
+ sys.exit(1)
|
|
|
|
|
|
-compileDirs=['utils']
|
|
|
+ base_name = os.path.splitext(os.path.basename(py_file))[0]
|
|
|
+ found = False
|
|
|
+ for ext in [".pyd", ".so"]:
|
|
|
+ pattern = re.escape(base_name) + r".*" + re.escape(ext)
|
|
|
+ for f in os.listdir(output_dir):
|
|
|
+ if re.match(pattern, f):
|
|
|
+ src = os.path.join(output_dir, f)
|
|
|
+ dst = os.path.join(output_dir, base_name + ext)
|
|
|
+ shutil.move(src, dst)
|
|
|
+ log(f"重命名: {src} -> {dst}")
|
|
|
+ found = True
|
|
|
+ break
|
|
|
+ if found:
|
|
|
+ break
|
|
|
+ if not found:
|
|
|
+ log(f"错误:未找到编译产物 {py_file}")
|
|
|
+ sys.exit(1)
|
|
|
+
|
|
|
+def clean_build_dir():
|
|
|
+ dirs_to_clean = ["build", f"{PACKAGE_NAME}.egg-info"]
|
|
|
+ for d in dirs_to_clean:
|
|
|
+ if os.path.exists(d):
|
|
|
+ shutil.rmtree(d)
|
|
|
+ log(f"已删除: {d}")
|
|
|
|
|
|
class CustomBuildPy(build_py):
|
|
|
def run(self):
|
|
|
- # 获取当前 Python 版本信息
|
|
|
- py_version = f".cpython-{sys.version_info.major}{sys.version_info.minor}"
|
|
|
+ src_root = os.getcwd()
|
|
|
+ log(f"源码根目录: {src_root}")
|
|
|
+
|
|
|
+ # 1. 编译所有需要编译的目录(包括根目录 ".")
|
|
|
+ for compile_dir in COMPILE_DIRS:
|
|
|
+ if compile_dir == ".":
|
|
|
+ target_dir = src_root
|
|
|
+ else:
|
|
|
+ target_dir = os.path.join(src_root, compile_dir)
|
|
|
+ if not os.path.isdir(target_dir):
|
|
|
+ log(f"警告: 目录不存在 {target_dir}")
|
|
|
+ continue
|
|
|
+ all_py = []
|
|
|
+ for root, _, files in os.walk(target_dir):
|
|
|
+ for file in files:
|
|
|
+ if file.endswith(".py"):
|
|
|
+ all_py.append(os.path.join(root, file))
|
|
|
+ if all_py:
|
|
|
+ compile_with_nuitka(all_py)
|
|
|
+ else:
|
|
|
+ log(f"在 {target_dir} 中没有找到 .py 文件")
|
|
|
|
|
|
- for dir in compileDirs:
|
|
|
- for root,_,subFiles in os.walk(dir):
|
|
|
- compileall.compile_dir(root, force=True)
|
|
|
+ # 2. 手动复制:对于 utils 目录作为顶级包,对于根目录下的文件直接复制到 build/lib 根目录
|
|
|
+ build_lib = self.build_lib
|
|
|
+ if not build_lib:
|
|
|
+ build_lib = os.path.join(src_root, "build", "lib")
|
|
|
|
|
|
- for file in subFiles:
|
|
|
- if file.endswith('.pyc'):
|
|
|
- pyc_path = os.path.join(root, file)
|
|
|
- new_File = file.replace(py_version, '')
|
|
|
- new_path=os.path.join(Path(root).parent,new_File)
|
|
|
- shutil.move(pyc_path, new_path)
|
|
|
+ # 处理 utils 目录(作为包)
|
|
|
+ utils_src = os.path.join(src_root, "utils")
|
|
|
+ if os.path.isdir(utils_src):
|
|
|
+ utils_dst = os.path.join(build_lib, "utils")
|
|
|
+ self.mkpath(utils_dst)
|
|
|
+ for root, _, files in os.walk(utils_src):
|
|
|
+ rel_path = os.path.relpath(root, utils_src)
|
|
|
+ target_subdir = os.path.join(utils_dst, rel_path) if rel_path != '.' else utils_dst
|
|
|
+ self.mkpath(target_subdir)
|
|
|
+ for file in files:
|
|
|
+ src_file = os.path.join(root, file)
|
|
|
+ if file == "__init__.py":
|
|
|
+ dst_file = os.path.join(target_subdir, file)
|
|
|
+ self.copy_file(src_file, dst_file)
|
|
|
+ log(f"复制 {src_file} -> {dst_file}")
|
|
|
+ elif file.endswith(".pyd") or file.endswith(".so"):
|
|
|
+ dst_file = os.path.join(target_subdir, file)
|
|
|
+ self.copy_file(src_file, dst_file)
|
|
|
+ log(f"复制 {src_file} -> {dst_file}")
|
|
|
|
|
|
- super().run()
|
|
|
+ # 处理根目录下的文件(作为顶级模块,直接放在 build/lib 根目录)
|
|
|
+ for file in os.listdir(src_root):
|
|
|
+ if file.endswith(".pyd") or file.endswith(".so"):
|
|
|
+ src_file = os.path.join(src_root, file)
|
|
|
+ dst_file = os.path.join(build_lib, file)
|
|
|
+ self.copy_file(src_file, dst_file)
|
|
|
+ log(f"复制根模块 {src_file} -> {dst_file}")
|
|
|
+ elif file == "__init__.py":
|
|
|
+ # 如果根目录有 __init__.py,也复制(让根目录本身成为一个包)
|
|
|
+ src_file = os.path.join(src_root, file)
|
|
|
+ dst_file = os.path.join(build_lib, file)
|
|
|
+ self.copy_file(src_file, dst_file)
|
|
|
+ log(f"复制根 __init__.py {src_file} -> {dst_file}")
|
|
|
|
|
|
-class InstallCommand(install):
|
|
|
+ # 3. 清理源码目录中的 .pyd/.so
|
|
|
+ if CLEAN_COMPILED_AFTER_BUILD:
|
|
|
+ for compile_dir in COMPILE_DIRS:
|
|
|
+ if compile_dir == ".":
|
|
|
+ target_dir = src_root
|
|
|
+ else:
|
|
|
+ target_dir = os.path.join(src_root, compile_dir)
|
|
|
+ if not os.path.isdir(target_dir):
|
|
|
+ continue
|
|
|
+ for root, _, files in os.walk(target_dir):
|
|
|
+ for file in files:
|
|
|
+ if file.endswith(".pyd") or file.endswith(".so"):
|
|
|
+ os.remove(os.path.join(root, file))
|
|
|
+ log(f"清理源码编译产物: {os.path.join(root, file)}")
|
|
|
+
|
|
|
+class CustomBdistWheel(bdist_wheel):
|
|
|
def run(self):
|
|
|
- super().run()
|
|
|
- # Remove all .py files from the installed package
|
|
|
- # 若用于开发,可查看导入的自定义package 则注释本代码段
|
|
|
- # 若用于部署交付,可应用本代码
|
|
|
- # for root, _, files in os.walk(self.install_lib):
|
|
|
- # for file in files:
|
|
|
- # if file.endswith('.py'):
|
|
|
- # os.remove(os.path.join(root, file))
|
|
|
-
|
|
|
-setup(
|
|
|
- name='repositoryZN',
|
|
|
- version='1.2.202505131440',
|
|
|
- description='Repository Package', # 描述信息
|
|
|
- author='Xie Zhou Yang', # 作者
|
|
|
- packages=find_packages(),
|
|
|
- cmdclass={
|
|
|
- 'build_py': CustomBuildPy,
|
|
|
- 'install': InstallCommand,
|
|
|
- },
|
|
|
- package_data={
|
|
|
- 'utils': ['*.pyc'],
|
|
|
- 'utils.minioUtil': ['*.pyc'],
|
|
|
- 'utils.rdbmsUtil': ['*.pyc']
|
|
|
- },
|
|
|
- exclude_package_data={'': ['*.py']}
|
|
|
-)
|
|
|
-
|
|
|
-# 获取 setup.py 所在的绝对路径
|
|
|
-setup_dir = os.path.abspath(os.path.dirname(__file__))
|
|
|
-# 编译打包后,删除pyc后缀文件
|
|
|
-for root, _, files in os.walk(setup_dir):
|
|
|
- for file in files:
|
|
|
- if file.endswith('.pyc') or file.endswith('.c'):
|
|
|
- print(os.path.join(root, file))
|
|
|
- os.remove(os.path.join(root, file))
|
|
|
+ self.run_command("build_py")
|
|
|
+ self.plat_name = self.get_platform()
|
|
|
+ bdist_wheel.run(self)
|
|
|
+
|
|
|
+ def get_platform(self):
|
|
|
+ if sys.platform == "win32":
|
|
|
+ return "win_amd64"
|
|
|
+ elif sys.platform == "linux":
|
|
|
+ return "linux_x86_64"
|
|
|
+ else:
|
|
|
+ return super().get_platform()
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ try:
|
|
|
+ subprocess.run([sys.executable, "-m", "nuitka", "--version"], capture_output=True, check=True)
|
|
|
+ except subprocess.CalledProcessError:
|
|
|
+ log("请先安装 Nuitka: pip install nuitka", "ERROR")
|
|
|
+ sys.exit(1)
|
|
|
+
|
|
|
+ clean_build_dir()
|
|
|
+
|
|
|
+ # 动态确定要安装的包和模块
|
|
|
+ packages = []
|
|
|
+ if os.path.isdir("utils"):
|
|
|
+ packages.append("utils")
|
|
|
+ # 根目录下的顶级模块(如果存在这些 .py 文件,它们会被编译成 .pyd 并安装)
|
|
|
+ py_modules = []
|
|
|
+ for mod in ["jsonUtil", "logUtil", "csvFileUtil"]:
|
|
|
+ if os.path.exists(f"{mod}.py"):
|
|
|
+ py_modules.append(mod)
|
|
|
+
|
|
|
+ setup(
|
|
|
+ name=PACKAGE_NAME,
|
|
|
+ version="1.0.202508190930",
|
|
|
+ description="Repository ZN Package (compiled, flat structure)",
|
|
|
+ author="Xie Zhou Yang",
|
|
|
+ packages=packages,
|
|
|
+ py_modules=py_modules,
|
|
|
+ package_dir={"": "."},
|
|
|
+ cmdclass={
|
|
|
+ "build_py": CustomBuildPy,
|
|
|
+ "bdist_wheel": CustomBdistWheel,
|
|
|
+ },
|
|
|
+ install_requires=INSTALL_REQUIRES,
|
|
|
+ zip_safe=False,
|
|
|
+ )
|