Чтение онлайн

ЖАНРЫ

Программирование на языке Ruby
Шрифт:

Неудивительно, что на вход Rake подается командный файл (rake-файл), который по умолчанию называется

rakefile
или
Rakefile
. Если вы хотите назвать его иначе, укажите имя с помощью флага
– f
или
– -rakefile
:

$ rake # Искать сначала 'rakefile', потом 'Rakefile'.

$ rake -f myfile # Использовать файл с именем 'myfile'.

Основная «единица работы» в Rake — задание; именуются задания посредством символов Ruby. Предполагается, что в каждом rake-файле есть задание по умолчанию

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

$ rake # Выполнить задание по умолчанию.

$ rake mytask # Выполнить задание с именем 'mytask'.

Внутри rake-файла мы указываем задания с помощью метода

task
, передавая символ и блок:

task :mytask do

 # ...

end

Содержимое блока в примере выше опущено. То, что в нем находится, называется действием.

В действии можно выполнять произвольный код на Ruby. Для типичных операций предусмотрены готовые методы. Так, метод

sh
(название которого напоминает об интерпретаторе команд в UNIX) запускает системную команду.

Методы

cp
,
mv
и
rm
предназначены соответственно для копирования, перемещения и удаления файлов. (Как и
make
, Rake беззастенчиво выдает свое происхождение от UNIX.) Есть и другие подобные команды; дополнительную информацию вы найдете в онлайновой документации на сайте http://docs.rubyrake.org.

При желании можете заключать блок в фигурные скобки, но обычно в этом случае интерпретатор Ruby ожидает, что параметры будут заключены в круглые скобки.

task(:mytask) { do_something }

Рассмотрим более конкретный пример. Предположим, что имеется программа

myprog.с
, написанная на С, и еще два связанных с ней исходных файла (каждый со своим заголовочным файлом). Иными словами, у нас есть пять исходных файлов:

myprog.с

sub1.с

sub1.h

sub2.с

sub2.h

Мы хотим собрать из них исполняемый файл

myprog
. Эта процедура состоит из нескольких шагов: откомпилировать все файлы с расширением
, а затем скомпоновать получившиеся в результате файлы с расширением
.

Начнем с метода

file
, который определяет зависимости файлов:

file "myprog.о" => ["myprog.с"]

file "sub1.о" => ["sub1.с", "sub1.h"]

file "sub2.o" => ["sub2.c", "sub2.h"]

file "myprog" => ["sub1.o", "sub2.o"]

Отметим, что метод

file
принимает хэш, который ассоциирует имя файла с массивом имен файлов, от которых он зависит.

Теперь перейдем к построению двоичных файлов. Расширим написанный выше код. Если после вызова метода

file
указать блок, то мы сможем ассоциировать с файлом набор действий, которые необходимо выполнить для создания этого файла:

file "myprog.о" => ["myprog.с"] do

 sh "сс -с -о myprog.о myprog.с"

end

file "sub1.o" => ["sub1.с", "sub1.h"] do

 sh "сс -с -o sub1.o sub1.c"

end

file "sub2.o" => ["sub2.c", "sub2.h"] do

 sh "сс -с -o sub2.o sub2.c"

end

file "myprog" => ["sub1.o", "sub2.o"] do

 sh "cc -o myprog myprog.о sub1.o sub2.o"

end

Здесь

имеется некоторое дублирование, но от него можно избавиться. В Rake есть специальный механизм, который называется
FileList
; он понимает метасимволы (шаблоны) и позволяет работать сразу с несколькими файлами. В данном случае поместим все файлы с расширением
.c
в список
SRC
. Константа типа
FileList
ведет себя как массив:

SRC = FileList["*.с"]

Теперь можно определить действия в цикле, как показано ниже. И обратите внимание, что зависимости здесь не упоминаются — Rake самостоятельно учтет эту информацию, если она была задана в другом месте.

SRC.each do |src|

 obj = src.sub(/.c$/,".о")

 file(obj) { sh "cc -с -o #{obj} #{src}" }

end

Однако проще пользоваться правилами. Это еще один механизм Rake, естественно, позаимствованный у

make
:

rule '.о' => '.с' do |target|

 sh "сс -с -о #{target.name} #{target.source}"

end

Тут мы наблюдаем небольшое волшебство. Rake устанавливает атрибут

source
, подставляя расширение имени файла из хэша (в данном случае
.o
заменяется на
.c
).

Продолжим сеанс магии. Если затребовать библиотеку

rake/clean
, то появляются константы
clean
и
clobber
(первоначально пустые) и задания
:clean
и
:clobber
. По сложившейся традиции
clean
удаляет временные файлы, a
clobber
— еще и собранный исполняемый файл.

Для этих напоминающих массив констант определен метод

include
, принимающий маску имени файлов; это неявное использование механизма
FileList
.

Теперь наш rake-файл принимает такой вид:

require 'rake/clean'

CLEAN.include("*.о")

CLOBBER.include("myprog")

SRC = FileList['*.с']

OBJ = SRC.ext('o')

rule '.o' => '.c' do |t|

 sh "cc -с -o #{t.name} #{t.source}"

end

file "hello" => OBJ do

 sh "cc -o hello #{OBJ}"

end

file "myprog.o" => ["myprog.c"]

file "sub1.o" => ["sub1.c", "sub1.h"]

file "sub2.o" => ["sub2.c", "sub2.h"]

task :default => ["myprog"]

Обратите внимание, что мы не задавали задания «clean» и «clobber» явно. Кроме того, отметим что «clobber» неявно включает операцию «clean». И наконец, мы определили задание

default
для удобства запуска rake-файла; теперь можно не указывать явно имя задания, осуществляющего компиляцию и сборку.

Поделиться с друзьями: