[26461] users/pipping/merge.rb
source_changes at macosforge.org
source_changes at macosforge.org
Sun Jun 24 06:57:23 PDT 2007
Revision: 26461
http://trac.macosforge.org/projects/macports/changeset/26461
Author: pipping at macports.org
Date: 2007-06-24 06:57:23 -0700 (Sun, 24 Jun 2007)
Log Message:
-----------
initial upload of <merge.rb>
merge.rb is designed to merge two or more trees of single-arch destdirs
into a single destdir of universal binaries.
build_coreutils.sh serves as a test, 'port destroot openssl +universal' can
be used as well (port install zlib +universal is required)
see ./merge.rb --help for the usage
Added Paths:
-----------
users/pipping/merge.rb
Added: users/pipping/merge.rb
===================================================================
--- users/pipping/merge.rb (rev 0)
+++ users/pipping/merge.rb 2007-06-24 13:57:23 UTC (rev 26461)
@@ -0,0 +1,221 @@
+#!/usr/bin/env ruby -w
+
+# Copyright (c) 2007 Elias Pipping
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+require 'fileutils'
+require 'find'
+require 'optparse'
+require 'set'
+
+###
+# we need GNU file with Apple's patches applied, available here:
+# http://www.opensource.apple.com/darwinsource/Current/file-6.2/patches/
+#
+# Its output might span multiple lines, causing problems when parsing, even
+# with `file -b`, hence we'll assume we're not passed universal binaries
+# TODO: do a real check, maybe using `lipo -info` (fails on non-Mach-O files)
+FILE="/usr/bin/file"
+
+class MergeArguments < Hash
+ def initialize(args)
+ super()
+
+ # set up defaults
+ self[:dry_run] = false
+ self[:force] = false
+ self[:verbose] = false
+
+ self[:exclude] = Set.new << '.svn' << 'CVS'
+ self[:root] = Dir.pwd
+
+ opts = OptionParser.new do |opts|
+ opts.banner = "Usage: #$0 [options] <arch> <arch> [<arch> ...]"
+
+ opts.on('-r', '--root DIRECTORY', 'specify root directory') do |root|
+ self[:root] = root || Dir.pwd
+ end
+
+# opts.on('-o', '--output DIRECTORY', 'specify output directory') do |out|
+# self[:output] = File.expand_path(out) || File.join(self[:root], 'out')
+# end
+
+ opts.on('-e', '--exclude NAMES', 'specify names of files/directories to exclude') do |exclude|
+ self[:exclude] = Set.new
+ exclude.split(" ").each do |item|
+ self[:exclude] << item
+ end
+ end
+
+ opts.on('-d', '--dry-run', 'perform a dry run') do
+ self[:dry_run] = true
+ end
+
+ opts.on('-f', '--force', 'force writing, ignoring collisions') do
+ self[:force] = true
+ end
+
+ opts.on('-v', '--verbose', 'enable verbose output') do
+ self[:verbose] = true
+ end
+
+ opts.on_tail('-h', '--help', 'display this help and exit') do
+ puts opts
+ exit
+ end
+ end
+
+ opts.parse!(args)
+ end
+end
+
+arguments = MergeArguments.new(ARGV)
+
+ARGS=ARGV.uniq
+
+def true_for_all? (filepath, args, &block)
+ result=true
+ ARGS.each {|arch|
+ result=false unless yield(File.join(args[:root], arch), filepath, arch)
+ }
+ return result
+end
+
+def lipo (filepath,architectures,args)
+ lipoargs = Array.new
+ architectures.each {|arch|
+ lipoargs << sprintf('-arch %s %s', arch, File.join(
+ args[:root], arch, filepath
+ ))
+ }
+ lipotarget=File.join(args[:root], 'out', filepath)
+ lipocmd = sprintf(
+ 'lipo %s -create -o %s',
+ lipoargs.join(' '),
+ lipotarget
+ )
+ if !File.exist?(lipotarget) or args[:force]
+ puts lipocmd if args[:verbose]
+ system lipocmd if !args[:dry_run]
+ end
+end
+
+original_dir=Dir.pwd
+processed=Set.new
+
+if File.directory?(File.expand_path(arguments[:root]))
+ ARGS.each {|architecture|
+ FileUtils.cd original_dir, :verbose => false
+ if File.directory? File.join(
+ File.expand_path(arguments[:root]), architecture
+ )
+ FileUtils.cd(
+ File.join(arguments[:root], architecture),
+ :verbose => arguments[:verbose]
+ )
+ Find.find('.') {|path|
+ arguments[:exclude].each {|exclude_me|
+ Find.prune if File.basename(path) == exclude_me
+ }
+ unless processed.include? path
+ my_dir=File.dirname(File.join(arguments[:root], 'out', path))
+ # TODO: what if ppc/foo is a dir and i386/foo is a file (symlink)? (1)
+ unless File.exist? my_dir
+ FileUtils.mkdir_p(
+ my_dir,
+ :verbose => arguments[:verbose],
+ :noop => arguments[:dry_run]
+ )
+ end
+ if true_for_all?(path, arguments) {|dir,filename,arch|
+ File.exist?(File.join(dir, filename))
+ }
+ unless true_for_all?(path, arguments) {|dir,filename,arch|
+ File.directory?(File.join(dir, filename))
+ }
+
+ if true_for_all?(path, arguments) {|dir,filename,arch|
+ FileUtils.identical?(
+ File.join(dir, path),
+ File.join(arguments[:root], ARGS[0], path)
+ )
+ }
+ copytarget=File.join(arguments[:root],'out',path)
+ if !File.exist?(copytarget) or arguments[:force]
+ FileUtils.cp(
+ File.join(arguments[:root],ARGS[0],path),
+ copytarget,
+ :preserve => !arguments[:force],
+ :verbose => arguments[:verbose],
+ :noop => arguments [:dry_run]
+ )
+ end
+ else
+ # TODO: make this not-blindly lipo but check filetypes / archs
+ # TODO: beware of symlinks!
+ case File.basename path
+ when /\.dylib(\.\d*)*/, /\.so(\.\d*)*/, /\.a$/
+ lipo(path,ARGS,arguments)
+ when /\.h$/, /\.hpp$/
+ # TODO: handle header files
+ when /\.pc$/
+ # TODO: handle pkgconfig files
+ when /\.sh$/
+ # TODO: handle shell scripts
+ else
+ case %x{#{FILE} -b "#{File.join(arguments[:root],ARGS[0],path)}"}
+ when sprintf("Mach-O executable %s\n", ARGS[0])
+ if true_for_all?(path, arguments) {|dir,filename,arch|
+ %x{#{FILE} -b "#{File.join(dir,path)}"} == sprintf("Mach-O executable %s\n", arch)
+ }
+ lipo(path,ARGS,arguments)
+ else
+ # one of the files is a mach-o file that matches its
+ # desired architecture but one of the others doesn't
+ end
+ # else
+ # TODO: deal with whatever else can differ
+ end
+ end
+ end
+ else
+ # TODO: at least one of the files is a directory (1)
+ end
+ else
+ # TODO: a file is not present in all trees. what's wrong?
+ end
+ processed << path
+ end
+ }
+ else
+ raise sprintf(
+ 'architecture missing from root directory: %s',
+ architecture
+ )
+ end
+ }
+else
+ raise sprintf(
+ 'invalid root directory: %s',
+ arguments[:root]
+ )
+end
+
+FileUtils.cd original_dir, :verbose => false
Property changes on: users/pipping/merge.rb
___________________________________________________________________
Name: svn:executable
+ *
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070624/8f2b599d/attachment.html
More information about the macports-changes
mailing list