Неопределенная ссылка на vtable для grpc::experimental при добавлении флага --coverage

У меня есть проект C++ на основе CMake. Начальная точка проекта была создана с помощью cmake-init. Я пытаюсь добавить gRPC в проект. Однако при использовании флагов покрытия возникает ошибка компоновщика:

build] /usr/bin/ld: CMakeFiles/demo_lib.dir/source/lib.cpp.o: warning: relocation against `_ZTVN4grpc12experimental38FileWatcherAuthorizationPolicyProviderE' in read-only section `.text._ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC2EP34grpc_authorization_policy_provider[_ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC5EP34grpc_authorization_policy_provider]'
[build] /usr/bin/ld: /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: warning: relocation against `_ZTVN4grpc12experimental38FileWatcherAuthorizationPolicyProviderE' in read-only section `.text._ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC2EP34grpc_authorization_policy_provider[_ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC5EP34grpc_authorization_policy_provider]'
[build] /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:48: undefined reference to `vtable for grpc::experimental::StaticDataAuthorizationPolicyProvider'
[build] /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::FileWatcherAuthorizationPolicyProvider::FileWatcherAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:73: undefined reference to `vtable for grpc::experimental::FileWatcherAuthorizationPolicyProvider'
[build] CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:48: undefined reference to `vtable for grpc::experimental::StaticDataAuthorizationPolicyProvider'
[build] /usr/bin/ld: CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::FileWatcherAuthorizationPolicyProvider::FileWatcherAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:73: undefined reference to `vtable for grpc::experimental::FileWatcherAuthorizationPolicyProvider'

Отличие от подобных вопросов здесь в том, что без флагов покрытия этого не происходит + я никак не использую AuthorizationPolicy. Код, который я сейчас использую, по сути, тот, что вы можете найти на https://github.com/faaxm/exmpl-cmake-grpc

Вот соответствующие флаги из CMakePresets.json:

{
      "name": "flags-unix",
      "hidden": true,
      "cacheVariables": {
        "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Werror=float-equal -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wl,--whole-archive -Wl,--allow-multiple-definition"
      }
    },
{
      "name": "coverage-unix",
      "binaryDir": "${sourceDir}/build/coverage",
      "inherits": "ci-unix",
      "hidden": true,
      "cacheVariables": {
        "ENABLE_COVERAGE": "ON",
        "CMAKE_BUILD_TYPE": "Coverage",
        "CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage -fkeep-inline-functions -fkeep-static-functions",
        "CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage",
        "CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage",
        "CMAKE_MAP_IMPORTED_CONFIG_COVERAGE": "Coverage;RelWithDebInfo;Release;Debug;"
      }
    },

Редактировать:

Заголовок, на который есть ссылка, находится здесь: https://grpc.github.io/grpc/cpp/authorization__policy__provider_8h_source.html (всего 80 строк). мне не кажется, что какой-то чисто-виртуальный метод не определен. Я ошибаюсь?

Вот как выглядит исходный файл: https://github.com/faaxm/exmpl-cmake-grpc/blob/master/server/src/main.cpp за исключением того, что в моем случае это функция void launch_server() из int main(), а настоящие int main() звонки launch_server(). Одна (возможно) подсказка, которая у меня есть, заключается в том, что класс ServerBuilder ('grpcpp/server_builder.h') имеет:

class ServerBuilder {
 public:
  ServerBuilder();
  virtual ~ServerBuilder();
  // (...)
  /// NOTE: class experimental_type is not part of the public API of this class.
  /// TODO(yashykt): Integrate into public API when this is no longer
  /// experimental.
  class experimental_type {
   public:
    // (...)

    /// Sets server authorization policy provider in
    /// GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER channel argument.
    void SetAuthorizationPolicyProvider(
        std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
            provider);

   private:
    ServerBuilder* builder_;
  };
  //(...)
  private:
  std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
      authorization_provider_;

Это единственный способ, которым AuthorizationPolicyProvider каким-то образом попадает в мой код, через класс gRPC ServerBuilder. Что мне делать тогда?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

IIRC это связано с чем-то, что называется независимым кодом позиции. По сути, у вас есть статическая библиотека, которую вы хотите связать в общей библиотеке (это, скорее всего, вызвано флагом --coverage), вы не можете сделать это без независимого от позиции кода. Что вам нужно сделать, так это перекомпилировать статические библиотеки, передав -fPIC.

Затем вы можете перекомпилировать свой проект, и он должен работать.

Обновлено: Вот ссылка на вопрос stackoverflow с объяснением того, как выяснить, была ли библиотека скомпилирована с помощью -fPIC.

Спасибо за совет. Я добавил set(CMAKE_POSITION_INDEPENDENT_CODE ON) поверх файла CMakeLists.txt (я также проверил -fPIC с помощью readelf). Я получаю те же undefined reference to vtable for grpc::experimental::... ошибки, но не получаю warning: relocation against ... предупреждений. Ошибка продолжает появляться...

mmnano50 24.01.2023 14:11

@mmnano50 Обратитесь к часто задаваемым вопросам GCC для неопределенной ссылки на vtable, то есть вы, вероятно, не определяете некоторые чисто виртуальные методы, которые вам следует.

Milan Š. 24.01.2023 14:20

Если не считать того, что я не использую провайдер политики авторизации, если посмотреть шапку grpc.github.io/grpc/cpp/… (это всего 80 строк), которая выдаёт эти ошибки, то не похоже мне что никакие чисто-виртуальные методы не определены. Я ошибаюсь?

mmnano50 24.01.2023 14:28

Возможно, вы не делаете этого явно, но какой-то класс/функция, которую вы используете, использует его. Трудно сказать без минимального воспроизводимого примера. Мое дикое предположение (основываясь на том факте, что вы упомянули, что это не работает с флагом --coverage), что каким-то образом генерация покрытия пытается его использовать, и поскольку у него нет определенного деструктора, он выдает эту ошибку. Но это всего лишь предположение.

Milan Š. 24.01.2023 14:34

Я поставил = default для деструкторов реализации AuthorizationPolicy в заголовке gRPC, и теперь он работает как задумано. Меня это все еще немного беспокоит, поэтому я открыл вопрос на странице gRPC github, чтобы посмотреть, что они предлагают.

mmnano50 24.01.2023 15:39

@ mmnano50 Я не думаю, что есть другой способ обойти это, кроме того, что вы описали. Вы также можете (теоретически) сделать все возможное и написать #ifdef guards, чтобы разделить его для целей тестирования (покрытия) и не тестирования. Я буду честен, я сам не уверен, как бы я подошел к этому по-другому.

Milan Š. 24.01.2023 16:26

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