1. 项目概述与背景最近在做一个物流路径优化的项目核心算法部分需要用到Google的OR-Tools。这玩意儿在Python环境里用pip装一下就能跑但项目本身是历史遗留的C项目必须得把OR-Tools的C库编译出来集成进去。网上搜了一圈发现关于在Windows下特别是用老版本的Visual Studio 201732位编译OR-Tools 9.6的完整教程少之又少大部分都是Linux或者用新版本VS的。踩了无数坑从环境配置、依赖下载到编译参数、项目集成每一步都可能遇到“加载完就没反应了”或者各种诡异的链接错误。今天就把这个完整的过程包括我遇到的坑和解决方案手把手地记录下来。如果你也困在类似的环境里比如公司规定必须用VS2017或者项目目标平台是x8632位那么这篇内容应该能帮你省下大把的调试时间。OR-Tools本身是一个功能强大的开源优化工具套件包含了线性规划、整数规划、约束规划、车辆路径问题VRP等一大堆求解器。它的C版本性能最好但编译过程也最麻烦尤其是在Windows上因为它依赖一堆第三方库比如用于线性规划的GLPK、CBC用于处理大型稀疏矩阵的Eigen等。官方文档主要面向Linux/macOS和较新的Visual Studio版本对于VS2017这种“老家伙”很多预设的脚本和配置需要手动调整。我们的目标很明确在Windows 10/11系统上使用Visual Studio 201732位编译器成功编译出OR-Tools 9.6的静态库.lib并创建一个简单的C控制台项目来验证集成是否成功。2. 环境准备与工具链确认编译OR-Tools第一步不是急着下载源码而是把环境彻底理清楚。很多编译失败的问题根源都在于环境不匹配或者依赖缺失。2.1 核心工具版本锁定首先必须明确并严格锁定以下工具的版本任何版本的偏差都可能导致不可预知的问题操作系统Windows 10 或 Windows 11。我是在Windows 11 22H2上完成的但Win10 20H2及以上版本应该都兼容。确保系统更新到最新避免一些底层系统库缺失。Visual StudioVisual Studio 2017 (版本15.9)。这是关键中的关键。你需要安装的是“Visual Studio 2017”而不是2019或2022。安装时必须勾选“使用C的桌面开发”工作负载。在这个工作负载下务必确保“MSVC v141 - VS 2017 C x64/x86 生成工具(v14.16)”和“Windows 10 SDK (10.0.17763.0)”被选中安装。OR-Tools 9.6的CMake配置对VS2017的Toolset版本有特定要求v141是匹配的。安装完成后你可以在开始菜单找到“x86 Native Tools Command Prompt for VS 2017”这是我们后续所有编译命令的起点。不要用普通的CMD或PowerShell必须用这个针对32位环境配置好的命令提示符。CMake版本需要 3.12。我使用的是CMake 3.26.4。去CMake官网下载Windows x64 Installer安装时选择“Add CMake to the system PATH for all users”或“Add CMake to the system PATH for current user”这样在命令行里就能直接用了。Git用于克隆OR-Tools源码和它的子模块。安装最新版即可。编译目标我们编译的是32位x86的静态库MT/MTd。这意味着你的最终C项目运行时库也需要设置为“多线程/MT”或“多线程调试/MTd”以匹配。2.2 第三方依赖管理手动下载与安置OR-Tools编译需要一堆第三方库。官方推荐用make third_party在Linux下但在Windows下特别是VS2017环境下自动下载脚本经常出问题比如网络超时、下载的压缩包不完整、或者解压工具不兼容。最稳妥的方式是手动下载并放置。创建依赖目录在你打算存放OR-Tools源码的目录例如D:\Dev\OR-Tools下创建一个名为dependencies的文件夹。最终的路径会是D:\Dev\OR-Tools\dependencies。手动下载存档你需要下载一个名为ortools_dependencies.zip的压缩包。这个包包含了所有必要的第三方库的预编译版本或源码。由于网络环境问题直接从Google的存储桶下载可能很慢或失败。一个可行的方法是在能顺利访问的外部环境中比如一台Linux机器按照OR-Tools官方GitHub仓库的说明先执行make third_party然后将生成的dependencies目录整个打包成zip。或者在网上寻找热心开发者分享的对应版本的依赖包注意安全核对哈希值。对于OR-Tools 9.6你需要的是与其匹配的依赖包。安置依赖将下载好的ortools_dependencies.zip解压将其中的install文件夹直接复制到上一步创建的D:\Dev\OR-Tools\dependencies目录下。最终结构应该是D:\Dev\OR-Tools\dependencies\install并且install里面应该有很多像include、lib、bin这样的子文件夹。注意绝对不要尝试在Windows下用make命令去自动下载依赖失败率极高且错误信息难以排查。“加载完就没反应了”很多时候就是卡在下载某个依赖的步骤上。手动准备依赖包是Windows下编译成功的第一步也是最重要的一步。3. 源码获取与CMake配置详解环境准备好后我们就可以开始处理OR-Tools本体了。3.1 克隆源码与子模块打开之前提到的“x86 Native Tools Command Prompt for VS 2017”。这个命令行环境已经自动设置了VS2017的编译工具链、库路径等所有必要变量。# 切换到你的工作目录比如D盘根目录 D: cd D:\Dev # 克隆 OR-Tools 仓库指定 9.6 版本 git clone -b stable https://github.com/google/or-tools.git cd or-tools git checkout v9.6 # 同步子模块主要是 protobuf 等 git submodule update --init --recursive这一步完成后你就拥有了OR-Tools 9.6的完整源码。目录结构里你会看到ortoolsC源码、cmakeCMake配置、bazel等文件夹。3.2 CMake生成VS2017解决方案这是核心步骤我们需要告诉CMake使用VS2017的32位编译器并指向我们手动准备的依赖库。在“x86 Native Tools Command Prompt for VS 2017”中进入OR-Tools源码目录并创建一个专门的构建目录通常叫build这样做可以保持源码目录的清洁。# 在 or-tools 源码根目录下 mkdir build cd build接下来执行CMake配置命令。下面这条命令包含了所有关键参数cmake .. -G Visual Studio 15 2017 -A Win32 ^ -DCMAKE_BUILD_TYPERelease ^ -DBUILD_DEPSOFF ^ -DBUILD_PYTHONOFF ^ -DBUILD_JAVAOFF ^ -DBUILD_DOTNETOFF ^ -DBUILD_EXAMPLESOFF ^ -DCMAKE_INSTALL_PREFIX..\install ^ -DCMAKE_PREFIX_PATH..\dependencies\install让我们逐条拆解这些参数理解其背后的“为什么”-G Visual Studio 15 2017指定生成器为Visual Studio 2017。15对应VS2017的内部版本号。-A Win32指定目标平台为32位x86。这是编译32位库的关键。如果你想编译64位这里应该是-A x64并且你需要使用“x64 Native Tools Command Prompt for VS 2017”。-DCMAKE_BUILD_TYPERelease指定生成Release版本的配置。我们首先编译Release版稳定后再考虑Debug版。Debug版-DCMAKE_BUILD_TYPEDebug会链接调试库体积更大运行稍慢。-DBUILD_DEPSOFF至关重要告诉CMake不要尝试自动下载和编译第三方依赖。因为我们已经在dependencies目录下手动放置了预编译好的依赖所以必须关闭此选项。-DBUILD_PYTHONOFF、-DBUILD_JAVAOFF、-DBUILD_DOTNETOFF关闭Python、Java、.NET等语言接口的编译。我们的目标只有C核心库关闭它们可以显著减少编译时间和复杂度避免不必要的错误。-DBUILD_EXAMPLESOFF暂时关闭示例程序的编译。先集中精力把库编出来示例可以后续单独编译。-DCMAKE_INSTALL_PREFIX..\install指定make install或cmake --install时的安装目录。编译完成后我们可以将头文件和库文件安装到这个目录方便后续项目引用。-DCMAKE_PREFIX_PATH..\dependencies\install这是指向手动依赖的核心参数。它告诉CMake去这个路径下寻找第三方库的CMake配置包FindXXX.cmake或直接包含的库文件。CMake会在这里找到GLPK、CBC、Eigen等库的头文件和链接库。执行这条命令后CMake会开始配置。如果一切顺利你会在最后看到Configuring done和Generating done的输出并在build目录下生成一个or-tools.sln解决方案文件。实操心得如果配置失败最常见的错误是“Could NOT find XXX”。请首先检查-DCMAKE_PREFIX_PATH的路径是否正确以及dependencies\install目录下的结构是否完整。另一个常见错误是CMake版本太高与VS2017的旧工具链有兼容性问题可以尝试稍旧一点的CMake 3.18~3.20版本。错误信息通常会明确指出缺失了什么根据提示去检查依赖目录即可。4. 编译、安装与库文件整理生成解决方案文件后我们就可以开始编译了。4.1 使用MSBuild进行编译在“x86 Native Tools Command Prompt for VS 2017”中我们继续留在build目录下使用MSBuild命令进行编译。MSBuild是Visual Studio的构建引擎用命令行比用IDE更清晰也便于自动化。# 编译整个解决方案的Release版本 msbuild or-tools.sln /p:ConfigurationRelease /p:PlatformWin32 /m/p:ConfigurationRelease指定构建配置为Release。/p:PlatformWin32指定平台为32位。/m启用多核并行编译加快速度。你可以根据CPU核心数调整例如/m:4。编译过程会比较漫长取决于你的CPU性能可能需要10到30分钟。期间会编译OR-Tools自身以及其依赖的Protobuf等库。请耐心等待只要前期配置正确通常都能成功。编译成功后你会在build\Release目录下找到生成的主要静态库文件例如ortools.libOR-Tools的核心库。ortools_gen.lib由Protobuf定义的协议缓冲区相关代码生成的库。4.2 安装头文件与库文件为了方便后续项目集成我们将编译好的头文件和库文件“安装”到我们指定的目录..\install。cmake --install . --config Release --prefix ..\install这条命令会将所有必要的文件包括头文件*.h、库文件*.lib以及一些CMake配置文件复制到D:\Dev\or-tools\install目录下。查看这个目录你会看到典型的include、lib、bin可能为空或包含少量dll、cmake子目录。4.3 库文件整理与验证进入install\lib目录你应该能看到一堆.lib文件。除了ortools.lib和ortools_gen.lib还有很多第三方库的.lib文件比如cbc.lib,glpk.lib,protobuf.lib等。一个重要步骤为了在VS2017项目中方便地设置链接库我们可以将所有需要的.lib文件复制到一个单独的文件夹或者直接让项目链接整个lib目录。但更清晰的做法是我们明确知道需要链接哪些核心库。对于一个基本的线性规划或约束规划项目你通常需要链接以下库在项目属性-链接器-输入-附加依赖项中设置ortools.lib ortools_gen.lib cbc.lib cgl.lib clp.lib coinutils.lib osi.lib osi_clp.lib glpk.lib protobuf.lib absl_*.lib (多个如absl_strings.lib, absl_time.lib等)实际上由于库比较多更推荐的做法是在VS项目里直接引用install\lib目录让链接器自己去找。验证库是否有效可以尝试用dumpbin命令VS工具链自带查看库的信息确保是32位的。dumpbin /headers install\lib\ortools.lib | findstr “machine”如果输出中包含machine (x86)说明这是32位库与我们的目标一致。5. 创建VS2017 C测试项目并集成库编译好了接下来就是创建一个简单的C项目来验证集成是否成功。5.1 创建新项目与基础配置打开Visual Studio 2017选择“文件”-“新建”-“项目”。选择“Visual C” - “Windows 桌面” - “Windows 控制台应用程序”给项目起个名字比如TestORtools选择合适的位置点击确定。在解决方案资源管理器中右键项目名选择“属性”。我们需要配置两个关键点平台和运行时库。在右上角的“配置”下拉框选择“所有配置”这样Debug和Release能一起设置。在“配置属性”-“常规”中平台工具集确认是“Visual Studio 2017 (v141)”。Windows SDK 版本选择你安装的版本如10.0.17763.0。在“配置属性”-“C/C”-“代码生成”中运行时库对于Release配置选择“多线程 (/MT)”对于Debug配置选择“多线程调试 (/MTd)”。这必须与编译的OR-Tools库完全匹配。我们编译OR-Tools时默认就是/MT和/MTd。5.2 配置包含目录与库目录还是在项目属性页进行以下设置同样建议在“所有配置”下操作除非Debug和Release的库路径不同。包含目录头文件路径进入“C/C” - “常规” - “附加包含目录”。添加OR-Tools安装目录下的include文件夹路径。例如D:\Dev\or-tools\install\include。通常你还需要添加依赖库的一些特定头文件路径但OR-Tools的install\include目录已经组织好了一般只需添加这一个。库目录.lib文件路径进入“链接器” - “常规” - “附加库目录”。添加OR-Tools安装目录下的lib文件夹路径。例如D:\Dev\or-tools\install\lib。5.3 编写测试代码与链接库编写测试代码打开TestORtools.cpp替换为以下简单的线性规划示例代码。这个例子来自OR-Tools官方示例用于求解一个简单的最大化问题。#include iostream #include “ortools/linear_solver/linear_solver.h” namespace operations_research { void SimpleLpProgram() { // 创建求解器实例使用GLPK后端确保glpk库已链接 MPSolver solver(“SimpleLpProgram”, MPSolver::GLPK_LINEAR_PROGRAMMING); // 创建两个变量取值范围为0到正无穷 MPVariable* const x solver.MakeNumVar(0.0, INFINITY, “x”); MPVariable* const y solver.MakeNumVar(0.0, INFINITY, “y”); // 添加约束条件x 2y 14 MPConstraint* const c0 solver.MakeRowConstraint(-INFINITY, 14.0); c0-SetCoefficient(x, 1); c0-SetCoefficient(y, 2); // 添加约束条件3x - y 0 MPConstraint* const c1 solver.MakeRowConstraint(0.0, INFINITY); c1-SetCoefficient(x, 3); c1-SetCoefficient(y, -1); // 添加约束条件x - y 2 MPConstraint* const c2 solver.MakeRowConstraint(-INFINITY, 2.0); c2-SetCoefficient(x, 1); c2-SetCoefficient(y, -1); // 设置目标函数最大化 3x 4y MPObjective* const objective solver.MutableObjective(); objective-SetCoefficient(x, 3); objective-SetCoefficient(y, 4); objective-SetMaximization(); // 求解 const MPSolver::ResultStatus result_status solver.Solve(); // 检查结果并输出 if (result_status MPSolver::OPTIMAL) { std::cout “Solution found!” std::endl; std::cout “Objective value “ objective-Value() std::endl; std::cout “x “ x-solution_value() std::endl; std::cout “y “ y-solution_value() std::endl; } else { std::cout “The problem does not have an optimal solution.” std::endl; } } } // namespace operations_research int main() { operations_research::SimpleLpProgram(); return 0; }链接库文件在项目属性中进入“链接器” - “输入” - “附加依赖项”。这里需要添加所有必需的.lib文件。由于库很多我们可以采用一种省事的方法编辑install\lib目录下的ortools.lib文件列表。实际上OR-Tools的CMake安装过程会在install\lib下生成一个cmake目录里面包含OR_TOOLSConfig.cmake文件它定义了所有需要链接的库。但对于简单的VS项目我们可以手动添加核心库。一个相对安全的做法是在“附加依赖项”中手动输入以下核心库Debug配置对应*d.lib如ortoolsd.libortools.lib glpk.lib cbc.lib cgl.lib clp.lib coinutils.lib osi.lib osi_clp.lib protobuf.lib更推荐的做法避免遗漏由于absl等库很多手动列举易错。我们可以让链接器自动链接整个目录下的所有.lib。在“附加依赖项”中可以尝试只写ortools.lib因为ortools.lib在链接时会自动将其依赖的其他静态库如absl系列也链接进来前提是这些库都在“附加库目录”指定的路径下且是静态库。如果遇到“无法解析的外部符号”错误通常就是缺少了某个特定的库需要根据错误信息提示的符号去install\lib目录下找到对应的.lib文件并添加到列表中。5.4 编译与运行测试将解决方案平台设置为“Win32”32位。将配置设置为“Release”。按F7或点击“生成解决方案”。如果一切配置正确编译应该成功。按CtrlF5运行程序不调试。如果看到控制台输出类似以下内容恭喜你集成成功了Solution found! Objective value 33 x 6 y 46. 常见问题排查与深度解析即使按照步骤操作也可能会遇到各种问题。这里汇总了我遇到的一些典型问题及其解决方法。6.1 编译期问题CMake配置失败提示找不到GLPK、CBC等问题Could NOT find GLPK (missing: GLPK_LIBRARY GLPK_INCLUDE_DIR)原因CMAKE_PREFIX_PATH设置错误或者dependencies\install目录结构不正确。解决检查dependencies\install目录下是否有glpk子目录里面是否包含include和lib。确保CMAKE_PREFIX_PATH指向的是...\install这一级而不是...\install\glpk。MSBuild编译失败错误 C1083: 无法打开包括文件: “xxx.h”问题例如fatal error C1083: 无法打开包括文件: “absl/strings/string_view.h”: No such file or directory原因包含目录设置不正确或者依赖库的头文件没有正确安装到install\include下。解决首先检查项目属性中的“附加包含目录”是否包含了install\include。其次检查install\include目录下是否存在absl等子文件夹。如果缺失可能是cmake --install步骤没有完全成功可以尝试重新执行安装命令或者手动将build\Release下生成的部分头文件如果有复制过去。链接错误 LNK1104: 无法打开文件“xxx.lib”问题error LNK1104: 无法打开文件“glpk.lib”原因库目录设置错误或者库文件名不匹配Debug/Release混淆。解决确认项目属性中“附加库目录”路径正确。确认你编译的库是Release版glpk.lib而项目配置也是Release。Debug配置需要链接glpkd.lib如果有的话。在install\lib目录下确认该文件存在。6.2 链接期问题无法解析的外部符号 __imp_xxx问题大量以__imp_开头的无法解析的外部符号错误。原因这是最经典的链接错误之一通常意味着你试图链接一个动态库DLL的导入库.lib但运行时库设置不匹配或者你实际上需要的是静态库。在我们的场景中更可能的原因是运行时库/MT, /MTd不匹配。OR-Tools依赖的第三方库如GLPK和我们编译的OR-Tools库本身都是用特定的运行时库编译的很可能是/MT。如果你的项目设置是/MD动态链接运行时库就会导致这种符号冲突。解决确保你的项目属性中“代码生成”-“运行时库”设置与OR-Tools及其依赖库编译时使用的设置完全一致。对于我们手动用CMake/VS2017编译的流程默认就是/MT和/MTd。因此你的测试项目也必须设置为/MTRelease和/MTdDebug。无法解析的外部符号 google::protobuf::xxx问题提示Protobuf相关的符号找不到。原因没有链接protobuf.lib或者链接了错误版本Debug vs Release的protobuf库。解决在项目的“附加依赖项”中明确添加protobuf.lib。并确保路径install\lib下有这个文件。链接成功但运行时崩溃或找不到DLL问题程序编译链接成功但运行时提示“无法找到VCRUNTIME140.dll”或“应用程序无法正常启动(0xc000007b)”。原因如果链接的是动态库.dll需要将对应的DLL文件放在可执行文件同级目录或系统PATH中。但我们的目标是静态链接不应该依赖额外的DLL。出现此问题可能是因为某些依赖如GLPK在dependencies包里是以动态库形式提供的或者项目设置中不小心链接了动态库版本。解决首先确保所有链接的库都是静态库.lib。检查install\bin目录下是否有.dll文件如果有尝试将它们复制到你的可执行文件输出目录如TestORtools\x64\Release。但更好的做法是在CMake配置时尝试寻找或要求编译静态版本的依赖库。对于手动准备的dependencies包可能需要寻找一个完全提供静态库.lib的版本。6.3 环境与路径问题“x86 Native Tools Command Prompt for VS 2017”找不到或环境变量无效解决如果开始菜单里没有可以手动运行%comspec% /k “C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat”路径根据你的VS2017安装位置调整。这个批处理文件会设置正确的环境变量。CMake不是内部或外部命令解决安装CMake时没有勾选“添加CMake到系统PATH”或者需要重启命令行。你可以将CMake的安装路径如C:\Program Files\CMake\bin手动添加到系统的环境变量PATH中。7. 进阶配置与项目迁移建议成功运行测试程序只是第一步。在实际项目中你还需要考虑更多。7.1 编译Debug版本库为了调试你需要编译Debug版本的OR-Tools库。步骤与Release类似在build目录下或新建一个build_debug目录使用CMake配置时将-DCMAKE_BUILD_TYPE设置为Debug。cmake .. -G “Visual Studio 15 2017” -A Win32 -DCMAKE_BUILD_TYPEDebug ... (其他参数不变)使用MSBuild编译Debug版本。msbuild or-tools.sln /p:ConfigurationDebug /p:PlatformWin32 /m安装Debug版本库到另一个目录例如..\install_debug。cmake --install . --config Debug --prefix ..\install_debug在你的VS项目中为Debug配置单独设置包含目录和库目录指向install_debug下的对应路径并链接ortoolsd.lib等以d结尾的库文件。7.2 在项目中使用CMake管理依赖推荐对于更复杂的C项目手动在VS里配置包含目录和库目录很繁琐。更好的做法是使用CMake来管理你的整个项目并利用find_package来查找OR-Tools。在你的项目CMakeLists.txt中可以这样写cmake_minimum_required(VERSION 3.12) project(MyORtoolsProject) set(CMAKE_CXX_STANDARD 11) # 告诉CMake在哪里寻找OR-Tools的配置 set(OR_TOOLS_ROOT “D:/Dev/or-tools/install”) list(APPEND CMAKE_PREFIX_PATH ${OR_TOOLS_ROOT}) # 查找OR-Tools包 find_package(OR_TOOLS REQUIRED) add_executable(MyApp main.cpp) # 链接OR-Tools库这个命令会自动添加所有必要的包含目录和链接库 target_link_libraries(MyApp PRIVATE OR_TOOLS::ortools)这样你只需要在配置项目时通过-DOR_TOOLS_ROOT指定路径CMake会自动处理所有复杂的依赖关系。这是现代C项目更优雅的集成方式。7.3 迁移到其他机器或构建系统当你需要将项目迁移到其他开发机器或者集成到持续集成CI系统如Jenkins、GitLab CI时你需要确保依赖包可移植将完整的dependencies\install目录和or-tools源码或编译好的install目录作为项目的一部分进行管理或者提供脚本自动下载。固化环境在CI脚本中明确指定使用VS2017的构建工具链例如通过调用vcvars32.bat。路径抽象在项目的CMakeLists.txt或构建脚本中不要使用绝对路径如D:\Dev\...而是使用相对路径或从环境变量中读取。整个流程走下来虽然步骤繁多但每一步都有其必要性。从锁定环境版本、手动准备依赖到精细化的CMake配置、解决链接时符号冲突最终在VS2017的32位环境下成功集成OR-Tools 9.6这个过程本身也是对Windows下C项目依赖管理和构建系统的一次深度实践。希望这份详尽的记录能帮你扫清障碍顺利地将强大的OR-Tools优化库应用到你的C项目之中。如果在实际操作中遇到了本文未涵盖的特定错误建议仔细阅读编译和链接的错误信息结合OR-Tools的GitHub Issues和官方文档大部分问题都能找到解决线索。