[[!summary chatGPT: This post discusses using Nix for source deployment and binary deployment on Windows, and explores how to build a MinGW-based Nix toolchain for Windows.]] [[!tag nixos]] [[!meta date="2011-02-14 11:30"]] [[!img media/nixos-lores.png alt="" style="float: right"]] # motivation searching for a '**cross platform**', '**cross distribution**' package manager, one question that arises in regards to nix is: can nix be used for '**source deployment' and 'binary deployment**' on windows? in the last post i discussed how to install nix 0.16 [1] on windows but back then i could not find any working gui tool. i was not able to compile such a tool either with the tools found in nixpkgs [2]. the problem is that the used toolchain is optimized for posix environments (linux and others) with dependencies to X11. **how to use nix to build software for windows then? **the solution to this problem is easy: we have to extend the current toolchain (used in nixpkgs) by a new one.** ** first, let's see what others do: other distributions already support 'cross compilers' to compile program in linux (but for windows). the drawback of such a solution is that it binds the developer to a certain distribution. so what concepts do exist, in order to build software, for windows: * **windows+cygwin (running nix inside cygwin)** using the posix toolchain (nixpkgs) this is already working and supported * **windows+cygwin (running nix inside cygwin)** using a different toolchain: MinGW this is what this blog posting is about * **using nix on any posix conform distrubtion** with a **cross compiler setup** using the MinGW toolchain there are some references to MinGW found in the nixpkgs already, according to developers on irc.freenode.org#nixos [10] this is used for cross compiler setups. still i could not find any mingw expression to experiment with such a cross compiler setup in nix. so why would i want to have **windows+cygwin+nix** with a ** native windows mingw toolchain**? * **nix can be used as a package manager for windows** * **nix does support 'source deployment' and 'binary deployment' ** so it is a important target for developers on all platforms/distributions * **nix is not bound to any distribution in particular ** which also makes it an excellent tool for 'cross distribution' packaging (when using nix in a prefix installation in contrast to using NIX OS) * **nix can be used to create abstract targets of all kind** examples: creating NSIS installers, automated software builds/tests * **nix can be used to build 'cross compiler chains' **this would actually be interesting for me as well (but not covered here)** ** # creating a new mingw based nix toolchain this is not that easy, but we somehow have to** replace/extend the linux based toolchain with a MinGW toolchain** optimized for windows. ## first: what should be supported? on windows, that is: * **direct hardware access** (using windows api and device drivers) / directX * using Qt natively (**without X11**) * things like 'start menu' shortcuts we will use qt 4.7 as an example how to do that. ## how to build software for windows natively? first let's build software for windows, how it would be done using windows: * download the **Automated MinGW installer** (should contain gcc 4.x) at [ ](http://sourceforge.net/projects/mingw/files/Automated%20MinGW%20Installer/)[3] * download the **qt 4.7.1 library** (i used the zip distribution for this experiment) [4] to build the libraries (&later the software) ### making mingw work (native installation) 1. as already mentioned, download the 'Automated MinGW installer' 2. install MinGW NOTE: do not add anything to the global PATH, as we are going to setup multiple toolchains, this would be a source of horrible side-effects. so instead of a global PATH, we could alter the PATH used in cmd.exe on the fly (every time we start a new cmd.exe) with: PATH = %PATH%;c:\mingw\bin; NOTE: windows does not have something like RPATH [5] (rpath is not cmake specific but that linked page should give you an basic idea what rpath is about), that means a windows program is lost if the library (something like mingw.dll) is not found in the same directory as the binary is in. as a quick fix to the problem one could expand the PATH variable to include also the place, where the respective library is in. as we'll with the new nix-toolchain, this simple fact is very problematic. [7] provides an interesting (maybe outdated) table about how such things are handled in other distributions. ### making qt work (using mingw, still native installation) so as the compiler setup is done, we need to add the qt library. download a file called qt-everywhere-opensource-src-4.7.1.zip at [5]. 1. **using the cmd.exe** from above (with the PATH adaption) 2. **unzip** qt-everywhere-opensource-src-4.7.1.zip 3. **cd qt-everywhere-opensource-src-4.7.1** 4. **configure.exe** 5. **make install** (will install into the same directory, but we don't care right now) afterwards we can execute qt programs from the cmd.exe shell. to make the examples executable from everywhere either: * (DON'T DO THAT!): **add the MinGW path and the Qt-library path to the global PATH** variable * (DON'T DO THAT!): **copy the needed dll files into EACH qt example directory** to make the examples work from everywhere (either from cmd.exe shell or when starting from explorer.exe) * add another PATH, namely: c:\qt-everywhere-opensource-src-4.7.1\bin in the cmd.exe shell as a final step we test if the qt examples work (this is kind of a module test), **run any qt example from cmd.exe with the extended PATH settings applied**. as we now know how to get this toolchain working in a native environment, we can try to automate this process using nix expressions. ## adapting this buildchain into nix expressions to get a working toolchain inside nix i packaged the installation of MinGW from c:\MinGW and created something like mingw.tar.bz2 for redistribution. see the nix expressions in [6] and consult the README in order to get the nix expression to work in your cygwin environment (this time not cmd.exe anymore, instead use the cygwin shell). * winmingw.nix downloads my re-release of mingw and installs it * it also makes the tools like mingw32-make available for use inside your cygwin shell NOTE: make sure your cygwin (not cmd.exe) has ~/.nix-profile/bin in your PATH environment variable (example: export PATH=~/.nix-profile/bin:$PATH). ### how to install cygwin/nix and my nix expressions on windows: 1. **install a full cygwin environment** (several gb of files, use the setup.exe installer) or see my last post about this 2. **make nix 0.16 work ** again: see my last post about this 3. use **git clone with my local repo** in [6] cd ~; mkdir .nixpkgs; cd .nixpkgs; git clone ... 4. install winmingw: **nix-env.exe -i winmingw** 5. check that the mingw tools are there, type: **mingw32-make.exe** or **mingw32-make** NOTE: after installing winmingw notice that there are a lot of new tools symlinked from '~/.nix-profile/bin'. **interestingly this also includes symlinks to libraries (read dll files) files**. so why symlink dll files? ## installing qt using the new mingw toolchain there is another **anomaly** using cygwin in comparison to all other posix systems. in windows all executables do have the **.exe suffix** while on linux they don't. as the cygwin shell must be compatible to both worlds, the designer of cygwin made this decision: * programs can be **executed by typing: 'curl.exe' but also by typing 'curl'**, both times it is the same program which gets executed * there is an **exception to the rule above**, if a **script called 'curl'** also exists (which is executable), it is **executed instead** of curl.exe * if the script 'curl' and the binary 'curl.exe' are in the same directory, then the **'curl' script has precedence**, when typing 'curl' in a shell at least [8] states it that way. i also experimented with these commands: 1. touch AA; touch AA.exe (both files get created) 2. touch AA.exe; touch AA (only AA.exe is created and later the timestamp is updated) i guess (1) is true on all posix systems (at least for those i've been working with so far). but **(2) is cygwin specific and implies some issues on would not think of**. to track down an issue which is caused by the fromer rule it cost me at least 1-2 hours. the problem was that my winqt.nix expression was fine but always exited with 'error 1' after the unzip operation (without any error message, except the exit 1 code). i always thought that i did something wrong with the nix language. but then i decided to run the command (which would normally be executed by nix) in a shell and found out that the **cygwin shell bahaves differently than the cmd.exe shell for the exact same command**. to my surprise i got prompted by unzip (in the cygwin shell) with the question if i want to [o]verwrite or [r]ename 'configure.exe' (cause by a file configure). i wondered quite some time what problem could cause this?! so i extracted it again, but this time in cmd.exe with no prompt. # important conclusions Edit: further discussion should be redirected to the nix wiki [11]. ## problem 1: symlinks and dll files * **all programs in nix are installed into a unique prefix** but are available as a symlink from ~/.nix-profile/bin * **symlinking the same program twice does therefore not work** but happens rarely anyway * however: **symlinking two different dll files sharing the same name is not possible**, this is the biggest issue right now a solution would be static linking. therefore: * two programs having the same binary name ('firefox' for example) * two programs sharing the same library name ('mingw32.dll' for example) the former point is easy to accomplish but the later is not. 'viric' (a developer from irc.freenode.org#nixos) pointed out that in order to fix this issue we could use 'side-by-side sharing' [9]. NOTE: **it would be very interesting to see, if such a thing would actually work.** ## problem 2: directory and file handling the other important problem is how file handling is implemented in cygwin. the **current behaviour seems to be convenient for users but is a no-go for packaging **as it might cause a lot of unforeseen consequences (and we all have played halfile and know where this could be going). # links * [1] * [2] * [3] * [4] * [5] * [6] * [7] * [8] * [9] * [10] * [11]