2009-02-14 6 views

ответ

8

Прежде чем я отвечу на ваш вопрос, как было описано, я хочу отметить, что в конце концов не совсем ясно, чего вы пытаетесь достичь, и, вероятно, лучшее решение вашей проблемы.

Это говорит - есть две основные проблемы, связанные с пытается сделать то, что вы описали:

  1. Один, что вам нужно будет разлагаться libpthread и libstdc++ в объектных файлов они сделаны с. Это связано с тем, что В двоичных файлах ELF (используется в Linux) есть два уровня загрузки библиотеки «время выполнения» - даже когда статический файл исполняемого файла загружается, загрузчик должен загружать статически связанные библиотеки в исполняемом файле и отображать право адреса памяти. Это делается перед общей связью библиотек, которые динамически загружаются (общие объекты) и отображаются в общую память. Таким образом, общий объект не может быть статически связан с такими библиотеками, как в момент загрузки объекта, все статические связанные библиотеки уже были загружены. Это одно различие между связыванием со статической библиотекой и файлом простого объекта - статическая библиотека не просто склеивается, как любой объектный файл, в исполняемый файл, но все еще содержит отдельные таблицы, которые упоминаются при загрузке. (Я считаю, что это в отличие от гораздо более простых статических библиотек в MS-DOS и классических файлах Windows, .LIB, но может быть и больше тех, которые я помню).

    Конечно, вам не нужно разлагать libpthread и libstdc++, вы можете просто использовать объектные файлы, сгенерированные при их создании. Сбор их может быть немного сложным (искать объекты, на которые ссылается окончательное правило Makefile этих библиотек). И вам нужно будет напрямую использовать ld, а не gcc/g++, чтобы не связываться с динамическими версиями.

  2. Вторая проблема является последовательной. Если вы сделаете это, вы обязательно получите такую ​​общую/динамическую библиотеку, которую вы хотите создать. Однако это будет не очень полезно, так как как только вы попытаетесь связать обычный исполняемый файл, который использует эти libpthread/libstdc++ (последний является любой программой на C++) с этим общим объектом, он будет терпеть неудачу с конфликтами символов - символы статического libpthread/libstdc++ объекты, с которыми вы связали свой общий объект, будут сталкиваться с символами из стандартного libpthread/libstdc++, используемым этим исполняемым файлом, независимо от того, динамически или статически связаны со стандартными библиотеками.

    Вы можете, конечно, попытаться либо скрыть все символы в статических объектах от libstdc++/libpthread, используемые вашей общей библиотекой, сделать их частными в некотором роде или переименовать их автоматически по ссылке, чтобы не было конфликтов. Тем не менее, даже если вы получите это на работу, вы найдете некоторые нежелательные результаты во время выполнения, так как оба libstdc++/libpthread сохраняют довольно немного состояния в глобальных переменных и структурах, которые у вас теперь будут иметь дубликат и каждый не знает о другом. Это приведет к несогласованности между этими глобальными данными и базовым состоянием операционной системы, таким как дескрипторы файлов и ограничения памяти (и, возможно, некоторые значения из стандартной библиотеки C, такие как errno для libstdc++, а также обработчики сигналов и таймеры для libpthread.

Чтобы избежать чрезмерного расширительное толкование, я добавлю замечание: иногда там может быть разумным основаниям для желающих статически связать даже против таких базовых библиотек, как libstdc++ и даже libc, и даже несмотря на это становится немного более сложным с недавними системами и версиями этих библиотек (из-за немного сцепления с погрузчиком и специальными трюками компоновщика используется), то определенно можно - Я сделал это несколько раз, и знаю других случаев в которое оно все еще сделано. Однако, в этом случае вам необходимо соединить целое исполнимым статически. Статическая связь со стандартными библиотеками в сочетании с динамической связью с другими объектами обычно невозможен.


Edit: Один вопрос, который я забыл упомянуть, но важно принять во внимание, является C++ специфичны. C++, к сожалению, не был хорошо разработан для классической модели связывания и загрузки объектов (используется в Unix и других системах). Это делает разделяемые библиотеки на C++ не очень портативными, как и должно быть, потому что многие вещи, такие как информация о типе и шаблоны, не разделяются между объектами (часто берутся вместе с большим количеством фактического кода библиотеки во время компиляции из заголовков). libstdc++ по этой причине тесно связан с GCC, и код скомпилирован с одной версией g++ будет вообще работать только с libstdc++ из с этим (или очень похожими) версиями g++. Поскольку вы наверняка заметите, что когда-либо попытаетесь создать программу с GCC 4 с любой нетривиальной библиотекой в ​​вашей системе, которая была построена с помощью GCC 3, это не только libstdc++. Если причина для желания сделать это пытается гарантировать, что ваш общий объект всегда связан с определенными версиями libstdc++ и libpthread, что он был построен против, это не поможет, потому что программа, которая использует различную/несовместимую libstdc++ бы также построенный с несовместимым компилятором C++ или версиями g++, и, таким образом, не в состоянии связать с общим объектом в любом случае, в стороне от реальных libstdc++ конфликтов.

Если Вы задаетесь вопросом «почему это не сделано проще?», Общий руминацию стоит задуматься: Для C++, чтобы хорошо работать с динамическими/разделяемых библиотек (что означает совместимость между составителями, а также возможность заменить динамическую библиотеку с другой версией с совместимым интерфейсом, не перестраивая все, что его использует), а не просто стандартизация компилятора, но на уровне загрузчика операционной системы структура и интерфейс файлов объектов и библиотек и работа компоновщика должны будут быть значительно расширен за пределы относительно простых классических Unix, используемых на распространенных операционных системах (систем на базе Microsoft Windows, Маха и NeXTStep родственников, таких как Mac OS, VMS родственников и некоторых мэйнфреймов также включены) для изначально построенного кода сегодня. Компилятор и динамический загрузчик должны были бы знать о таких вещах, как шаблоны и типизация, , имеющие в некоторой степени функциональность небольшого компилятора, чтобы фактически адаптировать код библиотеки к типу, данному ему, - и (личное субъективное наблюдение здесь) кажется, что промежуточный промежуточный код более высокого уровня (вместе с языками более высокого уровня и компиляция «точно вовремя») быстрее ловят землю и, скорее всего, будут стандартизированы раньше, чем такие расширения для собственных объектных форматов и компоновщиков.

+0

Что я пытаюсь достичь, чтобы узнать, как переносить библиотеку C++ на встроенное устройство. uClibc отлично работает. Тем не менее, мне нужен stdC++, который довольно громоздкий, и учитывая, что я использую только часть того, что внутри связывания статически, может помочь. Есть идеи? – 2009-02-14 11:04:34

+0

Некоторые простые идеи, которые я вложил в отдельный ответ (я новичок в StackOverflow, но думал, что это лучший способ), могут помочь вам в зависимости от ваших потребностей, которые также могут быть более сложными. Вы можете получить более подробные ответы на ваш вопрос, если вы отредактируете свой вопрос, добавив конкретные детали в конце. Ура! –

0

Я думаю, что this guy объясняет хорошо, почему это не будет иметь смысла.C++-код, который использует ваш общий объект, но другой libstdC++ будет правильно связываться, но работать не будет.

1

Вы упомянули в отдельном комментарии, что вы пытаетесь перенести библиотеку C++ на встроенное устройство. (я добавляю новый ответ здесь вместо того, чтобы редактировать свой оригинальный ответ здесь, потому что я думаю, что другие пользователи StackOverflow, заинтересованные в этом оригинальном вопросе все еще могут быть заинтересованы в том, что ответ в контексте)

  • Очевидно, что в зависимости от как урезано встроенная система (у меня мало опыта работы с Linux, поэтому я не уверен, что наиболее вероятно), вы можете, конечно, просто установить общий libstdc++ на нее и динамически связать все, как в противном случае ,

  • Если динамическая компоновка с libstdc++ не было бы хорошо для вас или не работать на вашей системе (есть так много различных уровней встраиваемых систем, которые никто не может знать), и вам необходимо связать со статической libstdc++, то в качестве Я сказал, что ваш единственный реальный вариант - статическое связывание исполняемого файла с использованием библиотеки с ним и libstdc++. Вы упомянули о переносе библиотеки на встроенное устройство, но если это предназначено для использования в каком-то коде, вы пишете или создаете устройство, и вы не возражаете против статического libstdc++, тогда все статичное связывание (кроме, возможно, libc) вероятно, ОК.

  • Если проблема связана с размером libstdc++, и вы обнаружите, что ваша библиотека на самом деле использует только небольшую часть своих интерфейсов, то я бы предложил сначала попытаться определить фактическое пространство, которое вы бы сэкономили, части, которые вам нужны. Это может быть значительным или нет, я никогда не смотрел так глубоко в libstdc++, и я подозреваю, что он имеет множество внутренних зависимостей, поэтому, хотя вам наверняка не нужны некоторые интерфейсы, вы можете или не можете по-прежнему зависеть от большой части его внутренности - я не знаю и не пытался, но это может вас удивить. Вы можете получить представление, просто связав бинарную библиотеку с ее статической сборкой и libstdc++ (не забывая разделить двоичный код, конечно), и сравните размер полученного исполняемого файла с общим размером (strip ped), динамически связанный вместе с полными (strip ped) совместно используемыми объектами библиотеки и libstdc++.

    Если вы обнаружили, что разница в размерах значительна, но не хотите статически связывать все, вы пытаетесь уменьшить размер libstdc++, перестроив его без некоторых частей, которые, как вы знаете, вам не нужны (есть время настройки варианты для некоторых его частей, а также вы можете попытаться удалить некоторые независимые объекты при окончательном создании libstdc++.so. Есть некоторые инструменты для оптимизации размера библиотек - поиск в Интернете (я помню один из компании с именем MontaVista, но не см. его на своем веб-сайте сейчас, есть и некоторые другие).

Помимо простых выше, некоторые идеи и предложения, чтобы думать:

Вы упомянули, что используете uClibc, который я никогда не играл с собой (мой опыт с встроенным программированием намного более примитивен, в основном с использованием программирования сборки для встроенного процессора и кросс-компиляции с минимальными встроенными библиотеками).Я предполагаю, что вы проверили это, и я знаю, что uClibc предназначен для простой, но достаточно полной стандартной библиотеки C, но не забывайте, что код C++ вряд ли является независимым от библиотеки C, а g++ и libstdc++ зависят от довольно тонких вещей (Я помню проблемы с libc на некоторых проприетарных версиях Unix), поэтому я бы просто не предполагал, что g++ или GNU libstdc++ действительно работает с uClibc без попытки - я не помню, чтобы это упоминалось на страницах uClibc.

Кроме того, если это встроенная система, подумайте о ее производительности, вычислительной мощности, общей сложности и сроках/простоте/надежности. Примите во внимание сложность и подумайте, подходит ли использование C++ и потоков в вашей встроенной системе, и если ничто в системе не использует их, стоит ли ее использовать для этой библиотеки. Это может быть, не зная библиотеку или систему, которую я не могу сказать (опять же, встроенные системы в настоящее время такие широкие диапазоны).

И в этом случае, просто быстрая ссылка я наткнулся ищет uClibc - если вы работаете на встроенной системе, используя uClibc, и вы хотите использовать C++ код на нем - посмотрите на uClibc++. Я не знаю, сколько из стандартных материалов C++ вам нужно, и оно уже поддерживает, и, похоже, это постоянный проект, поэтому неясно, достаточно ли он в состоянии, достаточном для вас, но предполагая, что ваша работа также тем не менее, это может быть хорошей альтернативой libstdc++ GCC для вашей встроенной работы.

+0

Том, спасибо за подробное объяснение. Моя первоначальная идея состояла в том, чтобы не устанавливать libstdC++ на устройство, связывая его с ним статически (библиотека не использует исключения и rtti). Однако похоже, что uClibC++ может быть сейчас. – 2009-02-14 15:15:12