Skip to content

Instantly share code, notes, and snippets.

@myd7349
Last active June 18, 2024 16:30
Show Gist options
  • Save myd7349/9f7c6334e67d1aee68a722a15df4a62a to your computer and use it in GitHub Desktop.
Save myd7349/9f7c6334e67d1aee68a722a15df4a62a to your computer and use it in GitHub Desktop.

每个 Python 程序员可能都会遇到这样的场景:你写了一个 Python 程序,可能是一个简单的、包含单个文件的 、只使用了标准库的 Python 脚本,抑或是一个庞大的、包含多个模块的、甚至引用了大量的第三方库的复杂 Python 应用,如何将他们送到目标用户手中,让他们能很顺利地使用起来呢?

一种方案就是写一个详尽的文档,连带着你的程序一起发送给用户。文档中要说明,目标用户如何在自己机器上安装 Python 环境及依赖的包,如何对程序进行配置,等等。但倘若你的目标用户没用过 Python 甚至不懂编程,此种方案执行起来便困难重重。

另一种方案,就是将 Python 程序“打包”成可执行程序(.exe),只要目标用户具备基本的电脑操作技能,便能很容易地将程序运行起来。

在 Windows 平台上,将 Python 程序“打包”为可执行程序(.exe)的方案很多,我尝试过的方案有如下几种:

本文将讲解如何使用 PyStand 打包你的 Python 程序。

PyStand 是由国内编程大神韦易笑开发的。作者本人在知乎上对 PyStand 的用法进行了详尽的介绍。推荐读者在阅读接下来的内容前先阅读一下知乎上这个问答:

怎么样打包 pyqt 应用才是最佳方案?或者说 pyqt 怎样的发布方式最优?

一个简单的例子:Hello PyStand

我们先来看一个简单的用 PyStand 打包的 Python 程序的目录结构:

22071001

其中:

  • runtime 目录:存放嵌入式(embeddable)Python 解释器;
  • site-packages 目录:存放依赖的第三方包;
  • PyStand.exe:可执行程序,供目标用户使用;
  • PyStand.int:初始化脚本(启动代码),由 PyStand.exe 调用;

这里的 PyStand.int 实际上是一个普通的 Python 脚本,它的后缀也可以是 .py 或 .pyw。

.py 后缀大家都很熟悉。如果你写的 Python 脚本是一个图形用户界面(GUI)程序,将后缀由 .py 改为 .pyw 后,程序启动时就不会再弹出一个黑色的命令行窗口。

下面来看一个简单的打包示例。假设我们有一个 Python 脚本 HelloPyStand.py

# coding: utf-8

import ctypes

MB_OK = 0x0
ICON_INFO = 0x40


ctypes.windll.user32.MessageBoxW(
    None,
    'Hello, PyStand!',
    'A simple PyStand sample:',
    MB_OK | ICON_INFO)


# References:
# [Python MessageBox with Icons using ctypes and windll](https://stackoverflow.com/questions/27257018/python-messagebox-with-icons-using-ctypes-and-windll)

这个程序很简单:使用 Win32 API MessageBoxW 弹出一个消息提示框。

从 PyStand 的 Releases 页面下载一个预编译版本的 PyStand。以最新版的 PyStand v1.0.6 为例,作者提供了如下四个预编译版本:

  • PyStand-py37.7z:PyStand 32 位 GUI 程序,搭配的是 Python 3.7 的 32 位嵌入式包。
  • PyStand-py38.7z:PyStand 32 位 GUI 程序,搭配的是 Python 3.8 的 32 位嵌入式包。
  • PyStand-py38-pyqt5.7z:PyStand 32 位 GUI 程序预,搭配的是 Python 3.8 的 32 位嵌入式包。此外,site-packages 中还包含了一个经过简单裁剪的 PyQt5。
  • PyStand-py38-pyqt5-lite.7z:PyStand 32 位 GUI 程序预编译版,搭配的是 Python 3.8 的 32 位嵌入式包。此外,site-packages 中还包含了一个经过大幅裁剪的 PyQt5 包。

如果你的程序不依赖于 PyQt5,下载前两个版本即可。前两个版本搭载的 Python 版本分别是 3.7 和 3.8。如果你需要更新版本的 Python,可自行去 Python 官网下载相应版本的 embeddable Python 即可。

我们的 HelloPyStand.py 不依赖于 PyQt5,因此下载前两个版本任一即可。我这里选择 PyStand-py38.7z。下载后,解压,用文本编辑器打开 PyStand.int,用 HelloPyStand.py 中的代码替换掉原来的内容,然后双击 PyStand.exe。如果你看到了如下界面,那么恭喜你,你成功了!

22071002

当然,你也可以不要 PyStand.int,直接将你的 HelloPyStand.py 复制到解压后 PyStand.exe 所在的目录下,然后将 PyStand.exe 重命名为 HelloPyStand.exe,双击,也可以运行。

一个复杂的例子:ViTables

刚刚的例子有些简单,以至于成功来得太突然!下面,我们看一个复杂的例子。

去年,我接触了一个 HDF5 文件查看器 ViTables。它是用 PyQt 开发的。最初,我尝试在 Anaconda 里安装它,结果失败(uvemas/ViTables#79 )。后来,有了 PyStand 后,我又做了一次尝试。

对于像 ViTables 这样的依赖第三方库的 Python 程序,能否成功地安装所有其依赖的第三方库,是成败的关键。

我们可以考虑从 PyStand-py38-pyqt5.7z 作为起点来打包 ViTables,但这里为了让读者对用 PyStand 打包的流程有更深入的了解,我们还使用刚刚上面的那个演示里用到的不包含 PyQt5 包的预编译版作为起点。

第一步:安装 pip,有了 pip 才能安装其它第三方包。

StackOverflow 上有个问题:pip with embedded python,按照高票答案操作即可。

先用文本编辑器打开 runtime 目录下的 python38._pth,我们可以看到如下内容:

python38.zip
.

# Uncomment to run site.main() automatically
#import site

取消注释最后一行代码:

python38.zip
.

# Uncomment to run site.main() automatically
import site

然后,去 get-pip-py 下载 get-pip.py,并将其放置在 runtime 目录下。

打开命令行窗口,cd 到 runtime 目录下,然后用 runtime 目录下的 python.exe 执行 get-pip.py:

.\python.exe get-pip.py

安装成功后,我们便可以进行下一步。

第二步:下载 ViTables 最新版本代码,并安装其依赖的包。

ViTables 没有依赖的 git 子模块,因此我们从其仓库主页通过浏览器下载其最新版本的源码压缩包即可。下载完成后,将其解压,并放置在与 runtime、site-packages 同级的目录下:

22071003

ViTables 依赖的第三方库记录在 ViTables\requirements.txt 这个文件里。

打开命令行窗口,cd 到 runtime 目录下,然后用 runtime 目录下的 python.exe 安装 ViTables 依赖的第三方包:

.\python.exe -m pip install -r ..\ViTables\requirements.txt

这样,安装的包就会放置在 runtime\Lib\site-packages 下。

22071004

在 PyStand 中,site-packages 要和 runtime 在同一个目录下。因此,将 runtime\Lib 目录下 site-packages 这个文件夹挪至 runtime 的外面。

第三步:尝试运行 ViTables。

经过前两步,我们已成功地安装了 ViTables 及其全部依赖,是时候运行一下了。

我们首先把 PyStand.exe 重命名为 ViTables.exe,然后,将 PyStand.int 重命名为 ViTables.int。ViTables.int 中的内容如下:

# coding: utf-8

from ViTables.vitables.start import gui
gui()

运行 ViTables.exe。咦!不对!过了半天也没弹出任何窗体。是时候进行故障排查了。

PyStand.exe 虽是个 GUI 应用,却用 freopen 对 stdout、stderr 进行了重定向。只要从命令行或 PowerShell 中运行它,错误信息便会打印出来:

22071005

原来是找不到模块。

ViTables 源码目录如下:

22071006

而主程序源码实际上全部在 vitables 子目录下(见图中红框所示)。因此,为确保 ViTables 各模块正确加载,我们需要将 ViTables 添加到 sys.path 下。修改我们的 ViTables.int 如下:

# coding: utf-8

import sys
sys.path.append(r'.\ViTables')

from vitables.start import gui
gui()

再次运行,成功!

第四步:清理。

最后一步是清理不必要的文件,以减小打包后的文件体积。

就拿 ViTables 来说,我们可以只保留 ViTables\vitables 这个子目录,doc、examples、macoxapp、mswindows、tests 等目录以及其他文件都可以不要。

裁剪完 ViTables 后,我们发现我们实际上可以不必要多级目录。因此,先将 ViTables 重命名为 ViTables-old。然后将 ViTables-old 下的 vitables 剪切到上一级目录,使它和 ViTables-old 在同一目录,然后删除 ViTables-old 即可。我们的 ViTables.int 就可以简化为:

# coding: utf-8

from vitables.start import gui
gui()

清理完 ViTables 中的无用文件后,接下来就是清理第三方包中的多余文件。这一步需要你对你所使用的库有一些基础的了解,哪些可以删,哪些不能删,要做到心里有数。裁剪 PyQt 的话,具体可以参考韦易笑大神在知乎上的回答。

当然,在裁剪过程中也记得多备份,如果某一步删错了文件,还可以回退重来。

PyStand 定制

如果 PyStand Releases 页面提供的预编译版本无法满足我们的使用要求,我们也可以自己编译 PyStand。

目前,PyStand Releases 页面只提供了 32 位 GUI 版的 PyStand,如果你想要一个命令行版的 PyStand(比如:你要打包的 Python 脚本是命令行应用,而非 GUI 应用),或是 64 位的 PyStand(比如:你想使用 64 位的 Python),亦或是你想更改 PyStand 的图标(比如:ViTables 就有自己的图标),均需要自己去编译 PyStand。

要从源码编译 PyStand,你需要先在电脑上安装:

C++ 编译器可以选择微软的 MSVC 或是 GCC。

其中,MSVC 可以通过在电脑上安装 Visual Studio 获得。Visual Studio 分很多版本:社区版、专业版、企业版等。对于 PyStand,Visual Studio Community(社区版)就够用了。安装的时候记得勾选 C++ 编程语言支持。我在 VS2010、VS2017、VS2019、VS2022 中均成功编译过 PyStand。

GCC 则可以通过安装 MinGW/MinGW-w64/TDM-GCC 获得,也可以通过安装 CLion/CodeBlocks/CodeLite/Qt 等集成开发环境来获得。

无论是 MSVC 还是 MinGW,为了便于开发人员从命令行调用它们,它们一般上都提供了一个命令提示符开发环境。在这个开发环境里,PATH 环境变量、头文件路径、库文件路径均已设置停当,用户可以直接在命令行里调用编译器、链接器等工具。如果安装了 Visual Studio,我们一般上可以在开始菜单程序列表里找到名为 Developer Command Prompt(翻译为:开发人员命令提示符)的快捷方式。

PyStand 使用 CMake 作为其构建系统,要想自己编译,需要在电脑上安装 CMake,并要求你掌握 CMake 的基本用法。

CMake 可以作为命令行工具来调用。此外,CMake 一般上还提供了一个 GUI 工具(在 Windows 上,这个 GUI 版的一般叫:cmake-gui.exe)。CMake GUI 版对新手可能够友好一些,你可以通过搜索引擎搜索 CMake GUI 的基本用法。接下来,我主要讲一下 CMake 命令行工具的基本用法。这要求你安装 CMake 后将 CMake 可执行文件的路径添加到 Windows 系统的 PATH 环境变量里。

大部分命令行工具会提供一个 -h/--help 参数(或者两者皆有),用于查看该命令行工具的帮助信息。在我的机器上,执行:

cmake --help

后的输出如下:

Usage

  cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
  cmake [options] -S <path-to-source> -B <path-to-build>

Specify a source directory to (re-)generate a build system for it in the
current working directory.  Specify an existing build directory to
re-generate its build system.

Options
  -S <path-to-source>          = Explicitly specify a source directory.
  -B <path-to-build>           = Explicitly specify a build directory.
  -C <initial-cache>           = Pre-load a script to populate the cache.
  -D <var>[:<type>]=<value>    = Create or update a cmake cache entry.
  -U <globbing_expr>           = Remove matching entries from CMake cache.
  -G <generator-name>          = Specify a build system generator.
  -T <toolset-name>            = Specify toolset name if supported by
                                 generator.
  -A <platform-name>           = Specify platform name if supported by
                                 generator.
  --toolchain <file>           = Specify toolchain file
                                 [CMAKE_TOOLCHAIN_FILE].
  --install-prefix <directory> = Specify install directory
                                 [CMAKE_INSTALL_PREFIX].
  -Wdev                        = Enable developer warnings.
  -Wno-dev                     = Suppress developer warnings.
  -Werror=dev                  = Make developer warnings errors.
  -Wno-error=dev               = Make developer warnings not errors.
  -Wdeprecated                 = Enable deprecation warnings.
  -Wno-deprecated              = Suppress deprecation warnings.
  -Werror=deprecated           = Make deprecated macro and function warnings
                                 errors.
  -Wno-error=deprecated        = Make deprecated macro and function warnings
                                 not errors.
  --preset <preset>,--preset=<preset>
                               = Specify a configure preset.
  --list-presets               = List available presets.
  -E                           = CMake command mode.
  -L[A][H]                     = List non-advanced cached variables.
  --build <dir>                = Build a CMake-generated project binary tree.
  --install <dir>              = Install a CMake-generated project binary
                                 tree.
  --open <dir>                 = Open generated project in the associated
                                 application.
  -N                           = View mode only.
  -P <file>                    = Process script mode.
  --find-package               = Legacy pkg-config like mode.  Do not use.
  --graphviz=[file]            = Generate graphviz of dependencies, see
                                 CMakeGraphVizOptions.cmake for more.
  --system-information [file]  = Dump information about this system.
  --log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>
                               = Set the verbosity of messages from CMake
                                 files.  --loglevel is also accepted for
                                 backward compatibility reasons.
  --log-context                = Prepend log messages with context, if given
  --debug-trycompile           = Do not delete the try_compile build tree.
                                 Only useful on one try_compile at a time.
  --debug-output               = Put cmake in a debug mode.
  --debug-find                 = Put cmake find in a debug mode.
  --trace                      = Put cmake in trace mode.
  --trace-expand               = Put cmake in trace mode with variable
                                 expansion.
  --trace-format=<human|json-v1>
                               = Set the output format of the trace.
  --trace-source=<file>        = Trace only this CMake file/module.  Multiple
                                 options allowed.
  --trace-redirect=<file>      = Redirect trace output to a file instead of
                                 stderr.
  --warn-uninitialized         = Warn about uninitialized values.
  --no-warn-unused-cli         = Don't warn about command line options.
  --check-system-vars          = Find problems with variable usage in system
                                 files.
  --profiling-format=<fmt>     = Output data for profiling CMake scripts.
                                 Supported formats: google-trace
  --profiling-output=<file>    = Select an output path for the profiling data
                                 enabled through --profiling-format.
  --help,-help,-usage,-h,-H,/? = Print usage information and exit.
  --version,-version,/V [<f>]  = Print version number and exit.
  --help-full [<f>]            = Print all help manuals and exit.
  --help-manual <man> [<f>]    = Print one help manual and exit.
  --help-manual-list [<f>]     = List help manuals available and exit.
  --help-command <cmd> [<f>]   = Print help for one command and exit.
  --help-command-list [<f>]    = List commands with help available and exit.
  --help-commands [<f>]        = Print cmake-commands manual and exit.
  --help-module <mod> [<f>]    = Print help for one module and exit.
  --help-module-list [<f>]     = List modules with help available and exit.
  --help-modules [<f>]         = Print cmake-modules manual and exit.
  --help-policy <cmp> [<f>]    = Print help for one policy and exit.
  --help-policy-list [<f>]     = List policies with help available and exit.
  --help-policies [<f>]        = Print cmake-policies manual and exit.
  --help-property <prop> [<f>] = Print help for one property and exit.
  --help-property-list [<f>]   = List properties with help available and
                                 exit.
  --help-properties [<f>]      = Print cmake-properties manual and exit.
  --help-variable var [<f>]    = Print help for one variable and exit.
  --help-variable-list [<f>]   = List variables with help available and exit.
  --help-variables [<f>]       = Print cmake-variables manual and exit.

Generators

The following generators are available on this platform (* marks default):
* Visual Studio 17 2022        = Generates Visual Studio 2022 project files.
                                 Use -A option to specify architecture.
  Visual Studio 16 2019        = Generates Visual Studio 2019 project files.
                                 Use -A option to specify architecture.
  Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 14 2015 [arch] = Generates Visual Studio 2015 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 12 2013 [arch] = Generates Visual Studio 2013 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 11 2012 [arch] = Generates Visual Studio 2012 project files.
                                 Optional [arch] can be "Win64" or "ARM".
  Visual Studio 10 2010 [arch] = Deprecated.  Generates Visual Studio 2010
                                 project files.  Optional [arch] can be
                                 "Win64" or "IA64".
  Visual Studio 9 2008 [arch]  = Generates Visual Studio 2008 project files.
                                 Optional [arch] can be "Win64" or "IA64".
  Borland Makefiles            = Generates Borland makefiles.
  NMake Makefiles              = Generates NMake makefiles.
  NMake Makefiles JOM          = Generates JOM makefiles.
  MSYS Makefiles               = Generates MSYS makefiles.
  MinGW Makefiles              = Generates a make file for use with
                                 mingw32-make.
  Green Hills MULTI            = Generates Green Hills MULTI files
                                 (experimental, work-in-progress).
  Unix Makefiles               = Generates standard UNIX makefiles.
  Ninja                        = Generates build.ninja files.
  Ninja Multi-Config           = Generates build-<Config>.ninja files.
  Watcom WMake                 = Generates Watcom WMake makefiles.
  CodeBlocks - MinGW Makefiles = Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles = Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles JOM
                               = Generates CodeBlocks project files.
  CodeBlocks - Ninja           = Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles  = Generates CodeBlocks project files.
  CodeLite - MinGW Makefiles   = Generates CodeLite project files.
  CodeLite - NMake Makefiles   = Generates CodeLite project files.
  CodeLite - Ninja             = Generates CodeLite project files.
  CodeLite - Unix Makefiles    = Generates CodeLite project files.
  Eclipse CDT4 - NMake Makefiles
                               = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - MinGW Makefiles
                               = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Ninja         = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles= Generates Eclipse CDT 4.0 project files.
  Kate - MinGW Makefiles       = Generates Kate project files.
  Kate - NMake Makefiles       = Generates Kate project files.
  Kate - Ninja                 = Generates Kate project files.
  Kate - Unix Makefiles        = Generates Kate project files.
  Sublime Text 2 - MinGW Makefiles
                               = Generates Sublime Text 2 project files.
  Sublime Text 2 - NMake Makefiles
                               = Generates Sublime Text 2 project files.
  Sublime Text 2 - Ninja       = Generates Sublime Text 2 project files.
  Sublime Text 2 - Unix Makefiles
                               = Generates Sublime Text 2 project files.

我们接下来会讲到这些参数:

  • -S
  • -B
  • -G
  • -A
  • -D
  • --build
  • --config
  • --target

使用 CMake 构建工具的 C、C++ 项目源码根目录里一般上包含一个名为 CMakeLists.txt 的 CMake 脚本。CMake 工具也主要围绕该脚本来工作。使用 CMake 构建一个项目一般上分为三步(假设 CMakeLists.txt 是现成的):

  1. 接:配置(Configure)
  2. 化:生成(Generate)
  3. 发:构建(Build)

在配置阶段,用户可以指定:

  • 生成器(Generator)的类型(通过 -G 参数指定)
  • 要生成的库的位数(32 位、64 位)(通过 -A 参数指定)
  • 库的类型(静态库、动态库)(通过 -D 参数指定)
  • 库的安装路径(通过 -D 或 --install-prefix 参数指定)
  • CMake options(通过 -D 参数指定)
  • 额外的宏定义(通过 -D 参数指定)
  • 额外的头文件/库文件查找路径等(通过 -D 参数指定)

在配置阶段,需要将包含 CMakeLists.txt 的源码路径作为一个参数传给 CMake。如果项目中包含多个模块目录,且每个模块都有自己的 CMakeLists.txt,则需要指定最顶层的 CMakeLists.txt 所在路径。指定 CMakeLists.txt 需要用到 -S 参数。例如:

cmake -S ..

习惯上,人们会省去 -S,直接写:

cmake ..

使用 CMake 构建项目的过程中会生成大量临时文件。为了避免这些临时文件“污染”源码,以及方便后续清理,人们推荐使用“out of source build”。所谓“out of source build”就是建立一个独立于源码的路径,作为构建目录,用于存储 CMake 构建过程中产生的临时文件。可以通过 -B 参数指定生成目录。例如:

cmake .. -B .

如果想用当前路径作为生成路径,则可省略 -B 参数。

以 PyStand 为例,你可以从如下几种实践中选择其一:

实践一:

# 克隆源代码到本地
git clone https://github.com/skywind3000/PyStand

# 建立一个与 PyStand 源码目录同级的目录用于存储构建过程中的临时文件
mkdir PyStand-build

# cd 至 build 目录
cd PyStand-build

# 指定源码的相对路径,开始 Configure
# 等价于:
# cmake -S ../PyStand -B .
cmake ../PyStand

# 开始 Build
cmake --build . --config Release

实践二:

# 克隆源代码到本地
git clone https://github.com/skywind3000/PyStand

# cd 到 PyStand 源码的根目录(CMakeLists.txt 所在目录)
cd PyStand

# 在 PyStand 目录下创建一个 build 子目录,用于存储构建过程中生成的临时文件
mkdir build

# cd 到 build 目录,你也可以用 pushd build(构建完成后 popd build)
cd build

# 指定源码的相对路径,开始 Configure
# 等价于:
# cmake -S .. -B .
cmake ..

# 开始 Build
cmake --build . --config Release

实践三:

# 克隆源代码到本地
git clone https://github.com/skywind3000/PyStand

# cd 到 PyStand 源码的根目录(CMakeLists.txt 所在目录)
cd PyStand

# 在 PyStand 目录下创建一个 build 子目录,用于存储构建过程中生成的临时文件
mkdir build

# 当前路径依然在 PyStand 根目录,但我们通过 -B 参数指定了构建目录
# 等价于:
# cmake -S . -B build
cmake -B build

# 开始 Build
cmake --build build --config Release

我个人更习惯使用第二或第三种方案。

CMake 每个版本所支持的 Generator 都会有所区别,具体可通过 --help 参数查阅帮助信息。

以上面我的机器上执行 cmake --help 的输出为例,自 Generators 开始的内容便是我安装的 CMake 所支持的生成器的列表。从这个列表中可以看出,该版本的 CMake 支持的 Visual Studio 为 2008~2022。Visual Studio 17 2022 生成器开头的星号表示,在不指定生成器参数的情况下,该生成器便是默认生成器。如果我们不想使用默认生成器,便可以使用 CMake 的 -G 参数来指定生成器类别。例如:

使用 VS2022 作为生成器:

cmake -G "Visual Studio 17 2022"

使用 VS2019 作为生成器:

cmake -G "Visual Studio 16 2019"

如果我们要指定生成的程序或库的位数该怎么办?可以再加一个 -A 参数。

使用 VS2022 作为生成器,32 位构建:

cmake -G "Visual Studio 17 2022" -A Win32

使用 VS2022 作为生成器,64 位构建:

cmake -G "Visual Studio 17 2022" -A x64

细心的读者可能注意到,如果 Visual Studio 版本低于 VS2019(比如:VS2010、VS2017 等),则生成器名称里有一个可选的 [arch] 占位符。以 VS2017 为例:

  Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files.
                                 Optional [arch] can be "Win64" or "ARM".

这表示,你可以这样指定生成器:

cmake -G "Visual Studio 15 2017"

或是:

cmake -G "Visual Studio 15 2017 Win64"

或是:

cmake -G "Visual Studio 15 2017 ARM"

分别对应 x86、x64、ARM 架构。

这里简单总结一下:

在 VS2019 之前,我们可以通过在生成器名称里增加可选的 [arch] 来指定目标架构。从 VS2019 开始,则是通过 -A 来指定目标架构。

如果配置(Configure)成功的话,上述这些命令最终会帮你生成(Generate)对应版本的 Visual Studio 解决方案&工程文件。接下来,你就可以用对应版本的 Visual Studio 打开解决方案文件,一键编译即可。

如果你想直接通过 cmake 来发起 Build,可以:

cmake --build <build 目录> --config <Config> --target <Target>

这里:

  • <build 目录> 要输入实际的 build 目录。
  • <Config> 用于设置 Debug 或 Release 模式。
  • <Target> 则用于指定生成目标的名称。如果你想编译所有目标,可以忽略 --target <Target>

使用 NMake 生成器:

cmake -G "NMake Makefiles"

生成成功后,可以使用 MSVC 的 nmake 来构建项目。如果提示找不到 nmake,可以尝试从 VS 提供的开发人员命令提示符(Developer Command Prompt)运行这些命令。

如果你想要使用 MinGW,则可以指定:

cmake -G "MinGW Makefiles"

然后运行:

mingw32-make

即可。

注意:上面的这些命令均未指定 -S、-B 参数,具体操作时,记得加上。

接下来,简单介绍一下 CMake 的 -D 参数。在 Configure 阶段,-D 参数发挥着重要的作用。-D 参数类似于编程语言里定义/设置一个变量的值。这些“变量”,有些是 CMake 预定义的(大部分以 CMAKE 开头,如:CMAKE_INSTALL_PREFIX、CMAKE_PREFIX_PATH),有些则是开发人员在 CMakeLists.txt 中使用 option 定义的一些编译开关项(比如:PyStand 的 CMakeLists.txt 里的 PYSTAND_CONSOLE)。在 Configure 阶段,通过 -D 参数便可以影响到最终 Generate 得到的结果。下面举一些例子。

大部分同时支持动态库和静态库的 C、C++ 项目的 CMakeLists.txt 可能会根据 BUILD_SHARED_LIBS 来决定是生成动态库还是静态库。

生成动态库:

cmake -DBUILD_SHARED_LIBS=ON

生成静态库:

cmake -DBUILD_SHARED_LIBS=OFF

指定目标安装路径:

cmake -DCMAKE_INSTALL_PREFIX=<install path>

PyStand 则定义了 PYSTAND_CONSOLE,其默认值为 OFF。如果想要将 PyStand 编译为一个控制台项目,则需要在 Configure 阶段指定:

cmake -DPYSTAND_CONSOLE=ON

经过了上面的介绍,相信你已掌握了 CMake 命令行的基本用法。接下来,让我们实操一下:

下载 PyStand 源码后,cd 到源码的目录下,我们就可以用 CMake 来构建自己的 PyStand 了。

cd PyStand

mkdir build

cd build

构建 32 位版本的 PyStand:

cmake .. -A Win32

构建 64 位版本的 PyStand:

cmake .. -A x64

PyStand 默认为 GUI 应用。如果我们想构建控制台版的 PyStand,只需要在配置阶段加上 -DPYSTAND_CONSOLE=ON 参数即可:

cmake .. -A x64 -DPYSTAND_CONSOLE=ON

配置完成后,即可生成 PyStand.exe:

cmake --build . --config Release

如果想要替换 PyStand 的图标,可以把 PyStand 目录下的 appicon.ico 替换为自己想要使用的图标(文件名要一致)。

或者,将你要使用的图标复制到 PyStand 源码目录下,然后用文本编辑器编辑 resource.rc,将其中的图标文件名改为对应名称即可。

ViTables 的图标文件在 vitables\icons\mswindows 路径下,读者可以自己尝试一下。

此外,经过稍许改动,读者也可以将 PyStand.int 中的启动代码直接嵌入到 PyStand.exe 中。感兴趣的读者可以尝试一下。

最后

与其它几种主流打包方案相比,使用 PyStand 打包应用的自主可控性较高,你有很大的自由度对你的包进行裁剪,以尽量减小打包后程序的总体积。

PyStand 生来就不是为了将你的 Python 程序打包成一个独立的 exe 的。如果你需要将你的 Python 应用打包为单个 exe 文件,可以考虑 PyInstaller、Nuitka、py2exe,亦或是 cx_Freeze 结合 UPX。在使用 PyInstaller 等工具时,你也可以了解一下其工作原理,具体参考韦易笑大神在知乎上的回答。

如果你想“加密”你的 Python 源码,亦或增加反编译的难度,也可以参考韦易笑大神在知乎上的回答。

@Ephemeralwanning
Copy link

请问怎么进行加密呢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment