[Scons-dev] Are any maintainers listening?

Eric S. Raymond esr at thyrsus.com
Thu Jun 14 11:25:40 EDT 2012


Gary Oberbrunner <garyo at oberbrunner.com>:

> Hi -- yes we are! You're not the only one who's wanted versioned shared

> libs, so this would be a welcome addition. Let me look back at your

> message (8/8/11, "soname support" I believe). I apologize for the lack of

> response last year; SCons wasn't getting a lot of love right around then

> for various reasons.


I like SCons a lot, but I was beginning to worry that the dev team had
gone so catatonic that I couldn't recommend it any more. Please try to
to disappear again?

For reference, here is my latest version of these builders:

# Cope with scons's failure to set SONAME in its builtins.
# Inspired by Richard Levitte's (slightly buggy) code at
# http://markmail.org/message/spttz3o4xrsftofr

def VersionedSharedLibrary(env, libname, version, lib_objs=[], parse_flags=[]):
platform = env.subst('$PLATFORM')
shlib_pre_action = None
shlib_suffix = env.subst('$SHLIBSUFFIX')
shlib_post_action = None
shlink_flags = SCons.Util.CLVar(env.subst('$SHLINKFLAGS'))

if platform == 'posix':
ilib_suffix = shlib_suffix + '.' + version
(major, age, revision) = version.split(".")
soname = "lib" + libname + shlib_suffix + "." + major
shlink_flags += [ '-Wl,-Bsymbolic', '-Wl,-soname=%s' % soname ]
elif platform == 'cygwin':
ilib_suffix = shlib_suffix
shlink_flags += [ '-Wl,-Bsymbolic',
'-Wl,--out-implib,${TARGET.base}.a' ]
elif platform == 'darwin':
ilib_suffix = '.' + version + shlib_suffix
shlink_flags += [ '-current_version', '%s' % version,
'-compatibility_version', '%s' % version,
'-undefined', 'dynamic_lookup' ]

ilib = env.SharedLibrary(libname,lib_objs,
SHLIBSUFFIX=ilib_suffix,
SHLINKFLAGS=shlink_flags, parse_flags=parse_flags)

if platform == 'darwin':
if version.count(".") != 2:
# We need a library name in libfoo.x.y.z.dylib form to proceed
raise ValueError
lib = 'lib' + libname + '.' + version + '.dylib'
lib_no_ver = 'lib' + libname + '.dylib'
# Link libfoo.x.y.z.dylib to libfoo.dylib
env.AddPostAction(ilib, 'rm -f %s; ln -s %s %s' % (
lib_no_ver, lib, lib_no_ver))
env.Clean(lib, lib_no_ver)
elif platform == 'posix':
if version.count(".") != 2:
# We need a library name in libfoo.so.x.y.z form to proceed
raise ValueError
lib = "lib" + libname + ".so." + version
suffix_re = '%s\\.[0-9\\.]*$' % re.escape(shlib_suffix)
# For libfoo.so.x.y.z, links libfoo.so libfoo.so.x.y libfoo.so.x
major_name = shlib_suffix + "." + lib.split(".")[2]
minor_name = major_name + "." + lib.split(".")[3]
for linksuffix in [shlib_suffix, major_name, minor_name]:
linkname = re.sub(suffix_re, linksuffix, lib)
env.AddPostAction(ilib, 'rm -f %s; ln -s %s %s' % (
linkname, lib, linkname))
env.Clean(lib, linkname)

return ilib

def VersionedSharedLibraryInstall(env, destination, libs):
platform = env.subst('$PLATFORM')
shlib_suffix = env.subst('$SHLIBSUFFIX')
ilibs = env.Install(destination, libs)
if platform == 'posix':
suffix_re = '%s\\.[0-9\\.]*$' % re.escape(shlib_suffix)
for lib in map(str, libs):
if lib.count(".") != 4:
# We need a library name in libfoo.so.x.y.z form to proceed
raise ValueError
# For libfoo.so.x.y.z, links libfoo.so libfoo.so.x.y libfoo.so.x
major_name = shlib_suffix + "." + lib.split(".")[2]
minor_name = major_name + "." + lib.split(".")[3]
for linksuffix in [shlib_suffix, major_name, minor_name]:
linkname = re.sub(suffix_re, linksuffix, lib)
env.AddPostAction(ilibs, 'cd %s; rm -f %s; ln -s %s %s' % (destination, linkname, lib, linkname))
env.Clean(lib, linkname)
return ilibs




> Looking back at it, I have a few comments.

> 1. it'll need documentation. We can help with that, though if you could

> rough it out that would be helpful.


-----------------------------------------------------------------------------
I am quite willing to write documentation. In fact, instead of just talking
about it, here it is:

VersionedSharedLibrary()
env.VersionedSharedLibrary()

Builds a versioned shared library (.so.X.Y.Z on a POSIX system,
.so.X.Y.Z.dylib under Darwin) given one or more object files or C,
C++, D or Fortran source files. If any source files are given, then
they will be automatically compiled to object files. $SHLIBPREFIX
and $SHLIBSUFFIX are honored as with SharedLibrary(). Example:

env.SharedLibrary(target='bar', version="2.3.1", source=['bar.c', 'foo.o'])

This builder may create multiple links to the library. On a POSIX system, the
links created by the example would be libbar.so.2.3.1, libbar.so.2.3, and
libbar.so.2; on a Darwin system the links would be libbar.2.3.1.dylib
and libbar.dylib.

As with SharedLibrary(), any object files listed in the source must
have been built for a shared library (that is, using the
SharedObject() builder method). scons will raise an error if there is
any mismatch.

VersionedSharedLibraryInstall()
env.VersionedSharedLibraryInstall()

Behaves like Install(), but takes versioned shared libraries (each must have
a full X.Y.Z version suffix) and installs their X.Y and X links in the target
dierectory as well.

-----------------------------------------------------------------------------

Looking at the above, I'm thinking this may be a more complex interface than
the capability demands. Is there any reason not to fold this logic into
SharedLibrary and Install()? The former could just do the right thing if
a 'version' argument is specified; the latter could do the right thing if it
sees a version suffix .X.Y.Z on a source and the corresponding .X.Y and .X
links.


> 2. it'll need tests. Is that something you could work on?


Probably not very effectively. I know nothing about your test strategy
or frameworks. I've been using this code for production in GPSD for
about a year.


> 3. There are some places where you substitute vars earlier than they

> normally would be substituted, which might cause subtle bugs -- e.g.

> $SHLINKFLAGS gets substituted right when the user calls

> VersionedSharedLibrary, rather than at build time. There are SConsish ways

> around this.

> 4. (minor) I'd prefer names like shlib_pre_action_target to

> shlib_pre_action_output (at least if I understand the code correctly)


I don't care about the names or the implementation details. It's not
really my design, I just fixed bugs in Ruchard Levitte's hack.


> Maybe the best way forward is to start a branch for it?


Not sure what that would gain. I don't know your project's workflow
or practices.
--
<a href="http://www.catb.org/~esr/">Eric S. Raymond</a>


More information about the Scons-dev mailing list