KnigaRead.com/

Д. Стефенс - C++. Сборник рецептов

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Д. Стефенс, "C++. Сборник рецептов" бесплатно, без регистрации.
Перейти на страницу:

Пример 1.7. Использование атрибута visibility с опцией командной строки -fvisibility=hidden

extern __attribute__((visibility("default"))) int m; // экспортируется

extern int n; // не экспортируется


__attribute__((visibility("default"))) void f(); // экспортируется

void g(); // не экспортируется

struct __attribute__((visibility("default"))) S { }; // экспортируется

struct T { }; //не экспортируется

В примере 1.7 атрибут __attribute__((visibility("default"))) играет ту же роль, что и __declspec(dllexport) в коде Windows.

Использование атрибута visibility представляет те же проблемы, что и использование __declspec(dllexport) и __declspec(dllimport), так как вам требуется, чтобы этот атрибут присутствовал при сборке общей библиотеки и отсутствовал при компиляции кода, использующего эту общую библиотеку, и чтобы он полностью отсутствовал на платформах, его не поддерживающих. Как и в случае с __declspec(dllexport) и __declspec(dllimport), эта проблема решается с помощью препроцессора. Например, вы можете изменить заголовочный файл georgeringo.hpp из примера 1.2 так, чтобы использовать атрибут видимости, следующим образом.

georgeringo/georgeringo.hpp


#ifndef GEORGERINGO_HPP_INCLUDED

#define GEORGERINGO_HPP_INCLUDED


// определите GEORGERINGO_DLL при сборке libgeorgeringo

#if defined(_WIN32) && !defined(__GNUC__)

#ifdef GEORGERINGO_DLL

#define GEORGERINGO_DECL __declspec(dllexport)

#else

#define GEORGERINGO_DECL __declspec(dllimport)

#endif

#else // Unix

# if defined(GEORGERINGO_DLL) && defined(HAS_GCC_VISIBILITY)

# define GEORGERINGO_DECL __attribute__((visibility("default")))

# else

#define GEORGERINGO_DECL

#endif

# endif


// Печатает "George, and Ringon"

GEORGERINGO_DECL void georgeringo();


#endif // GEORGERINGO_HPP_INCLUDED

Чтобы заставить это работать, вы должны при сборке в системах, поддерживающих опцию -fvisibility, определить макрос HAS_GCC_VISIBILITY.

Последние версии компилятора Intel для Linux также поддерживают опцию -fvisibility.

Видимость символов в Metrowerks для Mac OS X

Metrowerks для Mac OS X предоставляет несколько опций для экспорта символов из динамической библиотеки. При использовании IDE CodeWarrior вы можете использовать файл экспорта символов, который играет роль файла .def в Windows. Вы также можете экспортировать все символы с помощью опции -export all, что при сборке из командной строки является поведением по умолчанию. Я рекомендую метод, использующий для пометки в вашем исходном коде экспортируемых функций #pragma export, и указание в командной строке -export pragma при сборке динамической библиотеки. Использование #pragma export иллюстрируется в примере 1.2: просто вызовите #pragma export on в ваших заголовочных файлах сразу перед группой функций, которые требуется экспортировать, а сразу после нее — #pragma export off. Если вы хотите, чтобы ваш код работал с инструментарием, отличным от Metrowerks, вы должны поместить обращения к #pragma export между директивами #ifdef/#endif, как показано в примере 1.2.

Опции командной строки

Давайте кратко посмотрим на опции, использованные в табл. 1.11. Каждая строка команды определяет:

• имя (имена) входного файла (файлов): george.obj, ringo.obj и georgeringo.obj;

• имя создаваемой динамической библиотеки;

• в Windows имя библиотеки импорта.

Кроме того, компоновщик требует опции, которая говорит ему создать динамическую библиотеку, а не исполняемый файл. Большинство компоновщиков используют опцию -shared, но Visual C++ и Intel для Windows используют -dll, Borland и Digital Mars используют -WD, a GCC для Mac OS X использует -dynamiclib.

Несколько опций в табл. 1.11 способствуют более эффективному использованию динамических библиотек во время выполнения. Например, некоторым компоновщикам для Unix требуется с помощью опции -fPIC сгенерировать независимый от положения код (position- independent code) (GCC и Intel для Linux). Эта опция приводит к тому, что несколько процессов смогут использовать единственную копию кода динамической библиотеки. На некоторых системах отсутствие этой опции приведет к ошибке компоновщика. Аналогично в Windows опция компоновщика GCC --enable-auto-image-base снижает вероятность того, что операционная система попытается загрузить две динамические библиотеки в одно и то же место. Использование этой опции помогает ускорить загрузку DLL.

Передать опцию в компоновщик GCC можно через компилятор, используя опцию g++ -Wl,<option>. (За буквой W следует строчная буква l.)

Большая часть других опций используется для указания вариантов рабочей библиотеки и описывается в рецепте 1.23.

Смотри также

Рецепты 1.9, 1.12, 1.17, 1.19 и 1.23.

1.5. Сборка сложного приложения из командной строки

Проблема

Вы хотите использовать для сборки исполняемого файла, зависящего от нескольких статических и динамических библиотек, инструменты командной строки.

Решение

Начните со сборки статических и динамических библиотек, от которых зависит ваше приложение. Если библиотеки получены от сторонних разработчиков, следуйте инструкциям, поставляемым с этими библиотеками; в противном случае соберите их так, как описано в рецептах 1.3 и 1.4.

Затем скомпилируйте в объектные файлы .cpp-файлы своего приложения, как описано в разделе «Сборка простой программы «Hello, World» из командной строки». Чтобы сказать компилятору, где искать заголовочные файлы, требуемые для вашего приложения, используйте опцию -I, как показано в табл. 1.12.


