簡體   English   中英

使用 cmake 在 windows 上編譯 c++ 數據庫時出錯

[英]Error compiling a c++ database on windows with cmake

對於我的碩士學位,我需要在一個名為 Dukedb 的數據庫上工作(它在 git 集線器上)。 通常在 Linux 上,您可以簡單地克隆它並“制作”它來安裝。

在安裝 CMake 和 Cygwin 之后,我在 windows 上也感到厭煩。

但是在編譯過程中我得到了錯誤

'DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96:
錯誤:ISO C++ 禁止指針和 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%] 構建 CXX object 測試/sql/capi/CMakeFiles/test_sql_capi.dir/ub_test_sql_capi.cpp.obj 包含在 C:/duckdb/test/sql/capi/test_capi.c 的文件中。 cpp:0:

C:/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp: 在 '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: 需要來自 '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: 從這里需要 C:/DB/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp1: : ISO C++ 禁止比較 > 指針和 integer [-fpermissive] auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return >static_cast(lhs;= r }

我只在路徑等中編輯了我的用戶名。

我不知道圖書館,所以我不能給出肯定的答案。 我將使用https://github.com/cwida/duckdb的代碼。

根據問題代碼中的錯誤信息在test/sql/capi/test_capi.cpp的第 332 行,即:

REQUIRE(stmt != NULL);

REQUIRE是單元測試庫 Catch2 中的一個宏,它在解析給它的表達式時做了一些魔術。 重要的部分是stmt != NULL實際上不會立即執行,而只能通過 function 間接執行。

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 宏引入了中間 function 調用而不是直接評估此表達式,因此不應用特定於文字的隱式轉換。

特別是NULL根據標准是std::nullptr_t類型的純右值或值為 0 的 integer 文字。其中哪一個(以及哪個 Z157DB7ZDF530023577515D366E8Z)是實現定義的。

通常禁止比較整數和指針,但是值為零的 integer 文字有一個特殊例外,允許它們隱式轉換為任何指針類型的 null 指針。 如果stmt != NULL將被直接評估,就會發生這種情況。

然而,由於 Catch2 的插入, NULL首先被傳遞,然后通過變量與stmt進行比較,這使得特殊的零文字規則不再適用。 因此,如果NULL在當前實現中是 integer 文字,則通過REQUIREstmtNULL進行比較將失敗。

Catch2 確實考慮了這個問題,並且在third_party/catch/catch.hpp中存在compareNotEqual的重載,它處理了NULL為零 integer 文字的intlong類型的情況,但由於某種原因,不考慮long long的情況. 不知道這是否是 Catch2 的問題,還是僅存在於duckdb 中包含的克隆版本中。

因此,如果實現對NULL使用long long類型的零字面量,那么您觀察到的錯誤將會發生。

真正的duckdb應該使用nullptr而不是NULL (就像它在初始化中所做的那樣),它沒有這些問題,正是因為這些問題才被添加到語言中。

我想你可以簡單地嘗試通過用nullptr替換NULL來解決這個問題(也許在其他測試用例中也是如此)。

但是,有問題的代碼僅存在於文件中,這些文件本身就是實際庫代碼的單元測試。 因此,cmake 應該有一些選項,或者使該選項將禁用構建單元測試,以便您可以忽略此特定錯誤,希望它不會出現在實際庫代碼中的任何地方。

如果我的評估是正確的,那么您可能需要考慮使用duckdb 提交一個錯誤報告,假設他們首先支持您的平台。

與使用 Cygwin 相比,使用 CMake 結合 Visual Studio 編譯項目可能更容易。 這是作者自己在 Windows 上編譯和測試 DuckDB 的方式。

使用 CMake,生成一組 Visual Studio 項目文件。 然后在 Visual Studio 中打開這些項目文件(我們使用 Visual Studio Community 2019),編譯並運行測試套件(unittest)。 可以通過將測試名稱添加為命令行參數來運行單個測試。

DuckDB 目前似乎沒有發布版本。 所以不要以為創作者沒有留下任何錯誤......

您可以添加編譯器標志-fpermissive以忽略錯誤(例如make CXX="g++ -fpermissive" )。

但是忽略這樣的錯誤並不總是安全的。

所以我試圖解決這個問題,我能夠在 Windows 上構建一個版本。 有關我的解決方案,請參閱https://github.com/cwida/duckdb/issues/361

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM