En tant que développeur PostgreSQL, j'ai parfois besoin de faire fonctionner mon code sous Windows. Comme je n'utilise normalement pas Windows et que je n'ai pas d'installation permanente de Windows, cela a toujours été un peu fastidieux. J'ai développé quelques techniques pour rendre cela plus facile, et je pense qu'elles valent la peine d'être partagées. Et en fait, ce texte est devenu assez long, donc ce sera une série de plusieurs articles de blog.
La première chose qu'il est utile de comprendre est les différentes variantes de cibles de construction Windows et en quoi elles sont similaires et différentes.
La principale façon de créer pour Windows est sans doute d'utiliser Microsoft Visual Studio suite de compilateurs. C'est ce que vous pourriez considérer comme l'environnement le plus natif. La plupart sinon toutes les distributions binaires de PostgreSQL pour Windows utilisent cette version. Cette construction n'utilise pas les makefiles Unix normaux mais un système de construction séparé sous src/tools/msvc/
. Cela analyse les makefiles et a une logique personnalisée et crée des fichiers "projet" spécifiques à cette chaîne d'outils, que vous pouvez ensuite exécuter pour créer le code. Appelons cela la construction MSVC ici. Cette construction est susceptible de se casser de deux manières :d'une part, si le code ne se construit pas ou ne s'exécute pas réellement sous Windows, et d'autre part, si vous modifiez quelque chose dans le système de construction normal (basé sur les makefiles) qui fait que ces scripts ad hoc Pause. C'est donc toujours très amusant à gérer.
La deuxième façon est d'utiliser MinGW . Cela utilise la chaîne d'outils GNU (GCC, GNU binutils, GNU ld, etc.) pour créer du code natif sur Windows. Vous pouvez le considérer comme "GCC sous Windows", mais en réalité, il contient un shim et un glue supplémentaires pour s'interfacer avec les bibliothèques système de Windows. Cela utilise le système de construction Unix-ish normal utilisant configure et makefiles, mais le code qu'il produit est du code Windows natif, en principe équivalent à la sortie de la construction MSVC. Cela signifie également que si le code ne se construit pas ou ne s'exécute pas avec la construction MSVC, il ne se construira pas ou ne s'exécutera pas non plus ici. Mais le système de construction est le même que pour Linux, etc., il sera donc plus difficile de casser accidentellement.
La troisième méthode est Cygwin . Cygwin est un sous-système qui présente un environnement de type POSIX sous Windows. Par exemple, Cygwin ajoute des utilisateurs, des groupes, fork()
, la mémoire partagée SysV et d'autres fonctionnalités qui n'existent pas sur Windows natif mais qui sont standard sur, disons, Linux. L'idée est que vous pourriez prendre le code source destiné à Linux ou BSD et le construire sous Cygwin sans changement (ou du moins avec seulement des changements qui seraient dans la plage typique de changements de portage entre les systèmes de type Unix). Pour cette raison, un port Cygwin de PostgreSQL existait bien avant le port Windows natif, car il s'agissait d'un effort beaucoup plus petit. En pratique, l'abstraction s'effondre dans certains domaines, en particulier dans le code réseau et autour de la dénomination et de l'accès aux fichiers, mais en général, la construction de Cygwin s'interrompt très rarement par rapport aux autres cibles.
Il y avait une autre façon de construire sur Windows. Il y avait win32.mak
fichiers que vous pouviez utiliser directement avec nmake sous Windows, et il y avait aussi un support pour les compilateurs Borland à un moment donné. Il s'agissait essentiellement de mesures provisoires pour construire uniquement libpq nativement sur Windows avant l'arrivée du port natif complet. Ceux-ci ont maintenant été supprimés.
Un autre terme apparaît dans ce contexte :MSYS . La raison en est que MinGW en lui-même n'est pas souvent utile. C'est juste une chaîne d'outils de compilation. Mais pour construire un logiciel Unix typique, vous avez besoin d'outils supplémentaires tels que bash, make, sed, grep et toutes ces choses qui sont généralement utilisées à partir d'un script configure ou d'un makefile. Ces outils n'existent pas tous en tant que ports Windows natifs. Mais vous pouvez les exécuter sur le sous-système Cygwin. Donc, une façon d'utiliser MinGW est de l'intérieur de Cygwin. Un autre est MSYS, qui signifie "système minimal", qui est en gros un sous-ensemble sur mesure de Cygwin et certains emballages spécifiquement pour l'utilisation de MinGW pour la construction de logiciels. Le MSYS original est maintenant abandonné pour autant que je sache, mais il existe une nouvelle alternative populaire MSYS2. Plus d'informations à ce sujet dans un article de blog ultérieur. Pour l'instant, comprenez simplement la relation entre tous ces différents progiciels.
Voyons maintenant comment le code source voit ces différents environnements de construction.
Une construction native utilisant MSVC ou MinGW définit _WIN32
. (Étrangement, c'est le cas pour les versions 32 bits et 64 bits. Une version 64 bits définit également _WIN64
, mais cela est rarement utilisé.) Le code source PostgreSQL utilise WIN32
à la place, mais c'est spécifique à PostgreSQL, pas fait par le compilateur.
MSVC définit également _MSC_VER
à un certain numéro de version. C'est parfois utile pour contourner les problèmes avec une version particulière du compilateur (souvent le genre de choses pour lesquelles les builds Unix auraient tendance à utiliser configure). Notez que MinGW ne définit pas _MSC_VER
, donc le code doit être écrit avec soin pour gérer cela également. Il y a eu quelques bugs mineurs autour de cela car un code comme #if _MSC_VER < NNNN
peut-être contourner un problème avec un compilateur plus ancien se déclencherait également sur MinGW, ce qui n'aurait peut-être pas été prévu. (Plus correct serait #if defined(_MSC_VER) && _MSC_VER < NNNN
et bien sûr envelopper dans #ifdef WIN32
.) MinGW définit __MINGW32__
et __MINGW64__
, mais ceux-ci sont très rarement utilisés. De plus, MinGW définit bien sûr __GNUC__
puisqu'il s'agit de GCC, un code conditionnel spécifique à GCC ou à une version de GCC peut également être utilisé. En général, puisque MinGW utilise Autoconf, ces éléments doivent généralement être vérifiés dans configure
au lieu de dans le code.
Cygwin définit __CYGWIN__
. Notamment, Cygwin ne définit pas _WIN32
, ou WIN32
, etc., car il ne se considère pas comme Windows natif. C'est pourquoi dans certaines zones de code où Windows jette un coup d'œil à travers l'abstraction Cygwin, vous voyez beaucoup de code avec #if defined(WIN32) ||
pour gérer les deux cas.
defined(__CYGWIN__)
(Il y a des coins poussiéreux dans le code qui ne gèrent pas toujours toutes ces définitions de préprocesseur de manière sensée et cohérente. Dans certains cas, c'est intentionnel parce que la réalité est bizarre, dans d'autres cas, c'est du code pourri et incorrect qui doit être nettoyé.)
Chacune de ces cibles existe en principe sous la forme d'une variante 32 bits et d'une variante 64 bits. Une installation de système d'exploitation Windows 64 bits, qui est l'installation moderne normale, peut exécuter des logiciels 32 bits et 64 bits, vous pouvez donc installer et exécuter les deux variantes sur un tel système. Une installation de production devrait probablement utiliser une version 64 bits, et vous pouvez donc choisir de ne pas vous soucier de l'environnement 32 bits. En fait, la variante 32 bits de Cygwin semble être assez morte, et vous ne pourrez peut-être pas la faire fonctionner du tout. Un problème, cependant, est que MinGW 64 bits a quelques bogues obscurs, donc lors de l'utilisation de MinGW en particulier, il est parfois préférable d'utiliser l'environnement 32 bits, sauf si vous voulez combattre les bogues du système d'exploitation ou de la chaîne d'outils. Cependant, l'informatique 32 bits est évidemment en voie de disparition en général, ce n'est donc pas une option à l'épreuve du futur.
Maintenant, la question est peut-être de savoir lequel de ces environnements est « le meilleur ». En ce qui concerne le développement, cela n'a pas vraiment d'importance car tout le code doit fonctionner sur chacun d'eux. Comme je l'ai mentionné ci-dessus, la version MSVC est utilisée pour la plupart des déploiements de production de Windows. L'environnement MinGW (ou plutôt MSYS2) est plus agréable à développer si vous êtes habitué à un environnement de type Unix, mais surtout l'environnement MinGW 64 bits semble être quelque peu bogué, il est donc difficile de le recommander pour la production. Cygwin pourrait être considéré par certains comme une curiosité historique à ce stade. L'exécution d'un serveur de production sous Cygwin n'est pas recommandée car les performances sont assez mauvaises. Mais Cygwin est en fait utile dans certaines situations. Par exemple, Readline ne fonctionne sur aucune des versions natives de Windows, mais sur Cygwin, donc si vous êtes un utilisateur de psql, il est préférable d'utiliser une version Cygwin pour cela. De plus, Cygwin est utile dans la situation inverse de ce billet de blog :vous êtes un développeur principalement Windows et vous voulez vous assurer que votre code est principalement compatible avec Unix. Donc, ces trois environnements ont leur valeur et méritent d'être maintenus en ce moment.
Dans la prochaine partie de cette série, je discuterai de quelques techniques pour tester les changements de code sur et pour Windows s'il ne s'agit pas de votre environnement de développement principal.