Jako vývojář PostgreSQL občas potřebuji, aby můj kód fungoval ve Windows. Protože normálně nepoužívám Windows a nemám kolem sebe trvalou instalaci Windows, bylo to vždy trochu těžkopádné. Vyvinul jsem několik technik, jak to usnadnit, a myslím, že stojí za to se o ně podělit. A ve skutečnosti se tento text stal poměrně dlouhým, takže toto bude série několika blogových příspěvků.
První věc, kterou je užitečné pochopit, jsou různé varianty cílů sestavení systému Windows a jak jsou podobné a odlišné.
Pravděpodobně primárním způsobem sestavování pro Windows je použití Microsoft Visual Studio sada kompilátorů. To je to, co si můžete představit jako nejpřirozenější prostředí. Většina, pokud ne všechny binární distribuce PostgreSQL pro Windows používají toto sestavení. Toto sestavení nepoužívá normální unixové makefile, ale samostatný systém sestavení pod src/tools/msvc/
. To analyzuje soubory makefiles a má určitou vlastní logiku a vytváří soubory „projektu“ specifické pro tento řetězec nástrojů, které pak můžete spustit a vytvořit kód. Nazvěme to zde sestavení MSVC. Toto sestavení je náchylné k poškození dvěma způsoby:jedním, pokud se kód ve skutečnosti nesestaví nebo nespustí ve Windows, a druhým, pokud změníte něco v normálním (založeném na souborech) sestavení, což způsobí, že tyto ad-hoc skripty přestávka. Takže s tím je vždycky hodně legrace.
Druhým způsobem je použití MinGW . Toto používá GNU toolchain (GCC, GNU binutils, GNU ld atd.) k vytvoření nativního kódu ve Windows. Můžete si to představit jako „GCC on Windows“, ale ve skutečnosti obsahuje další podložku a lepidlo pro rozhraní se systémovými knihovnami Windows. Toto používá normální systém sestavení Unixu pomocí konfiguračních a makefiles, ale kód, který vytváří, je nativní kód Windows, v principu ekvivalentní výstupu sestavení MSVC. To také znamená, že pokud se kód nesestaví nebo nespustí se sestavením MSVC, nebude se zde stavět ani spouštět. Ale systém sestavení je stejný jako pro Linux atd., takže bude těžší jej náhodně rozbít.
Třetí způsob je Cygwin . Cygwin je subsystém, který ve Windows představuje prostředí podobné POSIXu. Například Cygwin přidává uživatele, skupiny, fork()
, sdílená paměť SysV a další zařízení, která v nativním systému Windows neexistují, ale jsou standardní například v Linuxu. Myšlenka je taková, že byste mohli vzít zdrojový kód určený pro Linux nebo BSD a sestavit jej pod Cygwinem beze změn (nebo alespoň pouze se změnami, které by byly v typickém rozsahu změn portování mezi systémy podobnými Unixu). Z tohoto důvodu existoval Cygwin port PostgreSQL dlouho před nativním portem Windows, protože to bylo mnohem menší úsilí. V praxi se abstrakce v některých oblastech rozpadá, zejména v síťovém kódu a kolem pojmenovávání souborů a přístupu k nim, ale obecně se sestavení Cygwin ve srovnání s ostatními cíli zlomí velmi zřídka.
Kdysi existoval jiný způsob, jak stavět na Windows. Byly tam win32.mak
soubory, které jste mohli používat přímo s nmake na Windows, a v určitém okamžiku existovala také podpora pro kompilátory Borland. V zásadě šlo o opatření pro zastavení nativního sestavení pouhé libpq na Windows, než dorazil úplný nativní port. Ty byly nyní odstraněny.
V této souvislosti se objevuje další termín:MSYS . Důvodem je to, že MinGW sám o sobě není často užitečný. Je to jen řetězec nástrojů kompilátoru. Ale abyste mohli vytvořit typický unixový software, potřebujete další nástroje, jako je bash, make, sed, grep a všechny ty věci, které se obvykle používají z konfiguračního skriptu nebo souboru makefile. Všechny tyto nástroje neexistují jako nativní porty Windows. Ale můžete je spustit nad subsystémem Cygwin. Takže jeden způsob, jak používat MinGW, je zevnitř Cygwin. Dalším je MSYS, což je zkratka pro „minimální systém“, což je zhruba řečeno zakázková podmnožina Cygwin a nějaké balení speciálně pro použití MinGW pro vytváření softwaru. Původní MSYS je nyní opuštěn, pokud vím, ale existuje populární nová alternativa MSYS2. Více o tom v následujícím příspěvku na blogu. Pro tuto chvíli stačí pochopit vztah mezi všemi těmito různými softwarovými balíčky.
Nyní se podívejme, jak zdrojový kód vidí tato různá prostředí sestavení.
Nativní sestavení pomocí MSVC nebo MinGW definuje _WIN32
. (Je to zvláštní případ pro 32bitové i 64bitové sestavení. 64bitové sestavení také definuje _WIN64
, ale to se používá zřídka.) Zdrojový kód PostgreSQL používá WIN32
místo toho, ale to je specifické pro PostgreSQL, neprovádí to kompilátor.
MSVC také definuje _MSC_VER
na nějaké číslo verze. To je někdy užitečné k vyřešení problémů s konkrétní verzí kompilátoru (často ten druh věcí, pro které by sestavy Unixu měly tendenci používat konfiguraci). Všimněte si, že MinGW nedefinuje _MSC_VER
, takže kód musí být napsán pečlivě, aby to také zvládl. Kolem toho se vyskytly nějaké drobné chyby, protože kód jako #if _MSC_VER < NNNN
možná vyřešit problém se starším kompilátorem by se spustilo i na MinGW, což možná nebylo zamýšleno. (Správnější by bylo #if defined(_MSC_VER) && _MSC_VER < NNNN
a samozřejmě zabalit do #ifdef WIN32
.) MinGW definuje __MINGW32__
a __MINGW64__
, ale tyto se používají velmi zřídka. MinGW také samozřejmě definuje __GNUC__
protože se jedná o GCC, lze tedy použít i podmíněný kód specifický pro GCC nebo verzi GCC. Obecně, protože MinGW používá Autoconf, měly by se tyto věci obvykle kontrolovat v configure
místo v kódu.
Cygwin definuje __CYGWIN__
. Je pozoruhodné, že Cygwin nedefinuje _WIN32
nebo WIN32
a tak dále — protože se nepovažuje za nativní Windows. To je důvod, proč v některých oblastech kódu, kde Windows prohlíží abstrakci Cygwin, vidíte spoustu kódu s #if defined(WIN32) ||
zvládnout oba případy.
defined(__CYGWIN__)
(V kódu jsou některé zaprášené rohy, které ne vždy zvládají všechny tyto definice preprocesoru rozumným a konzistentním způsobem. V některých případech je to záměrné, protože realita je divná, v jiných případech je to prohnilý a nesprávný kód, který je třeba vyčištěno.)
Každý z těchto cílů v zásadě existuje jako 32bitová a 64bitová varianta. Instalace 64bitového operačního systému Windows, což je běžná moderní instalace, může spouštět 32bitový i 64bitový software, takže na takovém systému můžete nainstalovat a spustit obě varianty. Produkční instalace by pravděpodobně měla používat 64bitové sestavení, takže se můžete rozhodnout, že se nebudete obtěžovat s 32bitovým prostředím. Ve skutečnosti se zdá, že 32bitová varianta Cygwin je docela mrtvá a možná ji nebudete moci vůbec uvést do provozu. Jedním problémem však je, že 64bitový MinGW má některé nejasné chyby, takže zvláště při používání MinGW je někdy lepší použít 32bitové prostředí, pokud nechcete bojovat s chybami operačního systému nebo toolchainu. 32bitové výpočty jsou však očividně obecně na ústupu, takže se nejedná o možnost, která by byla vhodná do budoucna.
Nyní je možná otázka, které z těchto prostředí je „nej“. Pokud jde o vývoj, na tom opravdu nezáleží, protože veškerý kód musí fungovat na všech z nich. Jak jsem uvedl výše, MSVC sestavení se používá pro většinu produkčních nasazení Windows. Prostředí MinGW (nebo spíše MSYS2) je hezčí na vývoj, pokud jste zvyklí na prostředí podobné Unixu, ale zejména 64bitové prostředí MinGW se zdá být poněkud zabugované, takže je těžké jej doporučit pro produkci. Cygwin může být některými považován za historickou kuriozitu v tomto bodě. Spuštění produkčního serveru pod Cygwinem se nedoporučuje, protože výkon je dost špatný. Ale Cygwin je v některých situacích skutečně užitečný. Například Readline nefunguje na žádném z nativních sestavení Windows, ale funguje na Cygwin, takže pokud jste uživatelem psql, je lepší k tomu použít sestavení Cygwin. Cygwin je také užitečný v situaci, která je opakem tohoto blogového příspěvku:Jste vývojář převážně pro Windows a chcete se ujistit, že váš kód je většinou kompatibilní s Unixem. Všechna tři tato prostředí tedy mají svou hodnotu a v tuto chvíli stojí za to je udržovat.
V další části této série proberu některé techniky pro testování změn kódu ve Windows a pro Windows, pokud to není vaše primární vývojové prostředí.