Boost's bjam выполняет тесты до завершения сборки
У меня есть довольно простое расширение Boost.Python, которое я создаю с помощью bjam. Проблема в том, что порядок, в котором происходят вещи, не имеет смысла для меня, и я не вижу, как это исправить.
Мой проект состоит из корневого каталога с Jamroot и одного подкаталога проекта с Jamfile, файлом C++, файлом заголовка и скриптом Python.
В корне у меня есть файл Jamroot, который выглядит примерно так, в основном собранные из примеров и документов. Он отделен от Jamfile проекта, потому что я действительно хочу поделиться этим среди нескольких проектов, которые будут существовать в других подкаталогах.
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
use-project boost
: ./boost ;
project
: requirements <library>/boost/python//boost_python ;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
build-project hello_world ;
# build-project [[other projects]]... ;
Затем у меня есть подкаталог, содержащий мой проект hello_world (имя изменено для защиты невинных), который содержит Jamfile:
PROJECT_NAME = hello_world ;
import python ;
python-extension interpolation_ext :
$(PROJECT_NAME).cpp
:
<define>FOO
;
# Put the extension and Boost.Python DLL in the current directory, so that running script by hand works.
install convenient_copy
: $(PROJECT_NAME)_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
# Declare test targets
run-test $(PROJECT_NAME) : $(PROJECT_NAME)_ext test_$(PROJECT_NAME)_ext.py ;
Это удобно, но я не нашел много документации по этому поводу, к сожалению.
В любом случае, идея заключается в том, что, находясь в каталоге проекта hello_world, я делаю изменения кода и регулярно набираю 'bjam'. В результате создается расширение Python, а затем запускается файл test_hello_world_ext.py, который выполняет "импорт hello_world_ext" для проверки правильности сборки расширения, а затем связку довольно тривиальных модульных тестов. Если они все проходят, то bjam сообщает об успехе.
Кажется, что проблема в том, что иногда bjam запускает тест Python до того, как он запускает правило 'смысл_копии', что означает, что он выполняет тест с предыдущей версией расширения, а затем перезаписывает его новой версией. Это означает, что мне часто приходится запускать bjam дважды. Фактически, во второй раз bjam знает, что что-то устарело, потому что оно действительно что-то делает. В третий и последующий раз ничего не происходит, пока я не внесу дополнительные изменения в источник. Это похоже на классическую двойную задачу, когда зависимость не верна.
Основная проблема заключается в том, что часто происходит сбой успешной сборки (поскольку существующее расширение было плохим), а в других случаях плохая сборка показывается как успешная. Мне потребовалось несколько недель, чтобы заметить такое поведение, примерно в то же время, когда я думал, что схожу с ума, возможно, не случайно...
Похоже, что в Linux это делается чаще, чем в OS X, но я не совсем уверен. Тем не менее, я чувствую это, и я делю свое время между обеими средами довольно равномерно.
Кроме того, я единственный человек, который находит синтаксис bjam 'jamfile' совершенно запутанным? Под капотом происходит много всего, что я просто не понимаю или не могу найти адекватную документацию. Я бы с удовольствием использовал make или SCons вместо этого, но я не смог заставить их работать из-за разбитых примеров здесь и там. Что меня действительно смущает, так это то, как bjam строит множество других целей, прежде чем перейти к моим файлам, что, на мой взгляд, делает написание make-файла довольно сложным делом? Поскольку я хорошо знаком с GNU Make и SCons, стоит ли мне отказаться от bjam, чтобы использовать один из них?
1 ответ
Порядок объявления целей в jamfile не определяет порядок построения целей. Используйте зависимости для управления порядком сборки. Это будет сделано вот так:
Изменить run-test
Правило принять требования аргумента:
rule run-test ( test-name : sources + : requirements * )
{
import testing ;
testing.make-test run-pyd : $(sources) : $(requirements) : $(test-name) ;
}
изменять $(PROJECT_NAME)
целевое объявление, чтобы добавить требование зависимости на convenient_copy
:
run-test $(PROJECT_NAME) : $(PROJECT_NAME)_ext test_$(PROJECT_NAME)_ext.py : <dependency>convenient_copy ;
Относительно части о синтаксисе jamfile и т.д.:
Если вы делаете что-то с Boost.Build, кроме действительно тривиальных вещей, вам обязательно следует прочитать руководство пользователя. Мой личный опыт показывает, что после прочтения от начала до конца я выбираю Boost.Build над другими системами сборки в любой день. YMMV