[Distutils] Compilation of extension modules
Florent Rougon
flo@via.ecp.fr
Sun Mar 3 18:40:01 2002
--=-=-=
Hello,
I am currently packaging an extension module that uses the glib library.
The correct way to compile such a program is:
gcc `glib-config --cflags` ... -c ... -o ...
That is, the output of "glib-config --cflags" must be near the beginning
of the compilation command (it usually contains -I options).
I tried to use the extra_compile_args argument to Extension's __init__()
method but it only adds arguments to the end of the compilation command.
I looked into Distutils' sources and found that the extra_preargs
argument to UnixCCompiler.compile() would do the trick, but it can't be
set from Extension's __init__() method. When the compile() method is
called in build_ext.py, no extra_preargs is passed, so it always gets
its default value: None.
Currently, I adopted the following "solution": strip the leading -I from
each argument output by "glib-config --cflags" and give it as
include_dirs to Extension.__init__().
This is somewhat ugly since the output of "glib-config --cflags" could
contain arguments that are not include directory specifications. My hack
would fail in such cases.
Is there a better solution I couldn't see? I searched the mailing-list
archive and didn't find anything really satisfactory.
If not, could we consider adding the possibility of specifying
some-arguments-of-any-kind (not only include dirs of macros or whatever)
to be put near the beginning of the compilation command from the setup()
call?
[ BTW, there is a similar issue with linking, but as `glib-config --libs`
is OK at the end of the link command line, extra_link_args does the
trick. However, it would be nice to be able to customize the beginning
if the link command. ]
Thank you for your comments. Here is my current setup.py.
--=-=-=
Content-Disposition: attachment; filename=setup.py
#! /usr/bin/env python
# setup.py --- Setup script for Python-XMMS
# Copyright (c) 2002 Florent Rougon
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA.
import os, string, sys
from distutils.core import setup, Extension
# Notes:
# 1) The Distutils included in Python 2.1 don't understand the "license"
# keyword argument of setup correctly (they only understand licence); as I
# don't want to mispell it, if you run the Distutils from Python 2.1, you
# will get License: UNKNOWN.
# 2) I would like to use the keyword argument "extra_compile_args" of setup to
# pass the output of glib-config --cflags to Distutils but it goes to the
# end of the gcc command, which is useless in this case. So, I use
# "include_dirs" instead.
GLIB_CONFIG = "glib-config"
glib_opts = {}
for op in ("cflags", "libs"):
glib_config_pipe = os.popen("%s --%s" % (GLIB_CONFIG, op), 'r')
glib_opts[op] = glib_config_pipe.read()[:-1] # strip the trailing newline
if glib_config_pipe.close() != None:
sys.exit("%s returned a non-zero exit status. Aborting." % GLIB_CONFIG)
# Suppress the -I in each -Idir output by glib-config --cflags (ugly)
glib_include_dirs = map(lambda s: s[2:],
string.split(glib_opts["cflags"], ' '))
setup(name="Python-XMMS",
version="1.0",
description="A Python interface to XMMS",
author="Florent Rougon",
author_email="flo@via.ecp.fr",
maintainer="Florent Rougon",
maintainer_email="flo@via.ecp.fr",
url="http://www.via.ecp.fr/~flo/",
license="GPL",
platforms="Unix",
long_description = """\
A Python interface to XMMS consisting of all the xmms_remote_* functions
from libxmms plus some higher-level functions. This should provide anything
needed to control XMMS from an external program.""",
py_modules=["xmms"],
ext_modules=[Extension("_xmms", ["_xmmsmodule.c"],
include_dirs=glib_include_dirs,
libraries=["xmms"],
extra_link_args=[glib_opts["libs"]])])
--=-=-=
--
Florent
--=-=-=--