Reputation: 299
I'm trying to make distutils build an extension with libtool by overriding CC, LDSHARED etc. This fails for one reason alone: I cannot, from the shell environment at least, change the extension stored in compiler.shared_lib_extension, but for libtool it must be .la for libtool to realize what it's supposed to do.
By deriving from build_ext I can override lots of things but I don't see an easy way to override what's in build_ext.run which both sets self.ccompiler and runs it.
Upvotes: 2
Views: 251
Reputation: 299
Turns out overriding the build_ext class works:
from distutils.command.build_ext import build_ext
import re
# run the customize_compiler
class custom_build_ext(build_ext):
def build_extension(self, ext):
self.compiler.shared_lib_extension = '.la'
self.compiler.obj_extension = '.lo'
build_ext.build_extension(self,ext)
def get_ext_filename(self, ext_name):
name = build_ext.get_ext_filename(self, ext_name)
name = re.sub('\.[^.]*$', '.la', name)
return name
But installation still gives me a headache: I need to run libtool in install mode to install the .la files.
So I'm trying to override dir_util.copy_tree
next.
class custom_install_lib(install_lib):
# re-assemble libtool install command
libtool_cmd = []
for env_var in ['LIBTOOL', 'AM_LIBTOOLFLAGS', 'LIBTOOLFLAGS', 'INSTALL']:
libtool_cmd += os.environ[env_var].split()
def copy_tree(self, infile, outfile,
preserve_mode=1, preserve_times=1, preserve_symlinks=0,
level=1):
"""almost identical to dir_util.copy_tree but for the special
treatment of .libs directories and .la files
"""
from distutils.file_util import copy_file
from distutils.dir_util import mkpath
verbose=1
update=0
if not self.dry_run and not os.path.isdir(infile):
raise DistutilsFileError, \
"cannot copy tree '%s': not a directory" % infile
try:
names = os.listdir(infile)
except os.error, (errno, errstr):
if self.dry_run:
names = []
else:
raise DistutilsFileError, \
"error listing files in '%s': %s" % (infile, errstr)
if not self.dry_run:
mkpath(outfile, verbose=verbose)
outputs = []
for n in names:
infile_name = os.path.join(infile, n)
outfile_name = os.path.join(outfile, n)
if n.startswith('.nfs') or n == '.libs':
# skip NFS rename files and libtool-internals
continue
if n.endswith('.la'):
print('installing libtool library', n, file=sys.stderr)
self.spawn(self.libtool_cmd + [infile_name, outfile_name])
continue
if preserve_symlinks and os.path.islink(infile_name):
link_dest = os.readlink(infile_name)
if verbose >= 1:
log.info("linking %s -> %s", outfile_name, link_dest)
if not self.dry_run:
os.symlink(link_dest, outfile_name)
outputs.append(outfile_name)
elif os.path.isdir(infile_name):
outputs.extend(
self.copy_tree(infile_name, outfile_name, preserve_mode,
preserve_times, preserve_symlinks))
else:
copy_file(infile_name, outfile_name, preserve_mode,
preserve_times, update, verbose=verbose,
dry_run=self.dry_run)
outputs.append(outfile_name)
return outputs
This is obviously much more than I had hoped for and I also needed to print the python-computed installation directory to get the libtool -rpath argument correct.
Upvotes: 1