Как запустить C препроцессор в Boost.Build V2. Часть II

Продолжаем начатое ранее. Мы остановились на том, что сумели вызвать компилятор и передать ему нужную команду. Теперь нам нужно научиться передавать все настройки компилятора, уже известные Boost.Build, в созданную командную строку. Для сначала нужно выяснить как же, собственно, Boost.Build узнает где находится компилятор и как задаются параметры компиляции.

Boost.Build использует так называемые features (на самом деле – именованные значения) для задания опций компиляции. В Jam коде они выглядят как “<имя>значение” (например “speed”), в параметрах командной строки – как пары ”имя=значение” (например “optimization=speed”). Именованные значения позволяют задавать параметры компиляции одинаково вне зависимости от особенностей используемого компилятора. К примеру, в случае Visual C++ 2005 значение “speed” будет преобразовано в “/O2”. В случае GCC то же значение трансформируется в “-O3”.

Соответствие между именованными значениями (features) и параметрами конкретного компилятора устанавливается с помощью механизма флагов. Не вдаваясь в детали, выглядит это вот так:

flags msvc.compile CFLAGS <optimization>speed : /O2 ;

Такая строка указывает, что в контексте правила (rule) и действий (actions) “msvc.compile” в значение переменной CFLAGS будет добавлен параметр “/O2” при условии, что в параметрах компиляции указано именованное значение “speed”. Далее, во время компиляции очередного файла, значение переменной CFLAGS будет подставлено в командную строку компилятора внутри блока действий “msvc.compile”. Кстати префикс “msvc” означает, что правило или действия заданы в модуле msvc.jam.

Далее Boost.Build использует файлы site-config.jam и user-config.jam для хранения глобальных и, соответственно, пользовательских настроек. site-config.jam находится в каталоге “$(BOOST_ROOT)/tools/build/v2”. user-config.jam обычно помещается в каталог $(HOME) (в Windows – “%HOMEDRIVE%%HOMEPATH%”). Мой файл user-config.jam выглядит просто до безобразия:

import toolset : using ;

# Использовать настройки Visual C++ по-умолчанию
using msvc ;

Первая строчка делает возможным вызов правила using из модуля toolset.jam. Строка “using msvc ;” указывает, что я хочу использовать MS Visual C++ с установками по умолчанию. Эта строка может быть и сложнее, например:

using msvc 7.1toolkit : X:/Microsoft Visual C++ Toolkit 2003/bin/cl.exe ;

Такая строка указывает использовать версию “7.1toolkit” и задаёт путь к компилятору, по которому будут заданы остальные настройки.

Интересно, что все настройки компиляторов, как заданные в файлах site- и user-config.jam, так и вычисленные автоматически, в конечном итоге (пройдя огонь, воду и кучу Jam кода) оседают в переменных с помощью того же самого механизма флагов, о котором я рассказывал выше. Например, для Visual C++ команда вызова компилятора задается в переменной “.CC”. Иными словами обе задачи, которые мы себе поставили в начале данного поста, решаются автоматически, как только мы получим доступ к этим переменным. Только вот как это сделать, если все переменные, определённые в модуле msvc.jam, видны только в контексте этого модуля или даже конкретного правила, если оно указано, как в случае с “msvc.compile”.

Оказывается стандартная библиотека Boost.Build предоставляет все средства для решения этой проблемы. Достаточно вызвать toolset.inherit-flags и все флаги, заданные в исходном модуле будут импортированы в целевой. Теперь наш генератор можно переписать вот таким образом:

# Импортируем нужные модули
import generators ;
import toolset ;
import type ;

# Регистрируем новый тип файла. "I" - имя типа, "i" - расширение файла
type.register I : i ;

# Регистрируем генератор для преобразования C в I. "pp.generate.c" -
# полное имя правила, которое быдет вызвано для выполнения преобразования.
generators.register-standard pp.compile.c : C : I ;

# Импортируем флаги из msvc
toolset.inherit-flags pp : msvc ;

# Правило, которое будет вызвано во время генерации
rule compile.c ( targets + : sources * : properties * )
{
}

# Команды, непосредственно работающие с файлами
actions compile.c
{
    $(.CC) /EP -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(>) > $(<)
}

Генерируемые команды теперь тоже выглядят по-другому:

mkdir "bin"
mkdir "bin\\msvc-8.0"
mkdir "bin\\msvc-8.0\\debug"
mkdir "bin\\msvc-8.0\\debug\\threading-multi"
call "C:\\Program Files\\Microsoft Visual Studio 8\\VC\\vcvarsall.bat" x86 >nul
cl /Zm800 -nologo /EP   /Z7 /Od /Ob0 /W3 /GR /MDd /Zc:forScope /Zc:wchar_t win32api.c > bin\\msvc-8.0\\debug\\threading-multi\\win32api.i

Обратите внимание, что правило “generate.c” было переименовано в “compile.c” чтобы соответствовать соглашениям, принятым в модуле msvc.jam. Без этого ничего работать не будет, так как имя правила – это часть контекста.

В таком виде генератор уже пригоден к использованию, однако его можно сделать ещё лучше. Как - читайте в следующей части.

comments powered by Disqus