Тема этой заметки будет следующая, — за что
я уважаю Unix. А уважаю я его за: bash, sed, grep, find. Казалось бы,
суть не в этом и профессионалы будут с пеной у рта доказывать, что сила, она,
брат, в концептуальном устройстве Unix, но нам бы что
попроще, на пальцах. Поэтому о самом главном как-нибудь потом, а пока
пройдемся по верхам.
Есть такая вещь, которая называется Cygwin.
Это — качественный порт под Win32 многих Unix’овых утилит. При этом
достигается великолепная совместимость. То есть скрипты, написанные и
отлаженные под Windows, с большой вероятностью будут работать под Unix и
наоборот. Альтернативы Cygwin’у на данный момент практически нет,
единственным соперником мог бы быть MKS Toolkit, но он продается за
деньги, а нас такой вариант не устраивает. Идем качать и устанавливать
Cygwin. (Тут вот проскочило некое подобие -
GnuWin32. Фанаты могут
посмотреть, мне — лень. 11.01.2004)
Стоп, а зачем он мне нужен?
Зачем он может пригодиться вам, я не знаю. Я могу только рассказать, зачем
он нужен мне:
- Во-первых, так уж сложилось, что я пишу программы, которые будут
использоваться, как на Windows, так и на unix-платформах. При этом
приходится создавать служебные скрипты, которые, например, производят
компиляцию всего проекта. Так вот с использованием Cygwin я могу написать
скрипты, которые одинаково запускаются и работают под обеими платформами
(Win/Solaris), мне не приходится делать отдельно bat и отдельно
shell-скрипты. Это сильно экономит время в момент написания
и, особенно, в момент модификации скриптов. Попробуйте параллельно править
обе версии, в которых различий больше чем сходства. - Во-вторых, я могу использовать gnumake. А это один из лучших
make-ов, которые есть на данный момент. Кстати makefile будет одним и тем
же для обеих платформ. - В-третьих, мощи CMD.EXE, который входит в Windows NT, не хватает
для написание серьезного скрипта. Есть, конечно, 4DOS
и 4NT, но это все равно не то. Одни регулярные выражения чего стоят
(тут автор мечтательно закатывает глаза и медитирует 5 минут). - В-четвертых. Вам никогда не приходилось скачивать из интернета
исходные тексты программ? Ага… Быть может и расширения вроде .tar.gz
для вас не пустой звук? Тем, кто по молодости да по неопытности с этим
никогда не сталкивался, поясню, — есть такая традиция у «юниксоидов» делать
архивы с помощью двух программ — tar и gzip. Первая соединяет все нужные
файлы в один, а вторая их сжимает. Степень сжатия при этом выше, чем, если
сжимать все файлы по отдельности. Очень похожим образом, кстати, работает
WinRar с его solid-сжатием. И все бы
было хорошо, если бы не было так плохо в Windows с tar’ом и gzip’ом. А в
Cygwin’е есть и tar и gzip. Все работает, все счастливы. Качайте исходники
мегабайтами, учитесь. - В-пятых, в-шестых, …
Э-э-э, ты мне пример реального использования покажи…
Хотите примеры? Пожалуйста. Последний пример из реальной жизни.
Писал я плагин для Far’а. Причем
писал на Visual C++. При этом нужно было получить список экспортируемых
плагином функций. То есть из:
UpAndDown.cpp
void WINAPI _export SetStartupInfo(struct PluginStartupInfo *psi){
...
}
void WINAPI _export GetPluginInfo(struct PluginInfo *pi){
...
}
HANDLE WINAPI _export OpenPlugin(int OpenFrom,int item){
...
}
нужно получить:
UpAndDown.def
EXPORTS
; Список функций
SetStartupInfo
GetPluginInfo
OpenPlugin
Это что ж получается — добавлю я еще одну экспортируемую функцию и мне
надо не забыть еще и def-файл параллельно править? Дудки. Смотрю на свои
исходники, — все экспортируемые функции выглядят очень и очень похоже, как
бы их имена выдрать из исходников?
Решение программиста:
Кусок из makefile
$(DEF): $(OBJS)
echo EXPORTS > $(DEF)
echo ; This file was created by makefile >> $(DEF)
cat *.cpp | grep _export | sed "s/.* \(.*\)(.*/ \1/" >> $(DEF)
Как это работает. Программа cat «передает по цепочке» текст всех
файлов с расширением cpp программе grep. Та оставляет только строки, в
которых присутствует ключевое слово _export и эти строки отдает sed’у:
void WINAPI _export SetStartupInfo(struct PluginStartupInfo *psi){
void WINAPI _export GetPluginInfo(struct PluginInfo *pi){
HANDLE WINAPI _export OpenPlugin(int OpenFrom,int item){
Дальше — сложнее, дальше регулярные выражения. Я минут 10 пытался
описать это простенькое в сущности регулярное выражение, но потом понял,
что тем, кто с ними еще не знаком, мне не удастся в двух словах изложить
материал. Поверьте на слово, что эта последовательность «скобочек и
палочек» берет со стандартного входа строку и заменяет ее словом,
«которое идет после пробела и за которым стоит открывающая круглая
скобка», то есть на выходе конвейера мы получаем только имена
экспортируемых функций из всех файлов, текущего каталога, что и
требовалось! Они перенаправляются в def-файл, а я про него могу забыть и
не вспоминать, он сам создается, сам модифицируется при необходимости.
Резюме
Лень — двигатель прогресса. Скачав и установив себе Cygwin, вы сможете
написать скрипт do_all, который будет делать за вас все, причем сразу и на
Solaris’е и Windows. Вам остается только курить и мечтательно плевать в
потолок. Кстати, хорошая идея…