c++ - 使用 cmake 在 Windows 上编译 C++ 数据库时出错

标签 c++ c duckdb

对于我的硕士学位,我需要在一个名为 duckdb 的数据库上工作(它在 git hub 上)。通常在 Linux 上,您可以简单地克隆它并“制作”它以进行安装。

安装 CMake 和 Cygwin 后,我在 Windows 上遇到了同样的问题。

编译到一半就报错

'DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96:
error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }'

因为我怀疑 duckdb 的创建者确实搞砸了这件事,我认为在尝试将 C 文件编译为 C++ 文件时可能存在编译器错误。

我的主要问题是:如何在 Windows 上配置 make 命令以阻止它产生此错误?

我在安装了 gcc 5.1 和当前 cmake 的 Windows 7 和 10 系统上都试过了,但都产生了这个错误。

编辑:这是完整的错误文本

[ 87%] Building CXX object test/sql/capi/CMakeFiles/test_sql_capi.dir/ub_test_sql_capi.cpp.obj In file included from C:/duckdb/test/sql/capi/test_capi.cpp:1:0, from test_capi.cpp:0:

C:/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp: In instantiation of 'bool >Catch::compareNotEqual(const LhsT&, RhsT&&) [with LhsT = void*; RhsT = const >long long int&]':

C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1471:37: required from 'const >Catch::BinaryExpr Catch::ExprLhs::operator!=(const >RhsT&) [with RhsT = long long int; LhsT = void* const&]'

C:/DB/duckdb/test/sql/capi/test_capi.cpp:332:2: required from here C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96: error: ISO C++ forbids comparison >between pointer and integer [-fpermissive] auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return >static_cast(lhs != rhs); }

我只在路径等中编辑掉了我的用户名。

最佳答案

我不了解图书馆,所以无法给出明确的答案。我将按照 https://github.com/cwida/duckdb 处的代码进行操作.

根据错误信息,有问题的代码在test/sql/capi/test_capi.cpp的第332行,即:

REQUIRE(stmt != NULL);

REQUIRE 是单元测试库 Catch2 中的一个宏,它执行一些魔术来解析给它的表达式。重要的是 stmt != NULL 实际上不会立即执行,而只会通过函数间接执行。

stmt 在第 324 行声明为

duckdb_prepared_statement stmt = nullptr;

duckdb_prepared_statementsrc/include/duckdb.h第94行的typedef:

typedef void *duckdb_prepared_statement;

因此,有问题的行的目的是检查 stmt 在一些中间操作之后是否仍然是 nullptr

通常 stmt != NULL 就可以了。但是,由于 Catch2 宏引入了中间函数调用而不是直接计算此表达式,因此不应用特定于文字的隐式转换。

特别是 NULL 根据标准是 std::nullptr_t 类型的纯右值或值为 0 的整数文字。这些中的哪一个(以及哪个整数类型)是实现定义的。

通常禁止比较整数和指针,但是值为零的整数文字有一个特殊的异常(exception),允许它们隐式转换为任何指针类型的空指针。如果直接计算 stmt != NULL,就会发生这种情况。

但是由于 Catch2 的插入,NULL 首先被传递,然后通过变量与 stmt 进行比较,这使得特殊的零文字规则不再适用.因此,如果 NULL 在当前实现中是整数文字,则通过 REQUIREstmtNULL 进行比较将失败。

Catch2 确实考虑了这个问题,并且在 third_party/catch/catch.hpp 中为 compareNotEqual 重载了处理 NULL 的情况> 是 intlong 类型的零整数文字,但出于某种原因,未考虑 long long 的情况。我不知道这是否是 Catch2 的问题,还是仅存在于 duckdb 中包含的克隆版本中。

因此,如果实现对 NULL 使用类型为 long long 的零文字,则会发生您观察到的错误。

真正的 duckdb 应该使用 nullptr 而不是 NULL (就像它在初始化时所做的那样),它没有这些问题并且因为这些而被添加到语言中问题。

我想您可以简单地尝试通过将 NULL 替换为 nullptr 来解决此问题(也许在其他测试用例中也是如此)。

然而,有问题的代码仅出现在文件中,这些文件本身就是实际库代码的单元测试。因此,cmake 或 make 应该有一些选项将禁止构建单元测试,这样您就可以忽略这个特定错误,希望它也不会出现在实际库代码中的任何地方。

如果我的评估是正确的,您可能需要考虑使用 duckdb 提交错误报告,假设他们首先支持您的平台。

关于c++ - 使用 cmake 在 Windows 上编译 C++ 数据库时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58486414/

相关文章:

c++ - 如何使用 Marching Squares 生成位图的多边形网格?

c++ - Getaddrinfo 不同的行为

c - 带括号和不带括号的指针

python - 在条件连接 + groupby/agg 上下文中,Polars 比 DuckDB 慢得多

parquet - 在 DuckDB 中读取分区的 Parquet 文件

c++ - 对象实例能否安全地将指向自身的 "this"指针置空?

c++ - 链接错误 : Multiple definitions

c - 为什么通过引用写入 bitfield-uint union 会产生错误的汇编指令?

c - 维度大于 3 的数组地址

python - DuckDB 不保存巨大的数据库