Программирование ARM SCons: управление целями и результатами сборки Tue, March 05 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

SCons: управление целями и результатами сборки Печать
Добавил(а) microsin   

[Цели сборки, указанные в командной строке]

Считывание целей из командной строки: переменная COMMAND_LINE_TARGETS. SCons предоставляет переменную COMMAND_LINE_TARGETS, которая позволит вам извлечь список целей (targets), которые были указаны в командной строке. Вы можете использовать targets для манипулирования сборкой любым способом, как пожелаете. В качестве простого примера предположим, что вы хотите напечатать напоминание всякий раз, когда собирается определенная программа. Вы можете сделать это проверкой target в списке COMMAND_LINE_TARGETS:

if 'bar' in COMMAND_LINE_TARGETS:
   print("Don't forget to copy `bar' to the archive!")
Default(Program('foo.c'))
Program('bar.c')

Теперь запуск SCons с default target работает как обычно, однако если указать bar для target в командной строке, то сгенерируется предупреждающее сообщение:

% scons -Q
cc -o foo.o -c foo.c
cc -o foo foo.o
% scons -Q bar
Don't forget to copy `bar' to the archive!
cc -o bar.o -c bar.c
cc -o bar bar.o

Другое практическое использование переменной COMMAND_LINE_TARGETS может ускорить сборку путем чтения только определенных дочерних файлов SConscript, если запрешена определенная target.

Управление целями по умолчанию: функция Default. Вы можете управлять, какие target-ы собираются по умолчанию, т. е. что является целью, когда в командной строке не указано никаких target. Как упоминалось ранее, SCons обычно собирает каждый target в текущей директории или в её подкаталоге, если вы явно не указали одну или большее количество target в командной строке. Однако вы можете иногда захотеть указать, что по умолчанию должны собираться только определенные программы, или программы в определенных директориях. Это можно сделать функцией Default:

env = Environment()
hello = env.Program('hello.c')
env.Program('goodbye.c')
Default(hello)

Этот файл SConstruct знает, как собрать две программы, hello и goodbye, однако по умолчанию (если цель в командной строке не указана) соберет программу hello:

% scons -Q
cc -o hello.o -c hello.c
cc -o hello hello.o
% scons -Q
scons: `hello' is up to date.
% scons -Q goodbye
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o

Обратите внимание, что даже если вы используете функцию Default в своем файле SConstruct, то вы все еще можете явно указать текущую директорию (.) в командной строке, чтобы указать SCons собрать все в текущей директории (или ниже, в подкаталоге):

% scons -Q .
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
cc -o hello.o -c hello.c
cc -o hello hello.o

Также можно вызвать функцию Default несколько раз, в таком случае каждый вызов добавит цель к списку target-ов, собираемых по умолчанию:

env = Environment()
prog1 = env.Program('prog1.c')
Default(prog1)
prog2 = env.Program('prog2.c')
prog3 = env.Program('prog3.c')
Default(prog3)

Или вы можете указать больше одной target в одном вызове функции Default:

env = Environment()
prog1 = env.Program('prog1.c')
prog2 = env.Program('prog2.c')
prog3 = env.Program('prog3.c')
Default(prog1, prog3)

Любой из этих двух последних примеров соберет по умолчанию только программы prog1 и prog3:

% scons -Q
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
cc -o prog3.o -c prog3.c
cc -o prog3 prog3.o
% scons -Q .
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o

Вы можете указать список директорий в качестве аргумента для Default:

env = Environment()
env.Program(['prog1/main.c', 'prog1/foo.c'])
env.Program(['prog2/main.c', 'prog2/bar.c'])
Default('prog1')

В этом случае по умолчанию создадутся только указанные цели в указанных директориях:

% scons -Q
cc -o prog1/foo.o -c prog1/foo.c
cc -o prog1/main.o -c prog1/main.c
cc -o prog1/main prog1/main.o prog1/foo.o
% scons -Q
scons: `prog1' is up to date.
% scons -Q .
cc -o prog2/bar.o -c prog2/bar.c
cc -o prog2/main.o -c prog2/main.c
cc -o prog2/main prog2/main.o prog2/bar.o

