3 # GObject-Introspection - a framework for introspecting GObject libraries
4 # Copyright (C) 2009 Red Hat, Inc.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 from .utils import get_libtool_command, extract_libtool_shlib
30 # For .la files, the situation is easy.
31 def _resolve_libtool(options, binary, libraries):
33 for library in libraries:
34 shlib = extract_libtool_shlib(library)
41 # Assume ldd output is something vaguely like
43 # libpangoft2-1.0.so.0 => /usr/lib/libpangoft2-1.0.so.0 (0x006c1000)
45 # We say that if something in the output looks like libpangoft2<blah>
46 # then the *first* such in the output is the soname. We require <blah>
47 # to start with [^A-Za-z0-9_-] to avoid problems with libpango vs libpangoft2
49 # The negative lookbehind at the start is to avoid problems if someone
50 # is crazy enough to name a library liblib<foo> when lib<foo> exists.
52 def _ldd_library_pattern(library_name):
53 return re.compile("(?<![A-Za-z0-9_-])(lib*%s[^A-Za-z0-9_-][^\s\(\)]*)"
54 % re.escape(library_name))
57 # This is a what we do for non-la files. We assume that we are on an
58 # ELF-like system where ldd exists and the soname extracted with ldd is
59 # a filename that can be opened with dlopen().
61 # On OS X this will need a straightforward alternate implementation
64 # Windows is more difficult, since there isn't always a straightforward
65 # translation between library name (.lib) and the name of the .dll, so
66 # extracting the dll names from the compiled app may not be sufficient.
67 # We might need to hunt down the .lib in the compile-time path and
68 # use that to figure out the name of the DLL.
70 def _resolve_non_libtool(options, binary, libraries):
74 if platform.platform().startswith('OpenBSD'):
75 # Hack for OpenBSD when using the ports' libtool which uses slightly
76 # different directories to store the libraries in. So rewite binary.args[0]
77 # by inserting '.libs/'.
78 old_argdir = binary.args[0]
79 new_libsdir = os.path.join(os.path.dirname(binary.args[0]), '.libs/')
80 new_lib = new_libsdir + os.path.basename(binary.args[0])
81 if os.path.exists(new_lib):
82 binary.args[0] = new_lib
83 os.putenv('LD_LIBRARY_PATH', new_libsdir)
85 binary.args[0] = old_argdir
90 for library in libraries:
91 shlibs.append(library + '.dll')
94 libtool = get_libtool_command(options)
97 args.append('--mode=execute')
98 platform_system = platform.system()
99 if platform_system == 'Darwin':
100 args.extend(['otool', '-L', binary.args[0]])
102 args.extend(['ldd', binary.args[0]])
103 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
105 for library in libraries:
106 patterns[library] = _ldd_library_pattern(library)
109 for line in proc.stdout:
110 for library, pattern in patterns.iteritems():
111 m = pattern.search(line)
113 del patterns[library]
114 shlibs.append(m.group(1))
117 if len(patterns) > 0:
119 "ERROR: can't resolve libraries to shared libraries: " +
120 ", ".join(patterns.keys()))
125 # We want to resolve a set of library names (the <foo> of -l<foo>)
126 # against a library to find the shared library name. The shared
127 # library name is suppose to be what you pass to dlopen() (or
128 # equivalent). And we want to do this using the libraries that 'binary'
129 # is linking against.
131 def resolve_shlibs(options, binary, libraries):
132 libtool = filter(lambda x: x.endswith(".la"), libraries)
133 non_libtool = filter(lambda x: not x.endswith(".la"), libraries)
135 return (_resolve_libtool(options, binary, libtool) +
136 _resolve_non_libtool(options, binary, non_libtool))