![]() |
![]() ![]() ![]() ![]() |
![]() |
TutorialBoost , The Boost C++ Libraries BoostBook Documentation Subset , Chapter 45. Boost.Build User Manual
|
||||||||||||||||||||||||
![]() |
Tip |
|---|---|
Значение< |
Если нам нужны те же требования к другой цели<hello2>, мы можем просто дублировать их. Тем не менее, по мере роста проектов этот подход приводит к большому количеству повторяющихся байлеров в Jamfiles. К счастью, есть способ получше. Каждый проект может указывать наборатрибутов, включая требования:
project
: requirements <include>/home/ghost/Work/boost <threading>multi
;
exe hello : hello.cpp ;
exe hello2 : hello.cpp ;
Результат будет таким, как если бы мы указали одно и то же требование для<hello>и<hello2>.
Пока мы рассматривали только примеры с одним проектом, с одним написанным пользователем Boost. Файл Джема,<Jamroot>. Типичная большая кодовая база состоит из множества проектов, организованных в дерево. Верхняя часть дерева называется корнем проекта. Каждый подпроект определяется файлом<Jamfile>в каталоге-потомке корня проекта. Родительский проект подпроекта определяется ближайшим<Jamfile>или<Jamroot>файлом в каталоге предков. Например, в следующем макете каталога:
top/
|
+-- Jamroot
|
+-- app/
| |
| +-- Jamfile
| `-- app.cpp
|
`-- util/
|
+-- foo/
. |
. +-- Jamfile
. `-- bar.cpp
Корень проекта<top/>. Проекты<top/app/>и<top/util/foo/>являются непосредственными детьми основного проекта.
![]() |
Note |
|---|---|
Когда мы ссылаемся на файл “Jamfile, ” установленный в нормальном типе, мы имеем в виду файл под названием< |
Проекты наследуют все атрибуты (например, требования) от своих родителей. Унаследованные требования сочетаются с любыми требованиями, указанными в подпроекте. Например, если<top/Jamroot>
<include>/home/ghost/local
В своих требованиях, тогда все его подпроекты будут иметь его в своих требованиях. Конечно, любой проект может добавить пути к тем, которые указаны его родителями.<hello2>Более подробную информацию можно найти вразделе под названием & #8220; Проекты & #8221;.
Включениеb2без явного указания каких-либо целей в командной строке строит проект, укорененный в текущем каталоге. Построение проекта автоматически не приводит к созданию его подпроектов, если только JAMFILE не запрашивает его. В нашем примере<top/Jamroot>может содержаться:
build-project app ;
Это означает, что проект в 90 году будет построен всякий раз, когда проект в 91 году будет построен. Однако цели в<top/util/foo/>будут строиться только в том случае, если они нужны целям в<top/>или<top/app/>.
При построении цели<X>, которая зависит от первого построения другой цели<Y>(например, библиотеки, которая должна быть связана сX),<Y>называется зависимостью<X>и<X>называется зависимостью<Y>.
Чтобы почувствовать зависимость от цели, давайте продолжим приведенный выше пример и посмотрим, как<top/app/Jamfile>может использовать библиотеки из<top/util/foo>. Если<top/util/foo/Jamfile>содержит
lib bar : bar.cpp ;
Чтобы использовать эту библиотеку в<top/app/Jamfile>, мы можем написать:
exe app : app.cpp ../util/foo//bar ;
Хотя<app.cpp>относится к обычному исходному файлу,<../util/foo//bar>является ссылкой на другую цель: библиотеку<bar>, объявленную в Jamfile на<../util/foo>.
![]() |
Tip |
|---|---|
Некоторые другие системы сборки имеют специальный синтаксис для перечисления зависимых библиотек, например< |
Предположим, что мы строим<app>:
b2 app optimization=full define=USE_ASM
Какие объекты будут использоваться для строительства<foo>? Ответ заключается в том, что некоторые функциираспространяютсяи #8212; Повышение. Создавайте попытки использовать зависимости с одинаковым значением распространяемых функций. Распространена функция<<optimization>>, поэтому и<app>, и<foo>будут скомпилированы с полной оптимизацией. Но<<define>>не распространяется: его значение будет добавлено как есть к флагам компилятора<a.cpp>, но не повлияет<foo>.
Давайте еще больше улучшим этот проект. Библиотека, вероятно, имеет некоторые заголовки, которые должны использоваться при компиляции<app.cpp>. Мы могли бы вручную добавить необходимые<#include>пути к<app>требованиям в качестве значений<<include> >функции, но затем эта работа будет повторяться для всех программ, которые используют<foo>. Лучшим решением является изменение<util/foo/Jamfile>таким образом:
project
: usage-requirements <include>.
;
lib foo : foo.cpp ;
Требования к использованию применяются не к заявленной цели, а к ее иждивенцам. В этом случае<<include>.>будет применяться ко всем целям, которые напрямую зависят от<foo>.
Еще одним усовершенствованием является использование символьных идентификаторов для ссылки на библиотеку, в отличие от местоположения<Jamfile>. В большом проекте библиотека может использоваться многими мишенями, и если все они используют<Jamfile
>местоположение, изменение организации каталогов влечет за собой большую работу. Решение заключается в использовании ids—символических имен, не привязанных к макету каталога. Во-первых, мы должны назначить идентификатор проекта, добавив этот код<Jamroot>:
use-project /library-example/foo : util/foo ;
Во-вторых, мы модифицируем<app/Jamfile>для использования идентификатора проекта:
exe app : app.cpp /library-example/foo//bar ;
Синтаксис</library-example/foo//bar>используется для обозначения цели<bar>в проекте с идентификатором<
/library-example/foo>. Мы достигли нашей цели— если библиотека перенесена в другой каталог, только<Jamroot
>должен быть изменен. Обратите внимание, что идентификаторы проектов являются глобальными— двум Jamfiles не разрешается назначать один и тот же идентификатор проекта в разные каталоги.
![]() |
Tip |
|---|---|
|
Если вы хотите, чтобы все приложения в каком-либо проекте ссылались на определенную библиотеку, вы можете избежать необходимости указывать непосредственно источники каждой цели, используя свойство< project : requirements <library>/boost/filesystem//fs ; |
Библиотеки могут быть либостатическими, что означает, что они включены в исполняемые файлы, которые их используют, илисовместно используемыми(а.к.а.динамическими), которые упоминаются только из исполняемых файлов и должны быть доступны во время выполнения. Повышаю. Построение может создавать и использовать оба вида.
Тип библиотеки, созданной из цели<lib>, определяется значением функции<link>. Значение по умолчанию составляет<shared>, а для построения статической библиотеки значение должно быть<static>. Вы можете запросить статическую сборку на командной строке:
b2 link=static
или в соответствии с требованиями библиотеки:
lib l : l.cpp : <link>static ;
Мы также можем использовать свойство<<link>>для выражения требований к увязке на целевой основе. Например, если конкретный исполняемый файл может быть правильно построен только со статической версией библиотеки, мы можем квалифицировать целевую ссылкуисполняемого файлана библиотеку следующим образом:
exe important : main.cpp helpers/<link>static ;
Независимо от того, какие аргументы указаны в командной строкеb2,<important>будет связан только со статической версией<helpers>.
Определение свойств в целевых ссылках особенно полезно, если вы используете библиотеку, определенную в каком-либо другом проекте (который вы не можете изменить), но вы все равно хотите статическую (или динамическую) связь с этой библиотекой во всех случаях. Если эта библиотека используется многими целями, вымогли быиспользовать ссылки на цели везде:
exe e1 : e1.cpp /other_project//bar/<link>static ; exe e10 : e10.cpp /other_project//bar/<link>static ;
Но это далеко не удобно. Лучшим подходом является введение уровня косвенности. Создайте локальныйпсевдоним, который относится к статической (или динамической) версии<foo>:
alias foo : /other_project//bar/<link>static ; exe e1 : e1.cpp foo ; exe e10 : e10.cpp foo ;
Правилопсевдонимаспециально используется для переименования ссылки на цель и, возможно, изменения свойств.
![]() |
Tip |
|---|---|
|
Когда одна библиотека использует другую, вы помещаете вторую библиотеку в список источников первой. Например: lib utils : utils.cpp /boost/filesystem//fs ; lib core : core.cpp utils ; exe app : app.cpp core ; Это работает независимо от того, какие ссылки используются. Когда< |
![]() |
Note |
|---|---|
(перенаправлено с «Unix System») Как правило, общие библиотеки должны быть установлены в каталог в пути поиска динамического линкера. В противном случае приложения, использующие общие библиотеки, не могут быть запущены. В Windows путь поиска динамического линкера определяется переменной среды< |
Иногда необходимо поддерживать определенные отношения между свойствами построения цели. Например, вы можете установить конкретный<
#define>, когда библиотека построена как общая, или когда построен вариант<release>цели. Этого можно добиться, используяусловные требования.
lib network : network.cpp : <link>shared:<define>NETWORK_LIB_SHARED <variant>release:<define>EXTRA_FAST ;
В приведенном выше примере, когда<network>построен с<<link>shared>,<<define>NETWORK_LIB_SHARED
>также будет в его свойствах. Кроме того, всякий раз, когда будет построен его вариант выпуска,<<define>EXTRA_FAST>появится в его свойствах.
Иногда способы построения цели настолько различны, что описать их с помощью условных требований будет сложно. Например, представьте, что библиотека на самом деле использует различные исходные файлы в зависимости от набора инструментов, используемых для ее создания. Мы можем выразить эту ситуацию, используяцелевые альтернативы:
lib demangler : dummy_demangler.cpp ; # alternative 1 lib demangler : demangler_gcc.cpp : <toolset>gcc ; # alternative 2 lib demangler : demangler_msvc.cpp : <toolset>msvc ; # alternative 3
При строительстве<demangler>. Build будет сравнивать требования к каждой альтернативе со свойствами сборки, чтобы найти лучшее соответствие. Например, когда будет выбрано здание с<<toolset>gcc>альтернативой 2, и когда будет выбрано здание с<<toolset>msvc>альтернативой 3. Во всех остальных случаях будет построена самая общая альтернатива 1.
Чтобы ссылаться на библиотеки, инструкции по сборке которых не даны в Jamfile, необходимо создать<lib>цели с соответствующим<file>свойством. Целевые альтернативы могут быть использованы для объединения нескольких библиотечных файлов с одной концептуальной целью. Например:
# util/lib2/Jamfile lib lib2 : : <file>lib2_release.a <variant>release ; lib lib2 : : <file>lib2_debug.a <variant>debug ;
В этом примере определены две альтернативы для<lib2>, и для каждого имени предварительно построенный файл. Естественно, источников нет. Вместо этого для указания имени файла используется функция<<file>>.
Как только предварительно построенная цель была объявлена, ее можно использовать так же, как и любую другую цель:
exe app : app.cpp ../util/lib2//lib2 ;
Как и в случае с любой мишенью, выбранная альтернатива зависит от свойств, распространяемых от иждивенцев<lib2>. Если мы создадим релиз и отладку, версии<app>будут связаны с<lib2_release.a>и<lib2_debug.a
>соответственно.
Системные библиотеки & #8212; те, которые автоматически обнаруживаются набором инструментов путем поиска по некоторому набору заранее определенных путей & #8212; должны быть объявлены почти как обычные:
lib pythonlib : : <name>python22 ;
Мы снова не указываем никаких источников, но даем<name>, который должен быть передан компилятору. Если набор инструментов gcc был использован для связи исполняемой цели с<pythonlib>,<-lpython22>появится в командной строке (другие компиляторы могут использовать разные опции).
Мы также можем указать, где набор инструментов должен искать библиотеку:
lib pythonlib : : <name>python22 <search>/opt/lib ;
И, конечно, целевые альтернативы можно использовать обычным способом:
lib pythonlib : : <name>python22 <variant>release ; lib pythonlib : : <name>python22_d <variant>debug ;
Более продвинутое использование предварительно построенных целей описано вразделе под названием “Цели в site-config.jam”.
<hello2>Многие функции будут отменены, а не добавлены в подпроекты. См.раздел под названием & #8220; Атрибуты характеристик & #8221;для получения дополнительной информации
Статья Tutorial раздела The Boost C++ Libraries BoostBook Documentation Subset Chapter 45. Boost.Build User Manual может быть полезна для разработчиков на c++ и boost.
:: Главная :: Chapter 45. Boost.Build User Manual ::
реклама |