Как заставить компоновщик отклонить определенные библиотеки без конфликта самих библиотек? - PullRequest
2 голосов
/ 07 мая 2019

Я пытаюсь добавить проверку работоспособности на этапе соединения. В частности, у меня есть программы, которые статически связывают библиотеки. Некоторые программы ограничены набором библиотек, которые разрешено связывать, а другие нет. Например, у меня есть две программы соответственно food.c и fruits.c, и у меня есть две библиотеки (для которых у меня есть источник) apple.a и broccoli.a. Между apple.a и broccoli.a.

нет никакой зависимости

Есть ли способ, которым я могу изменить свой источник и источник библиотек так, чтобы компоновщик позволил мне связать apple.a и broccoli.a в food.c, и позволит мне связать apple.a в fruits.c, но выдает ошибку компоновщика при попытке загрузить apple.a и broccoli.a (или просто broccoli.a) в fruits.c? Предположим, что в моем источнике нет #include каких-либо заголовков в библиотеках, которые они связывают, поскольку они ошибочно связаны, оставлены в удаленном коде, прототипы функций объявлены вручную и т. Д.

Было бы неплохо, если бы я мог как-то пометить эти библиотеки таким образом, чтобы моя программа могла отклонить определенный тег.

Конкретный компилятор, который я использую, не поддерживает #pragma poison, который был действительно единственным полезным инструментом, который я нашел в моем поиске. Я догадываюсь, что со слабыми символами можно что-то придумать, но я не совсем уверен, что и как.

Я также не верю, что использование #define поможет мне, так как я понимаю, что это только помешает мне #include загружать определенные файлы, но если я ошибаюсь в этом, то это также может быть штрафом решение.

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

Хорошо, обо всем по порядку: Это пахнет чрезвычайно как БОЛЬШОЙ, ПЛОХОЙ хак вокруг проблемы, которую можно решить проще!

Теперь одним из возможных способов было бы применение «ошибки множественного определения». Для моего примера есть следующие файлы:

  • broccoli_mark.c, который используется для «маркировки» (см. Ниже) библиотеки брокколи.
  • broccoli_fn.c, который содержит функциональные возможности библиотеки брокколи.
  • fruits.c - программа, которая не должна ссылаться на библиотеку брокколи. Это «помечено», чтобы запретить связывание с брокколи.

"маркировка" : Это можно реализовать, просто задав глобальный символ с некоторым известным именем в этих файлах. Например:

int broccoli_mark; // a global variable

Поместите только это в broccoli_mark.c и добавьте его куда-нибудь к fruit.c.

Теперь связываете ...

# Compile and ar the library
$ gcc -c broccoli_mark.c
$ gcc -c broccoli_fn.c
$ ar rcs broccoli.a broccoli_mark.o broccoli_fn.o
# Compile and link program
$ gcc -c fruits.c
$ gcc fruits.o broccoli.a

... работает .. , но только из-за того, как работает связывание со статической библиотекой: в основном компоновщик выбирает только (целые) объектные файлы, которые определяют символ, который является не определено в текущем наборе ссылок (сначала программа, затем также добавлены объектные файлы из библиотеки).

Таким образом, чтобы не удалось связать, мы должны убедиться, что broccoli_mark.o (или, более конкретно, содержащийся в нем символ broccoli_mark) включен. Подходы:

  • "Объединить" несколько объектных файлов в один:

    # Merge two object files into a single broccoli.o
    $ ld -r -o broccoli.o broccoli_fn.o broccoli_mark.o
    # create the library or not ..
    $ gcc fruits.o broccoli.o
    ld: broccoli.o:(.data+0x0): multiple definition of `broccoli_mark'; fruits.o:(.data+0x0): first defined here
    collect2: error: ld returned 1 exit status
    

    Да!

    Обратите внимание, что вы можете сделать это для всех .o файлов библиотеки брокколи ... но тогда вы отключите полезное свойство статических библиотек, чтобы включить только то, что необходимо.

    Также обратите внимание, что есть параметров , которые могут это сломать.

    (аналогичная альтернатива: --whole-archive опция )

  • Просто включите «метку» в исходный файл, который обязательно будет включен (например, в файл, который содержит «основную» функцию библиотеки).

Конечно, вся эта «маркировка» и т. Д. Может быть спрятана за описательными именами макросов ... но все равно выглядит как довольно плохой взлом!

0 голосов
/ 08 мая 2019

Некоторые программы ограничены набором библиотек, которые разрешено связывать, а другие нет.

Это не имеет особого смысла.

Есть ли способ, которым я могу изменить свой источник и исходный код библиотеки так, чтобы компоновщик позволил мне связать apple.a и broccoli.a в food.c, и позволит мне связать apple.a в fruits.c,но выдаст ошибку компоновщика при попытке загрузить apple.a и broccoli.a (или просто broccoli.a) в fruits.c?

Нет, поскольку язык C ничего не знаето библиотеках.Его спецификации написаны таким образом, чтобы реализации могли предоставлять и использовать их, но в языке C нет способа ссылаться на саму библиотеку.Это не концепция C.

И вообще, в этом нет особого смысла.Имена статических библиотек не имеют внутреннего значения.Они имеют смысл только в той степени, в которой они идентифицируют свое содержание.Ничего не получится, если запретить fruits.c связывание с broccoli.a, потому что это было бы легко обойти, и вполне возможно, что его даже можно было бы случайно обойти из-за ошибок в обслуживании системы сборки - , то есть объекты, предназначенные для broccoly.a, добавляются в apple.a дополнительно или взамен.

Более того, большинство компоновщиков умны - они не будут содержать функции и объекты без ссылок при создании исполняемого файла, включая ненужные (статические).библиотеки по ссылке вообще безвредны.

...