Skip to content

第2章 开发环境搭建

搭建一个稳定、可复现的 Pybind11 开发环境,是后续所有实战的前提。本章覆盖 Linux、macOS、Windows 三大平台的完整配置流程,并介绍 Docker 环境下的一致性构建方案。

CMake 是 Pybind11 官方推荐的构建工具。它的核心作用是:生成与平台无关的构建文件(Unix Makefile、Ninja 构建文件、Visual Studio 项目等),让你在 Windows、Linux、macOS 上使用同一套 CMakeLists.txt 描述构建过程。

Pybind11 本身只提供头文件,不提供可执行库。编译一个 Pybind11 模块需要:调用 C++ 编译器(gcc/clang/msvc)、链接 Python 解释器、设置正确的include路径和链接路径。手动编写这些编译命令在 Linux 上已经够复杂,跨平台时几乎不可维护。CMake 将这些平台差异封装为抽象层,你的 CMakeLists.txt 在所有平台上保持一致。

Linux(Ubuntu/Debian)

Terminal window
sudo apt-get install cmake

macOS

Terminal window
brew install cmake

Windows
下载 https://cmake.org/download/,选择 Windows x64 Installer,安装时勾选”Add CMake to the system PATH”。

Python(通过 pip)

Terminal window
pip install cmake # 适用于没有系统 CMake 的场景

验证安装:

Terminal window
cmake --version

:::note 版本要求 Pybind11 官方要求 CMake 3.4 以上,但推荐使用 3.18+ 以获得更好的 Ninja 支持和并行构建优化。 :::

CMake 的典型使用分为两步:配置(configure)和构建(build)。

Terminal window
cmake -B build -S .
cmake --build build

-B 指定构建目录,-S 指定源码目录。这种分离式布局(out-of-source build)避免了源码目录被构建产物污染,是 CMake 最佳实践。

CMake 找不到 Python
如果 CMake 报告 “Could NOT find Python”,你需要显式指定 Python 路径:

Terminal window
cmake -B build -S . \
-DPython_EXECUTABLE=/usr/bin/python3 \
-DPython_INCLUDE_DIR=/usr/include/python3.10 \
-DPython_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.10.so

多个 Python 版本冲突
在系统同时安装了 Python 2 和 Python 3 的机器上,CMake 可能会选错版本。使用虚拟环境(见 2.3 节)是最佳解决方案。

Xmake 是一个用 Lua 描述构建配置的现代化构建工具,相比 CMake,它的语法更简洁,对 Pybind11 的开箱即用支持更好。

Terminal window
curl -fsSL https://xmake.io/shget.text | sh
irm https://xmake.io/get.ps1 | iex

验证:

Terminal window
xmake --version
  1. 不需要单独安装:Xmake 可以直接编译 C/C++ 代码,不依赖 Make 或 Ninja
  2. 语法更简洁:用 Lua 描述构建逻辑,比 CMake 的 DSL 更直观
  3. 跨平台一致:同一个 xmake.lua 文件在所有平台上行为一致
Terminal window
xmake f -m release # 配置构建模式
xmake -b example # 编译名为 example 的 target
xmake run -d example # 编译并运行(-d 表示 debug 模式)
xmake config --python=/usr/bin/python3 # 指定 Python 解释器
add_rules("mode.debug", "mode.release")
add_requires("pybind11")
target("example")
set_kind("shared")
add_files("src/*.cpp")
add_includedirs("$(python_include_dir)")
add_linkdirs("$(python_lib_dir)")
add("deps", "pybind11")
target_end()

:::caution Xmake 的局限 Xmake 社区相对较小,遇到问题时 Stack Overflow 上的解决方案远不如 CMake 丰富。如果你在一个大型团队中工作,优先考虑 CMake 以获得更好的社区支持。 :::

Python 虚拟环境(venv)是隔离项目依赖的标准工具。每个 Pybind11 项目都应该使用独立的虚拟环境,避免不同项目之间的 Python 包版本冲突。

系统自带的 Python 通常被操作系统本身依赖(如 Ubuntu 的 apt 依赖系统 Python)。在这上面随意 pip install 可能破坏系统稳定性。而且系统 Python 的版本通常较旧,无法满足现代 Pybind11 项目的要求。

Terminal window
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
.venv\Scripts\activate # Windows PowerShell
(.venv) $ pip install cmake pybind11 numpy

验证虚拟环境:

Terminal window
(.venv) $ python --version
(.venv) $ which python
cmake>=3.18
pybind11>=2.11.0
numpy>=1.24.0
Terminal window
pip install -r requirements.txt

在 Windows 的 cmd(而非 PowerShell)中,激活命令是:

Terminal window
.venv\Scripts\activate.bat

如果使用 PowerShell,遇到执行策略限制:

