SCons это современная система сборки ПО (набор скриптов на языке Python), предназначенная для перекомпиляции проекта, когда меняется один или несколько его исходных файлов. Благодаря тому, что конфигурационные скрипты системы это по сути те же самые модули Python, благодаря чему значительно упрощается управление системой.
Выглядит парадоксальным, что использование Python в качестве формата конфигурационного делает систему SCons проще для освоения в сравнении с другими системами сборки (например на основе Makefile или CMake). Одна из причин этого - последовательное описание и читаемость кода Python. Так получилось, что использование реального, живого скриптового языка в качестве основы конфигурационных файлов SCons позволяет почти мгновенно освоить работу с ней. Для опытных программистов становится проще модифицировать поведение системы и добавлять к сборке любой необходимый функционал.
Есть несколько принципов, которым команда разработчиков SCons пытается следовать в разработке.
Функциональная корректность. По умолчанию SCons гарантирует правильную сборку, даже если для этого приходится немного пожертвовать производительностью. Разработчики SCons стараются гарантировать корректность сборки независимо от того, как структурировано собираемое ПО, как оно могло быть написано и независимо от того, насколько необычные инструменты сборки используются.
Производительность. С учетом вышеупомянутого принципа корректности разработчики SCons стараются реализовать максимально высокую скорость работы. В частности те места, где нужно замедлить поведение по умолчанию SCons, чтобы обеспечить корректную сборку, делается попытка ускорить работу с помощью опций оптимизации.
Удобство в использовании. SCons "из коробки" пытается максимально освободить вас он ненужной работы и сделать все самой, включая обнаружение правильных инструментов сборки в системе и корректное их использования для сборки ПО.
Если кратко, то разработчики стараются разработать SCons так, чтобы она "все делала правильно" при сборке ПО и доставляла при этом минимум хлопот.
Примечание: это руководство (перевод документации [1]) предназначено для ознакомления с эффективными методами использования SCons, с примерами. Если вы только начинаете работу с SCons, то рекомендуется последовательно прочитать [1] до 10 главы, это даст твердую основу для понимания принципов устройства и работы SCons. Новички могут смело пропустить разделы, посвященные расширению функционала SCons, такие как написание собственной функции (Writing your own Decider Function). Не забывайте о наличии (на Linux) команды справки man scons.
[Установка SCons]
Установка Python. Перед тем, как попробовать установить Python, сначала надо проверить, установлен ли уже Python в вашей системе. Для этого в приглашении команд выполните python -V (заглавная 'V') или python --version. Для Linux/Unix/MacOS/BSD это может выглядеть так:
$ python -V
Python 3.7.1
Внимание для пользователей Windows: на этой системе Python может быть установлен разными способами, и описание их всех выходит за рамки этого руководства. у многих есть дополнительная программа Python launcher (см. [3]): попробуйте использовать команду py вместо команды python, и если она недоступна, то используйте python.
C:\>py -V
Python 3.7.1
Если Python не установлен, или путь до его запуска не прописан в текущей переменной PATH, то вы увидите сообщение об ошибке наподобие "command not found" (на UNIX или Linux) или "'python' is not recognized as an internal or external command, operable program or batch file" (на Windows cmd). В таком случае перед установкой SCons нужно либо установить Python, либо исправить пути поиска запускаемых программ.
Для Linux-систем Python в основном доступен как поддерживаемый пакет, и по умолчанию он уже может быть установлен в системе. Причем стандартные способы установки предпочтительнее и проще, чем установка из исходного кода. На многих системах есть отдельные пакеты для Python 2 и Python 3 - убедитесь, что установлен пакет Python 3, поскольку именно его требует последняя версия SCons. Сборка из исходников все еще остается полезной опцией для установки, если вам нужна версия, которая не предоставляется для используемого вами дистрибутива.
SCons будет работать с Python 3.5 или более свежей версии (примечание переводчика: у меня scons 4 версии под Ubuntu работала на версии Python 2.7.18, когда компилировал проект на RT-Thread [2], правда некоторый код скриптов *.py пришлось поправить). Если нужно установить Python и есть при этом выбор, то рекомендуется установить Python самой свежей доступной версии. У новых версий Python есть значительные улучшения, помогающие ускорить работу SCons.
Если для вашей системы недоступен готовый, предварительно собранный пакет SCons, и установка через команду pip невозможна, то все еще можно установить SCons, используя традиционный Python-пакет setuptools.
Сначала загрузите либо архив scons-4.4.0.tar.gz, либо scons-4.4.0.zip, которые можно найти на страничке загрузки https://scons.org/pages/download.html. Распакуйте загруженный архив, используя на Linux/UNIX утилиту наподобие tar, или WinZip на Windows. Распаковка создаст папку scons-4.4.0, обычно в вашей локальной директории. После этого поменяйте свою рабочую директорию на эту папку, и установите SCons выполнением следующих команд:
# cd scons-4.4.0
# python setup.py install
Эти действия выполнят сборку SCons, установят скрипт scons в каталог python, который используется для запуска скриптов setup.py (/usr/local/bin или C:\Python37\Scripts), и установит систему сборки SCons в соответствующую директорию библиотек для использования python (/usr/local/lib/scons или C:\Python37\scons). Из-за того, что это системные директории, для установки такого типа понадобятся права root/sudo (на Linux или UNIX) или администратора (на Windows).
Сборка и установка нескольких версий SCons. У скрипта SCons setup.py есть некоторые расширения, которые поддерживают простую установку нескольких версий SCons на одной системе. Это упрощает, к примеру, экспериментирование с разными версиями SCons перед переводом налаженного процесса сборки на новую версию.
Для установки SCons в специальное место, выделенное для определенной версии, добавьте опцию --version-lib, когда вызываете setup.py:
# python setup.py install --version-lib
Эта команда, например, установит систему сборки SCons в папку /usr/lib/scons-4.4.0 или C:\Python27\scons-4.4.0.
Если вы используете опцию --version-lib для первой установки SCons, то вам не нужно указывать её каждый раз для установки новой версии. Скрипт SCons setup.py определит имя директории, специфическое для версии, и поймет, что нужно устанавливать каждую версию в отдельную папку, в имени которой будет указана версия. Вы можете отменить такое поведение в будущем, специально указав для этого опцию --standalone-lib.
Установка SCons в другое место. Можно установить SCons в места, отличающиеся от каталога установки по умолчанию, путем указания опции --prefix=:
# python setup.py install --prefix=/opt/scons
Это установит скрипт scons в /opt/scons/bin и систему сборки в /opt/scons/lib/scons.
Обратите внимание, что можно одновременно указать опции --prefix= и --version-lib, в таком случае setup.py установит систему сборки в директорию, специфичную для версии, относительно указанного префикса. Если добавить --version-lib к вышеуказанному примеру, то система сборки будет установлена в папку /opt/scons/lib/scons-4.4.0.
Сборка и установка без прав админа. Если у вас нет административных привилегий, чтобы установить SCons в системный каталог, то просто используйте опцию --prefix= для установки в любое выбранное место. Например, установите SCons в подходящее место относительно директории $HOME. Например, для установки скрипта scons в $HOME/bin и системы сборки в $HOME/lib/scons, просто введите команду:
$ python setup.py install --prefix=$HOME
Конечно, вы можете указать любое другое место для установки, и даже можете использовать опцию --version-lib, если хотите именовать папки для установки в соответствии с версиями SCons, относительно указанного префикса.
Это также можно использовать для экспериментов с более новыми версиями SCons, отличающимися от уже установленных в системных каталогах. Разумеется место, куда вы устанавливаете новые версии скрипта scons ($HOME/bin в примере выше) должны быть сконфигурированы в переменную PATH перед директорией, куда установлена "системная" версия скрипта scons.
[Быстрый старт]
Здесь мы рассмотрим несколько простых конфигураций SCons, которые вы сразу сможете попробовать для сборки программы на разных языках и на разных системах.
Простая программа C/C++. Простейший, всем известный пример программы, которая выводит "Hello, World!", на языке C:
// Модуль hello.c
#include < stdio.h>
intmain()
{
printf("Hello, world!\n");
}
Давайте посмотрим, как собрать этот код с использованием SCons. Сохраните код в файл hello.c, и создайте файл SConstruct со следующим содержимым:
Program('hello.c')
Это минимальный конфигурационный файл, который дает SCons следующую информацию: вы хотите выполнить сборку (создать исполняемый код программы), и указывается входной файл для этой сборки (файл hello.c). Здесь оператор Program это метод сборщика, вызов Python, который говорит для SCons, что вы хотите собрать исполняемую программу.
И на этом все. Выполните в текущем каталоге команду scons для сборки программы. На POSIX-совместимой системе наподобие Linux или UNIX вы увидите что-то подобное:
% scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
cc -o hello hello.o
scons: done building targets.
На системе Windows с установленным компилятором Microsoft Visual C++ можно увидеть следующее:
Все что нужно: только указать имя файла исходного кода, и SCons сама корректно вычислит для сборки имена объектных и выполняемых файлов на основе имени файла исходного кода.
Кроме того, один и тот же файл SConstruct, без каких-либо изменений, на разных системах будет генерировать разные имена файлов: hello.o и hello на системах POSIX, hello.obj и hello.exe на системах Windows.
Сборка объектных файлов. Метод Program сборщика этот только один из методов, который SCons предоставляет для сборки различных типов файлов. Другой метод сборщика это Object, который говорит SCons выполнить сборку объектного файла из указанного файла исходного кода (этот текст надо поместить в файл SConstruct):
Object('hello.c')
Если теперь запустить команду scons для сборки программы, то на POSIX-системе это создаст только объектный файл hello.o:
% scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -o hello.o -c hello.c
scons: done building targets.
И на системе Windows будет создан только объектный файл hello.obj (при использовании компилятора Microsoft Visual C++):
SCons также делает Java-сборку экстремально простой. В отличие от методов Program и Object, метод Java требует указать имя каталога назначения, куда вы хотите поместить файлы класса, за которым указывается папка исходного кода, где находятся .java-файлы:
Java('classes', 'src')
Если в папке src содержится один файл hello.java, то на POSIX-системе команда будет выглядеть примерно так:
Более подробно сборки Java, включая сборку Java-архива (.jar) и других типов файлов описываются далее в главе "Сборки Java" [1].
Очистка после сборки. При использовании SCons необязательно добавлять в конфигурацию специальные команды или target-имена, чтобы выполнить очистку (clean) после сборки. Вместо этого просто используйте опцию -c или --clean, когда запускаете SCons, и SCons удалит соответствующие файлы результатов сборки. Если мы выполним scons -c после сборки описанных выше примеров, то на системах POSIX вывод будет примерно такой:
Файл SConstruct. Если вы сталкивались с системами наподобие Make, то уже поняли, что файл SConstruct является в системе scons эквивалентом Makefile. Т. е. файл SConstruct это входной файл управления сборкой.
Файлы SConstruct это скрипты на языке Python, это основное отличие файла SConstruct и Makefile. Не стоит беспокоиться, если вы не особенно знакомы с языком Python. Это руководство даст пошаговое описание того относительно малого необходимого объема языка Python, который нужен для эффективного использования SCons.
В код Python можно добавлять комментарии, поэтому в файл SConstruct можно добавлять произвольный текст, используя систему комментариев Python. Комментарий обозначается символом '#', и все что находится в строке после этого символа, будет игнорировано:
# Пример для сборки программы "hello".
Program('hello.c') # Здесь "hello.c" это модуль исходного кода.
Еще одна важная особенность скрипта SConstruct заключается в том, что это не совсем обычный скрипт Python. Функции в SConstruct могут быть неупорядоченными, что делает SConstruct похожим на Makefile. Порядок, в котором функции SCons вызываются в файле SConstruct, не влияет на порядок, в котором SCons фактически выполняет сборку программы и объектных файлов. Другими словами, когда вы вызываете метод сборщика Program (или любой другой метод сборщика), вы не говорите в этот момент SCons выполнять сборку программы. Вместо этого, вы говорите SCons, чего вы хотите достичь, и именно SCons должна выяснить, как это сделать, и предпринять эти шаги, если/когда это необходимо. Подробнее о том, как SCons решает, когда необходимо построить или перестроить target, мы узнаем в главе 6 "Dependencies" [1].
SCons отражает это различие между вызовом метода сборки наподобие Program и реальной сборкой программы путем вывода сообщений статуса, которые показывают, что сначала происходит "только чтение" файла SConstruct, и только после этого выполняется сборка файлов target. Это дает понимание, когда SCons выполняет операторы Python, составляющие файл SConstruct, и когда SCons реально выполняет команды или другие действия для сборки необходимых файлов.
Объясним это на примере. На Python есть функция print, которая печатает строку символов. Если мы вставим вызовы print вокруг метода Program:
.. то когда запустим SCons, мы увидим сообщения операторов print между моментами чтения операторов Program, и это покажет, когда выполняются операторы Python:
% scons
scons: Reading SConscript files ...
Calling Program('hello.c')
Calling Program('goodbye.c')
Finished calling Program()
scons: done reading SConscript files.
scons: Building targets ...
cc -o goodbye.o -c goodbye.c
cc -o goodbye goodbye.o
cc -o hello.o -c hello.c
cc -o hello hello.o
scons: done building targets.
Обратите внимание, что сначала SCons соберет программу goodbye несмотря на то, что вывод чтения SConscript показывает, что вызов Program('hello.c') был первым.
Также обратите внимание, что SCons может получить некоторую информацию из двух вызовов Program. Из-за того, что SCons выяснила, что hello.c и goodbye.c являются исходным кодом на языке C, то она знает, что надо сначала сгенерировать промежуточные target-файлы hello.o и goodbye.o, и затем конечные файлы hello и goodbye. Не нужно было дополнительно программировать scons кроме простого вызова Program.
Как сделать вывод SCons более кратким. Как мы уже видели, SCons печатает сообщения о том, что делает при сборке ПО:
Эти сообщения подчеркивают порядок, в котором SCons выполняет свою работу: сначала читаются и выполняются конфигурационные файлы (в основном обозначаемые как файлы SConscript), и только после этого выполняется сборка файлов target. Такое поведение также дает возможность понять, на каком этапе произошла ошибка - на шаге чтения конфигурационных файлов, либо в процессе компиляции и преобразования target-файлов.
Недостаток конечно, состоит в том, что подробный вывод загромождает консоль. Существует опция -Q, которая помогает упростить вывод сообщений SCons:
Эта опция позволяет точнее сосредоточиться на том, что реально делает SCons, что особенно полезно при компиляции больших проектов, состоящих из множества модулей.