И наконец, если по какой-то причине вы не хотите собирать по умолчанию никакие target-ы, то можете использовать Python-переменную None:

env = Environment()
prog1 = env.Program('prog1.c')
prog2 = env.Program('prog2.c')
Default(None)

Тогда получится следующие результаты запуска:

% scons -Q
scons: *** No targets specified and no Default() targets found.  Stop.
Found nothing to build
% scons -Q .
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o

Выборка списка целей по умолчанию: переменная DEFAULT_TARGETS. SCons предоставляет переменную DEFAULT_TARGETS, которая позволит вам получить текущий список целей по умолчанию (default targets), указанный вызовами функции или метода Default. Переменная DEFAULT_TARGETS имеет 2 важных отличия от переменной COMMAND_LINE_TARGETS. Во-первых, переменная DEFAULT_TARGETS это список внутренних узлов (nodes) SCons, так что вам понадобится преобразовать список элементов DEFAULT_TARGETS в строки, если хотите напечатать их, или получить определенное имя target. Это можно просто реализовать вызовом str на элементах списка:

prog1 = Program('prog1.c')
Default(prog1)
print("DEFAULT_TARGETS is %s" % [str(t) for t in DEFAULT_TARGETS])

Следует иметь в виду, что все манипуляции со списком DEFAULT_TARGETS производятся на первой фазе обработки, когда SCons считывает файлы SConscript, что станет очевидным, если не указывать флаг -Q при запуске SCons:

% scons
scons: Reading SConscript files ...
DEFAULT_TARGETS is ['prog1']
scons: done reading SConscript files.
scons: Building targets ...
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
scons: done building targets.

Во-вторых, содержимое списка DEFAULT_TARGETS меняется в ответ на вызовы функции Default, как можно видеть из следующего файла SConstruct:

prog1 = Program('prog1.c')
Default(prog1)
print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS])
prog2 = Program('prog2.c')
Default(prog2)
print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS])

В результате получится следующий вывод:

% scons
scons: Reading SConscript files ...
DEFAULT_TARGETS is now ['prog1']
DEFAULT_TARGETS is now ['prog1', 'prog2']
scons: done reading SConscript files.
scons: Building targets ...
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o
scons: done building targets.

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

Извлечение списка целей сборки, независимо от источника: переменная BUILD_TARGETS. Вы уже видели переменную COMMAND_LINE_TARGETS, которая содержит список целей, указанных в командной строке, и переменную DEFAULT_TARGETS, где находится список целей, заданных вызовами метода Default. Однако иногда требуется получить список целей, которые SCons пытается собрать, независимо от того, откуда пришли target, из командной строки или из вызовов Default. Вы можете закодировать это вручную следующим образом:

if COMMAND_LINE_TARGETS:
   targets = COMMAND_LINE_TARGETS
else:
   targets = DEFAULT_TARGETS

Однако SCons предоставляет удобную переменную BUILD_TARGETS, которая устраняет необходимость этих ручных манипуляций. По сути переменная BUILD_TARGETS содержит список целей командной строки, если они были указаны, и если в командной строке цели указаны не были, то содержит список целей, заданных методом Default.

Из-за того, что BUILD_TARGETS может содержать список SCons-узлов (nodes), вы должны преобразовать список элементов в строки, если хотите напечатать их или найти определенное имя target. Это делается так же, как и для DEFAULT_TARGETS:

prog1 = Program('prog1.c')
Program('prog2.c')
Default(prog1)
print("BUILD_TARGETS is %s" % [str(t) for t in BUILD_TARGETS])

Обратите внимание, что значение BUILD_TARGETS меняется в зависимости от того, была ли указана цель в командной строке - BUILD_TARGETS получает значение из DEFAULT_TARGETS только если не было COMMAND_LINE_TARGETS:

% scons -Q
BUILD_TARGETS is ['prog1']
cc -o prog1.o -c prog1.c
cc -o prog1 prog1.o
% scons -Q prog2
BUILD_TARGETS is ['prog2']
cc -o prog2.o -c prog2.c
cc -o prog2 prog2.o
% scons -Q -c .
BUILD_TARGETS is ['.']
Removed prog1.o
Removed prog1
Removed prog2.o
Removed prog2

