Metadata-Version: 2.1
Name: py2pydso
Version: 1.3.8
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 --package-name loki_service
 ```
 
 构建保护版本的 wheel 包（`.pyd/.so` 原生扩展），不暴露源码。
 
 ```bash
 # 生成 .pyi 类型提示文件（需显式指定）
 python -m py2pydso package --package-name loki_service --pyi
 
 # 指定输出目录
 python -m py2pydso package --package-name loki_service --output-dir /path/to/wheelhouse
 
 # 排除指定文件不编译，保留原始 .py
 python -m py2pydso package --package-name loki_service --exclude-files config.py constants.py
 
 # 加固编译：隐藏内部符号 + 剥离调试信息
 python -m py2pydso package --package-name loki_service --harden
 ```
 
 输出：`<package_name>-x.x.x-cpYY-cpYY-<platform>.whl`
 
 ## 公共参数
 
 | 参数 | 适用命令 | 说明 |
 |------|----------|------|
 | `-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_*`）+ 剥离调试信息，增加逆向难度 |
 
 ## `--harden` 加固说明
 
 加 `--harden` 后，编译产物会经过两层加固：
 
 | 层级 | GCC / Clang（Linux / macOS） | MSVC（Windows） |
 |------|------------------------------|----------------|
 | 符号隐藏 | `-fvisibility=hidden` + version script，仅导出 `PyInit_*` | 无编译期支持，依赖 strip |
 | 符号剥离 | `strip --strip-unnecessary` | 需手动安装 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: setuptools>=69
Requires-Dist: mypy
Requires-Dist: Cython
Requires-Dist: tomli>=1.1.0;python_version<'3.11'
