Обход некоторых ограничений утилиты BUILD

Система сборки в Windows Driver Kit базируется на утилите BUILD. Эта утилита сканирует структуру проектов, отслеживает зависимости (к сожалению далеко не все) и подготавливает окружение для запуска NMAKE, который, собственно, и выполняет всю черновую работу по сборке. К сожалению, BUILD создавался и развивался по принципу «так получилось», исключительно эволюционным путем – как средство сборки исходников Windows. Так что эта утилита некоторыми неудобными ограничениями.

Одно из них – полное непонимание переменных и директив препроцессора. К примеру, нужно исключить определённую директорию из дерева сборки если объявлен макрос NOBUILD. Пишем вот такой DIRS файл:

!if defined(NOBUILD) 

DIRS = \
    foo \

!else

DIRS = \
    foo \
    bar \

!endif

Вне зависимости от того, объявлен макрос NOBUILD или нет, BUILD попытается собрать обе директории foo и bar. Более того, вот такой DIRS файл тоже не вызовет ошибку:

Some random garbage in DIRS file.

DIRS = \
    foo \
    bar \

More random garbage.

Почему? Потому, что BUILD просто сканирует файл в поиске текста, похожего на объявление директив DIRS и OPTIONAL_DIRS игнорируя остальной текст. Впрочем, макроподстановки разворачиваются правильно:

FOO = \
    foo \

DIRS = \
    $(FOO) \
    bar \

Аналогичная ситуация с файлом SOURCES. BUILD игнорирует директивы препроцессора, интересуясь только объявлением макроса SOURCES и его платформо-зависимых вариантов. Полностью, все эти директивы обрабатываются только утилитой NMAKE. Как же быть?

Каждая директория, предназначенная для сборки, содержит файл MAKEFILE:

#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the components of NT OS/2
#
!INCLUDE $(NTMAKEENV)\makefile.def

Именно этот файл читается NMAKE, для каждого из трех проходов (PASS0, PASS1 и PASS2). По умолчанию, он просто включает стандартные правила сборки, работающие с SOURCES. (Начиная с WDK для Vista MAKEFILE стал опциональным. В случае его отсутствия, автоматически используется MAKEFILE.DEF.) Примерное дерево включений make-файлов выглядит вот так:

MAKEFILE
+- MAKEFILE.DEF
   +- MAKEFILE.NEW
      +- MAKEFILE.PLT
         +- PROJECT.MK
      +- SOURCES
      +- _OBJECTS.MAC
      +- $(TARGET_DIRECTORY)mk.inc
      +- MAKEFILE.INC
      +- …

Откуда видно, что MAKEFILE и MAKEFILE.INC – крайне полезны для нетривиальных манипуляций с логикой сборки. Так, чтобы решить оригинальную задачу, достаточно не включать MAKEFILE.DEF в случае, если объявлен макрос NOBUILD:

!if !defined(NOBUILD)

#
# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the components of Windows NT
#
!INCLUDE $(NTMAKEENV)\makefile.def

!endif

В результате, BUILD по-прежнему вызовет NMAKE, но тот проигнорирует данную директорию.

comments powered by Disqus