Като разработчик на PostgreSQL, понякога трябва да накарам кода си да работи в Windows. Тъй като обикновено не използвам Windows и нямам постоянна инсталация на Windows, това винаги е било малко тромаво. Разработих няколко техники, за да улесня това и смятам, че си струва да ги споделя. И всъщност този текст стана доста дълъг, така че това ще бъде поредица от няколко публикации в блога.
Първото нещо, което е полезно да разберете, е различните варианти на целите за компилиране на Windows и как те са сходни и различни.
Вероятно основният начин за изграждане за Windows е използването на Microsoft Visual Studio компилаторски пакет. Това е, което бихте могли да си представите като най-родната среда. Повечето, ако не всички двоични дистрибуции на PostgreSQL за Windows използват тази сборка. Тази компилация не използва нормалните Unix make файлове, а отделна система за компилиране под src/tools/msvc/
. Това анализира make-файловете и има някаква персонализирана логика и изгражда „проектни“ файлове, специфични за тази верига от инструменти, които след това можете да стартирате, за да изградите кода. Нека наречем това MSVC изграждане тук. Тази компилация е склонна да се счупи по два начина:един, ако кодът всъщност не се изгражда или изпълнява в Windows, и два, ако промените нещо в нормалната (базирана на makefiles) система за компилиране, което кара тези ad-hoc скриптове да прекъсване. Така че това винаги е много забавно да се справяте.
Вторият начин е да използвате MinGW . Това използва веригата от инструменти на GNU (GCC, GNU binutils, GNU ld и т.н.) за изграждане на собствен код на Windows. Можете да го мислите като „GCC на Windows“, но в действителност той съдържа допълнителна подложка и лепило за взаимодействие със системните библиотеки на Windows. Това използва нормалната система за изграждане на Unix, използвайки configure и makefiles, но кодът, който произвежда, е естествен код на Windows, по принцип еквивалентен на изхода на MSVC build. Това също означава, че ако кодът не се изгражда или изпълнява с MSVC изграждането, той също няма да се изгражда или изпълнява тук. Но системата за компилиране е същата като за Linux и т.н., така че ще бъде по-трудно да се счупи случайно.
Третият начин е Cygwin . Cygwin е подсистема, която представя POSIX-подобна среда в Windows. Например Cygwin добавя потребители, групи, fork()
, споделена памет SysV и други съоръжения, които не съществуват в родния Windows, но са стандартни за, да речем, Linux. Идеята е, че можете да вземете изходния код, предназначен за Linux или BSD, и да го изградите под Cygwin без промяна (или поне само с промени, които биха били в рамките на типичния диапазон на промени в пренасянето между Unix-подобни системи). Поради тази причина Cygwin порт на PostgreSQL е съществувал много преди родния порт на Windows, тъй като това е било много по-малко усилие. На практика абстракцията се разпада в някои области, особено в мрежовия код и около именуването и достъпа на файлове, но като цяло сборката на Cygwin се прекъсва много рядко в сравнение с другите цели.
Имаше друг начин за изграждане на Windows. Имаше win32.mak
файлове, които можете да използвате директно с nmake в Windows, а в някакъв момент имаше и поддръжка за компилатори на Borland. Това бяха основно мерки за спиране за изграждане само на libpq на Windows, преди да пристигне пълният роден порт. Те вече са премахнати.
Има още един термин, който се появява в този контекст:MSYS . Причината за това е, че MinGW сам по себе си не е често полезен. Това е просто верига от инструменти за компилатор. Но за да създадете типичен Unix софтуер, имате нужда от допълнителни инструменти като bash, make, sed, grep и всички онези неща, които обикновено се използват от скрипт за конфигуриране или make-файл. Не всички тези инструменти съществуват като собствени Windows портове. Но можете да ги стартирате върху подсистемата Cygwin. Така че един от начините да използвате MinGW е отвътре в Cygwin. Друг е MSYS, което означава „минимална система“, което грубо казано е специално изработено подмножество на Cygwin и някои опаковки специално за използване на MinGW за изграждане на софтуер. Оригиналният MSYS сега е изоставен, доколкото знам, но има популярна нова алтернатива MSYS2. Повече за това в следваща публикация в блога. Засега просто разберете връзката между всички тези различни софтуерни пакети.
Сега нека разгледаме как изходният код вижда тези различни среди за компилиране.
Вградена компилация, използваща MSVC или MinGW, дефинира _WIN32
. (Странно, това е така както за 32-битови, така и за 64-битови компилации. 64-битовата компилация също така дефинира _WIN64
, но това се използва рядко.) Изходният код на PostgreSQL използва WIN32
вместо това, но това е специфично за PostgreSQL, а не е направено от компилатора.
MSVC също така дефинира _MSC_VER
към някакъв номер на версията. Това понякога е полезно за заобикаляне на проблеми с конкретна версия на компилатора (често нещата, за които Unix изгражда, биха използвали configure). Имайте предвид, че MinGW не дефинира _MSC_VER
, така че кодът трябва да бъде написан внимателно, за да се справи и с това. Имаше някои малки грешки около това, защото код като #if _MSC_VER < NNNN
може би заобикалянето на проблем с по-стар компилатор ще се задейства и на MinGW, което може да не е било предвидено. (По-правилно би било #if defined(_MSC_VER) && _MSC_VER < NNNN
и разбира се обвийте в #ifdef WIN32
.) MinGW дефинира __MINGW32__
и __MINGW64__
, но те се използват много рядко. Също така, MinGW разбира се дефинира __GNUC__
тъй като е GCC, така че може да се използва и условен код, специфичен за GCC или версия на GCC. Като цяло, тъй като MinGW използва Autoconf, тези неща обикновено трябва да се проверяват в configure
вместо в кода.
Cygwin дефинира __CYGWIN__
. Трябва да се отбележи, че Cygwin не дефинира _WIN32
или WIN32
, и така нататък — защото не се счита за собствен Windows. Ето защо в някои области на кода, където Windows надниква през абстракцията на Cygwin, виждате много код с #if defined(WIN32) ||
да се справя и с двата случая.
defined(__CYGWIN__)
(Има някои прашни ъгли в кода, които не винаги се справят с всички тези дефини на препроцесора по разумен и последователен начин. В някои случаи това е умишлено, защото реалността е странна, в други случаи е гнил и неправилен код, който трябва да бъде почистено.)
Всяка от тези цели съществува по принцип като 32-битов и 64-битов вариант. Инсталацията на 64-битова операционна система Windows, която е нормална съвременна инсталация, може да изпълнява както 32-битов, така и 64-битов софтуер, така че можете да инсталирате и стартирате и двата варианта на такава система. Производствената инсталация вероятно трябва да използва 64-битова компилация и затова може да изберете да не се занимавате с 32-битовата среда. Всъщност 32-битовият вариант на Cygwin изглежда е доста мъртъв и може изобщо да не успеете да го накарате да работи. Един проблем обаче е, че 64-битовият MinGW има някои неясни грешки, така че когато използвате MinGW, особено понякога е по-добре да използвате 32-битовата среда, освен ако не искате да се борите с грешки в операционната система или веригата от инструменти. Въпреки това 32-битовите изчисления очевидно са предимно на изход като цяло, така че това не е надеждна опция.
Сега въпросът е може би коя от тези среди е „най-добрата“. Що се отнася до разработката, това всъщност няма значение, защото целият код трябва да работи върху всички тях. Както споменах по-горе, MSVC build се използва за повечето производствени внедрявания на Windows. Средата MinGW (или по-скоро MSYS2) е по-приятна за разработване, ако сте свикнали с Unix-подобна среда, но особено 64-битовата среда MinGW изглежда донякъде бъгава, така че е трудно да се препоръча това за производство. Cygwin може да се счита от някои за историческо любопитство в този момент. Стартирането на производствен сървър под Cygwin не се препоръчва, тъй като производителността е доста лоша. Но Cygwin всъщност е полезен в някои ситуации. Например, Readline не работи на нито една от родните компилации на Windows, но работи на Cygwin, така че ако сте потребител на psql, по-добре е да използвате версия на Cygwin за това. Също така, Cygwin е полезен в ситуация, която е обратна на тази публикация в блога:Вие сте предимно разработчик на Windows и искате да сте сигурни, че кодът ви е предимно съвместим с Unix. Така че и трите от тези среди имат своята стойност и си струва да бъдат поддържани в момента.
В следващата част от тази поредица ще обсъдя някои техники за тестване на промените в кода на и за Windows, ако това не е основната ви среда за разработка.