windows环境下使用MSVC,在vscode中配置pybind11环境

pybind11 version:3.0.1 python version:3.14

一. cl.exe直接编译

前置准备

  • Visual Studio2022

  • Python,Pybind11

  • VScode

  • 在VScode中配置好MSVC

开始配置

  • 按下快捷键Ctrl+Shift+P 在顶部搜索框中输入> Configure Default Build Task

  • 选择C/C++ cl.exe build active file,VS Code会在.vscode文件夹中自动生成tasks.json

  • 对tasks.json文件进行如下配置

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "create-build-directories",
            "type": "shell",
            "command": "mkdir",
            "args": [
				"-Force",
				"-Path",
                "${workspaceFolder}/build,",
                "${workspaceFolder}/build/obj,",
                "${workspaceFolder}/build/dist,",
				"${workspaceFolder}/src/binding"
            ],
            "options": {
                "cwd": "${fileDirname}",
                "shell": {
                    "executable": "powershell.exe"  // 指定使用 PowerShell 执行
                }
            },
            "problemMatcher": [],
            "detail": "用 PowerShell 自动创建 build 相关目录"
        },
        {
            "type": "cppbuild",
            "label": "C/C++: cl.exe build pybind11 file",
            "command": "cl",
            "args": [
                "/O2",
                "/LD",
                "/EHsc",
                "/source-charset:utf-8",
                "/I",
                "D:\\Environment\\Miniconda3\\envs\\p3_14_pybind\\Lib\\site-packages\\pybind11\\include",
                "/I",
                "D:\\Environment\\Miniconda3\\envs\\p3_14_pybind\\Include",
                "/Fo\"${workspaceFolder}\\build\\obj\\${fileBasenameNoExtension}.obj\"",  // .obj 输出到 obj 目录
                "${workspaceFolder}\\src\\binding\\${fileBasenameNoExtension}.cpp",
                "/link",
                "/LIBPATH:\"D:\\Environment\\Miniconda3\\envs\\p3_14_pybind\\libs\"",
                "python314.lib",
                "/IMPLIB:\"${workspaceFolder}\\build\\obj\\${fileBasenameNoExtension}.lib\"",  // 强制 .lib 输出到 obj 目录
                "/OUT:\"${workspaceFolder}\\build\\dist\\${fileBasenameNoExtension}.pyd\"",  // .pyd 仍输出到 dist 目录
                "/EXPORT:PyInit_${fileBasenameNoExtension}"  // 显式导出 Python 初始化函数(可选,增强兼容性)
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$msCompile"
            ],
            "group": {
                "kind": "build",
                "isDefault": false
            },
            "dependsOn": "create-build-directories",
            "detail": "compiler: cl.exe"
        }
    ]
}
  • OK,大功告成,按下Ctrl+Shift+B 即可运行 (或在菜单中选择Terminal中的Run Task)

二. CMake构建

在 Windows 系统中,.pyd 文件本质上是一种特殊的动态链接库(DLL)

在 Linux/macOS 系统中,Python 扩展模块通常是 .so 文件,属于「共享库」

都会被CMake分配到 lib 目录下

CMakeLists.txt

cmake_minimum_required(VERSION 3.15...4.0)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# --------------------------
# 控制输出文件目录
# --------------------------
# 二进制文件输出目录(.pyd, .dll, .so等)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release)

# 库文件输出目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib/Debug)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib/Release)

# 静态库和目标文件输出目录(.obj, .a等)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/lib/Debug)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/lib/Release)

# PDB文件(调试符号)输出目录
set(CMAKE_PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/pdb)
set(CMAKE_PDB_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/pdb/Debug)
set(CMAKE_PDB_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/pdb/Release)

# --------------------------
# Python 配置
# --------------------------
find_package(Python REQUIRED COMPONENTS Interpreter Development)
# --------------------------
# pybind11 配置
# --------------------------
if(WIN32)
  set(pybind11_DIR "D:\\Environment\\Miniconda3\\envs\\p3_14_pybind\\Lib\\site-packages\\pybind11\\share\\cmake\\pybind11\\")
else()
  set(pybind11_DIR "~/pybind11/build")
endif()
find_package(pybind11 CONFIG REQUIRED)

# --------------------------
# 模块配置(支持分离写法)
# --------------------------
# 获取src目录下的直接子目录(每个子目录为一个模块)
file(GLOB MOD_DIRS LIST_DIRECTORIES TRUE "${CMAKE_SOURCE_DIR}/src/*")

