Как правильно скомпоновать библиотеку C++, которая ведет себя по-разному в зависимости от ее компиляции?

У меня есть библиотека под названием Print и функция println, которая имитирует printf. Если скомпилировано с директивой USE_DEBUG_PRINT, println на самом деле что-то напечатает. Если он скомпилирован без этого определения, он ничего не печатает.

Затем я хочу использовать эту библиотеку внутри другой библиотеки, назовем ее A. A использует Print с этой директивой. Другая библиотека, «B», использует «Print» без этой директивы, поэтому println имеет для них другое поведение.

Однако при компиляции в приложение, в зависимости от порядка ссылок, B будет использовать println из A или наоборот. Это происходит потому, что символ println определен для обеих библиотек, поэтому компоновщик просто выбирает первую.

Как я могу вместо этого сделать Print «приватным» для этих библиотек? Я не хочу, чтобы кто-либо, использующий A или B, независимо от этого имел доступ к функции println, чтобы их можно было просто «объединить» вместе, не допуская println к файлам 1.txt и используя их только в своих реализациях.

Я использую Clang и CMake для создания как библиотек, так и приложения. Print — это библиотека объектов, а остальные — статические.

Радости нарушения ODR.

Eljay 17.05.2023 22:16

Вы имеете в виду статическое связывание или динамическое связывание?

user17732522 17.05.2023 22:17

они статические или разделяемые библиотеки? Если они статичны, вы ничего не можете сделать, кроме как дать функциям разные имена/пространства имен.

Alan Birtles 17.05.2023 22:17

Кроме того, в любом случае, если вам удалось получить определение в каждой библиотеке, это указывает на то, что println является встроенной функцией. В этом случае вы даже не можете предотвратить его встраивание в сайты вызовов. Даже если он не является встроенным, вам нужно убедиться, что он определен в отдельной единице перевода без какой-либо оптимизации времени компоновки или (для динамической компоновки) что -fsemantic-interposition включен ((на данный момент?) по умолчанию на gcc, но не лязг).

user17732522 17.05.2023 22:20

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

KIIV 17.05.2023 22:34

«Печать — это библиотека объектов»: что вы имеете в виду под «библиотекой объектов»? Что еще более важно: является ли println встроенной функцией и где/как она определяется? Как вам удается компилировать библиотеки с разными версиями определения?

user17732522 17.05.2023 22:37

Похоже, у вас есть две библиотеки с идентичными API и в основном идентичными функциями, для которых вы поддерживаете единую базу кода. Я не знаю, используется ли println() внутри библиотеки. Если нет, вы можете попробовать изменить библиотеку и включить функции printlnDebug() и printlnDoNothing(). Затем вы можете предоставить 2 разных файловых интерфейса .h для клиентов. Эти файлы .h обеспечили бы тривиальную маршрутизацию println() в анонимном пространстве имен. С более обширным удалением с библиотекой это также может быть изменено для обработки внутреннего случая println().

Avi Berger 17.05.2023 23:08
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Мне удалось решить эту проблему, выполнив следующие действия:

  • Print теперь представляет собой интерфейс, содержащий только заголовочный файл.
  • println помечен как static.

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

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