Metadata-Version: 2.1
Name: py2pydso
Version: 1.4.5
Summary: Compile Python source files into .pyd or .so extension modules for distribution and source protection.
Home-page: https://github.com/zhenzi0322-package/py2pydso
Author: zhenzi0322
Author-email: zhenzi0322 <82131529@qq.com>
License: MIT
Requires-Python: >=3.8
description-content-type: text/markdown
Description:
 <p align="center">
   <h1>py2pydso</h1>
   <a href="https://pypi.org/project/py2pydso/"><img src="https://img.shields.io/pypi/v/py2pydso.svg" alt="PyPI version"></a>
   <a href="https://pypi.org/project/py2pydso/"><img src="https://img.shields.io/badge/Python-3.8~3.14-3776AB?logo=python&logoColor=white" alt="Python"></a>
   <a href="https://github.com/zhenzi0322-package/py2pydso/blob/master/LICENSE"><img src="https://img.shields.io/pypi/l/py2pydso.svg" alt="License"></a>
   <a href="https://tool.long920.cn/py2pydso"><img src="https://app.readthedocs.org/projects/zhenzi0322-tool/badge/?version=latest" alt="Documentation Status"></a>
 </p>
 
 > 将`Python`源文件编译为`.pyd/.so`原生扩展，以便分发和保护源代码。
 
 ---
 
 ## ✨ Features
 
 - 🔒 **源码保护** — 将 `.py` 编译为 `.pyd`/`.so` 原生扩展，不暴露源码
 - 📦 **三种编译模式** — 单文件 / 模块目录 / 完整 wheel 包
 - 🗂️ **智能过滤** — 自动保留 `__init__.py` 等元文件，支持自定义排除
 - 📝 **类型提示** — 可选生成 `.pyi` 存根文件（`--pyi`），保留 IDE 补全体验
 - 🌍 **跨平台** — `Windows` (`.pyd`) / `Linux` / `macOS` (`.so`) 全支持
 
 ---
 
 ## 安装
 
 ```bash
 pip install py2pydso
 ```
 
 安装完成后，可通过以下命令验证：
 
 ```bash
 python -m py2pydso --help
 ```
 
 ### 依赖
 
 `py2pydso` 在构建 wheel 包（`package` 子命令）时会自动安装项目依赖：
 
 | 依赖 | 用途 |
 |------|------|
 | `Cython` | 将 `.py` 转译为`C`代码并编译为原生扩展 |
 | `setuptools` | 驱动编译流程 |
 | `mypy` | 通过 stubgen 生成 `.pyi` 类型提示文件（指定 `--pyi` 时使用） |
 | `tomli` | 解析 `pyproject.toml`（Python < 3.11 时自动安装） |
 
 ### C 编译器
 
 编译原生扩展需要 C 编译器，请根据平台安装：
 
 - **Windows**: [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/)（勾选 "C++ build tools"）
 - **macOS**: `xcode-select --install`
 - **Linux**: `sudo apt install build-essential gcc`
 
 ## 使用方式
 
 ### 1. 编译文件
 
 ```bash
 # 编译单个文件，输出到源文件同目录
 python -m py2pydso file -i demo.py
 ```
 
 输出 `demo.pyd`（或 `demo.so`），位于 `demo.py` 同目录。
 
 ```bash
 # 同时编译多个文件
 python -m py2pydso file -i demo.py utils.py config.py
 ```
 
 每个文件输出到各自源文件所在目录。
 
 ```bash
 # 指定输出目录，所有产物统一输出
 python -m py2pydso file -i demo.py utils.py -o output
 ```
 
 输出 `output/demo.pyd`、`output/utils.pyd`。
 
 ```bash
 # 编译并生成 .pyi 类型存根文件
 python -m py2pydso file -i demo.py --pyi
 ```
 
 输出 `demo.pyd` + `demo.pyi`。
 
 ```bash
 python -m py2pydso file -i utils/demo.py
 ```
 
 输出 `utils/demo.pyd`（或 `utils/demo.so`）。
 
 ### 2. 编译模块目录
 
 ```bash
 # 编译单个模块
 python -m py2pydso module -i utils -o output
 
 # 同时编译多个模块
 python -m py2pydso module -i utils tools helpers -o output
 ```
 
 输入：
 ```
 utils/
   __init__.py
   __main__.py
   tools.py
   config.py
 ```
 
 输出（始终输出到 output/<模块名>）：
 
 ```
 output/
   utils/
     __init__.py      ← 原样保留（__开头）
     __main__.py      ← 原样保留（__开头）
     config.py        ← 原样保留（--exclude-files 指定）
     tools.pyd        ← 编译产物
 ```
 
 多模块时每个模块各自独立子目录：
 
 ```
 output/
   utils/
     __init__.py
     tools.pyd
   tools/
     __init__.py
     core.pyd
 ```
 
 - `__`开头的 `.py` 文件（如 `__init__.py`、`__main__.py`）原样保留，不参与编译
 - 支持 `-i` 指定多个模块目录，空格分隔
 - 支持 `--exclude-files` 指定额外排除的文件（可多个）：
 
   ```bash
   python -m py2pydso module -i utils -o output --exclude-files config.py constants.py
   ```
 
 - 支持 `--pyi` 生成 `.pyi` 类型存根文件（保留 IDE 补全提示）：
 
   ```bash
   python -m py2pydso module -i utils -o output --pyi
   ```
 
 - 支持子目录递归编译
 
 ### 3. 构建完整 wheel 包
 
 ```bash
 python -m py2pydso package -m <module_name>
 ```
 
 构建保护版本的 wheel 包（`.pyd/.so` 原生扩展），不暴露源码。
 
 ```bash
 # 生成 .pyi 类型提示文件（需显式指定）
 python -m py2pydso package -m <module_name> --pyi
 
 # 指定输出目录
 python -m py2pydso package -m <module_name> -o /path/to/wheelhouse
 
 # 排除指定文件不编译，保留原始 .py
 python -m py2pydso package -m <module_name> --exclude-files config.py constants.py
 
 # 加固编译：隐藏内部符号 + 剥离调试信息
 python -m py2pydso package -m <module_name> --harden
 
 # 不编译为 .pyd/.so，直接打包源码为纯 Python wheel
 python -m py2pydso package -m <module_name> --no-compile
 
 # src 布局：模块在 src 目录下
 python -m py2pydso package -m <module_name> --src-dir src
 
 # 额外目录：复制 setup.py 依赖的目录（如 C 源码目录）
 python -m py2pydso package -m <module_name> --extra-dirs libwebp third_party
 
 # 显示详细编译输出
 python -m py2pydso package -m <module_name> -v
 ```
 
 输出：
 - 编译模式：`<package_name>-x.x.x-cpYY-cpYY-<platform>.whl`
 - `--no-compile` 模式：`<package_name>-x.x.x-py3-none-any.whl`
 
 ## 公共参数
 
 | 参数 | 适用命令 | 说明 |
 |------|----------|------|
 | `-m` / `--module` | `package` | 要编译的模块目录名（必填），对应项目下的同名目录 |
 | `--src-dir` | `package` | 源码根目录（默认 `.`），如 src 布局使用 `--src-dir src` |
 | `--extra-dirs` | `package` | 额外需要复制到临时目录的目录名（可多个），如 `setup.py` 依赖的 C 源码目录：`--extra-dirs libwebp` |
 | `-i` / `--input` | `file`、`module` | 输入路径（均可指定多个，空格分隔）；`file` 为 `.py` 文件，`module` 为模块目录 |
 | `--exclude-files` | `module`、`package` | 排除不编译的文件（可多个），按相对路径匹配，保留原始 `.py`。如 `build.py` 仅排除包根目录的文件，`demo/build.py` 排除子目录的文件 |
 | `--pyi` | `file`、`module`、`package` | 生成 `.pyi` 类型存根文件（默认不生成） |
 | `--harden` | `file`、`module`、`package` | 加固编译：隐藏内部符号（仅导出 `PyInit_*`）+ 剥离调试信息，增加逆向难度 |
 | `--no-compile` | `package` | 不编译为 `.pyd/.so`，直接打包源码为纯 Python wheel（`py3-none-any`），跨平台通用 |
 | `-v` / `--verbose` | `package` | 显示详细编译输出（CMake、Cython、编译器日志），调试问题时使用 |
 
 ## `--harden` 加固说明
 
 加 `--harden` 后，编译产物会经过两层加固：
 
 | 层级 | GCC / Clang（Linux / macOS） | MSVC（Windows） |
 |------|------------------------------|----------------|
 | 符号隐藏 | version script，仅导出 `PyInit_*` | 无编译期支持，依赖 `strip` |
 | 符号剥离 | `strip --strip-unneeded` | 需手动安装 MinGW `strip`，未安装则跳过 |
 
 效果：
 - 用 `nm` / `dumpbin /exports` 查看 `.pyd/.so` 时，内部函数符号全部消失
 - 文件体积显著减小（去除调试段）
 - 逆向工具无法通过符号表快速定位函数
 
 > **注意**：`--harden` 不影响 Python 层的功能，模块加载和调用完全正常。
 
 ## 命令行帮助
 
 ```bash
 python -m py2pydso --help
 python -m py2pydso file --help
 python -m py2pydso module --help
 python -m py2pydso package --help
 ```
 
Requires-Dist: mypy
Requires-Dist: Cython
Requires-Dist: tomli>=1.1.0;python_version<'3.11'
