Note: this is directed at Python 2.7 developers, but the same principles should apply to Python 3.x as well.
First, a shout-out for the Unofficial Windows Binaries for Python site: as noted below you can get the binaries for many commonly used packages simply by downloading and installing them, with no need to compile.
However, when it comes to things like Cython that NEED a working compiler at some point you’ll have to set one up. I wrote this post to help you with that, hopefully saving you many hours of frustration!
Conclusions first: properly configuring Windows to compile for Python/Cython takes a little effort but the hardest part is getting the details in one place (which this post is intended to do). The total setup time if you go the full Windows SDK/Microsoft Visual Studio Express/MinGW route isn’t that long – less than 30 minutes with a decent connection on a fast machine, with the majority of it spent in the download/install phases.
I DO suggest you install Microsoft Visual Studio Express 2008 and the Windows SDK. As for MinGW, I strongly suspect there are limits to what you can ultimately do with it in this context but it’s presented here as an option for the adventurous (and it’s rather nice to have GCC handy in general!)
Windows isn’t the easiest system to work with, especially when you want to go the FOSS development route. In the case of Python 2.7 development involving things like Cython or many pip installs, if you don’t have the right Microsoft compilers installed (why?) you’ll most likely see the dreaded “error: Unable to find vcvarsall.bat” at some point… usually the moment you REALLY don’t have time for it. What to do?
One solution is to install Microsoft Visual Studio 2008 itself (at least the Express version, as well as the Windows SDK – it’s evident now that the SDK alone will NOT suffice). I’ve outlined that path below.
Another possible solution is to use GCC via MinGW, but you’ll need to jump through a few hoops to do it (and it won’t work with Cython for x64 builds of Python!) I can’t say for certain how far this approach will get you, but it worked for me when I tried it for 32-bit build tests. YMMV… it’s probably not the most stable way to go for linking with a code-base originally built via MSVS.
Installing the Windows SDK
I’ve read that you can do everything with the Windows SDK alone, at least for Cython (also here and here, among other places). So, get the Windows SDK 7.1 (IMHO) and install it. Note that you should only need the Developer tools, which clock in at 1.1 GB (Documentation and Samples take up an extra 3.5 GB!)
You may get the following error: SDKSetup – Another running instance of this application was detected. Only one instance of this application may be running at any time.
Close that error window and you get the Program Compatibility Assistant. I’m quite used to closing that thing out of habit and searching Google in frustration, which I did, and found zero answers to this problem. I searched running processes – nothing. I ran Process Monitor – nothing stood out. I don’t have another instance installed. WTH?
After a reboot and a few more failed attempts, I accidentally chose the “Reinstall using recommended settings” option. Suddenly, it worked! I have NO idea what special setting Windows “chose” for me (there’s no way to readily see that) but it worked.
At this point enjoy your favorite soothing beverage and/or blood pressure medication while the installation proceeds at the speed of a turtle crossing a busy highway. Poor turtle!
All done? Good! I created a little build.cmd script in the folder with my code that has the following (“::” is the same thing as “REM” in batch/cmd files). You may need to adjust the paths slightly from what’s shown, and comment/uncomment the appropriate bits (the SDK path may vary, for example):
::@echo off :: Selects the compiler AND Python27 target this works with! (x86 or x64) ::set MYTGT=x64 set MYTGT=x86 :: The SDK you actually installed set MYSDK=v7.1 :: I've made basic installs of Python with distribute, pip and cython in :: folders C:\Python27_x86 and C:\Python_x64 (so as not to collide with :: my usual Python at C:\Python27) :: We set the path accordingly PATH=C:\Python27_%MYTGT%;C:\Python27_%MYTGT%\Scripts;%PATH% :: Replicate cmd option /E:ON (command extensions - haven't needed yet) ::setlocal EnableExtensions :: Replicate cmd option /V:ON (delayed expansion - required) setlocal EnableDelayedExpansion :: Run SetEnv as the SDK cmd shell does (needs to be the same tgt as Python's: call "C:\Program Files\Microsoft SDKs\Windows\%MYSDK%\Bin\SetEnv.cmd" /%MYTGT% /release :: I've seen this setting mentioned for other projects but haven't had to use it myself ::set MSSdk=1 :: Select the proper SDK for Python 2.7 (6.0A versus a later one - VERY important!) set DISTUTILS_USE_SDK=1 echo. echo -- Compiler and Python version check echo. echo Compilation target: %TARGET_PLATFORM%-%TARGET_CPU% for Python27_%MYTGT% echo. python -c "import sys;print('Python '+sys.version.replace('\n','')+' on '+sys.platform)" :: Your build commands go below, e.g.: echo. echo -- Building it echo. ::del *.pyd ::python setup.py build_ext --inplace echo. echo -- Testing it echo. ::python testhello.py echo. echo -- Done! echo. pause
If running that worked (even with no code to compile it’ll at least turn green and mention that it’s using SDK v6.0A) then congratulations: you should be ready to go on! We hope!
Note: If you try to run these commands directly in a command prompt it’ll likely *fail*. Either ensure you started cmd.exe with the “/V:ON” option, or start one from where you are at by typing “cmd.exe /V:ON”. Why? Because “setlocal EnableDelayedExpansion” ONLY works in a batch file, that’s why.
You’ll need to perform these steps before installing any package that requires compilation (such as Cython) or building your code. You could make some shortcuts so you can just click and have an environment ready to use.
Installing Microsoft Visual Studio Express 2008
(might not be necessary) (oh yeah, it’s necessary!)
Though some of what I’ve read suggested MSVS is not required, to avoid the missing vcvarsall.bat problem you still need to install MSVS “Express” 2008 as found in (of all things) a closed thread on StackOverflow. You can find the official installer at http://go.microsoft.com/?linkid=7729279
Skip the SQL part of the install to save time and space.
Have another beverage…
it’s gonna be a while. Actually, it was blazingly fast on this machine. Still… refreshing!
Dealing with despair
At this point you may be considering wiping your system and installing some version of Linux (or possibly buying an entirely new piece of hardware simply to run a hardware-locked Linux-like commercial OS). But, you’re a trouper and you hung on this long – you may yet be rewarded! (And despite all this, knowing how to build in Windows is a handy if esoteric skill).
Going the GCC route, or thinking about it? Install the 32-bit version of TDM-GCC (the 32/64-bit version will NOT work).
When using newer versions of MinGW, you need to edit C:\Python27\Lib\distutils\cygwinccompiler.py and remove all refs to -mno-cygwin (this is an obsolete option in GCC 4.7)
To actually use MinGW32’s gcc instead of MSVS with Python, you’ll need to create C:\Python27\Lib\distutils\distutils.cfg with the contents:
[build] compiler = mingw32
(If later you decide to use MSVS, be sure to rename or remove this file if it’s present. You probably should reinstall Python and your packages using MSVS at that point to ensure it’s consistent.)
Installing Python 2.7
Install Python 2.7.x from the main site. I had three versions installed for the purpose of all this testing: the x86 one in C:\Python27_x86, the x64 one in C:\Python_x64, and my “default” version in C:\Python27. that was really just a copy of one of the other two. You will likely just have one version installed (32- or 64-bit) so you’ll adjust the script above accordingly.
People seem to use the 32-bit version quite a lot…. the one with “X86-64” by it is the 64-bit version (note that the 64-bit version will identify itself as AMD64 when you run it. Why so many ways to say the same thing, you ask?)You can always use the 32-bit version, while the 64-bit one only works with a 64-bit OS. Also, 64-bit modules sometimes have less support so keep that in mind as well. Not sure? Do what I did and build for both! 🙂
Another random note: IA64 is NOT another name for x64/X86-64/AMD64 and it’s totally outside the scope of what I’m presenting here. If you have to ask you probably aren’t using it (is anyone anymore?) I mention it only because I got confused by it back when I was using MSVS 2008 more regularly and it led to a lot of confusion. If you are confused now just forget this little paragraph.
There. All better!
The easy way: Install the unofficial WIndows binary that matches your version of Python!
The harder but eminently fulfilling way (based on this comment):
Save http://python-distribute.org/distribute_setup.py as C:\Python27\Scripts\distribute_setup.py (you may need to create that Scripts directory). Python ought to be in your path, as should this Scripts folder. Set your system or user path correctly or ensure it’s set during your command prompt sessions thus:
Run the script:
Now install pip:
The easy way: Install the unofficial WIndows binary that matches your version of Python!
The harder but more rewarding way:
THIS is where that Windows SDK you installed becomes important.
First, run the setenv and other commands as you did above to test the SDK!
pip install cython
It should “just work”, compiling and installing without failures.
Remember: if you’re using 32-bit python you need to be using the 32-bit x86 settings! 64-bit? Use the 64-bit x64 settings! Got a raft of “unresolved external symbol” errors? You probably chose the wrong one, or forgot to choose one.
I tried it on both 32- and 64-bit versions of Python 2.7.5 (selecting the proper target for each). It worked. I was pretty amazed. A beverage was forthcoming!
Finally, create and compile something with Cython, such as the “helloworld” example from the Cython tutorial.
(Remember the “handy” build.cmd file I mentioned above? This would be a great time to use it!)
Note that the compiled version ends in .pyd NOT .dll (typo in the docs)