Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11565 - in main/branches/prefix: bin pym/portage/dbapi
Date: Sat, 27 Sep 2008 14:52:14
Message-Id: E1Kjb9X-0004mk-9i@stork.gentoo.org
1 Author: grobian
2 Date: 2008-09-27 14:52:10 +0000 (Sat, 27 Sep 2008)
3 New Revision: 11565
4
5 Modified:
6 main/branches/prefix/bin/misc-functions.sh
7 main/branches/prefix/pym/portage/dbapi/vartree.py
8 Log:
9 Now we have scanmacho, we can eventually do some fast examination of libraries and get all info at once that we need. Get rid of otool, and now also store the arch of objects (enabling theoretical support for FAT objects), hence bump to NEEDED.MACHO.3
10
11 Modified: main/branches/prefix/bin/misc-functions.sh
12 ===================================================================
13 --- main/branches/prefix/bin/misc-functions.sh 2008-09-27 05:55:10 UTC (rev 11564)
14 +++ main/branches/prefix/bin/misc-functions.sh 2008-09-27 14:52:10 UTC (rev 11565)
15 @@ -407,53 +407,56 @@
16 done
17 [[ ${abort} == "yes" ]] && die "soiled libtool library files found"
18
19 - # Check that we don't get kernel traps at runtime because of broken
20 - # install_names on Darwin, at the same time generate the NEEDED
21 - # entries. As long as we don't have a "scanelf" tool for this, we
22 - # use otool to do the magic. Since this is expensive, we do it
23 - # together with the scan for broken installs.
24 + # While we generate the NEEDED files, check that we don't get kernel
25 + # traps at runtime because of broken install_names on Darwin.
26 rm -f "${T}"/.install_name_check_failed
27 - [[ ${CHOST} == *-darwin* ]] && find "${ED}" -type f | while IFS= read f ; do
28 - rm -f "${T}"/.NEEDED.tmp
29 - install_name=$(otool -DX "${f}")
30 - otool -LX "${f}" \
31 - | grep -v "Archive : " \
32 - | sed -e 's/^\t//' -e 's/ (compa.*$//' \
33 - | while read r ;
34 - do
35 - # skip the self reference in libraries
36 - [[ -n ${install_name} && ${install_name} == ${r} ]] && continue
37 + [[ ${CHOST} == *-darwin* ]] && scanmacho -qyRF '%a;%p;%S;%n' "${D}" | { while IFS= read l ; do
38 + arch=${l%%;*}; l=${l#*;}
39 + obj="/${l%%;*}"; l=${l#*;}
40 + install_name=${l%%;*}; l=${l#*;}
41 + needed=${l%%;*}; l=${l#*;}
42
43 - if [[ ! -e ${r} && ! -e ${D}${r} && ${r} != *"@executable_path"* ]] ; then
44 + # this is ugly, paths with spaces won't work
45 + reevaluate=0
46 + for lib in $(echo ${needed} | tr , ' '); do
47 + if [[ ! -e ${lib} && ! -e ${D}${lib} && ${lib} != *"@executable_path"* ]] ; then
48 # try to "repair" this if possible, happens because of
49 # gen_usr_ldscript tactics
50 - s=${r%usr/*}${r##*/usr/}
51 + s=${lib%usr/*}${lib##*/usr/}
52 if [[ -e ${D}${s} ]] ; then
53 - ewarn "correcting install_name from ${r} to ${s} in ${f#${D}}"
54 + ewarn "correcting install_name from ${lib} to ${s} in ${obj}"
55 install_name_tool -change \
56 - "${r}" "${s}" "${f}"
57 - r=${s} # for the NEEDED entries
58 + "${lib}" "${s}" "${D}${obj}"
59 + reevaluate=1
60 else
61 - eqawarn "QA Notice: invalid reference to ${r} in ${f}"
62 + eqawarn "QA Notice: invalid reference to ${lib} in ${obj}"
63 # remember we are in an implicit subshell, that's
64 # why we touch a file here ... ideally we should be
65 # able to die correctly/nicely here
66 touch "${T}"/.install_name_check_failed
67 fi
68 fi
69 - echo -n ",${r}" >> "${T}"/.NEEDED.tmp
70 done
71 - if [[ -f "${T}"/.NEEDED.tmp ]] ; then
72 - needed=$(< "${T}"/.NEEDED.tmp)
73 - echo "/${f#${D}} ${needed#,}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
74 - echo "/${f#${D}};${install_name};${needed#,}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.MACHO.2
75 + if [[ reevaluate == 1 ]]; then
76 + # install_name(s) have been changed, refresh data so we
77 + # store the correct meta data
78 + l=$(scanmacho -qyF '%a;%p;%S;%n' ${D}${obj})
79 + arch=${l%%;*}; l=${l#*;}
80 + obj="/${l%%;*}"; l=${l#*;}
81 + install_name=${l%%;*}; l=${l#*;}
82 + needed=${l%%;*}; l=${l#*;}
83 fi
84 - done
85 +
86 + # backwards compatability
87 + echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED
88 + # what we use
89 + echo "${arch};${obj};${install_name};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.MACHO.3
90 + done }
91 if [[ -f ${T}/.install_name_check_failed ]] ; then
92 # secret switch "allow_broken_install_names" to get
93 # around this and install broken crap (not a good idea)
94 hasq allow_broken_install_names ${FEATURES} || \
95 - die "invalid install_name found, your application will crash at runtime"
96 + die "invalid install_name found, your application or library will crash at runtime"
97 fi
98
99 # Evaluate misc gcc warnings
100
101 Modified: main/branches/prefix/pym/portage/dbapi/vartree.py
102 ===================================================================
103 --- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-09-27 05:55:10 UTC (rev 11564)
104 +++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-09-27 14:52:10 UTC (rev 11565)
105 @@ -622,10 +622,6 @@
106 return hash(self._key)
107
108 def __eq__(self, other):
109 - if isinstance(other, self.__class__):
110 - other_key = other._key
111 - else:
112 - other_key = other
113 return self._key == other_key
114
115 def _generate_object_key(self, object):
116 @@ -669,59 +665,39 @@
117 obj_properties = {}
118 lines = []
119 for cpv in self._dbapi.cpv_all():
120 - lines += self._dbapi.aux_get(cpv, ["NEEDED.MACHO.2"])[0].split('\n')
121 + lines += self._dbapi.aux_get(cpv, ["NEEDED.MACHO.3"])[0].split('\n')
122 # Cache NEEDED.* files avoid doing excessive IO for every rebuild.
123 self._dbapi.flush_cache()
124
125 if include_file:
126 lines += grabfile(include_file)
127
128 - # have to call otool for preserved libs here as they aren't
129 - # registered in NEEDED.MACHO.2 files
130 + # have to call scanmacho for preserved libs here as they aren't
131 + # registered in NEEDED.MACHO.3 files
132 if self._dbapi.plib_registry and self._dbapi.plib_registry.getPreservedLibs():
133 - otool = EPREFIX+"/usr/bin/otool"
134 + args = [EPREFIX+"/usr/bin/scanmacho", "-qF", "%a;%F;%S;%n"]
135 for items in self._dbapi.plib_registry.getPreservedLibs().values():
136 - for x in items:
137 - try:
138 - proc = subprocess.Popen([otool, "-DX", x.lstrip(".")],
139 - stdout=subprocess.PIPE)
140 - install_name = proc.communicate()[0].split("\n")[0]
141 - proc = subprocess.Popen([otool, "-LX", x.lstrip(".")],
142 - stdout=subprocess.PIPE)
143 - output = [l.lstrip() for l in proc.communicate()[0].split("\n")]
144 - except OSError:
145 - # if otool can't be found (like in an odcctools
146 - # upgrade -> binutils-config needs to update
147 - # symlinks) just ignore it, don't crash
148 - lines += [x + ";" + x.lstrip(".") + ";\n"]
149 - continue
150 + args += [x.lstrip(".") for x in items]
151 + proc = subprocess.Popen(args, stdout=subprocess.PIPE)
152 + output = [proc.communicate()[0].split("\n")]
153 + lines += output
154
155 - n = ""
156 - for l in output:
157 - if l == '':
158 - continue
159 - p = l.rfind(" (compatibility")
160 - if p != -1:
161 - l = l[:p]
162 - n += "," + l
163 -
164 - lines += [x + ";" + install_name + ";" + n.lstrip(",") + "\n"]
165 -
166 for l in lines:
167 if l.strip() == "":
168 continue
169 fields = l.strip("\n").split(";")
170 - if len(fields) < 3:
171 + if len(fields) < 4:
172 print "Error", fields
173 # insufficient field length
174 continue
175
176 # Linking an object to a library is registered by recording
177 # the install_name of the library in the object.
178 - obj = fields[0]
179 + arch = fields[0]
180 + obj = fields[1]
181 obj_key = self._ObjectKey(obj)
182 - install_name = os.path.normpath(fields[1])
183 - needed = filter(None, fields[2].split(","))
184 + install_name = os.path.normpath(fields[2])
185 + needed = filter(None, fields[3].split(","))
186
187 # build an internal structure that contains for each
188 # install_name, what libs have that install_name
189 @@ -730,16 +706,19 @@
190 # reference the install_name
191 if install_name:
192 libs.setdefault(install_name, \
193 + {arch: {"providers": set(), "consumers": set()}})
194 + libs[install_name].setdefault(arch, \
195 {"providers": set(), "consumers": set()})
196 - libs[install_name]["providers"].add(obj_key)
197 + libs[install_name][arch]["providers"].add(obj_key)
198 for x in needed:
199 libs.setdefault(x, \
200 - {"providers": set(), "consumers": set()})
201 - libs[x]["consumers"].add(obj_key)
202 + {arch: {"providers": set(), "consumers": set()}})
203 + libs[x].setdefault(arch, {"providers": set(), "consumers": set()})
204 + libs[x][arch]["consumers"].add(obj_key)
205 obj_key_cache.setdefault(obj, obj_key)
206 # All object paths are added into the obj_properties tuple
207 obj_properties.setdefault(obj_key, \
208 - (needed, install_name, set()))[2].add(obj)
209 + (arch, needed, install_name, set()))[3].add(obj)
210
211 self._libs = libs
212 self._obj_properties = obj_properties
213 @@ -798,13 +777,13 @@
214 if obj_key.file_exists():
215 # Get the install_name from LinkageMapMachO._obj_properties if
216 # it exists. Otherwise, None.
217 - _, install_name, _ = \
218 - self._obj_properties.get(obj_key, (None,)*3)
219 + arch, _, install_name, _ = \
220 + self._obj_properties.get(obj_key, (None,)*4)
221 return cache_self.cache.setdefault(obj, \
222 - (install_name, obj_key, True))
223 + (arch, install_name, obj_key, True))
224 else:
225 return cache_self.cache.setdefault(obj, \
226 - (None, obj_key, False))
227 + (None, None, obj_key, False))
228
229 rValue = {}
230 cache = _LibraryCache()
231 @@ -812,7 +791,7 @@
232
233 # Iterate over all obj_keys and their providers.
234 for obj_key, install_names in providers.items():
235 - _, _, objs = self._obj_properties[obj_key]
236 + arch, _, _, objs = self._obj_properties[obj_key]
237 # Iterate over each needed install_name and the set of
238 # library paths that fulfill the install_name to determine
239 # if the dependency is broken.
240 @@ -823,12 +802,12 @@
241 # If unsatisfied, objects associated with obj_key must
242 # be emerged.
243 validLibrary = None
244 - cachedInstallname, cachedRealpath, cachedExists = \
245 + cachedArch, cachedInstallname, cachedRealpath, cachedExists = \
246 cache.get(install_name)
247 # Check that the this library provides the needed soname. Doing
248 # this, however, will cause consumers of libraries missing
249 # sonames to be unnecessarily emerged. (eg libmix.so)
250 - if cachedInstallname == install_name:
251 + if cachedInstallname == install_name and cachedArch == arch:
252 validLibrary = cachedRealpath
253 if debug and cachedRealpath not in libraries:
254 print "Found provider outside of findProviders:", \
255 @@ -894,7 +873,7 @@
256 obj_key = self._ObjectKey(obj)
257 if obj_key not in self._obj_properties:
258 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
259 - install_name = self._obj_properties[obj_key][1]
260 + install_name = self._obj_properties[obj_key][2]
261 return (len(basename) < len(os.path.basename(install_name)))
262
263 def listLibraryObjects(self):
264 @@ -911,8 +890,9 @@
265 if not self._libs:
266 self.rebuild()
267 for install_name in self._libs:
268 - for obj_key in self._libs[install_name]["providers"]:
269 - rValue.extend(self._obj_properties[obj_key][2])
270 + for arch in self._libs[install_name]:
271 + for obj_key in self._libs[install_name][arch]["providers"]:
272 + rValue.extend(self._obj_properties[obj_key][3])
273 return rValue
274
275 def getSoname(self, obj):
276 @@ -929,7 +909,7 @@
277 self.rebuild()
278 if obj not in self._obj_key_cache:
279 raise KeyError("%s not in object list" % obj)
280 - return self._obj_properties[self._obj_key_cache[obj]][1]
281 + return self._obj_properties[self._obj_key_cache[obj]][2]
282
283 def findProviders(self, obj):
284 """
285 @@ -968,15 +948,15 @@
286 if obj_key not in self._obj_properties:
287 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
288
289 - needed, install_name, _ = self._obj_properties[obj_key]
290 + arch, needed, install_name, _ = self._obj_properties[obj_key]
291 for install_name in needed:
292 rValue[install_name] = set()
293 - if install_name not in self._libs:
294 + if install_name not in self._libs or arch not in self._libs[install_name]:
295 continue
296 # For each potential provider of the install_name, add it to
297 # rValue if it exists. (Should be one)
298 - for provider_key in self._libs[install_name]["providers"]:
299 - providers = self._obj_properties[provider_key][2]
300 + for provider_key in self._libs[install_name][arch]["providers"]:
301 + providers = self._obj_properties[provider_key][3]
302 for provider in providers:
303 if os.path.exists(provider):
304 rValue[install_name].add(provider)
305 @@ -1012,7 +992,7 @@
306 obj_key = obj
307 if obj_key not in self._obj_properties:
308 raise KeyError("%s not in object list" % obj_key)
309 - objs = self._obj_properties[obj_key][2]
310 + objs = self._obj_properties[obj_key][3]
311 else:
312 objs = set([obj])
313 obj_key = self._obj_key_cache.get(obj)
314 @@ -1026,7 +1006,7 @@
315 # other version, this lib will be shadowed and won't
316 # have any consumers.
317 if not isinstance(obj, self._ObjectKey):
318 - master_link = self._obj_properties[obj_key][1]
319 + master_link = self._obj_properties[obj_key][2]
320 try:
321 master_st = os.stat(master_link)
322 obj_st = os.stat(obj)
323 @@ -1037,12 +1017,12 @@
324 (master_st.st_dev, master_st.st_ino):
325 return set()
326
327 - _, install_name, _ = self._obj_properties[obj_key]
328 - if install_name in self._libs:
329 + arch, _, install_name, _ = self._obj_properties[obj_key]
330 + if install_name in self._libs and arch in self._libs[install_name]:
331 # For each potential consumer, add it to rValue if an object from the
332 # arguments resides in the consumer's runpath.
333 - for consumer_key in self._libs[install_name]["consumers"]:
334 - _, _, consumer_objs = \
335 + for consumer_key in self._libs[install_name][arch]["consumers"]:
336 + _, _, _, consumer_objs = \
337 self._obj_properties[consumer_key]
338 rValue.update(consumer_objs)
339 return rValue