Ошибка компиляции базы данных C++ в Windows с помощью cmake

Для получения степени магистра мне нужно работать с базой данных под названием duckdb (ее на git hub). Обычно в Linux вы можете просто клонировать его и "заставить" установить.

Я устал от того же на Windows после установки CMake и Cygwin.

Но на полпути к компиляции я получаю ошибку

'DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp:1445:96:
ошибка: ISO C++ запрещает сравнение между указателем и целым числом [-fpermissive]

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

Поскольку я сомневаюсь, что создатели duckdb все испортили, я думаю, что это ошибка компилятора, пытающаяся скомпилировать файл C как файл C++.

Моя основная проблема: как мне настроить команду make в Windows, чтобы она не создавала эту ошибку?

Я пробовал это как в системе Windows 7, так и в системе 10 с установленным gcc 5.1 и текущим cmake, и оба вызывают эту ошибку.

Изменить: вот полный текст ошибки

[ 87%] Создание объекта CXX test/sql/capi/CMakeFiles/test_sql_capi.dir/ub_test_sql_capi.cpp.obj В файле, включенном из C:/duckdb/test/sql/capi/test_capi.cpp:1:0, из test_capi. cpp: 0:

C:/DUCKDB~2/duckdb/THIRD_~1/catch/catch.hpp: при создании экземпляра 'bool >Catch::compareNotEqual(const LhsT&, RhsT&&) [с 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.hpp:1445:96: ошибка: ISO C++ запрещает сравнение> между указателем и целым числом [-fpermissive] auto compareNotEqual( LhsT const& lhs, RhsT&& rhs) -> bool { return >static_cast(lhs!= Rhs); }

Я только отредактировал свое имя пользователя в пути и т. Д.

3 ответа

Библиотеку не знаю, поэтому однозначного ответа дать не могу. Я буду использовать код на https://github.com/cwida/duckdb.

Согласно сообщению об ошибке в проблемном коде находится в строке 332 test/sql/capi/test_capi.cpp, который:

REQUIRE(stmt != NULL);

REQUIRE- это макрос из библиотеки модульного тестирования Catch2, который творит чудеса для синтаксического анализа данного ему выражения. Важная часть состоит в том, чтоstmt != NULL фактически не будет выполняться немедленно, а только через косвенное обращение к функции.

stmt объявлен как в строке 324 как

duckdb_prepared_statement stmt = nullptr;

а также duckdb_prepared_statement это typedef в строке 94 src/include/duckdb.h:

typedef void *duckdb_prepared_statement;

Поэтому цель проблемной строки - проверить, stmt все еще nullptr после некоторых промежуточных операций.

Как обычно stmt != NULLбыло бы хорошо для этого. Однако, поскольку макрос Catch2 вводит промежуточные вызовы функций, а не вычисляет это выражение напрямую, неявные преобразования, специфичные для литерала, не применяются.

Особенно NULL в соответствии со стандартом либо prvalue типа std::nullptr_t или целочисленный литерал со значением 0. Какой именно из них (и какой целочисленный тип) определяется реализацией.

Сравнение целых чисел и указателей обычно запрещено, однако целочисленные литералы с нулевым значением имеют специальное исключение, позволяющее неявно преобразовывать их в нулевой указатель любого типа указателя. Вот что случилось бы, если быstmt != NULL будет оцениваться напрямую.

Однако из-за вставки Catch2, NULL сначала передается, а затем сравнивается через переменную с stmt, в результате чего специальное правило нулевого литерала больше не применяется. Поэтому сравнениеstmt против NULL через REQUIRE потерпит неудачу, если NULL - это целочисленный литерал в текущей реализации.

Catch2 действительно учитывает эту проблему, и есть перегрузки для compareNotEqual в third_party/catch/catch.hpp которые позаботятся о случае, когда NULL представляет собой нулевой целочисленный литерал типа int или long, но почему-то случай long longне считается. Я не знаю, проблема ли это в Catch2 или только в клонированной версии, включенной в duckdb.

Итак, если в реализации используется нулевой литерал типа long long за NULL, то произойдет ошибка, которую вы наблюдали.

На самом деле duckdb должен использовать nullptr вместо того NULL (как и при инициализации), который не имеет этих проблем и был добавлен в язык именно из-за этих проблем.

Я полагаю, вы можете просто попытаться решить эту проблему, заменив NULL с участием nullptr (возможно, и в других тестовых примерах).

Однако проблемный код находится только в файлах, которые сами являются модульными тестами для фактического кода библиотеки. Таким образом, должна быть какая-то опция cmake или make, которая отключит сборку модульных тестов, чтобы вы могли игнорировать эту конкретную ошибку, надеясь, что она также не возникает нигде в фактическом коде библиотеки.

Если я был прав в своей оценке, вы можете подумать о том, чтобы заполнить отчет об ошибке для этого с помощью duckdb, если они в первую очередь поддерживают вашу платформу.

Вместо использования Cygwin может быть проще использовать CMake в сочетании с Visual Studio для компиляции проекта. Именно так авторы компилируют и тестируют DuckDB в Windows.

Используя CMake, сгенерируйте набор файлов проекта Visual Studio. Затем откройте эти файлы проекта в Visual Studio (мы используем Visual Studio Community 2019), скомпилируйте и запустите набор тестов (unittest). Отдельные тесты можно запустить, добавив имя теста в качестве параметра командной строки.

DuckDB, похоже, в настоящее время не имеет релизной версии. Так что не думайте, что создатели не оставили никаких ошибок в...

Вы можете добавить флаг компилятора -fpermissive игнорировать ошибку (например, make CXX="g++ -fpermissive").

Но игнорировать подобные ошибки не всегда безопасно.

Итак, я попытался исправить проблему и смог собрать версию для Windows. См. Мое решение на https://github.com/cwida/duckdb/issues/361.

Другие вопросы по тегам