简介面向使用Visual Studio 2022进行三维地理信息开发的工程师与研究者提供一份基于OSG 3.6.5的osgEarth自编译版本同时提供调试Debug与发布Release两种配置解决在Windows环境下手动编译osgEarth及其依赖库时流程繁琐、版本对齐困难的问题。压缩包采用7z格式体积约483.88MB共包含2000个文件其中绝大多数为头文件1948个h文件与47个hpp文件覆盖osgEarth主体及底层依赖库的全部接口声明另含少量txt、pdf、c、md文档用于编译说明、版本日志、源码片段和工程备注。目前已有1251人学习下载适合需要快速集成三维地球渲染能力的桌面应用开发者。包内目录规划清晰include提供完整头文件lib存放静态库cmake包含CMake配置脚本bin收录exe与dll并配套pdb调试符号Release版经优化可直接部署Debug版则能完整跟踪调试流程。拿到手即可关联工程省去从源码逐项编译的漫长步骤让开发者更专注于业务功能与可视化效果。1. 为什么宁可自己编译一套 osgEarth 3.4.0 OSG 3.6.5做数字孪生和三维 GIS 的开发者多半被 osgEarth 的二进制包坑过Release 跑得好好的切到 Debug 链接就报 LNK2038加载本地 DEM 没事换成在线影像就提示无法打开数据源。我现在的做法是绕开一切打包版本从源码在 VS2022 下自编译一套 64 位的 OSG 3.6.5 和 osgEarth 3.4.0Debug、Release 两个配置一起出第三方依赖、插件路径全部自己说了算。这篇按我实际走的顺序讲依赖怎么选、OSG 怎么编、osgEarth 怎么接、坑在哪适合准备把 osgEarth 写进正式项目的 C 开发者。2. 编译前的地基两条源码线、第三方依赖与目录规划2.1 依赖关系先理清OSG 和 osgEarth 各自要什么OSG 负责渲染osgEarth 负责地理数据组织。OSG 3.6.5 拆成 osgDB数据读写、osgUtil优化裁剪、osgViewer窗口与事件、osgText矢量字体等模块osgEarth 3.4.0 则是在它上面加了一层地图数据模型——加载 .earth 配置、解析地形、把影像和高程叠进场景。编译顺序因此唯一确定先编 OSG 并安装再让 osgEarth 通过 CMake 的 find_package(OSG) 找到它。顺序反了osgEarth 的 configure 阶段就会直接失败错误指向OSG not found。OSG 3.6.5 在 Windows 上默认要链接 zlib、libpng、libjpeg、freetype、expat 这几个第三方库。它们的作用分别是解压数据、读 PNG/JPG 贴图、渲染字体和解析 XML。缺任何一个编译到对应插件时就会报 cannot open include file。osgEarth 3.4.0 还额外需要三样GDAL 提供 GeoTIFF、矢量数据、mbtiles 等数据源驱动libcurl 负责访问在线影像和高程瓦片服务SQLite3 用于 .earth 文件里配置的本地瓦片缓存。这三样不是编译必须但属于不开就少半边功能的可选依赖。依赖谁需要作用我的建议zlibOSG压缩与 PNG 解码必选libpng / libjpegOSG贴图读写必选freetypeOSG矢量字体必选expatOSGXML 解析必选GDALosgEarth栅格/矢量数据源强烈建议 ONlibcurlosgEarth在线影像/高程瓦片强烈建议 ONSQLite3osgEarth本地瓦片缓存建议 ON版本匹配是这里最容易忽略的一条线。osgEarth 3.4.0 的代码已经用上 OSG 3.6 才调整过的接口标题里这对组合——OSG 3.6.5 配 osgEarth 3.4.0——是被验证过的搭配。拿 OSG 3.4 去配 osgEarth 3.4运气好能编过运行到地图初始化就会在 osgEarth 内部直接崩报的全是黑匣子级错误没法查。自编译第一步不是打开 CMake而是先把版本组合对死。2.2 第三方库怎么选GDAL 和 CURL 别省CRT 必须统一第三方库的获取方式常见做法有两种下预编译的 Windows 第三方集合包解压后就是 include、lib、bin 三个目录或者用 vcpkg 这类包管理器按清单一次装齐。我常年用前者原因是所有库的编译参数可控、目录固定给 OSG 和 osgEarth 指 CMAKE_PREFIX_PATH 时一个路径全解决。选择上有一条底线所有第三方库的运行时必须是同一个动态 CRT也就是 /MD 多线程 DLL。预编译包通常分不同 VS 工具集版本注意挑对应当前 VS2022 的别拿旧的硬顶。如果哪个库是 /MT 静态链接的编译时就会出现 RuntimeLibrary 不匹配或者更隐蔽——编过了跑起来偶发崩溃。这种崩溃最玄学和具体调用路径无关是启动时 CRT 状态已经冲突。GDAL 和 libcurl 我建议一开始就 ON。理由不是功能多而是改一次编译参数的成本远高于重新配一条依赖链先把离线高程、本地地理数据跑通等项目上线了才说在线影像也要那时再开 CURL 特性、重编 osgEarth意味着 GDAL 那套依赖也要跟着回归一遍。反过来部署时发现 GDAL 打不开某类数据源临时关掉重编更亏。少数纯桌面演示、完全离线且数据量小的场景可以只留 zlib 那套最小依赖但普通 GIS 项目别省。2.3 目录规划与 VS2022 工具链检查目录结构我固定这么摆几乎能规避一多半环境问题源码、构建、安装三层分离绝不在源码目录里直接编译也绝不把安装产物混进 dep。# 自编译目录规划示意 D:/osg/ src/OSG-3.6.5/ # OSG 源码包解压目录 src/osgEarth-3.4.0/ # osgEarth 源码包解压目录 dep/ # 第三方预编译库统一放这里 include/ lib/ bin/ build/OSG/ # OSG 构建目录CMake 生成 VS 工程 build/osgEarth/ # osgEarth 构建目录 install/OSG/ # OSG 安装前缀 install/osgEarth/ # osgEarth 安装前缀规划原则全路径不能用中文、空格和特殊符号。OSG 的 CMake 脚本在路径上很敏感含中文的路径会在插件加载阶段产生各种诡异行为报错又不会直接说路径里有中文。另外 install 和 build 分开方便以后删除中间产物也方便给多个工程共用一套安装好的库。工具链检查就两条。第一VS2022 要装使用 C 的桌面开发工作负载确认里面有对应的 MSVC 工具集和 Windows SDK。第二独立安装的 CMake 版本最好在 3.21 以上osgEarth 3.4.0 的 find 逻辑用到的 CMake 特性在老版本上会以奇怪的方式失败。命令行确认一下cmake --version # 期望看到 3.21 或更高版本例如 cmake version 3.28.3注意如果机器上装了多个版本的 VS-G 参数要写完整的 Visual Studio 17 2022避免 CMake 自动选到旧生成器。3. 先编 OSG 3.6.5CMake 配置、Debug/Release 双配置编译与安装3.1 CMake 关键参数与选型理由OSG 3.6.5 用的是标准 CMake 流程。我全程命令行因为参数要保留下来给别人复现也方便以后重编。首先要说清一个关键概念用 Visual Studio 17 2022 这种多配置生成器时CMAKE_BUILD_TYPE 是不生效的Debug 和 Release 由后续--config参数决定configure 阶段不要传它传了也只是被忽略。cmake -S D:/osg/src/OSG-3.6.5 -B D:/osg/build/OSG \ -G Visual Studio 17 2022 -A x64 \ -DCMAKE_INSTALL_PREFIXD:/osg/install/OSG \ -DCMAKE_PREFIX_PATHD:/osg/dep \ -DBUILD_OSG_EXAMPLESOFF \ -DBUILD_OSG_APPLICATIONSON \ -DOSG_USE_QTOFF逐项说理由。-A x64强制 64 位架构不写这行CMake 可能按机器默认挑到 Win32出来的库链接到 x64 工程时直接就是 LNK1112。BUILD_OSG_EXAMPLESOFF把示例工程关掉示例代码编译量大且用不上开着只会拖慢首批编译。BUILD_OSG_APPLICATIONSON保留 osgversion 等命令行小工具后面验证安装是否成功要用。OSG_USE_QTOFF关掉 Qt 支持不引入额外依赖如果确实要做 Qt 窗口集成那才需要单独提供 Qt 路径。第三方依赖靠CMAKE_PREFIX_PATH指过去OSG 的 FindZLIB、FindFreetype 等脚本会在这些路径下找头文件和库。这里容易踩的坑是 dep 里同时存在多套架构或版本的第三方库CMake 有时会先搜到不匹配的那套。如果 configure 输出里出现某个依赖 NOT FOUND先把 dep 里多余的库清掉再重新 configure。3.2 执行编译--config 与 --parallel生成完解决方案后不用打开 VS 手动构建直接在命令行编两个配置cmake --build D:/osg/build/OSG --config Debug --parallel 8 cmake --build D:/osg/build/OSG --config Release --parallel 8--parallel 8对应机器核数8 核及以上的机器一般写 8别贪多内存小的时候开太多编译进程会把系统拖死。两个配置都要编因为自编译版的价值就在同时拿到 Debug 和 ReleaseDebug 用于开发时断点调试 osgEarth 内部逻辑Release 用于部署和性能测试。只编 Release遇到 Debug 工程就抓瞎。首次编译耗时取决于机器两轮下来通常在半小时到一个小时之间。中途失败时不要盲目整包重编先看失败的是哪个项目。OSG 最常见的失败是某个第三方头文件找不到报错形如 cannot open include file: zlib.h。这说明第三方 include 路径没被识别回去检查CMAKE_PREFIX_PATH和 dep 目录结构修正后重新 configure 再增量编。如果想单独验证某个模块用 --target 指定cmake --build D:/osg/build/OSG --config Debug --target osgDB --parallel 8这行只编译 osgDB 一个目标其余不动。它适合排查总在某个模块失败、其他模块已经 ok的情况比反复整编快得多。3.3 安装与检查产物编译完成后安装注意两个配置都要装cmake --install D:/osg/build/OSG --config Debug cmake --install D:/osg/build/OSG --config Release安装到同一前缀是安全的原因是 OSG 对 Debug 产物统一加d后缀Release 下是 osg.lib、osgDB.libDebug 下是 osgd.lib、osgDBd.libDLL 同理osg.dll 对应 osgd.dll。两者共存于 install/OSG 的 lib 和 bin 目录不会互相覆盖。头文件是同一套 include不需要区分 Debug/Release。装完做三件事验证别急着往下编 osgEarth检查项位置 / 命令期望结果版本工具install/OSG/bin/osgversion.exe输出 OpenSceneGraph 3.6.5插件install/OSG/bin/osgPlugins-3.6.5/osgdb_png.dll、osgdb_jpeg.dll 等齐全库文件install/OSG/lib/osg.lib 与 osgd.lib 同时存在插件目录是整条链最容易出问题的部分先在 OSG 这一层确认它完整后面 osgEarth 的插件才能合流。如果 lib 下只有 Release 库、没有带 d 的 Debug 库说明 Debug 那轮--install没执行成功重跑一遍。4. 再编 osgEarth 3.4.0对接 OSG 的 CMake 配置与插件合流4.1 osgEarth 的 CMake 配置与特性开关osgEarth 3.4.0 的 configure 依赖 OSG 已经安装好关键参数不是路径而是三个特性开关。下面这组是我每次换新机器都会先跑一遍的cmake -S D:/osg/src/osgEarth-3.4.0 -B D:/osg/build/osgEarth \ -G Visual Studio 17 2022 -A x64 \ -DCMAKE_INSTALL_PREFIXD:/osg/install/osgEarth \ -DOSG_DIRD:/osg/install/OSG \ -DCMAKE_PREFIX_PATHD:/osg/install/OSG;D:/osg/dep \ -DUSE_GDALON \ -DUSE_CURLON \ -DUSE_SQLITE3ON \ -DBUILD_OSGEARTH_EXAMPLESONOSG_DIR指向 OSG 安装前缀osgEarth 的 CMake 用它定位 OSG 的 CMake 配置文件CMAKE_PREFIX_PATH里同时包含 OSG 安装目录和第三方 dep 目录让 GDAL、CURL、SQLite3 的查找脚本能命中。注意分号分隔Windows 下别用冒号。BUILD_OSGEARTH_EXAMPLESON会编出 osgearth_version、osgearth_viewer 这类工具验证时直接用不需要可以 OFF但 OFF 之后建议至少把 osgearth_version 的构建目标单独编一次。这三个 USE 开关决定 osgEarth 编译期支持什么数据源。ON 表示要求 CMake 找到对应库并链接进对应插件里。configure 过程会滚动输出摘要最后几行列出最终启用的特性。这是最容易踩空的一步你写了-DUSE_CURLON但如果 libcurl 没找到osgEarth 不会让 configure 失败而是默默把这个特性置为 NO。所以 configure 完必须回头确认摘要里 GDAL: YES、CURL: YES、SQLite3: YES否则后面打开在线瓦片时会发现一切都没编进去。找不到库时的修正方法是手动指定缓存变量比如 GDAL 目录偏就显式指过去cmake -S D:/osg/src/osgEarth-3.4.0 -B D:/osg/build/osgEarth \ -DGDAL_INCLUDE_DIRD:/osg/dep/include \ -DGDAL_LIBRARYD:/osg/dep/lib/gdal.lib显式指定后重新 configure照样检查摘要。CURL 同理用 CURL_INCLUDE_DIR 和 CURL_LIBRARY 两个缓存变量纠正。4.2 Debug 和 Release 一起编别忘了后缀 dosgEarth 的编译命令和 OSG 完全一致两轮构建、两轮安装cmake --build D:/osg/build/osgEarth --config Debug --parallel 8 cmake --build D:/osg/build/osgEarth --config Release --parallel 8 cmake --install D:/osg/build/osgEarth --config Debug cmake --install D:/osg/build/osgEarth --config Release产物同样带 d 后缀Release 下是 osgEarth.libDebug 下是 osgEarthd.lib。osgEarth 3.4 拆了多个子库Util、Features、Symbology、Annotation 这些同样遵循这个命名规则。如果只想先确认核心库能编过用 --target 指到 osgEarth 目标cmake --build D:/osg/build/osgEarth --config Release --target osgEarth --parallel 8Debug 配置最容易出现的问题是模板展开阶段报一堆 OSG 头文件错误原因多数不是代码坏了而是OSG_DIR指到了 OSG 源码目录而不是安装目录导致 osgEarth 引用了源码里的 include 和已安装库之间的版本不一致。回看 CMake 缓存里的OSG_DIR改成 install/OSG 再试。4.3 插件目录与 PATH让 exe 找到地球文件osgEarth 编出来的不只是库还有一批 OSG 插件osgdb_earth.dll 负责读 .earth 文件osgdb_osgearth_* 系列负责高程、影像、地形切片等驱动Debug 编译的插件文件名同样带 d。它们默认被装进 osgEarth 安装目录的 bin/osgPlugins-3.6.5 下。OSG 运行时只认一套插件搜索路径所以这里要处理两个插件目录怎么合流的问题。我的常见做法是让两个前缀合并configure osgEarth 时把CMAKE_INSTALL_PREFIX指到 D:/osg/install/OSG让 osgEarth 的插件和 OSG 的插件装进同一个目录OSG 自动找到全部插件不用管 OSG_PLUGIN_PATH。如果你保持两个前缀分开也就是 4.1 里的写法那必须设环境变量export OSG_PLUGIN_PATHD:/osg/install/OSG/bin/osgPlugins-3.6.5:D:/osg/install/osgEarth/bin/osgPlugins-3.6.5 export PATHD:/osg/install/OSG/bin:D:/osg/install/osgEarth/bin:D:/osg/dep/bin:$PATHPATH 里必须包含 OSG、osgEarth 和第三方 dep 的 bin 三个目录缺任何一个运行时都会弹找不到 DLL或者静默初始化失败。Windows 下改完环境变量要重启开发环境或新开终端才生效老生常谈但每次都有人栽在这。验证插件合流是否成功跑一下osgearth_version正常输出里能看到 osgEarth 版本、OSG 版本和当前可用的驱动列表。如果输出里找不到你需要的驱动回 4.1 检查特性开关如果程序直接报缺 DLL多半是 PATH 里 dep/bin 没在。5. 自编译避坑指南四个典型翻车现场与排查5.1 Debug/Release 混用LNK2038 与启动即崩溃现象自己的工程链接时报LNK2038 mismatch detected for RuntimeLibrary或者链接全过、exe 一启动就异常退出连主函数都没进。原因工程里把 Debug 配置的 osgd.lib 链进了 Release 工程或者反过来更隐蔽的是某个第三方库用了 /MT 静态运行时和 OSG 的 /MD 动态运行时冲突。这类问题编译期不一定暴露启动时才炸。解决统一运行时所有库和工程全部用动态 /MD。CMake 工程里显式加set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)并且不要手写硬编码库名用 find_package(OpenSceneGraph) 和 find_package(osgEarth) 返回的变量它们会自动按当前配置选 osgd.lib 还是 osg.lib。排查时看报错信息里的库名后缀带 d 的库只能进 Debug 配置。5.2 窗口起来但地表没加载osgPlugins 没找到现象程序运行不报错OSG 窗口黑屏或灰屏控制台输出Warning: Could not find plugin to read objects from file xxx.earth。原因OSG 启动时没找到 osgPlugins 目录。常见于把 exe 拷到别处跑、OSG_PLUGIN_PATH 没设、或者两个安装前缀没合并时只指了一个插件目录。解决确认环境变量OSG_PLUGIN_PATH同时包含 OSG 和 osgEarth 两个 osgPlugins-3.6.5 路径如果 exe 和插件不在同一磁盘目录别依赖相对路径直接临时把路径加进代码里的搜索列表#include osgDB/Registry // 在 main() 最前面执行用于快速定位插件路径问题 osgDB::Registry::instance()-getLibraryFilePathList().push_back( D:/osg/install/OSG/bin/osgPlugins-3.6.5);这行把插件目录手动塞进 OSG 的搜索列表适合临场确认是不是插件路径问题。确认后回归环境变量的正规做法别在业务代码里写死路径。5.3 版本组合不对osgEarth 3.4.0 遇旧 OSG现象编译期偶发报错或者运行时初始化地图时崩溃崩溃点在 osgEarth 内部堆栈很浅一看就是符号对不上。原因osgEarth 3.4.0 要求 OSG 3.6.x但机器上装了旧 OSG 3.4/3.5或者OSG_DIR指错了目录CMake 没找到就沿用了 PATH 里那个旧版本。osgEarth 编译过不代表链接到同一个 OSG运行时 DLL 加载才暴露。解决锁死组合 OSG 3.6.5 osgEarth 3.4.0configure 后查缓存变量里的OSG_VERSION确认是 3.6.5检查最终 exe 的导入表看 osgEarth.dll 依赖的 OSG DLL 文件名里的版本号是否和 install/OSG/bin 下的一致。这类问题先看导入表别在业务逻辑上浪费精力。5.4 在线瓦片全挂CURL/GDAL 特性没开现象.earth 里配了在线影像源运行后控制台持续刷无法打开数据源或者直接超时本地高程、模型都正常。原因编 osgEarth 时USE_CURL实际是 NO在线瓦片驱动根本不存在或者 GDAL 没开mbtiles 这类本地源也读不了。configure 摘要没看或者 -D 变量名写错都是常见起因。解决用osgearth_version看特性表确认 CURL、GDAL 是 YES。如果是 NO回到 4.1 修正缓存变量重新 configure 并完整重编一次不要只编单个库插件也要重新编。顺带检查 dep/bin 下的 libcurl 及它的依赖 DLL 都在 PATH 里Windows 上缺了这些动态库会在加载插件时直接崩溃。6. 最小地球程序验证与对接让自编译库真正进项目验证自编译库最快的方法是写一个读 .earth 文件的最小程序不碰任何在线数据源。先准备一个本地测试地图文件 test.earth用 osgEarth 自带的 tile 程序化驱动生成影像map image nametest drivertile / /map工程只要两个文件。CMakeLists.txt 负责找库cmake_minimum_required(VERSION 3.21) project(earth_test) set(CMAKE_PREFIX_PATH D:/osg/install/OSG;D:/osg/install/osgEarth) find_package(OpenSceneGraph REQUIRED COMPONENTS osgDB osgViewer) find_package(osgEarth REQUIRED) add_executable(earth_test main.cpp) target_link_libraries(earth_test ${OPENSCENEGRAPH_LIBRARIES} ${OSGEARTH_LIBRARIES})main.cpp 只做三件事初始化 osgEarth、读 earth 文件、交给 viewer#include osgViewer/Viewer #include osgDB/ReadFile #include osgEarth/EarthManipulator int main() { osgEarth::initialize(); osg::ref_ptrosg::Node node osgDB::readNodeFile(test.earth); osgViewer::Viewer viewer; viewer.setSceneData(node.get()); viewer.setCameraManipulator(new osgEarth::EarthManipulator()); return viewer.run(); }把 test.earth 放到 exe 同目录Debug 配置跑出来的程序能正常看到一块可旋转的测试地形就说明 OSG、osgEarth、插件、运行库四层全部打通。这一步通过后再去接你自己的数据源和业务逻辑有问题就排查自己的代码不再怀疑编译链。如果步骤上 osgEarth 没被找到多半是安装目录的 lib/cmake 没进CMAKE_PREFIX_PATH补上即可。我每换一台新机器都会先把这个最小程序跑通再谈项目集成这已经是雷打不动的习惯。自编译这东西一次配置对后面全是顺的配置错了越往后越难回头。希望帮到你。本文还有配套的精品资源点击获取