On 8/3/10 10:34 PM, Tomas Carnecky wrote:
> Especially difficult was to figure out which extensions depend on what,
> as you see in patch 3, OS_LIB depends on FIXES_LIB (EnabledCursor).
> Then also RENDER_LIB depends on OS_LIB (x_sha1_* methods) and there
> may be other dependencies which I'm not aware of. I'd like to see
> a list or document or even just a header which describes what each
> extension expects and relies on. I can do that for DPMS (now that I've

The attached ruby script scans all archives (*.a), extracts which
symbols are defined and which symbols are referenced. Then it reports
which other archives each archive depends on. When run with -v
(verbose), then it also lists referenced symbols and where the symbols
have been declared. Example:

Report for libos
  PictureCmapPolicy -> librender, libxorg
  serverClient -> libdix, libxorgxkb, libxorg
  ddxProcessArgument -> libcommon, libxorg
  ...
  Dependencies: libdixmods, libxkb, libdix, libXext, libxfixes,
libcommon, librender

You see that libos depends not only on libxfixes, but also librender,
libXext and libraries from the Xorg DDX. For each symbol you also see
where the symbol is defined. It lists all archives where each symbol was
found, and because libxorg includes many other libraries the symbols are
also defined there. However, the script tries to be smart and only put
the archive where the symbol was originally defined to the final
dependencies list (this is why you don't see libxorg there).

Run the script as: ./find-deps.rb [-v] [path which to scan for archives,
default is cwd]
I hope someone finds this useful.

tom
#!/usr/bin/env ruby

require 'find'

@root = "."
@verbose = false

# Parse commandline options
ARGV.each do |arg|
  if arg == "-v"
    @verbose = true
  else
    @root = arg
  end
end

# Set archives and the symbols the archives reference. The
# symbol name is the key in the hash, so it appears only
# once even if it is referenced by multiple objects within
# the archive.
@refs = { } # "archive" => { "symbol" => true, ... }

# Set of symbols and the archives in which they are defined
# A symbol may be defined in multiple archives, some
# libraries include other libraries. The archive list is
# sorted and the first element is the archive where
# the symbol was originally defined.
@defs = { } # { "symbol" => [ archive, ... ] }

# Method which adds the symbol to the correct set, depending
# on the type.
def update(archive, symbol, type)
  if [ "U" ].include?(type)
    if @refs[archive]
      @refs[archive][symbol] = true
    else
      @refs[archive] = { symbol => true }
    end
  elsif [ "B", "C", "D", "G", "S", "T" ].include?(type)
    if @defs[symbol]
      @defs[symbol] << archive
    else
      @defs[symbol] = [ archive ]
    end
  end
end

# List all symbols in the archive and update the
# corresponding set.
def archive(path)
  # Extract the archive name from the path
  archive = path.match(/\/([^\/]*)\.a$/)[1]

  results = %x[nm -a "#{path}"].lines
  results.each do |line|
    if line =~ /(.{16}) (\w) ([\w]*)$/ then
      update(archive, $3, $2)
    end
  end
end

# Scan all *.a files and parse their content
Find.find(@root) do |path|
  if FileTest.file?(path) and path =~ /\.a$/
    archive(path)
  end
end

# Report dependencies for the given archive
def report(archive)
  puts "Report for #{archive}:"

  deps = { }
  @refs[archive].keys.each do |symbol|
    if @defs[symbol]
      # Skip symbols which are resolved in the same archive
      next if @defs[symbol].include?(archive)

      puts "  #{symbol} -> #...@defs[symbol].join(", ")}" if @verbose
      de...@defs[symbol].first] = true
    end
  end

  puts "  Dependencies: #{deps.keys.join(", ")}"
end

# Clean up and sort the archive lists in the @defs set
@defs.keys.each do |symbol|
  # Some symbols are defined multiple times in an archive
  @defs[symbol].uniq!

  # Sort the list so that the archive where the symbol
  # is originally defined comes first. Actually, we do
  # it the other way around: move archives which include
  # other archives to the end of the list.
  ca = [ "libxorgxkb", "libcommon", "libxorg" ]
  @defs[symbol].sort! do |a,b|
    if ca.index(a) and ca.index(b)
      ca.index(a) <=> ca.index(b)
    elsif ca.index(a)
      1
    elsif ca.index(b)
      -1
    else
      a <=> b
    end
  end
end

# Make a report for each archive
@refs.keys.each do |archive|
  report(archive)
end
_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to