xref: /trunk/main/solenv/bin/linkoo (revision e76eebc6)
1:
2    eval 'exec perl -S $0 ${1+"$@"}'
3        if 0;
4
5#**************************************************************
6#
7#  Licensed to the Apache Software Foundation (ASF) under one
8#  or more contributor license agreements.  See the NOTICE file
9#  distributed with this work for additional information
10#  regarding copyright ownership.  The ASF licenses this file
11#  to you under the Apache License, Version 2.0 (the
12#  "License"); you may not use this file except in compliance
13#  with the License.  You may obtain a copy of the License at
14#
15#    http://www.apache.org/licenses/LICENSE-2.0
16#
17#  Unless required by applicable law or agreed to in writing,
18#  software distributed under the License is distributed on an
19#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20#  KIND, either express or implied.  See the License for the
21#  specific language governing permissions and limitations
22#  under the License.
23#
24#**************************************************************
25#
26#    This app makes it easy to link a live build
27# set into an install set. Then your devel iteration
28# is: 'build', execute.
29#
30#*************************************************************************
31
32# ends up in program/ooenv
33( $moz_lib = `pkg-config --variable=libdir mozilla-nss` ) =~ tr/\n/:/;
34$env_script = '
35java_path=`./javaldx`
36export LD_LIBRARY_PATH=".:$java_path:' . $moz_lib . '$LD_LIBRARY_PATH"
37ulimit -c unlimited
38export PATH=".:$PATH"
39export GNOME_DISABLE_CRASH_DIALOG=1
40export STAR_RESOURCEPATH=`pwd`/resource
41# debugging assistance
42export OOO_FORCE_SYSALLOC=1
43export MALLOC_CHECK_=2
44export OOO_DISABLE_RECOVERY=1
45';
46
47$program_dir = 'program';
48$program_dir = 'MacOS' if ($ENV{OS} eq 'MACOSX');
49
50my @exceptions = ( 'cppuhelper', 'sunjavaplugin', 'libjvmfwk' );
51
52%replaceable = (
53	$program_dir => '\.so',
54    $program_dir . '/resource' => '\.res$',
55    $program_dir . '/classes' => '\.jar$',
56    'share/config' => '\.zip$',
57#    'share/uno_packages' => '\.zip$'
58);
59
60# strangely enough, OSX has those small differences...
61$replaceable{$program_dir} = '\.dylib$' if ($ENV{OS} eq 'MACOSX');
62
63@search_dirs = ( 'lib', 'bin', 'class' );
64
65@known_duplicates = ( 'db.jar', 'libi18n' );
66
67sub sniff_target($)
68{
69    my $build_dir = shift;
70    my ($dirhandle, $fname);
71    my ($target, $libver, $lang) = ( 'unxlngi4.pro', '680', 'en-US' ); # defaults
72
73    opendir ($dirhandle, $build_dir) || die "Can't open $build_dir";
74    while ($fname = readdir ($dirhandle)) {
75	$fname =~ /Set.sh$/ || next;
76
77	my $file;
78	open ($file, "$build_dir/$fname") || die "Can't open $build_dir/$fname";
79	while (<$file>) {
80	    /\s*(\S+)\s*=\s*\"(\S+)\"/ || next;
81	    if ($1 eq 'INPATH') {
82		$target = $2;
83	    }
84	    if ($1 eq 'UPD') {
85		$libver = $2;
86	    }
87	}
88	close ($file);
89    }
90
91    closedir ($dirhandle);
92
93    print "Sniffed target: $target, $libver\n";
94
95    return ($target, $libver, $lang);
96}
97
98sub build_installed_list($)
99{
100    my $path = shift;
101    my %files = ();
102
103    for my $suffix (keys %replaceable) {
104	my $dirname = "$path/$suffix";
105	my $dirhandle;
106	my $pattern = $replaceable{$suffix};
107	if (opendir ($dirhandle, $dirname)) {
108	    while (my $fname = readdir ($dirhandle)) {
109		$fname =~ m/$pattern/ || next;
110
111		my $skip = 0;
112		for $pattern (@exceptions) {
113		    $fname =~ /$pattern/ || next;
114		    $skip = 1;
115		}
116		$files{$fname} = $dirname if !$skip;
117	    }
118	    closedir ($dirhandle);
119	} else {
120	    print "Couldn't find '$dirname': skipping\n";
121	}
122    }
123    return \%files;
124}
125
126sub check_create_linked($)
127{
128    my $path = shift;
129    my $linked_dir = "$path/linked";
130    if (! -d $linked_dir) {
131	mkdir $linked_dir || die "Can't make $linked_dir: $!";
132    }
133}
134
135sub do_link($$$$@)
136{
137    my $src = shift;
138    my $dest = shift;
139    my $src_name = shift;
140    my $dest_name = shift;
141    my $dont_check_link = shift;
142
143    if (-l "$dest/$dest_name" ) {
144	my $link = readlink ("$dest/$dest_name");
145	if ($link =~ /^\//) { # Absolute path
146	    if (!$dry_run) {
147		# re-write the link
148		unlink ("$dest/$dest_name");
149		symlink ("$src/$src_name", "$dest/$dest_name") || die "Failed to symlink: $!";
150		print " [$dest_name]";
151	    } else {
152		print "re-make link $src/$src_name => $dest/$dest_name\n";
153	    }
154	} elsif ($dry_run) {
155	    print "skipping symbolic link $dest/$dest_name -> $link\n";
156	}
157    } else {
158	check_create_linked ($dest);
159	if (!$dry_run) {
160	    # move / write the link
161	    rename ("$dest/$dest_name", "$dest/linked/$dest_name") ||
162		defined $dont_check_link || die "Failed rename of $dest/$dest_name: $!";
163
164	    symlink ("$src/$src_name", "$dest/$dest_name") || die "Failed to symlink: $!";
165	    print " $dest_name";
166	} else {
167	    print "move / symlink $src/$src_name => $dest/$dest_name\n";
168	}
169    }
170}
171
172sub scan_and_link_files($$$)
173{
174    my $build_path = shift;
175    my $installed_files = shift;
176    my $target = shift;
177
178    my @modules = ();
179    my $dirh_toplevel;
180    opendir ($dirh_toplevel, $build_path) || die "Can't open '$build_path': $!";
181    while (my $subdir = readdir ($dirh_toplevel)) {
182	$subdir =~ m/\./ && next; # eg. vcl.old,
183	my $test = "$build_path/$subdir/$target";
184	-d $test || next;
185	push @modules, $test;
186    }
187    closedir ($dirh_toplevel);
188
189# FIXME: re-implement the $product functionality
190    my $module;
191    my %build_files;
192    for $module (@modules) {
193	for $elem (@search_dirs) {
194	    my $dirh_module;
195	    my $module_path = "$module/$elem";
196	    if (opendir ($dirh_module, $module_path)) {
197			while (my $file = readdir($dirh_module)) {
198				if (defined $installed_files->{$file}) {
199					if (defined $build_files{$file}) {
200						my $known = 0;
201						for my $regexp (@known_duplicates) {
202							if ($file =~ m/$regexp/) {
203								$known = 1;
204							}
205						}
206						if (!$known) {
207							print "Unknown duplicate file '$file' in: '" .
208							$build_files{$file} . "' vs '" .
209							$module_path . "' in module $module\n";
210							exit (1);
211						}
212					}
213					$build_files{$file} = $module_path;
214				}
215			}
216		}
217	    closedir ($dirh_module);
218	}
219    }
220
221    for my $file (keys %build_files) {
222	my $src = $build_files{$file};
223	my $dest = $installed_files->{$file};
224
225	do_link ($src, $dest, $file, $file);
226    }
227    print "\n";
228}
229
230sub evilness($)
231{
232    my $doit = shift;
233    my $name = 'librecentfile.so';
234    my $src  = "$OOO_BUILD/shell/$TARGET/lib/$name";
235    my $dest = "$OOO_BUILD/sfx2/$TARGET/lib/$name";
236
237    if ($doit eq 'undo') {
238	if (-l $dest) {
239	    print " unlink $name\n";
240	    unlink $dest;
241	}
242    } else {
243	$doit eq 'do' || die;
244        if (-f $src) {
245	    print " link $name\n";
246	    symlink $src, $dest;
247	}
248    }
249}
250
251sub link_iso_res()
252{
253    print "Special iso.res case: ";
254    my $ooo_res="$OOO_INSTALL/" . $program_dir . "/resource/ooo".$LIBVER.$LANG.".res";
255    my $star_res="$OOO_INSTALL/" . $program_dir . "/resource/iso".$LIBVER.$LANG.".res";
256    if (-l $ooo_res && -l $star_res) {
257	if ($dry_run) {
258	    print "link $ooo_res to $star_res";
259	} else {
260	    unlink ($star_res);
261	    symlink ($ooo_res, $star_res);
262	    print "clobbered";
263	}
264    }
265    print "\n";
266}
267
268# Hack for (renamed) types.rdb (types.db)
269sub link_types_rdb()
270{
271    print "Types.rdb case:";
272    my $src  = "$OOO_BUILD/offapi/$TARGET/ucr";
273    my $dest = "$OOO_INSTALL/" . $program_dir;
274    do_link ($src, $dest, 'types.db', 'types.rdb');
275    print "\n";
276}
277
278# link installed files back into src tree:
279sub link_soffice_bin_files()
280{
281    my $dest;
282    my $src = "$OOO_INSTALL/" . $program_dir;
283
284    print "soffice files";
285    $dest = "$OOO_BUILD/desktop/$TARGET/bin";
286    do_link ($src, $dest, 'soffice', 'soffice.bin', 1);
287    do_link ($src, $dest, 'bootstraprc', 'bootstraprc', 1);
288    do_link ($src, $dest, 'intro.bmp', 'intro.bmp', 1);
289    do_link ("$OOO_INSTALL", "$OOO_BUILD/desktop/$TARGET", 'share', 'share', 1);
290
291    print "\n";
292}
293
294my $a;
295my $usage = 0;
296for $a (@ARGV) {
297
298# options
299    if ($a =~ /--product/) {
300	$product = 1;
301    } elsif ($a =~ /--dry-run/) {
302        $dry_run = 1;
303    } elsif (($a eq '--help') || ($a eq '-h')) {
304	$usage = 1;
305
306# ordered arguments
307    } elsif (!defined $OOO_INSTALL) {
308	$OOO_INSTALL = $a;
309    } elsif (!defined $OOO_BUILD) {
310	$OOO_BUILD = $a;
311    } else {
312	print "Unknown argument '$a'\n";
313	$usage = 1;
314    }
315}
316
317if (!defined $OOO_BUILD && defined $ENV{SRC_ROOT}) {
318    $OOO_BUILD = $ENV{SRC_ROOT};
319}
320
321if ($usage || !defined $OOO_INSTALL || !defined $OOO_BUILD) {
322    printf "Usage: linkoo </path/to/ooo/install> [</path/to/ooo/build/tree>] [--product] [--dry-run]\n";
323    exit (1);
324}
325
326substr ($OOO_INSTALL, 0, 1) eq '/' || die "linkoo requires absolute paths ($OOO_INSTALL does not qualify)";
327substr ($OOO_BUILD, 0, 1)   eq '/' || die "linkoo requires absolute paths ($OOO_BUILD does not qualify)";
328
329-d $OOO_INSTALL || die "No such directory $OOO_INSTALL";
330-w $OOO_INSTALL || die "You need write access to $OOO_INSTALL";
331-d $OOO_BUILD || die "No such directory $OOO_BUILD";
332-d "$OOO_INSTALL/" . $program_dir . "/resource" || die "$OOO_INSTALL doesn't look like an OO install";
333
334($TARGET, $LIBVER, $LANG) = sniff_target ($OOO_BUILD);
335
336evilness ('undo');
337
338my $installed_files = build_installed_list ($OOO_INSTALL);
339
340scan_and_link_files ($OOO_BUILD, $installed_files, $TARGET);
341link_iso_res();
342link_types_rdb();
343link_soffice_bin_files();
344
345if (!-f "$OOO_INSTALL/" . $program_dir . "/ooenv") {
346    print "Creating '$OOO_INSTALL/", $program_dir, "/ooenv'\n";
347    open ($ooenv, ">$OOO_INSTALL/" . $program_dir . "/ooenv") || die "Can't open $OOO_INSTALL/" . $program_dir . "/ooenv: $!";
348    print $ooenv $env_script;
349    close ($ooenv);
350}
351
352evilness ('do');
353
354print "\nlinkoo finished, please don't forget to source ooenv before ./soffice.\n";
355