[Установка файлов в другие директории: Install сборщика]

Когда программа собрана, часто нужно установить её в другую директорию для публичного использования. Для копирования программы или любого другого файла в конечный каталог используется метод Install:

env = Environment()
hello = env.Program('hello.c')
env.Install('/usr/bin', hello)

Однако обратите внимание, что установка файла все еще считается типом файла "build". Это важный момент если вспомнить, что поведение SCons по умолчанию заключается в построении файлов в текущей директории или ниже. Если, как в приведенном выше примере, вы устанавливаете файлы в директорию, которая находится не там, где файл SConstruct верхнего уровня, то должны указать эту директорию (или самую верхнюю директорию, такую как /), чтобы в ней произвести установку:

% scons -Q
cc -o hello.o -c hello.c
cc -o hello hello.o
% scons -Q /usr/bin
Install file: "hello" as "/usr/bin/hello"

Однако может быть утомительно помнить (и вводить) определенную директорию назначения, в которую должна быть установлена программа (или другой файл). Может использоваться вызов Default, чтобы добавить директорию в список default targets, что устраняет необходимость ввода пути директории назначения, но иногда вы можете не захотеть делать установку при каждой сборке. Это тот случай, когда становится удобной функция Alias, котороая позволит вам, например, создать pseudo-target с именем install, которое может быть развернуто в указанную директорию назначения:

env = Environment()
hello = env.Program('hello.c')
env.Install('/usr/bin', hello)
env.Alias('install', '/usr/bin')

В результате получается более естественная возможность установить программу в её отдельном вызове следующим образом:

% scons -Q
cc -o hello.o -c hello.c
cc -o hello hello.o
% scons -Q install
Install file: "hello" as "/usr/bin/hello"

Установка в директорию нескольких файлов. Вы можете установить несколько файлов в директорию простым вызовом функции Install несколько раз:

env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.Install('/usr/bin', hello)
env.Install('/usr/bin', goodbye)
env.Alias('install', '/usr/bin')

Или более кратко можно перечислить несколько входных файлов в списке (так же, как вы это делаете с любым другим сборщиком):

env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.Install('/usr/bin', [hello, goodbye])
env.Alias('install', '/usr/bin')

Любой из этих двух примеров даст следующий результат:

% scons -Q install
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
Install file: "goodbye" as "/usr/bin/goodbye"
cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"

Установка файла под другим именем, функция InstallAs. Метод Install сохраняет имя файла, когда копирует его в директорию назначения. Если вам надо поменять имя файла при копировании, то используйте функцию InstallAs:

env = Environment()
hello = env.Program('hello.c')
env.InstallAs('/usr/bin/hello-new', hello)
env.Alias('install', '/usr/bin')

Это установит программу hello с именем hello-new следующим образом:

% scons -Q install
cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"

Установка нескольких файлов под другим именем. Если имеется несколько файлов, которые нужно установить под другими именами, то вы можете либо вызвать функцию InstallAs несколько раз, или можете предоставить списки файлов одинаковой размерности для аргументов цели и источника:

env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.InstallAs(['/usr/bin/hello-new',
               '/usr/bin/goodbye-new'],
               [hello, goodbye])
env.Alias('install', '/usr/bin')

В этом случае функция InstallAs выполнит одновременную итерацию по предоставленным спискам, и выполнит копирования каждого файла источника в целевое имя файла назначения:

% scons -Q install
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
Install file: "goodbye" as "/usr/bin/goodbye-new"
cc -o hello.o -c hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"

Установка общей библиотеки (Shared Library). Если shared-библиотека создается с установленной переменной $SHLIBVERSION, то scons создаст необходимые символические ссылки, базируясь на этой переменной. Для правильной установки такой библиотеки, включая символические ссылки, используйте функцию InstallVersionedLib.

Например на системе Linux следующая инструкция:

foo = env.SharedLibrary(target="foo", source="foo.c", SHLIBVERSION="1.2.3")