foreach(MOD_DIR IN LISTS MOD_DIRS)
    # 确保这是一个目录
    if(IS_DIRECTORY ${MOD_DIR})
        # 提取子目录名作为模块名
        get_filename_component(MOD_NAME ${MOD_DIR} NAME)
        
        # 查找该目录下的所有源文件(.cpp)和头文件(.h/.hpp)
        file(GLOB MOD_SOURCES "${MOD_DIR}/*.cpp")
        file(GLOB MOD_HEADERS "${MOD_DIR}/*.h" "${MOD_DIR}/*.hpp")  # 新增:查找头文件
        
        # 只有当存在源文件时才创建模块
        if(MOD_SOURCES)
            pybind11_add_module(${MOD_NAME} MODULE ${MOD_SOURCES} ${MOD_HEADERS})  # 新增:将头文件加入目标(方便IDE识别)
            
            # 设置模块的输出名称(去除Python版本和平台后缀)
            set_target_properties(${MOD_NAME} PROPERTIES
                OUTPUT_NAME ${MOD_NAME}
                PREFIX ""
                SUFFIX ".pyd"
            )
            
            # 设置模块的输出目录属性
            set_target_properties(${MOD_NAME} PROPERTIES
                RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}
                RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}
                LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG}
                LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE}
                ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG}
                ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE}
                PDB_OUTPUT_DIRECTORY_DEBUG ${CMAKE_PDB_OUTPUT_DIRECTORY_DEBUG}
                PDB_OUTPUT_DIRECTORY_RELEASE ${CMAKE_PDB_OUTPUT_DIRECTORY_RELEASE}
            )
            
            # 核心:添加头文件目录(模块自身目录),确保.cpp能包含同目录的.h
            target_include_directories(${MOD_NAME} PRIVATE ${MOD_DIR})  # 新增:包含模块目录
            
            target_link_libraries(${MOD_NAME} PRIVATE Python::Python)
        endif()
    endif()
endforeach()

tasks.json

如果使用miniconda,在进行需先使用==conda activate [name]==激活对应环境,再进行cmake ..

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "cmake-clean",
            "type": "shell",
            "command": "cmake --build . --target clean; del * -Recurse -Force -Confirm:$false",
            "problemMatcher": [],
            "options": {
                "cwd": "${workspaceFolder}/build",
                "shell": {
                    "executable": "powershell.exe"
                }
            },
            "detail": "清理 build 目录"
        },
        {
            "label": "cmake-debug",
            "type": "shell",
            // CMake 生成 Debug 任务激活 Conda 环境
            "command": "& { conda activate p3_14_pybind; cmake -DCMAKE_BUILD_TYPE=Debug .. }",
            "dependsOn": "cmake-clean",
            "problemMatcher": [],
            "options": {
                "cwd": "${workspaceFolder}/build",
                "shell": {
                    "executable": "powershell.exe"
                }
            },
            "detail": "在指定 Conda 环境下生成 Debug 模式的 CMake 构建文件"
        },
        {
            "label": "cmake-release",
            "type": "shell",
            // CMake 生成 Release 任务激活 Conda 环境
            "command": "& { conda activate p3_14_pybind; cmake -DCMAKE_BUILD_TYPE=Release .. }",
            "dependsOn": "cmake-clean",
            "problemMatcher": [],
            "options": {
                "cwd": "${workspaceFolder}/build",
                "shell": {
                    "executable": "powershell.exe"
                }
            },
            "detail": "在指定 Conda 环境下生成 Release 模式的 CMake 构建文件"
        },
        {
            "label": "build-debug",
            "type": "shell",
            "command": "cmake --build . --config Debug -j 8",
            //"dependsOn": "cmake-debug",
            "group": {
                "kind": "build",
                "isDefault": false 
            },
            "problemMatcher": ["$gcc"],
            "options": {
                "cwd": "${workspaceFolder}/build",
                "shell": {
                    "executable": "powershell.exe"
                }
            },
            "detail": "编译 Debug 模式的项目"
        },
        {
            "label": "build-release",
            "type": "shell",
            "command": "cmake --build . --config Release -j 8",
            //"dependsOn": "cmake-release",
            "group": "build",
            "problemMatcher": ["$gcc"],
            "options": {
                "cwd": "${workspaceFolder}/build",
                "shell": {
                    "executable": "powershell.exe"
                }
            },
            "detail": "编译 Release 模式的项目"
        }
    ]
}

launch.json

{
    "configurations": [
        {
            "name": "Python Debugger: Current File (Release)",
            "type": "debugpy",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "preLaunchTask": "build-release",
            "env":{
                "PYTHONPATH":"${workspaceFolder}/build/lib/Release"
            }
        },
        {
            "name": "Python Debugger: Current File (Debug)",
            "type": "debugpy",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "preLaunchTask": "build-debug",
            "env":{
                "PYTHONPATH":"${workspaceFolder}/build/lib/Debug"
            }
        }
    ]
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