root/nicotine-app/trunk/nicotine/x11-rebuild

Revision 33, 4.7 KB (checked in by vasi, 4 years ago)

new module

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl
2use warnings;
3use strict;
4
5use English;
6use Storable;
7use File::Find;
8use File::Spec::Functions;
9use Fink::Command qw(touch);
10use Getopt::Long;
11use DB_File;
12
13my $DEBUG = 1;
14my $prefix = '/sw';
15my $db_path = '/Users/vasi/Hacking/Misc/x11-compat';
16my $x11_dir = '/Users/vasi/Hacking/fink-apps/x11/';
17my @prune;
18my $noprune;
19
20{
21        my $cached_fh;
22        my $cached_cmd;
23       
24        sub next_object {
25                my $gen_cmd = shift;
26               
27                if (!defined $cached_cmd || $cached_cmd ne $gen_cmd) {
28                        $cached_cmd = $gen_cmd;
29                        close $cached_fh if defined $cached_fh;
30                        undef $cached_fh;
31                        open $cached_fh, "$gen_cmd |"
32                                or die "Can't get file list: $!\n";
33                }
34               
35                while (my $file = <$cached_fh>) {
36                        chomp $file;
37                        return $file if is_macho($file);
38                }
39               
40                # No more left
41                close $cached_fh;
42                undef $cached_cmd;
43                return undef;
44        }
45}
46
47sub version_ok {
48        my ($vers, $compatl) = @_;
49        my @versl = split(/\./, $vers);
50        for my $i (0..2) {
51                if ($versl[$i] > $compatl->[$i]) {
52                        return 0;
53                } elsif ($versl[$i] < $compatl->[$i]) {
54                        return 1;
55                }
56        }
57        return 1;
58}
59
60{
61        my $test_compats;
62       
63        sub file_ok {
64                my $file = shift;
65               
66                $test_compats = retrieve($db_path) unless defined $test_compats;
67               
68                open OTOOL, "otool -L \Q$file\E |" or die "Can't run otool: $!\n";
69                my @otool = <OTOOL>;
70                close OTOOL;
71               
72                for my $libline (@otool) {
73                        $libline =~ m,X11R6/lib/(\S+)\.dylib.*
74                                        compatibility\sversion\s*([\d.]+),x or next;
75                        unless (exists $test_compats->{$1}
76                                        && version_ok($2, $test_compats->{$1})) {
77                                return 0;
78                        }
79                }
80               
81                return 1;
82        }
83}
84
85sub switch_x11 {
86        my $op = shift;
87       
88        if ( $EUID != 0 ) {
89                # We need root
90                exec('/usr/bin/sudo', '-H', $0, $op)
91                        or die "$0: couldn't become root: $!";
92        }
93       
94        my $patch = catfile($x11_dir, "include-2apple.patch.gz");
95        my $libs = catfile($x11_dir, "lib-$op.tgz");
96        my $patch_op = $op eq 'apple' ? '' : '-R';
97       
98        print "PATCHING\n";
99        chdir '/usr/X11R6/include';
100        if (! -f ".dist-$op") {
101                system("gzcat \Q$patch\E | patch -N $patch_op -p2") == 0
102                        or die "Patch failed: $!\n";
103                system("rm -v .dist* ; touch .dist-$op") == 0
104                        or die "Setting dist failed: $!\n";
105        }
106       
107        chdir '/usr/X11R6/lib';
108        print "\n\n\nREMOVING\n";
109        system("ls | grep -v ^X11 | xargs rm -rv") == 0
110                or die "Remove failed: $!\n";
111        print "\n\n\nRESTORING\n";
112        system("tar -xvzf \Q$libs\E") == 0
113                or die "Tar failed: $!\n";
114}
115
116{
117        my $magic = pack('L', 0xfeedface);
118       
119        sub is_macho {
120                my $file = shift;
121                return 0 unless -f $file && ! -l $file;
122               
123                my $header;
124                open FILE, $file or warn "Can't open $_: $!\n" && return 0;
125                read FILE, $header, 4;
126                close FILE;
127               
128                return (defined $header && $header eq $magic);
129        }
130}
131
132GetOptions(
133        'p|prefix=s'    => \$prefix,
134        'q|quiet'               => sub { $DEBUG = 0; },
135        'compat=s'              => \$db_path,
136        'prune=s'               => \@prune,
137        'noprune'               => \$noprune,
138) or die "Can't get options\n";
139
140my $op = shift;
141if ($op eq 'generate') {
142        # Must have Apple's X11 installed
143        my $compats = {};
144        while (my $lib = next_object('find /usr/X11R6/lib')) {
145                open OTOOL, "otool -L \Q$lib\E | tail +2 | head -n1 |"
146                        or die "Can't run otool: $!\n";
147                my $line = <OTOOL>;
148                close OTOOL;
149               
150                $line =~ m,X11R6/lib/(\S+)\.dylib.*compatibility\sversion\s*([\d.]+),x
151                        or die "Can't interpret compat version: $line\n";
152                $compats->{$1} = [ split(/\./, $2) ];
153        }
154        store($compats, $db_path);
155       
156} elsif ($op eq 'check') {
157        my @pkgs = @ARGV;
158        my @reb;
159               
160        print "CHECKING:\n" if $DEBUG;
161        PKG: for my $pkg (sort @pkgs) {
162                print "  pkg $pkg\n" if $DEBUG;
163               
164                while (my $file = next_object("dpkg -L \Q$pkg\E")) {
165                        next unless $file =~ m,^$prefix/,;
166                       
167                        print "    file $file\n" if $DEBUG;
168                        unless (file_ok($file)) {
169                                push @reb, $pkg;
170                                print "    status rebuild\n" if $DEBUG;
171                                next PKG;
172                        }
173                }
174                print "    status ok\n" if $DEBUG;
175        }
176       
177        print "\nPACKAGES: " if $DEBUG;
178        print join(' ', @reb), "\n";
179} elsif ($op eq 'apple' || $op eq 'xorg') {
180        switch_x11($op);
181} elsif ($op eq 'checkall') {
182        my $checkeddb = shift;
183        my %checked;
184        tie %checked, 'DB_File', $checkeddb or die "Can't open DB: $!\n";
185#use Data::Dumper; print Dumper(\%checked); exit 0;
186        my @bad;
187       
188        my $realp = (-l $prefix ? readlink $prefix : $prefix);
189        push @prune, map { "$realp/$_" }
190                qw/share fink var etc src/ unless defined $noprune;
191       
192        my %prune = map { $_ => 1 } @prune;
193        print "CHECKING:\n" if $DEBUG;
194        find({
195                wanted => sub {
196                        my $file = $_;
197                        if (exists $prune{$file}) {
198                                print " prune $file\n" if $DEBUG;
199                                $File::Find::prune = 1;
200                                return;
201                        }
202                        return if exists $checked{$file};
203                        my $macho = is_macho($file);
204                        print " file $file\n" if $macho && $DEBUG;
205                        if ($macho && !file_ok($file)) {
206                                print "   bad!\n" if $DEBUG;
207                                push @bad, $file;
208                        } else {
209                                $checked{$file} = 1;
210                        }
211                },
212                no_chdir => 1,
213        }, $realp);
214       
215        print "\nBAD FILES:\n" if $DEBUG;
216        print "$_\n" foreach @bad;
217} else {
218        die "Don't know what to do!\n";
219}
220
221
222       
Note: See TracBrowser for help on using the browser.