.. создаст shared-библиотеку libfoo.so.1.2.3 и символические ссылки libfoo.so и libfoo.so.1, указывающие на libfoo.so.1.2.3. Вы можете использовать Node, возвращенный сборщиком SharedLibrary для установки библиотеки и её символических ссылок в одном инструкции, без необходимости перечислять действия индивидуально:

env.InstallVersionedLib(target="lib", source=foo)

На системах, которые ожидают установку shared-библиотеки и вместе с именем, которое показывают версию, для разрешения run-time, и как простое имя, для разрешения link-time, можно использовать функцию InstallVersionedLib. Символические ссылки, соответствующие типу системы, будут сгенерированы на основе символьных ссылок исходной библиотеки.

[Манипуляции с файловой системой, не зависящие от платформы]

SCons предоставляет несколько платформо-независимых функций, которые называются факториями. Они выполняют общие манипуляции над файловой системой наподобие копирования, перемещения или удаления файлов и директорий, или создания директорий. Эти функции называются факториями потому, что они не выполняют действие в момент вызова, вместо этого возвращая объект Action, который может быть выполнен в подходящее время.

Копирование файлов или директорий: фактория Copy. Предположим, что вы хотите создать копию файла, и для этого у вас нет подходящего, готового сборщика. Один из способов для этого является использование фактории действия Copy вместе со сборщиком Command:

Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))

Примечание: к сожалению, на ранних стадиях разработки SCons имя Copy использовалось для функции, которая возвращала копию окружения (environment), в противном случае это было бы логическим выбором для сборщика, который копирует файл или дерево директории в место расположения target.

Обратите внимание, что действие (action), которое возвратила фактория Copy, будет разворачивать строки $TARGET и $SOURCE в момент сборки file.out, и что порядок аргументов такой же, как у самого сборщика - т. е. сначала target, за которым идет источник:

% scons -Q
Copy("file.out", "file.in")

Конечно, вы можете использовать явное имя файла вместо использования $TARGET или $SOURCE:

Command("file.out", [], Copy("$TARGET", "file.in"))

Результат запуска:

% scons -Q
Copy("file.out", "file.in")

Польза от фактории Copy становится более очевидной при использовании её в списке действий, переданных сборщику Command. Для примера предположим, что вам нужно пропустить файл через утилиту, которая модифицирует его по месту, и нельзя организовать "канал" от входа до выхода. Одно из решений - копировать исходный файл во временный файл с другим именем, запустить утилиту, и затем выполнить копирование модифицированного временного файла в target, что делается благодаря фактории Copy очень просто:

Command(
    "file.out",
    "file.in",
    action=[
        Copy("tempfile", "$SOURCE"),
        "modify tempfile",
        Copy("$TARGET", "tempfile"),
    ],
)

Тогда результат запуска будет выглядеть примерно так:

% scons -Q
Copy("tempfile", "file.in")
modify tempfile
Copy("file.out", "tempfile")

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

# Символическая ссылка неглубоко скопирована как новая символическая ссылка:
Command("LinkIn", "LinkOut", Copy("$TARGET", "$SOURCE"[, True]))
 
# Целевой объект символической ссылки копируется как файл или директория:
Command("LinkIn", "FileOrDirectoryOut", Copy("$TARGET", "$SOURCE", False))

Удаление файлов или директорий: фактория Delete. Если вам нужно удалить файл, то можно использовать факторию Delete почти так же, как факторию Copy. Например, если нужно гарантировать, что временный файл в последнем примере не существует перед тем, как выполняется копирование в него, мы должны добавить Delete в начало списка команд:

Command(
    "file.out",
    "file.in",
    action=[
        Delete("tempfile"),
        Copy("tempfile", "$SOURCE"),
        "modify tempfile",
        Copy("$TARGET", "tempfile"),
    ],
)

Это будет выполнено следующим образом:

% scons -Q
Delete("tempfile")
Copy("tempfile", "file.in")
modify tempfile
Copy("file.out", "tempfile")

Конечно, как и все такие Action-фактории, фактория Delete также развернет соответствующим образом переменные $TARGET и $SOURCE. Пример:

Command(
    "file.out",
    "file.in",
    action=[
        Delete("$TARGET"),
        Copy("$TARGET", "$SOURCE"),
    ],
)

Результат запуска:

% scons -Q
Delete("file.out")
Copy("file.out", "file.in")

Однако имейте в виду, что обычно не нужно таким способом явно вызывать факторию Delete; по умолчанию SCons удаляет свою цель (цели) перед выполнением любого действия.

Еще одно предупреждающее замечание по использованию фактории Delete: она так же разворачивает переменные, как любая другая фактория, включая переменную $SOURCE. Указывать Delete("$SOURCE") обычно плохая идея!

Перемещение (переименование) файлов или директорий: фактория Move. Например, если мы не хотим делать копию во временный файл, то можно использовать Move:

Command(
    "file.out",
    "file.in",
    action=[
        Copy("tempfile", "$SOURCE"),
        "modify tempfile",
        Move("$TARGET", "tempfile"),
    ],
)

Результат выполнения:

% scons -Q
Copy("tempfile", "file.in")
modify tempfile
Move("file.out", "tempfile")

Обновление времени модификации файла: фактория Touch. Если надо модифицировать записанную метку времени файла, то используйте факторию Touch:

Command(
    "file.out",
    "file.in",
    action=[
        Copy("$TARGET", "$SOURCE"),
        Touch("$TARGET"),
    ]
)

Результат выполнения:

% scons -Q
Copy("file.out", "file.in")
Touch("file.out")

Создание каталога: фактория Mkdir. Если вы хотите создать директорию, то используйте факторию Mkdir. Например, если мы хотим обработать файл во временной директории, в которой утилита обработки будет создавать другие файлы, о которых заботиться не нужно, то можно использовать:

Command(
    "file.out",
    "file.in",
    action=[
        Delete("tempdir"),
        Mkdir("tempdir"),
        Copy("tempdir/${SOURCE.file}", "$SOURCE"),
        "process tempdir",
        Move("$TARGET", "tempdir/output_file"),
        Delete("tempdir"),
    ],
)

Результат выполнения:

% scons -Q
Delete("tempdir")
Mkdir("tempdir")
Copy("tempdir/file.in", "file.in")
process tempdir
Move("file.out", "tempdir/output_file")
scons: *** [file.out] tempdir/output_file: No such file or directory

Модификация прав доступа на файл или директорию: фактория Chmod. Для изменения атрибутов доступа к файлу или директории используйте факторию Chmod. Аргумент permission использует биты разрешений доступа POSIX-стиля, что должно быть выражено в восьмеричном виде, а не в десятичном:

Command(
    "file.out",
    "file.in",
    action=[
        Copy("$TARGET", "$SOURCE"),
        Chmod("$TARGET", 0o755),
    ]
)

Результат выполнения:

% scons -Q
Copy("file.out", "file.in")
Chmod("file.out", 0755)

Немедленный запуск действия: функция Execute. Выше было показано, как использовать Action-фактории в функции Command. Также есть возможность запустить Action, возвращенный из фактории (или фактически любое Action) в момент чтения файла SConscript, используя функцию Execute. Например, если нам нужно гарантировать, что существует определенная директория перед выполнением любой сборки:

Execute(Mkdir('/tmp/my_temp_directory'))

Обратите внимание, что это создаст директорию в момент чтения файла SConscript:

% scons
scons: Reading SConscript files ...
Mkdir("/tmp/my_temp_directory")
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.

Если вы знакомы с языком Python, то можете удивиться, почему бы вместо этого не использовать обычную Python-функцию os.mkdir(). Преимущество в том, что действие Mkdir будет предприниматься подходящим образом в ответ на указание SCons-опций -n или -q - т. е. при указании -n будет выведено действие, но на самом деле никакая директория не будет создана, или при указании -q директория будет создана, нДа о информация о действии не будет выведена.

