2014-01-30 3 views
0

У меня есть программа foo Я пытаюсь скомпилировать и связать, и я сталкиваюсь с курицей и яйцом dillemma.G ++/LD не удается: не удается найти библиотеку, когда библиотека на самом деле не нужна

По причинам, которые я объясню ниже, внутри данной директории я вынужден добавить ссылку на несколько библиотек, которые мы построим (назовем их libA и libB) независимо от моей цели. Я знаю, что мне действительно нужно libA для моей программы; поэтому после того, как все библиотеки построены и этот двоичный файл построен, я проверил с ldd -u -r foo, чтобы показать, что libB является неиспользованной прямой зависимостью.

Будучи неиспользованным, я изменил make-файлы и флаги таким образом, чтобы libB был окутан -Wl --as-needed и -Wl --no-as-needed. Я делаю rebuild, снова использую ldd, и на этот раз он не показывает неиспользуемые депо. Все идет нормально.

Теперь самое интересное: С его неиспользованной я бы ожидать, что если libB не найден/в наличии/построен, что я все еще должен быть в состоянии собрать и связать foo, как долго libA доступна. (пример: если я сделал новую проверку и только построил libA, прежде чем пытаться скомпилировать этот конкретный тест). Но ld ошибки вне с /usr/bin/ld: cannot find -lB

Это говорит о том, что ld нужно найти libB, даже если он не будет нуждаться в какой-либо из символов, которые она предоставляет? Это не имеет смысла. Если все символические зависимости уже выполнены, зачем вообще нужно смотреть на эту другую библиотеку? (Это объясняло бы проблему ld и почему это невозможно)

Есть ли способ, который я могу сказать «Эй, не жалуйтесь, если вы не можете найти эту библиотеку, и нам не нужно будет связываться с ней ?»

Обещанные причины ниже
По различным причинам, независящим от меня, я должен поделиться MAKEFLAGS со многими другими тестами в этом каталоге из-за проектов Makefile иерархии. Существует два уровня makefile для всех этих тестов, в которых foo является фальшивой целью, его рецепт make -f generictest.mk target=foo, а generictest.mk просто говорит, что исходный файл $(target).C, что этот двоичный файл должен использовать каждую созданную библиотеку, указывает относительный путь к наш корневой каталог, а затем включает общий make-файл root. Основной make-файл корневого каталога расширяет все остальные компоненты (флаги, параметры, компилятор, авто-ген зависимостей через g ++ и т. Д.), А главное для каждого оператора, который сказал «использовать libX» в generictest.mk, добавляет -lX к флагам (или в моем случае окутаны по мере необходимости)

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

Я мог бы создать еще один файл generictest.mk, который можно использовать для некоторых тестов, и объединить их, используя каждый из них на основе фактических потребностей библиотеки, но это было бы довольно аккуратно, если бы мне не приходилось до тех пор, пока я сказал «вы не все из них, вам нужен каждый из них, но только если вы на самом деле его используете ».

+0

Файл makefile неверен - или разработан теперь устаревшие предположения. Перепроектируйте его так, чтобы вы не пытались связываться с библиотеками, которые не существуют и не являются необходимыми для рассматриваемой тестовой программы. Другой вариант - убедиться, что 'libB' построен - он становится явной зависимостью целей в' makefile' ('generictest.mk'). Во всяком случае, должно быть, конечно; если программы связаны с ним, программы (или линии командной строки) зависят от существующих библиотек. –

+0

@JonathanLeffler Я знаю, что он сильно искажен. У меня просто нет возможности изменить его. Опять я согласен со всем, что вы сказали; но это мне не помогает. Я могу заставить его зависеть от libB, но я не хочу тратить время на создание libB, когда мне это не нужно. Их не существует, потому что я их не построил; в «реальной» сборке они, как правило, все будут существовать. – UpAndAdam

+0

OK; если вы не будете слушать слова мудрости, вам придется продолжать гноиться в болоте разбитых сборок. Или подождите, пока какой-нибудь гений придумает решение. Но лучше всего не бороться с системой, навязанной компилятором и компоновщиком; лучше всего исправить нарушение в инструментах, которые злоупотребляют компилятором и компоновщиком (что означает файл 'generictest.mk'). Ваш звонок ... получайте удовольствие! («Я не могу исправить» не сокращает его в программном обеспечении, программное обеспечение податливо - вот почему оно называется _soft_. Если это сила, которая навязывает правила, спросите их, как обойти свою дилемму .) –

ответ

1

Невозможно, чтобы компоновщик мог знать, что библиотека не нужна.Даже после того, как все ваши «нормальные» библиотеки связаны, все еще есть много и много неразрешенных символов: символы для библиотеки времени выполнения C (printf и т. Д.). Компилятор понятия не имеет, откуда они берутся.

Лично я был бы удивлен, если бы линкер не сделал, даже если каждый символ уже разрешен. В конце концов, здесь могут быть причудливые вещи: слабые привязки и т. Д., Что может означать, что символы, найденные позже в линии ссылок, будут предпочтительнее, чем символы, найденные ранее (я не уверен на 100%, что это возможно, но я бы не стал Удивляться).

Что касается вашей ситуации, если вы знаете, что библиотека не нужна, можете ли вы просто использовать $(filter-out ...) в командной строке ссылки, чтобы избавиться от нее? Вам придется написать свое собственное явное правило для этого с помощью собственного рецепта, а не использовать по умолчанию, но, по крайней мере, вы можете использовать все те же переменные.

В качестве альтернативы МОЖНО играть в некоторые трюки с целевыми переменными. Объявите целевую переменную для этой цели, которая сбрасывает переменную, содержащую «плохую библиотеку», со значением, которое ее не содержит (возможно, с использованием $(filter-out ...), как указано выше), и оно переопределит это значение только для этой цели. Есть некоторые тонкие gotchas с целевыми переменными, которые переопределяют «более общие» переменные, но я думаю, что это сработает.

+0

Спасибо, я использую ваш первый момент, это становится проблемой для рода. – UpAndAdam

Смежные вопросы