Win32平台编译Pixar USD库并随exe程序分发的方法咨询
问题背景
本人开发的渲染器应用需要支持.usd/.usda/.usdc格式,安装阶段需要将项目生成的exe文件、USD相关的.lib/.dll文件分发给终端用户,现咨询两个核心问题:
- 如何编译Pixar USD库才能满足可分发要求?
- 若受库结构限制无法直接随程序分发,如何实现用户端所需依赖的自动安装?
已完成工作
目前已完成依赖项oneTBB的编译(TBB是USD的必选依赖,暂不确定USD是否适配oneTBB),编译步骤如下:
:: 当前编译产出为dll,原本期望输出静态库以便裁剪未使用的函数 1. 下载oneTBB源码 2. 解压得到oneTBB-master文件夹 3. 将源码内的include文件夹拷贝到指定依赖目录(cl编译命令通过/I.\include引用头文件) 4. 在oneTBB-master文件夹的地址栏输入cmd回车,打开对应目录的命令行窗口 5. 创建并进入构建目录:mkdir build && cd build :: 如需HWLOC支持需重新编译绑定TBB(一般用于OpenMPI场景,当前项目无该需求) 6. 执行cmake配置:cmake .. -G "Visual Studio 15 2017 Win64" -DTBB_TEST=OFF -DCMAKE_CXX_STANDARD=17 -DCMAKE_BUILD_TYPE=Release 7. 编译Release版本:cmake --build . --config Release 8. 进入产出目录msvc_19.16_cxx17_64_md_release 9. 拷贝tbb12.dll到目标依赖目录 10. 拷贝tbb12.lib到目标依赖目录(编译时链接该文件) :: 暂判断不需要tbbmalloc.dll/tbbmalloc_proxy.dll及对应lib文件
已通过命令行编译简单测试程序验证TBB可用性,构建脚本如下:
@echo off if not defined DevEnvDir ( call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat" ) set FILES=MinimalTBB.cpp set LIBS=kernel32.lib user32.lib gdi32.lib set DLLLIBS=tbb12.lib :: tbbmalloc.lib tbbmalloc_proxy.lib cl /nologo /W3 /Z7 /GS- /DEBUG:none /Gs999999 /MT /EHsc /O2 %FILES% -FeMinimalTBB.exe %LIBS% /I.\include /link %DLLLIBS% /incremental:no /opt:icf /opt:ref /subsystem:console
后续编译计划
后续将先完成Boost依赖的配置处理,再按如下流程编译USD:
1. 下载Pixar USD源码 2. 解压得到USD-release文件夹 3. 在USD-release文件夹的地址栏输入cmd回车,打开对应目录的命令行窗口 4. 创建并进入构建目录:mkdir build && cd build 5. 执行cmake配置:cmake .. -G "Visual Studio 15 2017 Win64" -DBUILD_SHARED_LIBS=ON -DPXR_BUILD_MONOLITHIC=OFF -DPXR_BUILD_IMAGING=OFF -DPXR_BUILD_USDVIEW=OFF -DPXR_ENABLE_PYTHON_SUPPORT=OFF -DPXR_BUILD_DOCUMENTATION=OFF -DPXR_BUILD_TESTS=OFF -DPXR_VALIDATE_GENERATED_CODE=OFF -DPXR_BUILD_PRMAN_PLUGIN=OFF -DPXR_BUILD_ALEMBIC_PLUGIN=OFF -DPXR_BUILD_DRACO_PLUGIN=OFF -DPXR_ENABLE_MATERIALX_SUPPORT=OFF -DCMAKE_BUILD_TYPE=Release 6. 编译Release版本:cmake --build . --config Release
预期通过上述流程编译得到dll文件后,和exe一同分发,项目直接链接对应lib文件即可,无需用户额外安装任何组件。
已遇问题
曾尝试使用NVIDIA提供的USD预编译版本编译项目,但出现大量python36.dll缺失报错,而本项目仅使用C++开发,完全未用到Python相关功能。
解答
可分发版本USD编译要点
你现有的cmake参数已经裁剪了大部分不需要的组件,调整以下几个关键点即可产出无额外隐式依赖、可直接分发的USD库:
- oneTBB兼容性无需额外处理:USD从21.08版本开始原生支持oneTBB,只要使用该版本之后的源码,直接用你已经编译好的oneTBB即可,cmake配置时加
-DTBB_ROOT=<你的oneTBB依赖存放路径>就能自动识别,不需要回退到旧版TBB。 - 必须统一所有依赖的运行时库:当前配置存在崩溃隐患:oneTBB默认cmake编译使用MD动态CRT,但你的测试exe编译参数加了
/MT静态CRT,两者混用会导致跨模块内存分配、释放的未定义行为。分发时二选一即可:- 把exe的
/MT参数改为/MD,随安装包打包对应版本的VC Redist安装程序 - 编译TBB、Boost、USD时都加
-DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>"参数,全部切到MT静态CRT,无需额外安装VC运行时
- 把exe的
- 补全cmake参数避免隐式依赖:Boost编译完成后,配置USD时要加
-DBOOST_ROOT=<你的Boost依赖存放路径>,防止cmake自动搜索到系统内其他版本的Boost,引入未知依赖。如果项目不需要USD的第三方插件扩展能力,可以再加-DPXR_BUILD_PLUGINS=OFF关闭插件加载逻辑,进一步裁剪二进制体积。 - 编译后做全量依赖校验:全部编译完成后,用Dependencies工具扫描所有产出的USD dll,确认导入表中没有python3x.dll、非系统目录下的第三方dll,之后把所有非系统dll和你的exe放在同一个安装目录,即可直接分发给用户,不需要用户额外安装组件。
- 之前用NVIDIA预编译包报python36.dll缺失,是因为公开的预编译包默认开启Python绑定,哪怕只调用C++接口,dll导入表也会强制依赖python dll,自行编译时关闭
PXR_ENABLE_PYTHON_SUPPORT即可解决该问题。
依赖自动安装实现方案
如果因为授权限制、安装包体积控制等原因无法直接打包所有依赖,可以选择以下两种成熟方案实现自动部署,全程无需用户手动操作:
- 安装包阶段部署:使用Inno Setup、NSIS等安装包制作工具编写安装脚本,安装时先检测系统是否存在对应版本的VC运行时、所需USD依赖,缺失则静默运行安装包内附带的依赖安装程序,完成后再执行主程序安装流程。
- 首次运行自修复:主程序启动时先校验自身目录下的依赖dll是否完整、版本是否匹配,检测到缺失则从自有文件服务器拉取对应版本的依赖包,校验文件SHA256哈希无误后解压到程序目录,再继续正常启动流程。
注意:如果选择运行时动态拉取依赖,必须对所有下载文件做哈希校验,避免文件被篡改引入安全风险。
内容的提问来源于stack exchange,提问作者yosmo78
相关产品推荐
相关产品推荐