Функция Execute возвратит статус выхода, или возвращаемое значение из нижележащего выполняемого действия (action). Также будет напечатано сообщение об ошибке, если действие потерпело неудачу, и будет возвращено ненулевое значение. Однако SCons не остановит сборку, если действие потерпело неудачу. Если вы хотите остановить сборку в ответ на ошибку при выполнении действия, вызванного функцией Execute, то должны это сделать вручную путем проверки статуса возврата Execute и выполнения функции Exit в случае ошибки (или выполнения эквивалентной Python-функции выхода):

if Execute(Mkdir('/tmp/my_temp_directory')):
    # Проблема при создании временной директории.
    Exit(1)

[Управление удалением целей сборки]

Существует два случая, когда SCons будет по умолчанию удалять файлы целей (target files). Первый - когда SCons определяет, что target-файл должен быть заново собран, и удаляет существующую версию файла цели перед выполнение его сборки. Второй случай - когда SCons была запущена с опцией -c для осуществления очистки дерева проекта (clean) от его собранных целей сборки. Эти варианты поведения по умолчанию можно подавить соответственно вызовами функций Precious и NoClean.

Предотвращение удаления цели во время сборки: функция Precious. По умолчанию SCons удаляет target-ы перед их сборкой. Однако иногда это не то, что нужно. Например, вы можете захотеть обновить библиотеку инкрементально, а не её удаление и последующее перестроение из всех составляющих её объектных файлов. В таких случаях вы можете использовать метод Precious, чтобы предотвратить удаление target перед его сборкой:

env = Environment(RANLIBCOM='')
lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
env.Precious(lib)

Хотя выход не выглядит как-то по-другому, SCons фактически не удалит целевую библиотеку перед её пересборкой:

% scons -Q
cc -o f1.o -c f1.c
cc -o f2.o -c f2.c
cc -o f3.o -c f3.c
ar rc libfoo.a f1.o f2.o f3.o

Однако при указании опции -c файлы, помеченные как Precious, будут все-таки SCons удалены.

Предотвращение удаления цели во время очистки: функция NoClean. По умолчанию SCons удалит все собранные файлы целей (targets), когда при её запуске была указана опция -c (clean, очистка). Не всегда это нужно, например вы можете захотеть удалить только промежуточные сгенерированные файлы (такие как объектные файлы), но оставить при этом конечные цели (библиотеки). В таких случаях вы можете использовать метод NoClean, чтобы не дать SCons удалить нужную цель при очистке:

env = Environment(RANLIBCOM='')
lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
env.NoClean(lib)

Обратите внимание, что libfoo.a не перечислен в этом выводе как удаленный файл:

% scons -Q
cc -o f1.o -c f1.c
cc -o f2.o -c f2.c
cc -o f3.o -c f3.c
ar rc libfoo.a f1.o f2.o f3.o
% scons -c
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed f1.o
Removed f2.o
Removed f3.o
scons: done cleaning targets.

Удаление дополнительных файлов при очистке: функция Clean. Могут быть дополнительные файлы, которые вы захотите удалить при использовании опции -c, о которых SCons ничего не знает, потому что они не являются обычными файлами target. Например, при вызове команды создается файл лога как часть сборки target-файла. Нужно также очистить и этот файл журнала, но вы не хотиие "учить" SCons, что команда выполняет сборку двух файлов.

Вы можете использовать функцию Clean, чтобы организовать удаление дополнительных файлов при указании опции -c. Однако обратите внимание, что функция Clean принимает два аргумента, и второй аргумент это имя дополнительного файла, который вы хотите очистить (в этом примере foo.log):

t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE')
Clean(t, 'foo.log')

Первый аргумент это цель, которую вы хотели бы очистить вместе со связанным дополнительным файлом. В примере, показанном выше, мы использовали возвращаемое из функции Command значение, которое представляло цель foo.out. Теперь всякий раз, когда очищается цель foo.out при указании опции -c, также будет очищен и файл foo.log:

% scons -Q
build -o foo.out foo.in
% scons -Q -c
Removed foo.out
Removed foo.log

[Ссылки]

1. SCons: руководство пользователя, быстрый старт.
2. SCons: иерархические сборки.

 

Добавить комментарий


Защитный код
Обновить

Top of Page