我想将 OpenVDB 接入 doyubkim 的流体引擎
https://github.com/doyubkim/fluid-engine-dev
然后搜到已经有人做过这件事了
https://github.com/yangfengzzz/fluid-engine-OpenVDB
Windows 编译 yangfengzzz/fluid-engine-OpenVDB
但是我是 windows,所以想要编译他这个库还要费一点精力
cmake
首先是,要使用 vcpkg 和 cmake 搭配,要注意配置 DCMAKE_TOOLCHAIN_FILE
@echo off
cls
REM Configure a release build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=E:/vcpkg/scripts/buildsystems/vcpkg.cmake
REM Actually build the binaries
cmake --build build/ --parallel 4
pause
然后这个仓库的 FindTBB.cmake 似乎有点问题,我就直接从 openvdb 的 cmake 文件夹里面复制所有的 FindXXX.cmake 过来了
他设置 CMAKE_MODULE_PATH
的方式似乎有点问题,直接追加 "../cmake"
的话,似乎不会转换为完整的路径。所以我就把这些都注释掉了
# list(APPEND CMAKE_MODULE_PATH "../cmake")
然后在最外层的 CMakeLists 设置 CMAKE_MODULE_PATH
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
第三方库可以找到了之后,然后是一些错误
attribute
log_manager.cpp
marching_cubes.cpp
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,26): error C2059: syntax error: '(' [E:\repositor
ies\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxproj]
(compiling source file '../../src.common/log_manager.cpp')
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,36): error C4430: missing type specifier - int as
sumed. Note: C++ does not support default-int [E:\repositories\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxpro
j]
(compiling source file '../../src.common/log_manager.cpp')
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,36): error C2059: syntax error: ')' [E:\repositor
ies\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxproj]
(compiling source file '../../src.common/log_manager.cpp')
E:\repositories\fluid-engine-OpenVDB\src.common\log_manager.cpp(81,9): error C2352: 'vox::ExceptionFactory::throwExcept
ion': a call of a non-static member function requires an object [E:\repositories\fluid-engine-OpenVDB\build\src.common\
Flex_Common.vcxproj]
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,43):
see declaration of 'vox::ExceptionFactory::throwException'
E:\repositories\fluid-engine-OpenVDB\src.common\log_manager.cpp(118,9): error C2352: 'vox::ExceptionFactory::throwExcep
tion': a call of a non-static member function requires an object [E:\repositories\fluid-engine-OpenVDB\build\src.common
\Flex_Common.vcxproj]
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,43):
see declaration of 'vox::ExceptionFactory::throwException'
parallel.cpp
E:\repositories\fluid-engine-OpenVDB\src.common\parallel.cpp(14,11): error C1083: Cannot open include file: 'tbb/task_s
cheduler_init.h': No such file or directory [E:\repositories\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxproj]
vox_exception.cpp
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,26): error C2059: syntax error: '(' [E:\repositor
ies\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxproj]
(compiling source file '../../src.common/vox_exception.cpp')
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,36): error C4430: missing type specifier - int as
sumed. Note: C++ does not support default-int [E:\repositories\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxpro
j]
(compiling source file '../../src.common/vox_exception.cpp')
E:\repositories\fluid-engine-OpenVDB\src.common\vox_exception.hpp(241,36): error C2059: syntax error: ')' [E:\repositor
ies\fluid-engine-OpenVDB\build\src.common\Flex_Common.vcxproj]
(compiling source file '../../src.common/vox_exception.cpp')
是 __attribute__
的问题,这个写法是 gcc 的,msvc 识别不了
修改为 [[]]
的形式就好了
后面知道属性只能用在定义
error C3829: attribute [[noreturn]] may only be applied to a function declaration
我就干脆把这个属性删了,不想再拆开了
tbb
然后是找不到 tbb 的头文件
看了一下才发现他没有在 CMakeLists 中包含 TBB 的头文件目录
不知道他是怎么编译通过的……
于是我给他两个目标加上了
target_include_directories(Flex_Common PUBLIC ${TBB_INCLUDE_DIRS})
target_include_directories(Flex_VDB PUBLIC ${TBB_INCLUDE_DIRS})
但是从 openvdb 复制过来的 FindTBB.cmake 里面设置的是 Tbb_INCLUDE_DIRS
,有点怪
我就从 doyubkim 复制 FindTBB.cmake 过来,结果这个还找不到 tbb 包
于是还是只能用 openvdb 的 FindTBB.cmake
target_include_directories(Flex_Common PUBLIC ${Tbb_INCLUDE_DIRS})
target_include_directories(Flex_VDB PUBLIC ${Tbb_INCLUDE_DIRS})
但是仍然报错说找不到 include 目录
不知道为什么,他把这个 include path 加到了 C/C++ - All Options - Additional Options 里面了,看上去像是命令行参数一样
之后我才发现,似乎我的 target_include_directories
没有产生效果
但是命令行里面有这个 /external:I "E:/vcpkg/installed/x64-windows/include"
似乎也是一样的
我不知道是哪个东西引出了 /external:I "E:/vcpkg/installed/x64-windows/include"
,应该是配置 DCMAKE_TOOLCHAIN_FILE
导致的吧
所以这似乎不是 VS 的问题,我看了我 vcpkg 下载的 tbb,还真的没有 task_scheduler_init.h 这个文件
所以这就是 tbb 的版本问题了
搜了一下,确实是 2021 版本的 tbb 删掉了这个头文件
搜到了怎么用 vcpkg 控制版本
https://devblogs.microsoft.com/cppblog/take-control-of-your-vcpkg-dependencies-with-versioning-support/
https://learn.microsoft.com/en-us/vcpkg/consume/lock-package-versions?tabs=inspect-powershell
根据它的说法,我首先在项目根目录创建了一个 vcpkg.json
{
"dependencies": [
"tbb",
"glog",
"openvdb"
],
"builtin-baseline": "3f6e8e9c09e28a0eae4b37cceb2982ca2518278c",
"overrides": [
{
"name": "tbb",
"version": "2020.02.0"
}
]
}
然后我直接调用 cmake 构建,vcpkg 对我这个设置的版本没有反应
我已经安装的 tbb 是 2021.10 的,我直接用 cmake 构建,tbb 的版本并没有变化
我把 tbb 和 openvdb 卸载了,然后我再
之后我看到教程里面说,版本控制暂时不适用于通过命令行安装的包
我才知道,原来可以有不通过命令行安装的方法……?
于是我重新看了一下,发现他有一个带有 version 标志的命令行
vcpkg --feature-flags="versions" install
运行了这个命令之后,提示说我这个版本号不正确,并且给出了一些正确的版本号
于是我把 json 改成了
{
"dependencies": [
"tbb",
"glog",
"openvdb"
],
"builtin-baseline": "3f6e8e9c09e28a0eae4b37cceb2982ca2518278c",
"overrides": [
{
"name": "tbb",
"version-string": "2020_U3#8"
}
]
}
现在 vcpkg 确实能够识别到我设定的这个版本,但是直接运行 cmake 还是找不到
现在他似乎把东西都下载到了 vcpkg_installed 这个文件夹里面了
比如我现在关心的这个 tbb,在我 vcpkg 的安装目录里面没找到 tbb,但是在工程目录的 vcpkg_installed 里面有
现在一个明显的问题是,我该怎么让 cmake 知道他要找工程目录的这个 vcpkg_installed 文件夹里面?
之后查到,用版本控制的这个方法属于清单模式
确实已经有使用清单模式构建的教程
https://learn.microsoft.com/en-us/vcpkg/consume/manifest-mode?tabs=cmake%2Cbuild-cmake
似乎他也没做什么
但是为什么我这里就找不到包呢,之后我删了 build 重新构建,似乎就行了
所以就是要清理构建缓存的事
uint
然后是 uint 不识别的问题,这不是一个标准的写法,直接替换成 unsigned int
连接不到 Flex_Common.lib
Flex_Common 是作为共享库来生成的,现在 cmake 需要它的 lib 文件,但是实际上没有生成
LINK : fatal error LNK1104: cannot open file '..\src.common\Debug\Flex_Common.lib' [E:\repositories\fluid-engine-OpenVDB\build\src.vdb\Flex_VDB.vcxproj]
查了一下,是因为实际上这个库没有导出符号
可以设置强制导出所有符号,来获得 lib 文件
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
但是实际上这就是代码结构的问题,为什么你没有用到共享库中的导出函数?
我查了一下,这里面的代码都没有用到 dllexport
所以我就直接改成了 STATIC
这样,终于能够正常编译了
Flex_Common
Flex_VDB
两个库都改成 STATIC
单元测试
然后就是编译单元测试和人工测试
他是在代码里面 hardcode 了一个外部的路径,然后 CMakeLists 里面也是 hardcode 的外部路径
所以我把 ../external/gtest/include/gtest
替换成 gtest
,把 ../external/gmock/include/gmock
替换成 gmock
然后在 vcpkg.json 里面添加这两个库
在 CMakeLists 里面添加
find_package(GTest)
CMakeLists 中把 gtest gmock
换成 GTest::gtest GTest::gtest_main GTest::gmock GTest::gmock_main
然后是 Eigen3,删了源文件里面的 ../external/
,CMakeLists 里面加上相关的
cg pcg 没有匹配的模板
之前把 uint 改成了 unsigned int,之后发现很多到 size_t 的类型转换的警告,所以又改成了 size_t
但是我只是在 src 里面把 unsigned int 改成 size_t,没有在单元测试里面改
才导致了这个错误
所以我重置了一下代码,只把 uint 换为 unsigned int
就不会有不匹配的情况
M_PI
在 M_PI 报错的那个源文件里面,在所有包括头文件之前定义宏
#define _USE_MATH_DEFINES
之所以在所有 include 之前定义,是为了防止头文件之间互相干扰