Можно ли статически связать libstdС++ в Mac OSX 10.6?

Я пытаюсь запустить свою программу на C++ на других машинах Mac OSX, на которых может быть более старая копия libstdc++, но есть все остальные инструменты. Я попытался следовать этому подходу, также упомянутому в этот вопрос SO, хотя в нем обсуждается установка Linux. У меня есть небольшая программа try.cpp:

#include <iostream>

int main() {
        int a = 10;
        std::cout << a << '\n';
        return 1;
}

Очевидно, что если я просто скомпилирую его, я получу

$ /usr/bin/g++ try.cpp 
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Я понимаю зависимость от libSystem.B.dylib, и мы можем оставить это в стороне. Чтобы попытаться избавиться от libstdС++, я пытаюсь сделать это:

$ /usr/bin/g++ try.cpp /usr/lib/libstdc++-static.a 
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Итак, я пытаюсь

$ ln /usr/lib/libstdc++-static.a .
$ /usr/bin/g++ try.cpp -L.
$ otool -L a.out 
a.out:
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

or,

$ /usr/bin/g++ try.cpp -L. -lstdc++-static
$ otool -L a.out 
a.out:
 /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Наконец, это работает:

$ /usr/bin/gcc try.cpp -L. -lstdc++-static
$ otool -L a.out 
a.out:
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.0)

Это нормально? (Чтобы использовать gcc для связывания программ C++ с libstdc++). Я где-то слышал, что g++ на самом деле является скриптом, который использует gcc и libstdc++ для компиляции программ на C++. Если это так, и мы используем его правильно, все должно быть в порядке.

Однако на самом деле я использую компилятор macport и более сложную программу, для которой gcc генерирует некоторые предупреждения, хотя она совместима с C++. Кое-что по эффекту:

ld: warning: std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf() has different visibility (hidden) in /opt/local/lib/gcc44/libstdc++.a(sstream-inst.o) and (default) in /var/folders/2u/2uLPtE+3HMi-BQIEfFVbSE+++TU/-Tmp-//ccoE2rqh.o

Это говорит о том, что мы не должны использовать gcc для компиляции C++. Итак, подводя итоги, вопросы:

  • Как слинковать libstdc++ статически
  • Если g++ этого не делает, можно ли использовать gcc и поставить libstdc++ вручную? Тогда почему предупреждения о видимости?
  • Если ни один из двух подходов не работает из-за проблем с видимостью в скомпилированных библиотеках, почему бы не использовать исходные файлы libstdc++ (sstream.h, list.h, vector.c) и т. д. и просто включить их в компиляция. Несмотря на то, что это замедлит компиляцию, это может быть полезно для некоторых приложений. Это может даже привести к лучшей оптимизации!

person highBandWidth    schedule 14.10.2010    source источник
comment
Чтобы наполовину ответить на мой собственный вопрос, можем ли мы сделать это, сначала скомпилировав его с помощью g++ -c и связав с помощью ld необходимые библиотеки. Я не вижу здесь никаких нарушенных правил, так как мы используем компилятор g++ для c++, а затем линкуем библиотеки, чтобы получить все функции. Чего я не знаю, так это какие библиотеки нам нужно предоставить ld. Очевидно, нам нужно нечто большее, чем просто libstdc++, так как ld выдает массу ошибок из-за отсутствующих символов.   -  person highBandWidth    schedule 15.10.2010


Ответы (2)


Похоже, вы просто хотите ориентироваться на более ранние версии Mac OS X, что можно сделать без статического связывания с libstdc++. Я думаю, что GCC, который поставляется с Xcode, по умолчанию нацелен на среду хоста. Однако он может обрабатывать специальный флаг -mmacosx-version-min для изменения целевой среды. Если вы укажете это с номером целевой версии OS X, он автоматически создаст двоичные файлы, совместимые с этой версией Mac OS X.

#include <iostream>

int main(void)
{
    std::cout << "Hello world!" << std::endl;
    return 0;
}

Скомпилируйте так:

g++ -mmacosx-version-min=10.4 test.cpp

Я скомпилировал эту программу дважды, один раз с флагом и один раз без него, а затем скопировал оба двоичных файла на Mac под управлением 10.4. Тот, скомпилированный с флагом, выполнился правильно, однако тот, скомпилированный без флага, сказал, что в исполняемом файле указан неверный тип процессора (несмотря на то, что он был скомпилирован на идентичной машине, только что запущенной более поздняя версия OS X).

Некоторые из заголовков имеют защиту макросов, которые не позволяют вам использовать функции/классы, представленные в 10.5 или 10.6, если вы указали 10.4 в качестве минимальной цели (я не уверен насчет заголовков C++, но заголовки фреймворка Cocoa, Foundation, AppKit и т. д. обязательно сделаю).

person dreamlax    schedule 14.10.2010
comment
Я согласен, флаг mmacosx-version-min должен компилироваться во что-то, совместимое с более ранней версией. Несмотря на то, что я привел тривиальный пример, на самом деле я использую некоторые функции tr1, которые не были включены в более ранние версии libstdc++ (некоторые хэш-функции, необходимые для std::tr1::unordered_set и карт). Так что мне действительно нужно связать с более новой libstdС++. Однако, если бы я связал его статически, код заработал бы! Таким образом, дело не в том, что ОС не предоставляет определенные функции. Функции предоставляются c++, и он может работать в более ранних версиях. Могу привести такой игрушечный пример, если кто спросит. - person highBandWidth; 15.10.2010

Это натяжка для моих знаний, но я вижу здесь мало ответов, так что!

GCC — это драйвер компилятора, который также будет управлять компоновщиком. g++, насколько я понимаю, это скорее компилятор. Поэтому, чтобы правильно построить G++, я считаю, что вам нужно создать объектные файлы и связать их вручную. Навскидку я не могу сказать, как это сделать, так как в данный момент у меня поврежден мозг IDE.

Что касается ошибки, которую вы видели, она может быть связана с неправильными ссылками на файлы. Я сейчас на своем iPhone, поэтому я не собираюсь расшифровывать сообщение об ошибке, которое вы распечатали. Я вообще не фанат MacPorts, так что не удивляйтесь, что эта установка облажалась. Сначала убедитесь, что вы используете библиотеки MacPorts с компилятором MacPorts.

В конце концов, я не сомневаюсь, что вы можете делать то, что хотите. Однако вам нужно будет начать читать Make files и другую документацию по набору инструментов GCC. Сосредоточьтесь на создании и связывании файлов с программами. Возможно, вы захотите найти небольшую программу с открытым исходным кодом, которая прекрасно работает на Mac, и посмотреть там файлы Make.

Конечно, найти хороший проект на C++ для обучения непросто. Однако я бы порекомендовал установить LLVM и CLang, особенно учитывая, что новая версия должна быть готова к C++. Очевидно, что это другой набор инструментов, но CLang может решить ваши проблемы или, по крайней мере, предоставить вам более качественную информацию об отладке. Может быть, кто-то может присоединиться к проекту C++ с открытым исходным кодом с простыми чистыми файлами make. Самое близкое, что я видел в последнее время, это проект под названием HeeksCAD.

В конце концов, когда вы создаете что-то нетривиальное, вам нужно больше, чем просто GCC. В наши дни многое из этого решается с помощью IDE, однако я не уверен, можно ли правильно настроить XCode для выполнения того, что вы хотите.

person David Frantz    schedule 15.10.2010
comment
Франц: Я согласен, и я упомянул кое-что ранее в комментарии к ответу dreamlax. Я пытаюсь найти такой makefile для просмотра. Генерирует ли xcode эти make-файлы? - person highBandWidth; 15.10.2010
comment
Я попробовал инструкции [здесь][1], чтобы получить Makefile, но это не сработало. [1]: richarddingwall.name/2007/04/08 / - person highBandWidth; 15.10.2010