Табл. 1.12. Указание директорий для поиска заголовочных файлов

Инструментарий Опция Все -I<директория>

Наконец, для создания исполняемого файла из набора объектных файлов и библиотек используйте компоновщик. Для каждой библиотеки вы должны либо указать ее полный путь и имя, либо сказать компоновщику, где ее искать.

На каждой стадии этого процесса при использовании инструментария, поставляемого со статическим и динамическим вариантами рабочих библиотек, и если программа использует хотя бы одну динамическую библиотеку, вы должны указать компилятору или компоновщику использовать динамическую библиотеку времени выполнения, как описано в рецепте 1.23.

Таблица 1.13 предоставляет команды для компоновки приложения hellobeatles из примера 1.3. Она предполагает, что:

• текущей директорией является hellobeatles;

• статическая библиотека libjohnpaul.lib или libjohnpaul.а была создана в директории johnpaul;

• динамическая библиотека georgeringo.dll, georgeringo.so или georgeringo.dylib и, если есть, ее библиотека импорта были созданы в директории georgeringo.

Так как Comeau, как сказано в рецепте 1.4, не может создавать динамические библиотеки, строка для Comeau в табл. 1.13 предполагает, что libgeorgeringo была создана как статическая, а не как динамическая библиотека. Чтобы собрать libgeorgeringo как статическую библиотеку, в примере 1.2 удалите из объявления функции georgeringo() модификатор GEORGERINGO_DECL.


Табл. 1.13. Команды для компоновки приложения hellobeatles.exe

Инструментарий Входные файлы Командная строка GCC (Unix) hellobeatles.o libjohnpaul.a libgeorgeringo.so g++ -о hellobeatles hellobeatles.o -L ./johnpaul -L./georgeringo -ljohnpaui -lgeorgeringo или g++ -o hellobeatles hellobeatles.o ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.so Intel (Linux) icpc -o hellobeatles hellobeatles.o -L./johnpaul -L./georgeringo -ljohnpaul -lgeorgeringo или icpc -о hellobeatles hellobeatles.o ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.so Comeau (Unix) como -no_prelink_verbose -o hellobeatles hellobeatles.o -L./johnpaul L./georgeringo -ljohnpaul -lgeorgeringo или como -no_prelink_verbose -o hellobeatles hellobeatles.о ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.a GCC (Mac OS X) hellobeatles.о libjohnpaul.a libgeorgeringo.dylib g++ -o hellobeatles hellobeatles.o -L/johnpaul -L./georgeringo -ljohnpaul -lgeorgeringo или g++ -o hellobeatles hellobeatles.o ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.dylib Metrowerks (Mac OS X) mwld -o hellobeatles hellobeatles.о -search -L/johnpaul -search -L ./georgeringo -ljohnpaui -lgeorgeringo или mwld -о hellobeatles hellobeatles.о ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.dylib GCC (Cygwin) hellobeatles.о libjohnpaul.a libgeorgeringo.dll.a g++ -о hellobeatles hellobeatles.o -L./johnpaul -L./georgeringo -Ijohnpaul -Igeorgeringo или g++ -o hellobeatles hellobeatles.о ./johnpaul/libjohnpaul.a ./georgeringo/libgeorgeringo.dll.a GCC (MinGW) hellobeatles.о libjohnpaul.a libgeorgeringo.a g++ -o hellobeatles hellobeatles.o -L./johnpaul -L./georgeringo -Ijohnpaul -Igeorgeringo или g++ -о hellobeatles hellobeatles.o ./johnpaul/libjohnpaul.a. /georgeringo/libgeorgeringo.a Visual C++ hellobeatles.obj libjohnpaul.lib libgeorgeringo.lib link -nologo -out:hellobeatles.exe -libpath:./johnpaul -libpath:./georgeringo libjohnpaul.lib libgeorgeringo.lib hellobeatles.obj Intel (Windows) xilink -nologo -out:hellobeatles -libpath:./johnpaul -libpath:./georgeringo.lib johnpaul.lib libgeorgeringo.lib hellobeatles.obj Metrowerks (Windows) mwld -o hellobeatles -search -L./johnpaul libjohnpaul.lib -search -L./georgeringo libgeorgeringo.lib hellobeatles.obj Metrowerks (Mac OS X)¹ mwld -o hellobeatles hellobeatles.o -search -L./johnpaul -search -L./georgeringo libjohnpaul libgeorgeringo.dylib CodeWarrior 10.0 (Mac OS X)² Сверьтесь с документацией Metrowerks Borland bcc32 -q -WR -WC -ehellobeatles -L./johnpaul -L./georgeringo/libjohnpaul.lib libgeorgeringo.lib hellobeatles.obj Digital Mars link -noi hellobeatles.obj,hellobeatles.exe,NUL,user32.lib kernel32.lib ..johnpaul .georgeringolibjohnpaul.lib libgeorgeringo.lib,, или link -noi hellobeatles.obj,hellobeatles.exe,NUL,user32.lib kernel32.lib ..johnpaullibjohnpaul.lib ..georgeringolibgeorgeringo.lib,, Comeau (Windows) hellobeatles.obj libjohnpaul.lib libgeorgeringo.lib como -no_prelink_verbose -o hellobeatles ./johnpaul/libjohnpaul.lib ./georgeringo/libgeorgeringo.lib hellobeatles.obj

¹ При сборке с помощью указанной командной строки hellobeatles может работать неправильно, так как это приложение будет использовать две копии рабочих библиотек Metrowerks. (См. рецепт 1.23.)

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*