Cygwin - это аббревиатура от 'Cygnus', группы
разработчиков свободного ПО в рамках
проекта 'RedHat' и 'Windows', всеми нами любимой
операционной системы. Спешу развеять очень
популярную точку зрения, будто бы cygwin - это
эмулятор UNIX под Windows: это не так! Cygwin - это
лишь мощный, очень развитый и, самое главное,
бесплатный набор программных средств
переноса (портирования) UNIX'ового ПО под Windows
и кросс-компиляции (создания бинарного кода
на одной платформе под другую) UNIX'овго софта.
Лично для меня, cygwin, прежде всего, это
мощнейший компилятор gcc с отшлифованными
под Windows хидерами и либами.
Cygwin нынче становится весьма популярным:
многие производители свободного ПО под UNIX
поддерживать '--target=cygwin' в конфигах своих
программ, благо, это не столь трудоёмко. А
cygwin, в свою очередь, расширяет
совместимость с UNIX, поддерживая не только
posix, но и другие, более узкоспецифичные
стандарты UNIX-систем.
Cygwin: где смотреть?
http://www.cygwin.com -
официальная страница cygwin'а, на которой Вы
сможете найти достаточное количество
информации о текущем состоянии проекта, об
обновлениях cygwin'овских релизов, а также
официальный список ftp-серверов, периодично
зеркалящих cygwin.
Cygwin: что и как устанавливать?
На Хакере уже несколько раз писали про
установку и использование Cygwin, поэтому
рекомендую вам обратится к тем статьям:
CYGWIN
- *nix в ваших Виндах
Особенности
настройки Cygwin
gcc: какой он?
Точно такой же, как и в UNIX. Сочный, мощный,
безглючный. Однако, не такой быстрый. Дело в
том, что запуск препроцессора, компилятора,
ассемблера и линковщика требует
определённого времени на загрузку и
пролинковку в памяти библиотеки cygwin1.dll,
требумую каждым из этих компонентов gcc.
Отмечу, что в Windows 2000 это требует на порядок
меньше времени, чем в Windows 98. Скорость
компиляции в Windows 2000 очень близка к скорости
компиляции в UNIX. Но сок остаётся соком:
генерируемый бинарный код cygwin'ным gcc
остаётся вне конкуренции по компактности и
эффективности!
Если Вы когда-либо писали или компилировали
программы под UNIX, Вы не будете испытывать
никаких трудностей в работе с cygwin. Только
помните, что cygwin'ный gcc может не
поддерживать некоторые опции, которыми Вы
пользуетесь в UNIX'е, хотя количество таких
недоразумений сведено к минимуму. На моём
веку, например, таких проблем не возникало.
В любом случае, если возникают какие-то
проблемы, все мы дружно знаем лучший способ
их решения: 'man gcc'! :)))
Если же Вам не доводилось прежде заниматься
программированием под UNIX и Вы привыкли жать
<F9> для того, чтобы скомпилировать Вашу
программу, расстраиваться не стоит.
Попробуйте 'man gcc' в bash'е cygwin'а: вполне
достойное и увлекательное чтиво.
Таки начнём?
Оригинальничать я не буду, поэтому начнём
мы, как всегда и везде, с вывода 'hello world!' на
консоль. Итак, hello.c:
#include <stdio.h>
int main () {
printf("Hello World!\n");
return 0;
}
Компилируем:
gcc -s hello.c -o hello.exe
и смотрим на бинарник. 3072 байта бинарного
кода, формат PE, portable executable, загружаемые dll:
cygwin1.dll, откуда hello.exe берёт нашу printf() и другие
функции, которые накомпилировал нам gcc;
kernel32.dll, откуда hello.exe берёт GetModuleHandleA.
Хидер <stdio.h> gcc берёт из /usr/include, который
является дефолтной инклудной директорией и
в UNIX, и в cygwin'е.
В cygwin'ном gcc есть одна очень приятная опция,
которая, почему-то, не задокументирована в
man-файле, '-mno-cygwin'. Скомпилируем нашу
программу с этой опцией:
gcc -mno-cygwin -s hello.c -o hello.exe
и смотрим на бинарник: опять, 3072 байта
бинарного кода, но наша программа больше не
нуждается в cygwin1.dll! вместо этого она
использует msvcrt.dll, где и находит нужную нам
функцию printf.
Если мы юзаем опцию '-mno-cygwin', cygwin кидает gcc'шный
препроцессор в директорию /usr/include/mingw, и,
соответственно, gcc компилирует <stdio.h>
именно из этой директории.
Настоятельно рекомендую совершить
прогулку по содержимому директории /usr/include
для того, чтобы понять, что к чему. Думаю, Вас
особо порадует содержимое директорий /usr/include/sys
и /usr/include/w32api.
Таким образом, cygwin находит компромисс между
двумя противоречащими друг с другом
платформами, UNIX и Windows и даёт нам уникальный
шанс изучать программирование под UNIX, не
покидая Windows. Далее следует пример
простенькой программки, компилирующейся и
под posix'овые BSD Sockets, и под WinSock2. Программка
открывает указанный в командной строчке
порт и ожидает tcp-соединение с любого IP-адреса,
принимает от клиента литеру и возвращает
клиенту эту же литеру, увеличенную на
единицу. Вы можете скомпилировать эту
программку, запустить её ('easy.exe 500'),
приконнектиться к ней телнетом ('telnet 127.0.0.1
500') и ввести любой символ.
---[ Makefile (для неюниксоидов, Makefile с
заглавной буквы 'M'):
# tiny makefile for a tiny program
all:
@echo Pick 'make posix' for UNIX/cygwin or 'make windows' for Windows
posix:
@printf "Building easy.c for posix..."
@printf "#define ENV_POSIX" > plateform.h
@gcc -s easy.c -o easy.exe
@echo ok!
windows:
@printf "Building easy.c for windows..."
@printf "#define ENV_WINDOWS" > plateform.h
@gcc -mno-cygwin -s easy.c -lws2_32 -o easy.exe
@echo ok!
---[ easy.c:
#include "plateform.h"
#include <stdio.h>
#ifdef ENV_POSIX
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> // для INADDR_ANY
#include <signal.h> // для signal()
#else
#include <winsock2.h>
#endif
int main (int argc, char **argv) {
struct sockaddr_in dst;
#ifdef ENV_POSIX
int sock, sid;
#else
SOCKET sock, sid;
WSADATA wsaData;
#endif
int len = sizeof(struct sockaddr);
char buf;
unsigned short port;
// entry point
if(argc<2) {
printf("Usage: easy.exe <tcp-port>\n");
return 1;
}
port = atoi(argv[1]);
if(!port) {
printf("Bad <tcp-port> defined!\n");
return 2;
}
#ifdef ENV_POSIX // в позиксе мы игнорируем сигналы, мало ли :)
signal(SIGPIPE, SIG_IGN);
#else ENV_WINDOWS // в Windows мы проверяем версию винсока, мало ли :)
printf("Testing if the WinSock2 version is equal or higher than 2.1...");
if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) {
printf("failed!\n");
return 1;
}
printf("ok!\n");
fflush(stdout);
#endif
dst.sin_family = AF_INET;
dst.sin_addr.s_addr = htonl(INADDR_ANY);
dst.sin_port = htons(port);
sock = socket(AF_INET,SOCK_STREAM,0);
printf("Waiting for an incoming connection..."); fflush(stdout);
bind(sock,(struct sockaddr*)&dst,len);
listen(sock,1);
sid = accept(sock,(struct sockaddr*)&dst,&len);
printf("done!\nWaiting for incoming data..."); fflush(stdout);
recv(sid,&buf,1,0);
printf("received: [%2X]..."); fflush(stdout);
buf++;
send(sid,&buf,1,0);
printf("done!\n");
#ifdef ENV_POSIX
close(sock);
#else
WSACleanup();
closesocket(sock);
#endif
return 0;
}
Итак, мы набираем 'make posix' для того, чтобы
собрать программу под UNIX'ом или под cygwin'ную
среду или 'make windows' для того, чтобы не
зависеть от cygwin'а и использовать лишь
kernel32.dll, ws2_32.dll и msvcrt.dll, которые входят в
стандартную поставку каждого дистрибутива
Windows. Обратите внимание на размер бинарника:
4096 байт для cygwin, 4608 байт для windows! :)
|