2010-10-14 2 views
4

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

#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, и мы можем оставить это в стороне. Для того, чтобы попытаться избавиться от libstdC++, я стараюсь это:

$ /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) 

или

$ /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++ статически
  • Если г ++ не делает, это нормально использовать GCC и поставить libstdC++ вручную? Тогда почему предупреждения о видимости?
  • Если ни один из двух подходов не работает из-за проблем видимости в скомпилированных библиотеках, почему бы не использовать libstdC++ файлы источника (sstream.h, list.h, vector.c) и т. Д. И просто включить их в компиляцию. Несмотря на то, что это сделает компиляцию медленной, она может быть полезна для некоторых приложений. Это может даже привести к лучшей оптимизации!
+0

Чтобы ответить наполовину на мой собственный вопрос, можем ли мы сделать это, скомпилировав его с помощью g ++ -c сначала и связав с ld требуемые библиотеки. Здесь я не вижу никаких нарушенных правил, так как мы используем компилятор g ++ для C++, а затем связываем библиотеки, чтобы предоставить все функции. Я не знаю, какие библиотеки нам нужно предоставить ld. По-видимому, нам нужно больше, чем просто libstdC++, поскольку ld дает массу ошибок для недостающих символов. – highBandWidth

ответ

3

Похоже, вы просто хотите нацелить более ранние версии 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; 
} 

Compile, как это:

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

Я скомпилированного эту программу в два раза, один раз с флагом и один раз без него, а затем я скопировал оба двоичных файла на Mac с 10.4.Скомпилированный с флаг выполнен правильно, однако один скомпилированный без флаг указан “ Плохой тип ЦП в исполняемом ” (несмотря на то, что он был скомпилирован на идентичном компьютере, который запускает более позднюю версию OS X).

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

+0

Согласен, флаг mmacosx-version-min должен компилироваться во что-то совместимое с более ранней версией. Несмотря на то, что я дал тривиальный пример, я фактически использую некоторые функции tr1, которые не включены в более ранние версии libstdC++ (некоторые хэш-функции, необходимые для std :: tr1 :: unordered_set и maps). Поэтому мне действительно нужно установить ссылку на новый libstdC++. Однако, если бы я связал его статически, код действительно запустится! Таким образом, дело не в том, чтобы ОС не предоставляла определенные функции. Функции предоставлены C++, и он __can__ запускается в более ранних версиях. Я могу привести такой игрушечный пример, если кто-то спросит. – highBandWidth

1

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

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

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

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

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

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

+0

Франц: Я согласен, и я упомянул что-то раньше в комментарии к ответу dreamlax. Я пытаюсь найти такой make-файл, чтобы посмотреть. Создает ли xcode эти make-файлы? – highBandWidth

+0

Я попробовал инструкции [здесь] [1], чтобы получить Makefile, но он не работал. [1]: http://richarddingwall.name/2007/04/08/generating-a-makefile-from-xcode/ – highBandWidth