Terminal window
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
.venv\Scripts\Activate.ps1

Linux 是 Pybind11 开发最友好的平台——gcc/clang 编译器质量高,Python 通常已预装,CMake 也能通过包管理器直接安装。

Terminal window
sudo apt-get update
sudo apt-get install -y build-essential cmake g++ python3-dev python3-pip
mkdir -p my-pybind11-project && cd my-pybind11-project
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install cmake pybind11 numpy
python -c "import pybind11; print(pybind11.__version__)"

常见问题:缺少 Python 开发头文件

Section titled “常见问题:缺少 Python 开发头文件”

如果编译时遇到 “Python.h: No such file”,说明缺少 Python 开发头文件。

Ubuntu/Debian:

Terminal window
sudo apt-get install python3-dev # 或 python3.10-dev, python3.11-dev

Fedora/RHEL:

Terminal window
sudo dnf install python3-devel

Arch Linux:

Terminal window
sudo pacman -S python

Python 开发头文件(Python.h)由 python-dev 或 python-devel 包提供,包含 Python C API 的接口定义。Pybind11 的 #include <pybind11/pybind11.h> 内部会包含 Python.h,没有这些头文件编译必失败。

macOS 上开发 Pybind11 的主要挑战是:苹果逐步淘汰了系统自带的旧版 Python,且 Xcode Command Line Tools 的安装有时会带来困惑。

Terminal window
xcode-select --install

如果已经安装,会提示 “command line tools are already installed”。

2. 安装 Homebrew(如果尚未安装)

Section titled “2. 安装 Homebrew(如果尚未安装)”
Terminal window
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Terminal window
brew install python@3.11

Homebrew 的 Python 3 会安装到 /usr/local/opt/python@3.11/Frameworks/Python.framework。

Terminal window
python3 -c "import sys; print(sys.executable)"
cmake -B build -S . \
-DPython_EXECUTABLE=/usr/local/opt/python@3.11/bin/python3 \
-DPython_INCLUDE_DIR=/usr/local/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/include \
-DPython_LIBRARY=/usr/local/opt/python@3.11/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib

5. 常见问题:apple-clang 不支持部分 STL 特性

Section titled “5. 常见问题:apple-clang 不支持部分 STL 特性”

苹果的 clang(apple-clang)对部分 C++ 标准库特性的支持不如 gcc。如果遇到编译错误,尝试:

Terminal window
brew install gcc
export CC=/usr/local/bin/gcc-13
export CXX=/usr/local/bin/g++-13
cmake -B build -S . ..

Windows 上的 Pybind11 开发相对最复杂,因为 Windows 没有统一的 C++ 工具链。本节以 Visual Studio Build Tools 2022 为基准。

下载地址:https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022

安装时选择”使用 C++ 的桌面开发” workloads,右侧详情中确保勾选:

  • MSVC v143 - VS 2022 C++ x64/x86 生成工具
  • Windows 11 SDK(或 Windows 10 SDK)
  • CMake 用于 Windows

从 python.org 下载 Python 3.11+ 安装包,安装时勾选 “Add Python to PATH”。

验证:

Terminal window
python --version

3. 配置 Visual Studio Developer Command Prompt

Section titled “3. 配置 Visual Studio Developer Command Prompt”

安装完 Build Tools 后,在开始菜单中找到 “x64 Native Tools Command Prompt for VS 2022”,打开它。这个命令提示符已经设置好了 MSVC 所需的环境变量(INCLUDE、LIB、PATH)。

4. 使用 Ninja 加速构建(可选但推荐)

Section titled “4. 使用 Ninja 加速构建(可选但推荐)”

MSBuild 在处理大型项目时速度较慢,Ninja 是更快的替代品:

Terminal window
pip install ninja
cmake -G "Ninja" -B build -S .
cmake --build build
Section titled “5. 常见问题:LINK : fatal error LNK1184”

如果遇到 “LINK : fatal error LNK1184: invalid option; no library specified”,通常是 CMake 找到的 Python 库路径有问题。检查:

Terminal window
python -c "import sys; print(sys.prefix)"
cmake -B build -S . ^
-DPython_EXECUTABLE=C:\Users\<user>\AppData\Local\Programs\Python\Python311\python.exe ^
-DPython_LIBRARY=C:\Users\<user>\AppData\Local\Programs\Python\Python311\libs\python311.lib ^
-DPython_INCLUDE_DIR=C:\Users\<user>\AppData\Local\Programs\Python\Python311\include

2.7 Docker 环境配置(跨平台一致性构建)

Section titled “2.7 Docker 环境配置(跨平台一致性构建)”

Docker 让你在容器中构建一次,然后在任何运行 Docker 的机器上复现相同的构建环境,彻底解决”在我机器上能跑”的问题。

FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /workspace
COPY . .
RUN cmake -B build -S . \
-DPython_EXECUTABLE=/usr/local/bin/python
RUN cmake --build build
Terminal window
docker build -t pybind11-project .
docker run -it --rm \
-v $(pwd):/workspace \
-w /workspace \
pybind11-project bash

社区提供了预配置好的 Pybind11 开发镜像,免去自己写 Dockerfile 的麻烦:

Terminal window
docker run -it --rm \
-v $(pwd):/workspace \
-w /workspace \
pybind11/pybind11:latest bash

这个镜像包含了 Pybind11 源码和所有依赖,可以直接 clone 你的项目并构建。

:::caution Docker 的文件权限问题 Linux 上 Docker 容器内构建生成的文件默认属于 root 用户。如果需要在宿主机上修改这些文件,运行 sudo chown -R $(id -u):$(id -g) build/。 :::

如果你的项目不需要在系统级别保留构建工具,可以用 pipx 在隔离的虚拟环境中安装 CMake:

Terminal window
pip install pipx
pipx install cmake
pipx ensurepath

pipx 会在每次调用时创建临时虚拟环境,运行完即销毁,磁盘占用极小。

现在你已经安装了所有必要工具,让我们来看一个 Pybind11 项目的最小骨架,理解每个文件的作用。

my-first-pybind11/
├── CMakeLists.txt # 构建配置
├── src/
│ └── example.cpp # C++ 源码(包含 PYBIND11_MODULE)
├── include/
│ └── hello.h # 可选:头文件(简单项目可直接写在 .cpp 中)
├── tests/
│ └── test_example.py # Python 测试
└── build/ # 构建产物(不要提交到 git)
#include <pybind11/pybind11.h>
#include "hello.h"
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
m.doc() = "My first pybind11 module - example"; // 模块文档字符串
// 注册 add 函数
m.def("add", [](int a, int b) { return a + b; }, R"pbdoc(
Adds two numbers together.
Args:
a (int): First number
b (int): Second number
Returns:
int: The sum of a and b
)pbdoc");
// 注册带默认参数的函数
m.def("greet", [](const std::string& name, bool formal = false) {
if (formal) {
return "Hello, " + name + ".";
} else {
return "Hey, " + name + "!";
}
}, py::arg("name"), py::arg("formal") = false);
// 注册一个 C++ 类
py::class_<Hello>(m, "Hello")
.def(py::init<>())
.def("say", &Hello::say, "Says hello")
.def_property_readonly("message", &Hello::get_message);
}
#pragma once
#include <string>
class Hello {
public:
Hello() : message_("Hello, World!") {}
void say() const;
std::string get_message() const { return message_; }
private:
std::string message_;
};
cmake_minimum_required(VERSION 3.18)
project(example VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Python REQUIRED COMPONENTS Interpreter Development)
find_package(pybind11 REQUIRED CONFIG)
pybind11_add_module(example src/example.cpp src/hello.cpp)
target_link_libraries(example PRIVATE pybind11::module)

pybind11_add_module 是 Pybind11 提供的一个 CMake 宏,它负责:

  • 设置编译选项(开启 -fPIC 等)
  • 设置include路径(Pybind11 头文件路径)
  • 链接 Python 库
  • 将输出文件的扩展名在 Windows 上改为 .pyd
Terminal window
mkdir build && cd build
cmake ..
make
mkdir build
cd build
cmake ..
cmake --build . --config Release

构建产物是一个 Python 扩展模块:

  • Linux/macOS: build/example.cpython-*.so
  • Windows: build/Release/example.pyd

测试它:

import sys
sys.path.insert(0, 'build') # 将 build 目录加入路径
import example
print(example.add(1, 2)) # 3
print(example.greet("Alice")) # Hey, Alice!
h = example.Hello()
print(h.message) # Hello, World!

:::note 常见的构建错误 Python.h 找不到:python3-dev 包未安装,或 CMake 找到了错误的 Python 版本。
符号未定义:PYBIND11_MODULE 宏使用错误——检查括号内的模块名与 cpp 文件名是否一致。
链接失败:Python 库路径不对——检查 Python_LIBRARY CMake 变量是否指向正确的 .so/.lib 文件。 :::

在开始实际开发之前,运行以下命令确认环境配置正确:

Terminal window
python --version # 应该是 3.8+
g++ --version # 或 clang++ --version
c++ --version
cmake --version # >= 3.18
python -c "import sysconfig; print(sysconfig.get_path('include'))"
python -c "import pybind11; print(pybind11.get_include())"
python -c "import pybind11; print(pybind11.__version__)"

所有检查通过后,你的环境就绪,可以开始真正的 Pybind11 开发了。