[Pythonmac-SIG] problems compiling Python 2.2.1 from source - pyexpat.c module failure

Bill Bug bbug@speakeasy.org
Thu, 6 Jun 2002 16:46:16 -0400

Hi All,

I've gotten stuck in my attempt to compile Python 2.2.1 from the source 
tarball on my 10.1.5 OS X machine that has the Apple Dev Suite installed 
with a functional gcc compiler.

Any help/corrections y'all could provide would be greatly appreciated.

Following the very clear README instructions on how to compile for Mac 
OS X, I built the Python core and most all the modules just fine using 
the recommended configure command:

./configure --enable-framework

I was even able to get my installed build to pass most all the 

All, that is, except for one module I know I need to use - and that the 
'smart' compile test suite knows should be functional under Darwin & OS 
X.  The module in question is pyexpat.o - the Python EXPAT-based XML 
Parser module.  The SAX module is also not created, since it requires an 
XML parser, which it expects will be coming via pyexpat.o.

I hunted through the Setup files in the /Modules directory and uncovered 
the line used by setup.py to create the compiler call designed to build 
this package.

#pyexpat pyexpat.c -I$(EXPAT_DIR)/xmlparse -L$(EXPAT_DIR) -lexpat

Unfortunately, my version of OS X does not contain that path, though it 
does contain EXPAT at /usr/local/expat.

To make a long story a bit shorter, I downloaded the EXPAT source and 
compiled it, just to make certain I had all the components required by 
pyexpat.c.  That placed the files the Python expat module requires - 
expat.h & libexpat.a - at /usr/local/include and /usr/local/lib, 
respectively.  That installation tested just fine.

I then added the following lines to my <PYTHON_HOME>/Modules/Setup.local 
pyexpat pyexpat.c -I$(EXPAT_DIR)/include -L$(EXPAT_DIR)/lib -lexpat

This info is used by the following code in setup.py to create the call 
to the gcc:

         expat_defs = []
         expat_incs = find_file('expat.h', inc_dirs, [])
         if expat_incs is not None:
             # expat.h was found
             expat_defs = [('HAVE_EXPAT_H', 1)]
             expat_incs = find_file('xmlparse.h', inc_dirs, [])

         if (expat_incs is not None and
             self.compiler.find_library_file(lib_dirs, 'expat')):
             exts.append( Extension('pyexpat', ['pyexpat.c'],
                                    define_macros = expat_defs,
                                    libraries = ['expat']) )

The following lines in the 'find_file(filename, std_dirs, paths) 
function ultimately define whether the proper gcc call will get 

f = os.path.join(dir, filename)
if os.path.exists(f): return []

Based on these lines, the call expat_incs = find_file('expat.h', 
inc_dirs, []) returns an empty array when it finds the 'expat.h' file at 
one of the include paths in 'inc_dirs'.  Because of this, the line 
'expat_defs = [('HAVE_EXPAT_H', 1)]' is never run and the 'HAVE_EXPAT_H' 
macro is not defined during compilation.

This creates the following line in the makefile:
cc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -no-cpp-precomp -fno-common 
-dynamic -I. -I./Include -DHAVE_CONFIG_H   -I/usr/local/include -c 
./Modules/pyexpat.c -o Modules/pyexpat.o

which leads to the following stderr msg during compilation:
./Modules/pyexpat.c:20: xmlparse.h: No such file or directory
make: *** [Modules/pyexpat.o] Error 1

Examining the pyexpat.c source file shows this line is nested amongst a 
set of pre-proc directives.  I've listed these nested booleans below 
with the offending line marked with an arrow.

	#ifdef HAVE_EXPAT_H
		#include "expat.h"
			#define EXPAT_VERSION (0x10000 * XML_MAJOR_VERSION \
                        	+ 0x100 * XML_MINOR_VERSION \
                        	+ XML_MICRO_VERSION)
			/* Assume the oldest Expat that used expat.h and did not 
have version info */
			#define EXPAT_VERSION 0x015f00
	#else /* !defined(HAVE_EXPAT_H) */
--->		#include "xmlparse.h"
		/* Assume Expat 1.1 unless told otherwise */
			#define EXPAT_VERSION 0x010100
	#endif /* !defined(HAVE_EXPAT_H) */

A quick scan of the logic confirms what I believe I see in setup.py - 
the 'HAVE_EXPAT_H' macro is not getting defined, because 'find_file'() 
in setup.py DOES find 'expat.h' at one of the paths in the INCLUDED 
directories variable sent into setup.py.

Have I misunderstood the compiler call in the makefile?  Have I 
misunderstood what setup.py doing?  I can't imagine why it would fail 
for this one module and work for all the others.  Does that relate to 
the fact that the this is the only module being defined via Setup.local?

  Not surprisingly, the following lines then show up when running the 
installation tests, along with many other statements:
test test_pyexpat skipped -- No module named pyexpat
test test_sax skipped -- no XML parsers available
3 skips unexpected on darwin:
     test_sax test_locale test_pyexpat

Once again, thanks very much for any assistance you can offer.

Bill Bug
Senior Analyst
Computer Vision Lab for Vertebrate Brain Mapping
MCP/Hahnemann University
Philadelphia, PA, USA 19129