Cygwin

Тема этой заметки будет следующая, — за что
я уважаю 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. Вам остается только курить и мечтательно плевать в
потолок. Кстати, хорошая идея…

Комментирование закрыто.