Here's my steps in debugging this issue. If you don't care about the steps, you can skip to the end, where I find what seems to be an issue... sorry this is so long but I spent a long time trying to figure this out.
The steps
I started by taking a statement, assert False, and putting it in various places - first near the top to make sure that I was debugging the right Cython (I was), and then other places too see if they are reached.
- CythonDebugWriter is what writes the debug information.
- But it is never constructed...
- the only place it's constructed is in create_pyx_pipeline, which is never called.
-
which is only called from Main.run_pipeline, which is never called.
- which is only called from compile_single and compile_multiple, which are never called.
- which is only called from Main.compile, which is never called(!)
- Main.compile is hard to track down because of its generic name :-( but is called by BuildExecutable.cycompile, Dependencies.cythonize_one, and Main.main
- ...and none of those functions are called! (but it is somehow compiling code...)
So I've hit a dead-end there - except I now know what to look for when I'm going top-down.
Unfortunately the code goes through distutils.setup which I'm not prepared to trace through.
I know that Dependencies.cythonize IS called. There is a call to cythonize_one from this BUT it's only called in the case that your Python DOES NOT have multiprocessing (i.e. version < 2.6).
Deceived by setup.py clean
At this point I discover that setup clean does not delete the generated .cpp files. :-( :-(
Overall, the "clean" target has been a disappointment - I already had to expand that class in order to get it to clean the linked output, but didn't catch the .cpp file. By default, setup.py clean should kill everything that's been made by setup.py, shouldn't it?
Things like this are a trap for development and, as you can see, consumptive of developer time.
Back into it.
I add the .cpp to the clean "target". This doesn't fix the issue, but now I can go back and correctly do the work I did before....
It seems that Main.compile is called and compile_multiple is called, and create_pyx_pipeline is called - but gdb_debug is NOT true at that point. So now I have to track down why gdb_debug isn't being set - which I actually attempted before going off track.
in build_ext.py, CompilationOptions is always constructed with cython_gdb = True. The issue is setting the gdb_debug flag.
There are only two places where gdb_debug is set - in CmdLine.parse_command_line, which is never called, and build_ext.cython_sources, which is never called.
I note that parse_command_line has another option for setting the output, namely --gdb - but this doesn't work as an argument to setup.py.
However, parse_command_line is only called if you directly call the cython compiler from the command line (question: why are these options so completely different?)
The issue?
So it has to be the call to cython_sources that we want to make go off. And this is only called from build_ext.build_extensions.
Which is never called anywhere in the code - grepping for build_extensions in the Cython directory finds only the definition, not a call.
And build_extensions also makes a call to self.build_extension() - which is not defined anywhere - so build_ext.build_extensions() couldn't possible work.
How can this be? It seems wrong.
For the moment, I'm going into the source and hard-coding gdb_debug to always be true and move forward from there.
And if you're skipping here from the start, I noted two other possible issues:
- make clean doesn't delete the .cpp's created by Cython
- the arguments to cython are quite different to the arguments you use in setup.py