1cdf0e10cSrcweir: 2cdf0e10cSrcweireval 'exec perl -wS $0 ${1+"$@"}' 3cdf0e10cSrcweir if 0; 4*7e90fac2SAndrew Rist#************************************************************** 5*7e90fac2SAndrew Rist# 6*7e90fac2SAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 7*7e90fac2SAndrew Rist# or more contributor license agreements. See the NOTICE file 8*7e90fac2SAndrew Rist# distributed with this work for additional information 9*7e90fac2SAndrew Rist# regarding copyright ownership. The ASF licenses this file 10*7e90fac2SAndrew Rist# to you under the Apache License, Version 2.0 (the 11*7e90fac2SAndrew Rist# "License"); you may not use this file except in compliance 12*7e90fac2SAndrew Rist# with the License. You may obtain a copy of the License at 13*7e90fac2SAndrew Rist# 14*7e90fac2SAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 15*7e90fac2SAndrew Rist# 16*7e90fac2SAndrew Rist# Unless required by applicable law or agreed to in writing, 17*7e90fac2SAndrew Rist# software distributed under the License is distributed on an 18*7e90fac2SAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19*7e90fac2SAndrew Rist# KIND, either express or implied. See the License for the 20*7e90fac2SAndrew Rist# specific language governing permissions and limitations 21*7e90fac2SAndrew Rist# under the License. 22*7e90fac2SAndrew Rist# 23*7e90fac2SAndrew Rist#************************************************************** 24*7e90fac2SAndrew Rist 25*7e90fac2SAndrew Rist 26cdf0e10cSrcweir 27cdf0e10cSrcweir# 28cdf0e10cSrcweir# deliver.pl - copy from module output tree to solver 29cdf0e10cSrcweir# 30cdf0e10cSrcweir 31cdf0e10cSrcweiruse Cwd; 32cdf0e10cSrcweiruse File::Basename; 33cdf0e10cSrcweiruse File::Copy; 34cdf0e10cSrcweiruse File::DosGlob 'glob'; 35cdf0e10cSrcweiruse File::Path; 36cdf0e10cSrcweiruse File::Spec; 37cdf0e10cSrcweir 38cdf0e10cSrcweir#### script id ##### 39cdf0e10cSrcweir 40cdf0e10cSrcweir( $script_name = $0 ) =~ s/^.*\b(\w+)\.pl$/$1/; 41cdf0e10cSrcweir 42cdf0e10cSrcweir$id_str = ' $Revision: 275594 $ '; 43cdf0e10cSrcweir$id_str =~ /Revision:\s+(\S+)\s+\$/ 44cdf0e10cSrcweir ? ($script_rev = $1) : ($script_rev = "-"); 45cdf0e10cSrcweir 46cdf0e10cSrcweir 47cdf0e10cSrcweir#### globals #### 48cdf0e10cSrcweir 49cdf0e10cSrcweir### valid actions ### 50cdf0e10cSrcweir# if you add a action 'foo', than add 'foo' to this list and 51cdf0e10cSrcweir# implement 'do_foo()' in the implemented actions area 52cdf0e10cSrcweir@action_list = ( # valid actions 53cdf0e10cSrcweir 'copy', 54cdf0e10cSrcweir 'dos', 55cdf0e10cSrcweir 'addincpath', 56cdf0e10cSrcweir 'linklib', 57cdf0e10cSrcweir 'mkdir', 58cdf0e10cSrcweir 'symlink', 59cdf0e10cSrcweir 'touch' 60cdf0e10cSrcweir ); 61cdf0e10cSrcweir 62cdf0e10cSrcweir# copy filter: files matching these patterns won't be copied by 63cdf0e10cSrcweir# the copy action 64cdf0e10cSrcweir@copy_filter_patterns = ( 65cdf0e10cSrcweir ); 66cdf0e10cSrcweir 67cdf0e10cSrcweir$strip = ''; 68cdf0e10cSrcweir$is_debug = 0; 69cdf0e10cSrcweir 70cdf0e10cSrcweir$error = 0; 71cdf0e10cSrcweir$module = 0; # module name 72cdf0e10cSrcweir$repository = 0; # parent directory of this module 73cdf0e10cSrcweir$base_dir = 0; # path to module base directory 74cdf0e10cSrcweir$dlst_file = 0; # path to d.lst 75cdf0e10cSrcweir$ilst_ext = 'ilst'; # extension of image lists 76cdf0e10cSrcweir$umask = 22; # default file/directory creation mask 77cdf0e10cSrcweir$dest = 0; # optional destination path 78cdf0e10cSrcweir$common_build = 0; # do we have common trees? 79cdf0e10cSrcweir$common_dest = 0; # common tree on solver 80cdf0e10cSrcweir 81cdf0e10cSrcweir@action_data = (); # LoL with all action data 82cdf0e10cSrcweir@macros = (); # d.lst macros 83cdf0e10cSrcweir@addincpath_list = (); # files which have to be filtered through addincpath 84cdf0e10cSrcweir@dirlist = (); # List of 'mkdir' targets 85cdf0e10cSrcweir@zip_list = (); # files which have to be zipped 86cdf0e10cSrcweir@common_zip_list = (); # common files which have to be zipped 87cdf0e10cSrcweir@log_list = (); # LoL for logging all copy and link actions 88cdf0e10cSrcweir@common_log_list = (); # LoL for logging all copy and link actions in common_dest 89cdf0e10cSrcweir$logfiledate = 0; # Make log file as old as newest delivered file 90cdf0e10cSrcweir$commonlogfiledate = 0; # Make log file as old as newest delivered file 91cdf0e10cSrcweir 92cdf0e10cSrcweir$files_copied = 0; # statistics 93cdf0e10cSrcweir$files_unchanged = 0; # statistics 94cdf0e10cSrcweir 95cdf0e10cSrcweir$opt_force = 0; # option force copy 96cdf0e10cSrcweir$opt_check = 0; # do actually execute any action 97cdf0e10cSrcweir$opt_zip = 0; # create an additional zip file 98cdf0e10cSrcweir$opt_silent = 0; # be silent, only report errors 99cdf0e10cSrcweir$opt_verbose = 0; # be verbose (former default behaviour) 100cdf0e10cSrcweir$opt_log = 1; # create an additional log file 101cdf0e10cSrcweir$opt_link = 0; # hard link files into the solver to save disk space 102cdf0e10cSrcweir$opt_deloutput = 0; # delete the output tree for the project once successfully delivered 103cdf0e10cSrcweir$opt_checkdlst = 0; 104cdf0e10cSrcweir$delete_common = 1; # for "-delete": if defined delete files from common tree also 105cdf0e10cSrcweir 106cdf0e10cSrcweirif ($^O ne 'cygwin') { # iz59477 - cygwin needes a dot "." at the end of filenames to disable 107cdf0e10cSrcweir $maybedot = ''; # some .exe transformation magic. 108cdf0e10cSrcweir} else { 109cdf0e10cSrcweir my $cygvernum = `uname -r`; 110cdf0e10cSrcweir my @cygvernum = split( /\./, $cygvernum); 111cdf0e10cSrcweir $cygvernum = shift @cygvernum; 112cdf0e10cSrcweir $cygvernum .= shift @cygvernum; 113cdf0e10cSrcweir if ( $cygvernum < 17 ) { 114cdf0e10cSrcweir $maybedot = '.'; 115cdf0e10cSrcweir } else { 116cdf0e10cSrcweir $maybedot = ''; # no longer works with cygwin 1.7. other magic below. 117cdf0e10cSrcweir } 118cdf0e10cSrcweir} 119cdf0e10cSrcweir 120cdf0e10cSrcweir($gui = lc($ENV{GUI})) || die "Can't determine 'GUI'. Please set environment.\n"; 121cdf0e10cSrcweir$tempcounter = 0; 122cdf0e10cSrcweir 123cdf0e10cSrcweir# zip is default for RE master builds 124cdf0e10cSrcweir$opt_zip = 1 if ( defined($ENV{DELIVER_TO_ZIP}) && uc($ENV{DELIVER_TO_ZIP}) eq 'TRUE' && ! defined($ENV{CWS_WORK_STAMP})); 125cdf0e10cSrcweir 126cdf0e10cSrcweir$has_symlinks = 0; # system supports symlinks 127cdf0e10cSrcweir 128cdf0e10cSrcweirfor (@action_list) { 129cdf0e10cSrcweir $action_hash{$_}++; 130cdf0e10cSrcweir} 131cdf0e10cSrcweir 132cdf0e10cSrcweir# trap normal signals (HUP, INT, PIPE, TERM) 133cdf0e10cSrcweir# for clean up on unexpected termination 134cdf0e10cSrcweiruse sigtrap 'handler' => \&cleanup_and_die, 'normal-signals'; 135cdf0e10cSrcweir 136cdf0e10cSrcweir#### main #### 137cdf0e10cSrcweir 138cdf0e10cSrcweirparse_options(); 139cdf0e10cSrcweir 140cdf0e10cSrcweirprint "$script_name -- version: $script_rev\n" if !$opt_silent; 141cdf0e10cSrcweir 142cdf0e10cSrcweirif ( ! $opt_delete ) { 143cdf0e10cSrcweir if ( $ENV{GUI} eq 'WNT' ) { 144cdf0e10cSrcweir if ($ENV{COM} eq 'GCC') { 145cdf0e10cSrcweir initialize_strip() ; 146cdf0e10cSrcweir }; 147cdf0e10cSrcweir } else { 148cdf0e10cSrcweir initialize_strip(); 149cdf0e10cSrcweir } 150cdf0e10cSrcweir} 151cdf0e10cSrcweir 152cdf0e10cSrcweirinit_globals(); 153cdf0e10cSrcweirpush_default_actions(); 154cdf0e10cSrcweirparse_dlst(); 155cdf0e10cSrcweircheck_dlst() if $opt_checkdlst; 156cdf0e10cSrcweirwalk_action_data(); 157cdf0e10cSrcweirwalk_addincpath_list(); 158cdf0e10cSrcweirwrite_log() if $opt_log; 159cdf0e10cSrcweirzip_files() if $opt_zip; 160cdf0e10cSrcweircleanup() if $opt_delete; 161cdf0e10cSrcweirdelete_output() if $opt_deloutput; 162cdf0e10cSrcweirprint_stats(); 163cdf0e10cSrcweir 164cdf0e10cSrcweirexit($error); 165cdf0e10cSrcweir 166cdf0e10cSrcweir#### implemented actions ##### 167cdf0e10cSrcweir 168cdf0e10cSrcweirsub do_copy 169cdf0e10cSrcweir{ 170cdf0e10cSrcweir # We need to copy two times: 171cdf0e10cSrcweir # from the platform dependent output tree 172cdf0e10cSrcweir # and from the common output tree 173cdf0e10cSrcweir my ($dependent, $common, $from, $to, $file_list); 174cdf0e10cSrcweir my $line = shift; 175cdf0e10cSrcweir my $touch = 0; 176cdf0e10cSrcweir 177cdf0e10cSrcweir $dependent = expand_macros($line); 178cdf0e10cSrcweir ($from, $to) = split(' ', $dependent); 179cdf0e10cSrcweir print "copy dependent: from: $from, to: $to\n" if $is_debug; 180cdf0e10cSrcweir glob_and_copy($from, $to, $touch); 181cdf0e10cSrcweir 182cdf0e10cSrcweir if ($delete_common && $common_build && ( $line !~ /%COMMON_OUTDIR%/ ) ) { 183cdf0e10cSrcweir $line =~ s/%__SRC%/%COMMON_OUTDIR%/ig; 184cdf0e10cSrcweir if ( $line =~ /%COMMON_OUTDIR%/ ) { 185cdf0e10cSrcweir $line =~ s/%_DEST%/%COMMON_DEST%/ig; 186cdf0e10cSrcweir $common = expand_macros($line); 187cdf0e10cSrcweir ($from, $to) = split(' ', $common); 188cdf0e10cSrcweir print "copy common: from: $from, to: $to\n" if $is_debug; 189cdf0e10cSrcweir glob_and_copy($from, $to, $touch); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir } 192cdf0e10cSrcweir} 193cdf0e10cSrcweir 194cdf0e10cSrcweirsub do_dos 195cdf0e10cSrcweir{ 196cdf0e10cSrcweir my $line = shift; 197cdf0e10cSrcweir 198cdf0e10cSrcweir my $command = expand_macros($line); 199cdf0e10cSrcweir if ( $opt_check ) { 200cdf0e10cSrcweir print "DOS: $command\n"; 201cdf0e10cSrcweir } 202cdf0e10cSrcweir else { 203cdf0e10cSrcweir # HACK: remove MACOSX stuff which is wrongly labled with dos 204cdf0e10cSrcweir # better: fix broken d.lst 205cdf0e10cSrcweir return if ( $command =~ /MACOSX/ ); 206cdf0e10cSrcweir $command =~ s#/#\\#g if $^O eq 'MSWin32'; 207cdf0e10cSrcweir system($command); 208cdf0e10cSrcweir } 209cdf0e10cSrcweir} 210cdf0e10cSrcweir 211cdf0e10cSrcweirsub do_addincpath 212cdf0e10cSrcweir{ 213cdf0e10cSrcweir # just collect all addincpath files, actual filtering is done later 214cdf0e10cSrcweir my $line = shift; 215cdf0e10cSrcweir my ($from, $to); 216cdf0e10cSrcweir my @globbed_files = (); 217cdf0e10cSrcweir 218cdf0e10cSrcweir $line = expand_macros($line); 219cdf0e10cSrcweir ($from, $to) = split(' ', $line); 220cdf0e10cSrcweir 221cdf0e10cSrcweir push( @addincpath_list, @{glob_line($from, $to)}); 222cdf0e10cSrcweir} 223cdf0e10cSrcweir 224cdf0e10cSrcweirsub do_linklib 225cdf0e10cSrcweir{ 226cdf0e10cSrcweir my ($lib_base, $lib_major,$from_dir, $to_dir); 227cdf0e10cSrcweir my $lib = shift; 228cdf0e10cSrcweir my @globbed_files = (); 229cdf0e10cSrcweir my %globbed_hash = (); 230cdf0e10cSrcweir 231cdf0e10cSrcweir print "linklib: $lib\n" if $is_debug; 232cdf0e10cSrcweir print "has symlinks\n" if ( $has_symlinks && $is_debug ); 233cdf0e10cSrcweir 234cdf0e10cSrcweir return unless $has_symlinks; 235cdf0e10cSrcweir 236cdf0e10cSrcweir $from_dir = expand_macros('../%__SRC%/lib'); 237cdf0e10cSrcweir $to_dir = expand_macros('%_DEST%/lib%_EXT%'); 238cdf0e10cSrcweir 239cdf0e10cSrcweir @globbed_files = glob("$from_dir/$lib"); 240cdf0e10cSrcweir 241cdf0e10cSrcweir if ( $#globbed_files == -1 ) { 242cdf0e10cSrcweir return; 243cdf0e10cSrcweir } 244cdf0e10cSrcweir 245cdf0e10cSrcweir foreach $lib (@globbed_files) { 246cdf0e10cSrcweir $lib = basename($lib); 247cdf0e10cSrcweir if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/ 248cdf0e10cSrcweir || $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)$/ ) 249cdf0e10cSrcweir { 250cdf0e10cSrcweir push(@{$globbed_hash{$1}}, $lib); 251cdf0e10cSrcweir } 252cdf0e10cSrcweir else { 253cdf0e10cSrcweir print_warning("invalid library name: $lib"); 254cdf0e10cSrcweir } 255cdf0e10cSrcweir } 256cdf0e10cSrcweir 257cdf0e10cSrcweir foreach $lib_base ( sort keys %globbed_hash ) { 258cdf0e10cSrcweir $lib = get_latest_patchlevel(@{$globbed_hash{$lib_base}}); 259cdf0e10cSrcweir 260cdf0e10cSrcweir if ( $lib =~ /^(lib\S+(\.so|\.dylib))\.(\d+)\.(\d+)(\.(\d+))?$/ ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir $lib_major = "$lib_base.$3"; 263cdf0e10cSrcweir $long = 1; 264cdf0e10cSrcweir } 265cdf0e10cSrcweir else 266cdf0e10cSrcweir { 267cdf0e10cSrcweir # $lib =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)$/; 268cdf0e10cSrcweir $long = 0; 269cdf0e10cSrcweir } 270cdf0e10cSrcweir 271cdf0e10cSrcweir if ( $opt_check ) { 272cdf0e10cSrcweir if ( $opt_delete ) { 273cdf0e10cSrcweir print "REMOVE: $to_dir/$lib_major\n" if $long; 274cdf0e10cSrcweir print "REMOVE: $to_dir/$lib_base\n"; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir else { 277cdf0e10cSrcweir print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_major\n" if $long; 278cdf0e10cSrcweir print "LINKLIB: $to_dir/$lib -> $to_dir/$lib_base\n"; 279cdf0e10cSrcweir } 280cdf0e10cSrcweir } 281cdf0e10cSrcweir else { 282cdf0e10cSrcweir if ( $opt_delete ) { 283cdf0e10cSrcweir print "REMOVE: $to_dir/$lib_major\n" if ($long && $opt_verbose); 284cdf0e10cSrcweir print "REMOVE: $to_dir/$lib_base\n" if $opt_verbose; 285cdf0e10cSrcweir unlink "$to_dir/$lib_major" if $long; 286cdf0e10cSrcweir unlink "$to_dir/$lib_base"; 287cdf0e10cSrcweir if ( $opt_zip ) { 288cdf0e10cSrcweir push_on_ziplist("$to_dir/$lib_major") if $long; 289cdf0e10cSrcweir push_on_ziplist("$to_dir/$lib_base"); 290cdf0e10cSrcweir } 291cdf0e10cSrcweir return; 292cdf0e10cSrcweir } 293cdf0e10cSrcweir my $symlib; 294cdf0e10cSrcweir my @symlibs; 295cdf0e10cSrcweir if ($long) 296cdf0e10cSrcweir { 297cdf0e10cSrcweir @symlibs = ("$to_dir/$lib_major", "$to_dir/$lib_base"); 298cdf0e10cSrcweir } 299cdf0e10cSrcweir else 300cdf0e10cSrcweir { 301cdf0e10cSrcweir @symlibs = ("$to_dir/$lib_base"); 302cdf0e10cSrcweir } 303cdf0e10cSrcweir # remove old symlinks 304cdf0e10cSrcweir unlink(@symlibs); 305cdf0e10cSrcweir foreach $symlib (@symlibs) { 306cdf0e10cSrcweir print "LINKLIB: $lib -> $symlib\n" if $opt_verbose; 307cdf0e10cSrcweir if ( !symlink("$lib", "$symlib") ) { 308cdf0e10cSrcweir print_error("can't symlink $lib -> $symlib: $!",0); 309cdf0e10cSrcweir } 310cdf0e10cSrcweir else { 311cdf0e10cSrcweir push_on_ziplist($symlib) if $opt_zip; 312cdf0e10cSrcweir push_on_loglist("LINK", "$lib", "$symlib") if $opt_log; 313cdf0e10cSrcweir } 314cdf0e10cSrcweir } 315cdf0e10cSrcweir } 316cdf0e10cSrcweir } 317cdf0e10cSrcweir} 318cdf0e10cSrcweir 319cdf0e10cSrcweirsub do_mkdir 320cdf0e10cSrcweir{ 321cdf0e10cSrcweir my $path = expand_macros(shift); 322cdf0e10cSrcweir # strip whitespaces from path name 323cdf0e10cSrcweir $path =~ s/\s$//; 324cdf0e10cSrcweir if (( ! $opt_delete ) && ( ! -d $path )) { 325cdf0e10cSrcweir if ( $opt_check ) { 326cdf0e10cSrcweir print "MKDIR: $path\n"; 327cdf0e10cSrcweir } else { 328cdf0e10cSrcweir mkpath($path, 0, 0777-$umask); 329cdf0e10cSrcweir if ( ! -d $path ) { 330cdf0e10cSrcweir print_error("mkdir: could not create directory '$path'", 0); 331cdf0e10cSrcweir } 332cdf0e10cSrcweir } 333cdf0e10cSrcweir } 334cdf0e10cSrcweir} 335cdf0e10cSrcweir 336cdf0e10cSrcweirsub do_symlink 337cdf0e10cSrcweir{ 338cdf0e10cSrcweir my $line = shift; 339cdf0e10cSrcweir 340cdf0e10cSrcweir $line = expand_macros($line); 341cdf0e10cSrcweir ($from, $to) = split(' ',$line); 342cdf0e10cSrcweir my $fullfrom = $from; 343cdf0e10cSrcweir if ( dirname($from) eq dirname($to) ) { 344cdf0e10cSrcweir $from = basename($from); 345cdf0e10cSrcweir } 346cdf0e10cSrcweir elsif ( dirname($from) eq '.' ) { 347cdf0e10cSrcweir # nothing to do 348cdf0e10cSrcweir } 349cdf0e10cSrcweir else { 350cdf0e10cSrcweir print_error("symlink: link must be in the same directory as file",0); 351cdf0e10cSrcweir return 0; 352cdf0e10cSrcweir } 353cdf0e10cSrcweir 354cdf0e10cSrcweir print "symlink: $from, to: $to\n" if $is_debug; 355cdf0e10cSrcweir 356cdf0e10cSrcweir return unless $has_symlinks; 357cdf0e10cSrcweir 358cdf0e10cSrcweir if ( $opt_check ) { 359cdf0e10cSrcweir if ( $opt_delete ) { 360cdf0e10cSrcweir print "REMOVE: $to\n"; 361cdf0e10cSrcweir } 362cdf0e10cSrcweir else { 363cdf0e10cSrcweir print "SYMLINK $from -> $to\n"; 364cdf0e10cSrcweir } 365cdf0e10cSrcweir } 366cdf0e10cSrcweir else { 367cdf0e10cSrcweir print "REMOVE: $to\n" if $opt_verbose; 368cdf0e10cSrcweir unlink $to; 369cdf0e10cSrcweir if ( $opt_delete ) { 370cdf0e10cSrcweir push_on_ziplist($to) if $opt_zip; 371cdf0e10cSrcweir return; 372cdf0e10cSrcweir } 373cdf0e10cSrcweir return unless -e $fullfrom; 374cdf0e10cSrcweir print "SYMLIB: $from -> $to\n" if $opt_verbose; 375cdf0e10cSrcweir if ( !symlink("$from", "$to") ) { 376cdf0e10cSrcweir print_error("can't symlink $from -> $to: $!",0); 377cdf0e10cSrcweir } 378cdf0e10cSrcweir else { 379cdf0e10cSrcweir push_on_ziplist($to) if $opt_zip; 380cdf0e10cSrcweir push_on_loglist("LINK", "$from", "$to") if $opt_log; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir } 383cdf0e10cSrcweir} 384cdf0e10cSrcweir 385cdf0e10cSrcweirsub do_touch 386cdf0e10cSrcweir{ 387cdf0e10cSrcweir my ($from, $to); 388cdf0e10cSrcweir my $line = shift; 389cdf0e10cSrcweir my $touch = 1; 390cdf0e10cSrcweir 391cdf0e10cSrcweir $line = expand_macros($line); 392cdf0e10cSrcweir ($from, $to) = split(' ', $line); 393cdf0e10cSrcweir print "touch: $from, to: $to\n" if $is_debug; 394cdf0e10cSrcweir glob_and_copy($from, $to, $touch); 395cdf0e10cSrcweir} 396cdf0e10cSrcweir 397cdf0e10cSrcweir#### subroutines ##### 398cdf0e10cSrcweir 399cdf0e10cSrcweirsub parse_options 400cdf0e10cSrcweir{ 401cdf0e10cSrcweir my $arg; 402cdf0e10cSrcweir my $dontdeletecommon = 0; 403cdf0e10cSrcweir $opt_silent = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'FALSE'); 404cdf0e10cSrcweir $opt_verbose = 1 if ( defined $ENV{VERBOSE} && $ENV{VERBOSE} eq 'TRUE'); 405cdf0e10cSrcweir while ( $arg = shift @ARGV ) { 406cdf0e10cSrcweir $arg =~ /^-force$/ and $opt_force = 1 and next; 407cdf0e10cSrcweir $arg =~ /^-check$/ and $opt_check = 1 and $opt_verbose = 1 and next; 408cdf0e10cSrcweir $arg =~ /^-quiet$/ and $opt_silent = 1 and next; 409cdf0e10cSrcweir $arg =~ /^-verbose$/ and $opt_verbose = 1 and next; 410cdf0e10cSrcweir $arg =~ /^-zip$/ and $opt_zip = 1 and next; 411cdf0e10cSrcweir $arg =~ /^-delete$/ and $opt_delete = 1 and next; 412cdf0e10cSrcweir $arg =~ /^-dontdeletecommon$/ and $dontdeletecommon = 1 and next; 413cdf0e10cSrcweir $arg =~ /^-help$/ and $opt_help = 1 and $arg = ''; 414cdf0e10cSrcweir $arg =~ /^-link$/ and $ENV{GUI} ne 'WNT' and $opt_link = 1 and next; 415cdf0e10cSrcweir $arg =~ /^-deloutput$/ and $opt_deloutput = 1 and next; 416cdf0e10cSrcweir $arg =~ /^-debug$/ and $is_debug = 1 and next; 417cdf0e10cSrcweir $arg =~ /^-checkdlst$/ and $opt_checkdlst = 1 and next; 418cdf0e10cSrcweir print_error("invalid option $arg") if ( $arg =~ /^-/ ); 419cdf0e10cSrcweir if ( $arg =~ /^-/ || $opt_help || $#ARGV > -1 ) { 420cdf0e10cSrcweir usage(1); 421cdf0e10cSrcweir } 422cdf0e10cSrcweir $dest = $arg; 423cdf0e10cSrcweir } 424cdf0e10cSrcweir # $dest and $opt_zip or $opt_delete are mutually exclusive 425cdf0e10cSrcweir if ( $dest and ($opt_zip || $opt_delete) ) { 426cdf0e10cSrcweir usage(1); 427cdf0e10cSrcweir } 428cdf0e10cSrcweir # $opt_silent and $opt_check or $opt_verbose are mutually exclusive 429cdf0e10cSrcweir if ( ($opt_check or $opt_verbose) and $opt_silent ) { 430cdf0e10cSrcweir print STDERR "Error on command line: options '-check' and '-quiet' are mutually exclusive.\n"; 431cdf0e10cSrcweir usage(1); 432cdf0e10cSrcweir } 433cdf0e10cSrcweir if ($dontdeletecommon) { 434cdf0e10cSrcweir if (!$opt_delete) { 435cdf0e10cSrcweir usage(1); 436cdf0e10cSrcweir } 437cdf0e10cSrcweir $delete_common = 0; 438cdf0e10cSrcweir }; 439cdf0e10cSrcweir # $opt_delete implies $opt_force 440cdf0e10cSrcweir $opt_force = 1 if $opt_delete; 441cdf0e10cSrcweir} 442cdf0e10cSrcweir 443cdf0e10cSrcweirsub init_globals 444cdf0e10cSrcweir{ 445cdf0e10cSrcweir my $ext; 446cdf0e10cSrcweir ($module, $repository, $base_dir, $dlst_file) = get_base(); 447cdf0e10cSrcweir 448cdf0e10cSrcweir # for CWS: 449cdf0e10cSrcweir $module =~ s/\.lnk$//; 450cdf0e10cSrcweir 451cdf0e10cSrcweir print "Module=$module, Base_Dir=$base_dir, d.lst=$dlst_file\n" if $is_debug; 452cdf0e10cSrcweir 453cdf0e10cSrcweir $umask = umask(); 454cdf0e10cSrcweir if ( !defined($umask) ) { 455cdf0e10cSrcweir $umask = 22; 456cdf0e10cSrcweir } 457cdf0e10cSrcweir 458cdf0e10cSrcweir my $build_sosl = $ENV{'BUILD_SOSL'}; 459cdf0e10cSrcweir my $common_outdir = $ENV{'COMMON_OUTDIR'}; 460cdf0e10cSrcweir my $inpath = $ENV{'INPATH'}; 461cdf0e10cSrcweir my $solarversion = $ENV{'SOLARVERSION'}; 462cdf0e10cSrcweir my $updater = $ENV{'UPDATER'}; 463cdf0e10cSrcweir my $updminor = $ENV{'UPDMINOR'}; 464cdf0e10cSrcweir my $updminorext = $ENV{'UPDMINOREXT'}; 465cdf0e10cSrcweir my $work_stamp = $ENV{'WORK_STAMP'}; 466cdf0e10cSrcweir 467cdf0e10cSrcweir # special security check for release engineers 468cdf0e10cSrcweir if ( defined($updater) && !defined($build_sosl) && !$opt_force) { 469cdf0e10cSrcweir my $path = getcwd(); 470cdf0e10cSrcweir if ( $path !~ /$work_stamp/io ) { 471cdf0e10cSrcweir print_error("can't deliver from local directory to SOLARVERSION"); 472cdf0e10cSrcweir print STDERR "\nDANGER! Release Engineer:\n"; 473cdf0e10cSrcweir print STDERR "do you really want to deliver from $path to SOLARVERSION?\n"; 474cdf0e10cSrcweir print STDERR "If so, please use the -force switch\n\n"; 475cdf0e10cSrcweir exit(7); 476cdf0e10cSrcweir } 477cdf0e10cSrcweir } 478cdf0e10cSrcweir 479cdf0e10cSrcweir # do we have a valid environment? 480cdf0e10cSrcweir if ( !defined($inpath) ) { 481cdf0e10cSrcweir print_error("no environment", 0); 482cdf0e10cSrcweir exit(3); 483cdf0e10cSrcweir } 484cdf0e10cSrcweir 485cdf0e10cSrcweir $ext = ""; 486cdf0e10cSrcweir if ( ($updminor) && !$dest ) { 487cdf0e10cSrcweir $ext = "$updminorext"; 488cdf0e10cSrcweir } 489cdf0e10cSrcweir 490cdf0e10cSrcweir # Do we have common trees? 491cdf0e10cSrcweir if ( defined($ENV{'common_build'}) && $ENV{'common_build'} eq 'TRUE' ) { 492cdf0e10cSrcweir $common_build = 1; 493cdf0e10cSrcweir if ((defined $common_outdir) && ($common_outdir ne "")) { 494cdf0e10cSrcweir $common_outdir = $common_outdir . ".pro" if $inpath =~ /\.pro$/; 495cdf0e10cSrcweir if ( $dest ) { 496cdf0e10cSrcweir $common_dest = $dest; 497cdf0e10cSrcweir } else { 498cdf0e10cSrcweir $common_dest = "$solarversion/$common_outdir"; 499cdf0e10cSrcweir $dest = "$solarversion/$inpath"; 500cdf0e10cSrcweir } 501cdf0e10cSrcweir } else { 502cdf0e10cSrcweir print_error("common_build defined without common_outdir", 0); 503cdf0e10cSrcweir exit(6); 504cdf0e10cSrcweir } 505cdf0e10cSrcweir } else { 506cdf0e10cSrcweir $common_outdir = $inpath; 507cdf0e10cSrcweir $dest = "$solarversion/$inpath" if ( !$dest ); 508cdf0e10cSrcweir $common_dest = $dest; 509cdf0e10cSrcweir } 510cdf0e10cSrcweir $dest =~ s#\\#/#g; 511cdf0e10cSrcweir $common_dest =~ s#\\#/#g; 512cdf0e10cSrcweir 513cdf0e10cSrcweir # the following macros are obsolete, will be flagged as error 514cdf0e10cSrcweir # %__WORKSTAMP% 515cdf0e10cSrcweir # %GUIBASE% 516cdf0e10cSrcweir # %SDK% 517cdf0e10cSrcweir # %SOLARVER% 518cdf0e10cSrcweir # %__OFFENV% 519cdf0e10cSrcweir # %DLLSUFFIX%' 520cdf0e10cSrcweir # %OUTPATH% 521cdf0e10cSrcweir # %L10N_FRAMEWORK% 522cdf0e10cSrcweir # %UPD% 523cdf0e10cSrcweir 524cdf0e10cSrcweir # valid macros 525cdf0e10cSrcweir @macros = ( 526cdf0e10cSrcweir [ '%__PRJROOT%', $base_dir ], 527cdf0e10cSrcweir [ '%__SRC%', $inpath ], 528cdf0e10cSrcweir [ '%_DEST%', $dest ], 529cdf0e10cSrcweir [ '%_EXT%', $ext ], 530cdf0e10cSrcweir [ '%COMMON_OUTDIR%', $common_outdir ], 531cdf0e10cSrcweir [ '%COMMON_DEST%', $common_dest ], 532cdf0e10cSrcweir [ '%GUI%', $gui ] 533cdf0e10cSrcweir ); 534cdf0e10cSrcweir 535cdf0e10cSrcweir # find out if the system supports symlinks 536cdf0e10cSrcweir $has_symlinks = eval { symlink("",""); 1 }; 537cdf0e10cSrcweir} 538cdf0e10cSrcweir 539cdf0e10cSrcweirsub get_base 540cdf0e10cSrcweir{ 541cdf0e10cSrcweir # a module base dir contains a subdir 'prj' 542cdf0e10cSrcweir # which in turn contains a file 'd.lst' 543cdf0e10cSrcweir my (@field, $repo, $base, $dlst); 544cdf0e10cSrcweir my $path = getcwd(); 545cdf0e10cSrcweir 546cdf0e10cSrcweir @field = split(/\//, $path); 547cdf0e10cSrcweir 548cdf0e10cSrcweir while ( $#field != -1 ) { 549cdf0e10cSrcweir $base = join('/', @field); 550cdf0e10cSrcweir $dlst = $base . '/prj/d.lst'; 551cdf0e10cSrcweir last if -e $dlst; 552cdf0e10cSrcweir pop @field; 553cdf0e10cSrcweir } 554cdf0e10cSrcweir 555cdf0e10cSrcweir if ( $#field == -1 ) { 556cdf0e10cSrcweir print_error("can't find d.lst"); 557cdf0e10cSrcweir exit(2); 558cdf0e10cSrcweir } 559cdf0e10cSrcweir else { 560cdf0e10cSrcweir if ( defined $field[-2] ) { 561cdf0e10cSrcweir $repo = $field[-2]; 562cdf0e10cSrcweir } else { 563cdf0e10cSrcweir print_error("Internal error: cannot determine module's parent directory"); 564cdf0e10cSrcweir } 565cdf0e10cSrcweir return ($field[-1], $repo, $base, $dlst); 566cdf0e10cSrcweir } 567cdf0e10cSrcweir} 568cdf0e10cSrcweir 569cdf0e10cSrcweirsub parse_dlst 570cdf0e10cSrcweir{ 571cdf0e10cSrcweir my $line_cnt = 0; 572cdf0e10cSrcweir open(DLST, "<$dlst_file") or die "can't open d.lst"; 573cdf0e10cSrcweir while(<DLST>) { 574cdf0e10cSrcweir $line_cnt++; 575cdf0e10cSrcweir tr/\r\n//d; 576cdf0e10cSrcweir next if /^#/; 577cdf0e10cSrcweir next if /^\s*$/; 578cdf0e10cSrcweir if (!$delete_common && /%COMMON_DEST%/) { 579cdf0e10cSrcweir # Just ignore all lines with %COMMON_DEST% 580cdf0e10cSrcweir next; 581cdf0e10cSrcweir }; 582cdf0e10cSrcweir if ( /^\s*(\w+?):\s+(.*)$/ ) { 583cdf0e10cSrcweir if ( !exists $action_hash{$1} ) { 584cdf0e10cSrcweir print_error("unknown action: \'$1\'", $line_cnt); 585cdf0e10cSrcweir exit(4); 586cdf0e10cSrcweir } 587cdf0e10cSrcweir push(@action_data, [$1, $2]); 588cdf0e10cSrcweir } 589cdf0e10cSrcweir else { 590cdf0e10cSrcweir if ( /^\s*%(COMMON)?_DEST%\\/ ) { 591cdf0e10cSrcweir # only copy from source dir to solver, not from solver to solver 592cdf0e10cSrcweir print_warning("illegal copy action, ignored: \'$_\'", $line_cnt); 593cdf0e10cSrcweir next; 594cdf0e10cSrcweir } 595cdf0e10cSrcweir push(@action_data, ['copy', $_]); 596cdf0e10cSrcweir # for each ressource file (.res) copy its image list (.ilst) 597cdf0e10cSrcweir if ( /\.res\s/ ) { 598cdf0e10cSrcweir my $imagelist = $_; 599cdf0e10cSrcweir $imagelist =~ s/\.res/\.$ilst_ext/g; 600cdf0e10cSrcweir $imagelist =~ s/\\bin%_EXT%\\/\\res%_EXT%\\img\\/; 601cdf0e10cSrcweir push(@action_data, ['copy', $imagelist]); 602cdf0e10cSrcweir } 603cdf0e10cSrcweir } 604cdf0e10cSrcweir # call expand_macros()just to find any undefined macros early 605cdf0e10cSrcweir # real expansion is done later 606cdf0e10cSrcweir expand_macros($_, $line_cnt); 607cdf0e10cSrcweir } 608cdf0e10cSrcweir close(DLST); 609cdf0e10cSrcweir} 610cdf0e10cSrcweir 611cdf0e10cSrcweirsub expand_macros 612cdf0e10cSrcweir{ 613cdf0e10cSrcweir # expand all macros and change backslashes to slashes 614cdf0e10cSrcweir my $line = shift; 615cdf0e10cSrcweir my $line_cnt = shift; 616cdf0e10cSrcweir my $i; 617cdf0e10cSrcweir 618cdf0e10cSrcweir for ($i=0; $i<=$#macros; $i++) { 619cdf0e10cSrcweir $line =~ s/$macros[$i][0]/$macros[$i][1]/gi 620cdf0e10cSrcweir } 621cdf0e10cSrcweir if ( $line =~ /(%\w+%)/ ) { 622cdf0e10cSrcweir if ( $1 ne '%OS%' ) { # %OS% looks like a macro but is not ... 623cdf0e10cSrcweir print_error("unknown/obsolete macro: \'$1\'", $line_cnt); 624cdf0e10cSrcweir } 625cdf0e10cSrcweir } 626cdf0e10cSrcweir $line =~ s#\\#/#g; 627cdf0e10cSrcweir return $line; 628cdf0e10cSrcweir} 629cdf0e10cSrcweir 630cdf0e10cSrcweirsub walk_action_data 631cdf0e10cSrcweir{ 632cdf0e10cSrcweir # all actions have to be excuted relative to the prj directory 633cdf0e10cSrcweir chdir("$base_dir/prj"); 634cdf0e10cSrcweir # dispatch depending on action type 635cdf0e10cSrcweir for (my $i=0; $i <= $#action_data; $i++) { 636cdf0e10cSrcweir &{"do_".$action_data[$i][0]}($action_data[$i][1]); 637cdf0e10cSrcweir if ( $action_data[$i][0] eq 'mkdir' ) { 638cdf0e10cSrcweir # fill array with (possibly) created directories in 639cdf0e10cSrcweir # revers order for removal in 'cleanup' 640cdf0e10cSrcweir unshift @dirlist, $action_data[$i][1]; 641cdf0e10cSrcweir } 642cdf0e10cSrcweir } 643cdf0e10cSrcweir} 644cdf0e10cSrcweir 645cdf0e10cSrcweirsub glob_line 646cdf0e10cSrcweir{ 647cdf0e10cSrcweir my $from = shift; 648cdf0e10cSrcweir my $to = shift; 649cdf0e10cSrcweir my $to_dir = shift; 650cdf0e10cSrcweir my $replace = 0; 651cdf0e10cSrcweir my @globbed_files = (); 652cdf0e10cSrcweir 653cdf0e10cSrcweir if ( ! ( $from && $to ) ) { 654cdf0e10cSrcweir print_warning("Error in d.lst? source: '$from' destination: '$to'"); 655cdf0e10cSrcweir return \@globbed_files; 656cdf0e10cSrcweir } 657cdf0e10cSrcweir 658cdf0e10cSrcweir if ( $to =~ /[\*\?\[\]]/ ) { 659cdf0e10cSrcweir my $to_fname; 660cdf0e10cSrcweir ($to_fname, $to_dir) = fileparse($to); 661cdf0e10cSrcweir $replace = 1; 662cdf0e10cSrcweir } 663cdf0e10cSrcweir 664cdf0e10cSrcweir if ( $from =~ /[\*\?\[\]]/ ) { 665cdf0e10cSrcweir # globbing necessary, no renaming possible 666cdf0e10cSrcweir my $file; 667cdf0e10cSrcweir my @file_list = glob($from); 668cdf0e10cSrcweir 669cdf0e10cSrcweir foreach $file ( @file_list ) { 670cdf0e10cSrcweir next if ( -d $file); # we only copy files, not directories 671cdf0e10cSrcweir my ($fname, $dir) = fileparse($file); 672cdf0e10cSrcweir my $copy = ($replace) ? $to_dir . $fname : $to . '/' . $fname; 673cdf0e10cSrcweir push(@globbed_files, [$file, $copy]); 674cdf0e10cSrcweir } 675cdf0e10cSrcweir } 676cdf0e10cSrcweir else { 677cdf0e10cSrcweir # no globbing but renaming possible 678cdf0e10cSrcweir # #i89066# 679cdf0e10cSrcweir if (-d $to && -f $from) { 680cdf0e10cSrcweir my $filename = File::Basename::basename($from); 681cdf0e10cSrcweir $to .= '/' if ($to !~ /[\\|\/]$/); 682cdf0e10cSrcweir $to .= $filename; 683cdf0e10cSrcweir }; 684cdf0e10cSrcweir push(@globbed_files, [$from, $to]); 685cdf0e10cSrcweir } 686cdf0e10cSrcweir if ( $opt_checkdlst ) { 687cdf0e10cSrcweir my $outtree = expand_macros("%__SRC%"); 688cdf0e10cSrcweir my $commonouttree = expand_macros("%COMMON_OUTDIR%"); 689cdf0e10cSrcweir if (( $from !~ /\Q$outtree\E/ ) && ( $from !~ /\Q$commonouttree\E/ )) { 690cdf0e10cSrcweir print_warning("'$from' does not match any file") if ( $#globbed_files == -1 ); 691cdf0e10cSrcweir } 692cdf0e10cSrcweir } 693cdf0e10cSrcweir return \@globbed_files; 694cdf0e10cSrcweir} 695cdf0e10cSrcweir 696cdf0e10cSrcweir 697cdf0e10cSrcweirsub glob_and_copy 698cdf0e10cSrcweir{ 699cdf0e10cSrcweir my $from = shift; 700cdf0e10cSrcweir my $to = shift; 701cdf0e10cSrcweir my $touch = shift; 702cdf0e10cSrcweir 703cdf0e10cSrcweir my @copy_files = @{glob_line($from, $to)}; 704cdf0e10cSrcweir 705cdf0e10cSrcweir for (my $i = 0; $i <= $#copy_files; $i++) { 706cdf0e10cSrcweir next if filter_out($copy_files[$i][0]); # apply copy filter 707cdf0e10cSrcweir copy_if_newer($copy_files[$i][0], $copy_files[$i][1], $touch) 708cdf0e10cSrcweir ? $files_copied++ : $files_unchanged++; 709cdf0e10cSrcweir } 710cdf0e10cSrcweir} 711cdf0e10cSrcweir 712cdf0e10cSrcweirsub is_unstripped { 713cdf0e10cSrcweir my $file_name = shift; 714cdf0e10cSrcweir my $nm_output; 715cdf0e10cSrcweir 716cdf0e10cSrcweir if (-f $file_name.$maybedot) { 717cdf0e10cSrcweir my $file_type = `file $file_name`; 718cdf0e10cSrcweir # OS X file command doesn't know if a file is stripped or not 719cdf0e10cSrcweir if (($file_type =~ /not stripped/o) || ($file_type =~ /Mach-O/o) || 720cdf0e10cSrcweir (($file_type =~ /PE/o) && ($ENV{GUI} eq 'WNT') && 721cdf0e10cSrcweir ($nm_output = `nm $file_name 2>&1`) && $nm_output && 722cdf0e10cSrcweir !($nm_output =~ /no symbols/i) && !($nm_output =~ /not recognized/i))) { 723cdf0e10cSrcweir return '1' if ($file_name =~ /\.bin$/o); 724cdf0e10cSrcweir return '1' if ($file_name =~ /\.so\.*/o); 725cdf0e10cSrcweir return '1' if ($file_name =~ /\.dylib\.*/o); 726cdf0e10cSrcweir return '1' if ($file_name =~ /\.com\.*/o); 727cdf0e10cSrcweir return '1' if ($file_name =~ /\.dll\.*/o); 728cdf0e10cSrcweir return '1' if ($file_name =~ /\.exe\.*/o); 729cdf0e10cSrcweir return '1' if (basename($file_name) !~ /\./o); 730cdf0e10cSrcweir } 731cdf0e10cSrcweir }; 732cdf0e10cSrcweir return ''; 733cdf0e10cSrcweir} 734cdf0e10cSrcweir 735cdf0e10cSrcweirsub initialize_strip { 736cdf0e10cSrcweir if ((!defined $ENV{DISABLE_STRIP}) || ($ENV{DISABLE_STRIP} eq "")) { 737cdf0e10cSrcweir $strip .= 'guw ' if ($^O eq 'cygwin'); 738cdf0e10cSrcweir $strip .= 'strip'; 739cdf0e10cSrcweir $strip .= " -x" if ($ENV{OS} eq 'MACOSX'); 740cdf0e10cSrcweir $strip .= " -R '.comment' -s" if ($ENV{OS} eq 'LINUX'); 741cdf0e10cSrcweir }; 742cdf0e10cSrcweir}; 743cdf0e10cSrcweir 744cdf0e10cSrcweirsub is_jar { 745cdf0e10cSrcweir my $file_name = shift; 746cdf0e10cSrcweir 747cdf0e10cSrcweir if (-f $file_name && (( `file $file_name` ) =~ /Zip archive/o)) { 748cdf0e10cSrcweir return '1' if ($file_name =~ /\.jar\.*/o); 749cdf0e10cSrcweir }; 750cdf0e10cSrcweir return ''; 751cdf0e10cSrcweir} 752cdf0e10cSrcweir 753cdf0e10cSrcweirsub execute_system { 754cdf0e10cSrcweir my $command = shift; 755cdf0e10cSrcweir if (system($command)) { 756cdf0e10cSrcweir print_error("Failed to execute $command"); 757cdf0e10cSrcweir exit($?); 758cdf0e10cSrcweir }; 759cdf0e10cSrcweir}; 760cdf0e10cSrcweir 761cdf0e10cSrcweirsub strip_target { 762cdf0e10cSrcweir my $file = shift; 763cdf0e10cSrcweir my $temp_file = shift; 764cdf0e10cSrcweir $temp_file =~ s/\/{2,}/\//g; 765cdf0e10cSrcweir my $rc = copy($file, $temp_file); 766cdf0e10cSrcweir execute_system("$strip $temp_file"); 767cdf0e10cSrcweir return $rc; 768cdf0e10cSrcweir}; 769cdf0e10cSrcweir 770cdf0e10cSrcweirsub copy_if_newer 771cdf0e10cSrcweir{ 772cdf0e10cSrcweir # return 0 if file is unchanged ( for whatever reason ) 773cdf0e10cSrcweir # return 1 if file has been copied 774cdf0e10cSrcweir my $from = shift; 775cdf0e10cSrcweir my $to = shift; 776cdf0e10cSrcweir my $touch = shift; 777cdf0e10cSrcweir my $from_stat_ref; 778cdf0e10cSrcweir my $rc = 0; 779cdf0e10cSrcweir 780cdf0e10cSrcweir print "testing $from, $to\n" if $is_debug; 781cdf0e10cSrcweir push_on_ziplist($to) if $opt_zip; 782cdf0e10cSrcweir push_on_loglist("COPY", "$from", "$to") if $opt_log; 783cdf0e10cSrcweir return 0 unless ($from_stat_ref = is_newer($from, $to, $touch)); 784cdf0e10cSrcweir 785cdf0e10cSrcweir if ( $opt_delete ) { 786cdf0e10cSrcweir print "REMOVE: $to\n" if $opt_verbose; 787cdf0e10cSrcweir $rc = unlink($to) unless $opt_check; 788cdf0e10cSrcweir return 1 if $opt_check; 789cdf0e10cSrcweir return $rc; 790cdf0e10cSrcweir } 791cdf0e10cSrcweir 792cdf0e10cSrcweir if( !$opt_check && $opt_link ) { 793cdf0e10cSrcweir # hard link if possible 794cdf0e10cSrcweir if( link($from, $to) ){ 795cdf0e10cSrcweir print "LINK: $from -> $to\n" if $opt_verbose; 796cdf0e10cSrcweir return 1; 797cdf0e10cSrcweir } 798cdf0e10cSrcweir } 799cdf0e10cSrcweir 800cdf0e10cSrcweir if( $touch ) { 801cdf0e10cSrcweir print "TOUCH: $from -> $to\n" if $opt_verbose; 802cdf0e10cSrcweir } 803cdf0e10cSrcweir else { 804cdf0e10cSrcweir print "COPY: $from -> $to\n" if $opt_verbose; 805cdf0e10cSrcweir } 806cdf0e10cSrcweir 807cdf0e10cSrcweir return 1 if( $opt_check ); 808cdf0e10cSrcweir 809cdf0e10cSrcweir # 810cdf0e10cSrcweir # copy to temporary file first and rename later 811cdf0e10cSrcweir # to minimize the possibility for race conditions 812cdf0e10cSrcweir local $temp_file = sprintf('%s.%d-%d', $to, $$, time()); 813cdf0e10cSrcweir $rc = ''; 814cdf0e10cSrcweir if (($strip ne '') && (defined $ENV{PROEXT}) && (is_unstripped($from))) { 815cdf0e10cSrcweir $rc = strip_target($from, $temp_file); 816cdf0e10cSrcweir } else { 817cdf0e10cSrcweir $rc = copy($from, $temp_file); 818cdf0e10cSrcweir }; 819cdf0e10cSrcweir if ( $rc) { 820cdf0e10cSrcweir if ( is_newer($temp_file, $from, 0) ) { 821cdf0e10cSrcweir $rc = utime($$from_stat_ref[9], $$from_stat_ref[9], $temp_file); 822cdf0e10cSrcweir if ( !$rc ) { 823cdf0e10cSrcweir print_warning("can't update temporary file modification time '$temp_file': $!\n 824cdf0e10cSrcweir Check file permissions of '$from'.",0); 825cdf0e10cSrcweir } 826cdf0e10cSrcweir } 827cdf0e10cSrcweir fix_file_permissions($$from_stat_ref[2], $temp_file); 828cdf0e10cSrcweir if ( $^O eq 'os2' ) 829cdf0e10cSrcweir { 830cdf0e10cSrcweir $rc = unlink($to); # YD OS/2 can't rename if $to exists! 831cdf0e10cSrcweir } 832cdf0e10cSrcweir # Ugly hack: on windows file locking(?) sometimes prevents renaming. 833cdf0e10cSrcweir # Until we've found and fixed the real reason try it repeatedly :-( 834cdf0e10cSrcweir my $try = 0; 835cdf0e10cSrcweir my $maxtries = 1; 836cdf0e10cSrcweir $maxtries = 5 if ( $^O eq 'MSWin32' ); 837cdf0e10cSrcweir my $success = 0; 838cdf0e10cSrcweir while ( $try < $maxtries && ! $success ) { 839cdf0e10cSrcweir sleep $try; 840cdf0e10cSrcweir $try ++; 841cdf0e10cSrcweir $success = rename($temp_file, $to); 842cdf0e10cSrcweir if ( $^O eq 'cygwin' && $to =~ /\.bin$/) { 843cdf0e10cSrcweir # hack to survive automatically added .exe for executables renamed to 844cdf0e10cSrcweir # *.bin - will break if there is intentionally a .bin _and_ .bin.exe file. 845cdf0e10cSrcweir $success = rename( "$to.exe", $to ) if -f "$to.exe"; 846cdf0e10cSrcweir } 847cdf0e10cSrcweir } 848cdf0e10cSrcweir if ( $success ) { 849cdf0e10cSrcweir # handle special packaging of *.dylib files for Mac OS X 850cdf0e10cSrcweir if ( $^O eq 'darwin' ) 851cdf0e10cSrcweir { 852cdf0e10cSrcweir system("macosx-create-bundle", "$to=$from.app") if ( -d "$from.app" ); 853cdf0e10cSrcweir system("ranlib", "$to" ) if ( $to =~ /\.a/ ); 854cdf0e10cSrcweir } 855cdf0e10cSrcweir if ( $try > 1 ) { 856cdf0e10cSrcweir print_warning("File '$to' temporarily locked. Dependency bug?"); 857cdf0e10cSrcweir } 858cdf0e10cSrcweir return 1; 859cdf0e10cSrcweir } 860cdf0e10cSrcweir else { 861cdf0e10cSrcweir print_error("can't rename temporary file to $to: $!",0); 862cdf0e10cSrcweir } 863cdf0e10cSrcweir } 864cdf0e10cSrcweir else { 865cdf0e10cSrcweir print_error("can't copy $from: $!",0); 866cdf0e10cSrcweir my $destdir = dirname($to); 867cdf0e10cSrcweir if ( ! -d $destdir ) { 868cdf0e10cSrcweir print_error("directory '$destdir' does not exist", 0); 869cdf0e10cSrcweir } 870cdf0e10cSrcweir } 871cdf0e10cSrcweir unlink($temp_file); 872cdf0e10cSrcweir return 0; 873cdf0e10cSrcweir} 874cdf0e10cSrcweir 875cdf0e10cSrcweirsub is_newer 876cdf0e10cSrcweir{ 877cdf0e10cSrcweir # returns whole stat buffer if newer 878cdf0e10cSrcweir my $from = shift; 879cdf0e10cSrcweir my $to = shift; 880cdf0e10cSrcweir my $touch = shift; 881cdf0e10cSrcweir my (@from_stat, @to_stat); 882cdf0e10cSrcweir 883cdf0e10cSrcweir @from_stat = stat($from.$maybedot); 884cdf0e10cSrcweir if ( $opt_checkdlst ) { 885cdf0e10cSrcweir my $outtree = expand_macros("%__SRC%"); 886cdf0e10cSrcweir my $commonouttree = expand_macros("%COMMON_OUTDIR%"); 887cdf0e10cSrcweir if ( $from !~ /$outtree/ ) { 888cdf0e10cSrcweir if ( $from !~ /$commonouttree/ ) { 889cdf0e10cSrcweir print_warning("'$from' does not exist") unless -e _; 890cdf0e10cSrcweir } 891cdf0e10cSrcweir } 892cdf0e10cSrcweir } 893cdf0e10cSrcweir return 0 unless -f _; 894cdf0e10cSrcweir 895cdf0e10cSrcweir if ( $touch ) { 896cdf0e10cSrcweir $from_stat[9] = time(); 897cdf0e10cSrcweir } 898cdf0e10cSrcweir # adjust timestamps to even seconds 899cdf0e10cSrcweir # this is necessary since NT platforms have a 900cdf0e10cSrcweir # 2s modified time granularity while the timestamps 901cdf0e10cSrcweir # on Samba volumes have a 1s granularity 902cdf0e10cSrcweir 903cdf0e10cSrcweir $from_stat[9]-- if $from_stat[9] % 2; 904cdf0e10cSrcweir 905cdf0e10cSrcweir if ( $to =~ /^\Q$dest\E/ ) { 906cdf0e10cSrcweir if ( $from_stat[9] > $logfiledate ) { 907cdf0e10cSrcweir $logfiledate = $from_stat[9]; 908cdf0e10cSrcweir } 909cdf0e10cSrcweir } elsif ( $common_build && ( $to =~ /^\Q$common_dest\E/ ) ) { 910cdf0e10cSrcweir if ( $from_stat[9] > $commonlogfiledate ) { 911cdf0e10cSrcweir $commonlogfiledate = $from_stat[9]; 912cdf0e10cSrcweir } 913cdf0e10cSrcweir } 914cdf0e10cSrcweir 915cdf0e10cSrcweir @to_stat = stat($to.$maybedot); 916cdf0e10cSrcweir return \@from_stat unless -f _; 917cdf0e10cSrcweir 918cdf0e10cSrcweir if ( $opt_force ) { 919cdf0e10cSrcweir return \@from_stat; 920cdf0e10cSrcweir } 921cdf0e10cSrcweir else { 922cdf0e10cSrcweir return ($from_stat[9] > $to_stat[9]) ? \@from_stat : 0; 923cdf0e10cSrcweir } 924cdf0e10cSrcweir} 925cdf0e10cSrcweir 926cdf0e10cSrcweirsub filter_out 927cdf0e10cSrcweir{ 928cdf0e10cSrcweir my $file = shift; 929cdf0e10cSrcweir 930cdf0e10cSrcweir foreach my $pattern ( @copy_filter_patterns ) { 931cdf0e10cSrcweir if ( $file =~ /$pattern/ ) { 932cdf0e10cSrcweir print "filter out: $file\n" if $is_debug; 933cdf0e10cSrcweir return 1; 934cdf0e10cSrcweir } 935cdf0e10cSrcweir } 936cdf0e10cSrcweir 937cdf0e10cSrcweir return 0; 938cdf0e10cSrcweir} 939cdf0e10cSrcweir 940cdf0e10cSrcweirsub fix_file_permissions 941cdf0e10cSrcweir{ 942cdf0e10cSrcweir my $mode = shift; 943cdf0e10cSrcweir my $file = shift; 944cdf0e10cSrcweir 945cdf0e10cSrcweir if ( ($mode >> 6) % 2 == 1 ) { 946cdf0e10cSrcweir $mode = 0777 & ~$umask; 947cdf0e10cSrcweir } 948cdf0e10cSrcweir else { 949cdf0e10cSrcweir $mode = 0666 & ~$umask; 950cdf0e10cSrcweir } 951cdf0e10cSrcweir chmod($mode, $file); 952cdf0e10cSrcweir} 953cdf0e10cSrcweir 954cdf0e10cSrcweirsub get_latest_patchlevel 955cdf0e10cSrcweir{ 956cdf0e10cSrcweir # note: feed only well formed library names to this function 957cdf0e10cSrcweir # of the form libfoo.so.x.y.z with x,y,z numbers 958cdf0e10cSrcweir 959cdf0e10cSrcweir my @sorted_files = sort by_rev @_; 960cdf0e10cSrcweir return $sorted_files[-1]; 961cdf0e10cSrcweir 962cdf0e10cSrcweir sub by_rev { 963cdf0e10cSrcweir # comparison function for sorting 964cdf0e10cSrcweir my (@field_a, @field_b, $i); 965cdf0e10cSrcweir 966cdf0e10cSrcweir $a =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/; 967cdf0e10cSrcweir @field_a = ($3, $4, $5); 968cdf0e10cSrcweir $b =~ /^(lib[\w-]+(\.so|\.dylib))\.(\d+)\.(\d+)\.(\d+)$/; 969cdf0e10cSrcweir @field_b = ($3, $4, $5); 970cdf0e10cSrcweir 971cdf0e10cSrcweir for ($i = 0; $i < 3; $i++) 972cdf0e10cSrcweir { 973cdf0e10cSrcweir if ( ($field_a[$i] < $field_b[$i]) ) { 974cdf0e10cSrcweir return -1; 975cdf0e10cSrcweir } 976cdf0e10cSrcweir if ( ($field_a[$i] > $field_b[$i]) ) { 977cdf0e10cSrcweir return 1; 978cdf0e10cSrcweir } 979cdf0e10cSrcweir } 980cdf0e10cSrcweir 981cdf0e10cSrcweir # can't happen 982cdf0e10cSrcweir return 0; 983cdf0e10cSrcweir } 984cdf0e10cSrcweir 985cdf0e10cSrcweir} 986cdf0e10cSrcweir 987cdf0e10cSrcweirsub push_default_actions 988cdf0e10cSrcweir{ 989cdf0e10cSrcweir # any default action (that is an action which must be done even without 990cdf0e10cSrcweir # a corresponding d.lst entry) should be pushed here on the 991cdf0e10cSrcweir # @action_data list. 992cdf0e10cSrcweir my $subdir; 993cdf0e10cSrcweir my @subdirs = ( 994cdf0e10cSrcweir 'bin', 995cdf0e10cSrcweir 'doc', 996cdf0e10cSrcweir 'inc', 997cdf0e10cSrcweir 'lib', 998cdf0e10cSrcweir 'par', 999cdf0e10cSrcweir 'pck', 1000cdf0e10cSrcweir 'rdb', 1001cdf0e10cSrcweir 'res', 1002cdf0e10cSrcweir 'xml' 1003cdf0e10cSrcweir ); 1004cdf0e10cSrcweir push(@subdirs, 'zip') if $opt_zip; 1005cdf0e10cSrcweir push(@subdirs, 'idl') if ! $common_build; 1006cdf0e10cSrcweir push(@subdirs, 'pus') if ! $common_build; 1007cdf0e10cSrcweir my @common_subdirs = ( 1008cdf0e10cSrcweir 'bin', 1009cdf0e10cSrcweir 'idl', 1010cdf0e10cSrcweir 'inc', 1011cdf0e10cSrcweir 'pck', 1012cdf0e10cSrcweir 'pus', 1013cdf0e10cSrcweir 'res' 1014cdf0e10cSrcweir ); 1015cdf0e10cSrcweir push(@common_subdirs, 'zip') if $opt_zip; 1016cdf0e10cSrcweir 1017cdf0e10cSrcweir if ( ! $opt_delete ) { 1018cdf0e10cSrcweir # create all the subdirectories on solver 1019cdf0e10cSrcweir foreach $subdir (@subdirs) { 1020cdf0e10cSrcweir push(@action_data, ['mkdir', "%_DEST%/$subdir%_EXT%"]); 1021cdf0e10cSrcweir } 1022cdf0e10cSrcweir if ( $common_build ) { 1023cdf0e10cSrcweir foreach $subdir (@common_subdirs) { 1024cdf0e10cSrcweir push(@action_data, ['mkdir', "%COMMON_DEST%/$subdir%_EXT%"]); 1025cdf0e10cSrcweir } 1026cdf0e10cSrcweir } 1027cdf0e10cSrcweir } 1028cdf0e10cSrcweir push(@action_data, ['mkdir', "%_DEST%/inc%_EXT%/$module"]); 1029cdf0e10cSrcweir if ( $common_build ) { 1030cdf0e10cSrcweir push(@action_data, ['mkdir', "%COMMON_DEST%/inc%_EXT%/$module"]); 1031cdf0e10cSrcweir push(@action_data, ['mkdir', "%COMMON_DEST%/res%_EXT%/img"]); 1032cdf0e10cSrcweir } else { 1033cdf0e10cSrcweir push(@action_data, ['mkdir', "%_DEST%/res%_EXT%/img"]); 1034cdf0e10cSrcweir } 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir # deliver build.lst to $dest/inc/$module 1037cdf0e10cSrcweir push(@action_data, ['copy', "build.lst %_DEST%/inc%_EXT%/$module/build.lst"]); 1038cdf0e10cSrcweir if ( $common_build ) { 1039cdf0e10cSrcweir # ... and to $common_dest/inc/$module 1040cdf0e10cSrcweir push(@action_data, ['copy', "build.lst %COMMON_DEST%/inc%_EXT%/$module/build.lst"]); 1041cdf0e10cSrcweir } 1042cdf0e10cSrcweir 1043cdf0e10cSrcweir # need to copy libstaticmxp.dylib for Mac OS X 1044cdf0e10cSrcweir if ( $^O eq 'darwin' ) 1045cdf0e10cSrcweir { 1046cdf0e10cSrcweir push(@action_data, ['copy', "../%__SRC%/lib/lib*static*.dylib %_DEST%/lib%_EXT%/lib*static*.dylib"]); 1047cdf0e10cSrcweir } 1048cdf0e10cSrcweir} 1049cdf0e10cSrcweir 1050cdf0e10cSrcweirsub walk_addincpath_list 1051cdf0e10cSrcweir{ 1052cdf0e10cSrcweir my (@addincpath_headers); 1053cdf0e10cSrcweir return if $#addincpath_list == -1; 1054cdf0e10cSrcweir 1055cdf0e10cSrcweir # create hash with all addincpath header names 1056cdf0e10cSrcweir for (my $i = 0; $i <= $#addincpath_list; $i++) { 1057cdf0e10cSrcweir my @field = split('/', $addincpath_list[$i][0]); 1058cdf0e10cSrcweir push (@addincpath_headers, $field[-1]); 1059cdf0e10cSrcweir } 1060cdf0e10cSrcweir 1061cdf0e10cSrcweir # now stream all addincpath headers through addincpath filter 1062cdf0e10cSrcweir for (my $i = 0; $i <= $#addincpath_list; $i++) { 1063cdf0e10cSrcweir add_incpath_if_newer($addincpath_list[$i][0], $addincpath_list[$i][1], \@addincpath_headers) 1064cdf0e10cSrcweir ? $files_copied++ : $files_unchanged++; 1065cdf0e10cSrcweir } 1066cdf0e10cSrcweir} 1067cdf0e10cSrcweir 1068cdf0e10cSrcweirsub add_incpath_if_newer 1069cdf0e10cSrcweir{ 1070cdf0e10cSrcweir my $from = shift; 1071cdf0e10cSrcweir my $to = shift; 1072cdf0e10cSrcweir my $modify_headers_ref = shift; 1073cdf0e10cSrcweir my ($from_stat_ref, $header); 1074cdf0e10cSrcweir 1075cdf0e10cSrcweir push_on_ziplist($to) if $opt_zip; 1076cdf0e10cSrcweir push_on_loglist("ADDINCPATH", "$from", "$to") if $opt_log; 1077cdf0e10cSrcweir 1078cdf0e10cSrcweir if ( $opt_delete ) { 1079cdf0e10cSrcweir print "REMOVE: $to\n" if $opt_verbose; 1080cdf0e10cSrcweir my $rc = unlink($to); 1081cdf0e10cSrcweir return 1 if $rc; 1082cdf0e10cSrcweir return 0; 1083cdf0e10cSrcweir } 1084cdf0e10cSrcweir 1085cdf0e10cSrcweir if ( $from_stat_ref = is_newer($from, $to) ) { 1086cdf0e10cSrcweir print "ADDINCPATH: $from -> $to\n" if $opt_verbose; 1087cdf0e10cSrcweir 1088cdf0e10cSrcweir return 1 if $opt_check; 1089cdf0e10cSrcweir 1090cdf0e10cSrcweir my $save = $/; 1091cdf0e10cSrcweir undef $/; 1092cdf0e10cSrcweir open(FROM, "<$from"); 1093cdf0e10cSrcweir # slurp whole file in one big string 1094cdf0e10cSrcweir my $content = <FROM>; 1095cdf0e10cSrcweir close(FROM); 1096cdf0e10cSrcweir $/ = $save; 1097cdf0e10cSrcweir 1098cdf0e10cSrcweir foreach $header (@$modify_headers_ref) { 1099cdf0e10cSrcweir $content =~ s/#include [<"]$header[>"]/#include <$module\/$header>/g; 1100cdf0e10cSrcweir } 1101cdf0e10cSrcweir 1102cdf0e10cSrcweir open(TO, ">$to"); 1103cdf0e10cSrcweir print TO $content; 1104cdf0e10cSrcweir close(TO); 1105cdf0e10cSrcweir 1106cdf0e10cSrcweir utime($$from_stat_ref[9], $$from_stat_ref[9], $to); 1107cdf0e10cSrcweir fix_file_permissions($$from_stat_ref[2], $to); 1108cdf0e10cSrcweir return 1; 1109cdf0e10cSrcweir } 1110cdf0e10cSrcweir return 0; 1111cdf0e10cSrcweir} 1112cdf0e10cSrcweir 1113cdf0e10cSrcweirsub push_on_ziplist 1114cdf0e10cSrcweir{ 1115cdf0e10cSrcweir my $file = shift; 1116cdf0e10cSrcweir return if ( $opt_check ); 1117cdf0e10cSrcweir # strip $dest from path since we don't want to record it in zip file 1118cdf0e10cSrcweir if ( $file =~ s#^\Q$dest\E/##o ) { 1119cdf0e10cSrcweir if ( $updminor ){ 1120cdf0e10cSrcweir # strip minor from path 1121cdf0e10cSrcweir my $ext = "%_EXT%"; 1122cdf0e10cSrcweir $ext = expand_macros($ext); 1123cdf0e10cSrcweir $file =~ s#^$ext##o; 1124cdf0e10cSrcweir } 1125cdf0e10cSrcweir push(@zip_list, $file); 1126cdf0e10cSrcweir } elsif ( $file =~ s#^\Q$common_dest\E/##o ) { 1127cdf0e10cSrcweir if ( $updminor ){ 1128cdf0e10cSrcweir # strip minor from path 1129cdf0e10cSrcweir my $ext = "%_EXT%"; 1130cdf0e10cSrcweir $ext = expand_macros($ext); 1131cdf0e10cSrcweir $file =~ s#^$ext##o; 1132cdf0e10cSrcweir } 1133cdf0e10cSrcweir push(@common_zip_list, $file); 1134cdf0e10cSrcweir } 1135cdf0e10cSrcweir} 1136cdf0e10cSrcweir 1137cdf0e10cSrcweirsub push_on_loglist 1138cdf0e10cSrcweir{ 1139cdf0e10cSrcweir my @entry = @_; 1140cdf0e10cSrcweir return 0 if ( $opt_check ); 1141cdf0e10cSrcweir return -1 if ( $#entry != 2 ); 1142cdf0e10cSrcweir if (( $entry[0] eq "COPY" ) || ( $entry[0] eq "ADDINCPATH" )) { 1143cdf0e10cSrcweir return 0 if ( ! -e $entry[1].$maybedot ); 1144cdf0e10cSrcweir # make 'from' relative to source root 1145cdf0e10cSrcweir $entry[1] = $repository ."/" . $module . "/prj/" . $entry[1]; 1146cdf0e10cSrcweir $entry[1] =~ s/$module\/prj\/\.\./$module/; 1147cdf0e10cSrcweir } 1148cdf0e10cSrcweir # platform or common tree? 1149cdf0e10cSrcweir my $common; 1150cdf0e10cSrcweir if ( $entry[2] =~ /^\Q$dest\E/ ) { 1151cdf0e10cSrcweir $common = 0; 1152cdf0e10cSrcweir } elsif ( $common_build && ( $entry[2] =~ /^\Q$common_dest\E/ )) { 1153cdf0e10cSrcweir $common = 1; 1154cdf0e10cSrcweir } else { 1155cdf0e10cSrcweir warn "Neither common nor platform tree?"; 1156cdf0e10cSrcweir return; 1157cdf0e10cSrcweir } 1158cdf0e10cSrcweir # make 'to' relative to SOLARVERSION 1159cdf0e10cSrcweir my $solarversion = $ENV{'SOLARVERSION'}; 1160cdf0e10cSrcweir $solarversion =~ s#\\#/#g; 1161cdf0e10cSrcweir $entry[2] =~ s/^\Q$solarversion\E\///; 1162cdf0e10cSrcweir # strip minor from 'to' 1163cdf0e10cSrcweir my $ext = "%_EXT%"; 1164cdf0e10cSrcweir $ext = expand_macros($ext); 1165cdf0e10cSrcweir $entry[2] =~ s#$ext([\\\/])#$1#o; 1166cdf0e10cSrcweir 1167cdf0e10cSrcweir if ( $common ) { 1168cdf0e10cSrcweir push @common_log_list, [@entry]; 1169cdf0e10cSrcweir } else { 1170cdf0e10cSrcweir push @log_list, [@entry]; 1171cdf0e10cSrcweir } 1172cdf0e10cSrcweir return 1; 1173cdf0e10cSrcweir} 1174cdf0e10cSrcweir 1175cdf0e10cSrcweirsub zip_files 1176cdf0e10cSrcweir{ 1177cdf0e10cSrcweir my $zipexe = 'zip'; 1178cdf0e10cSrcweir $zipexe .= ' -y' unless $^O eq 'MSWin32'; 1179cdf0e10cSrcweir 1180cdf0e10cSrcweir my ($platform_zip_file, $common_zip_file); 1181cdf0e10cSrcweir $platform_zip_file = "%_DEST%/zip%_EXT%/$module.zip"; 1182cdf0e10cSrcweir $platform_zip_file = expand_macros($platform_zip_file); 1183cdf0e10cSrcweir my (%dest_dir, %list_ref); 1184cdf0e10cSrcweir $dest_dir{$platform_zip_file} = $dest; 1185cdf0e10cSrcweir $list_ref{$platform_zip_file} = \@zip_list; 1186cdf0e10cSrcweir if ( $common_build ) { 1187cdf0e10cSrcweir $common_zip_file = "%COMMON_DEST%/zip%_EXT%/$module.zip"; 1188cdf0e10cSrcweir $common_zip_file = expand_macros($common_zip_file); 1189cdf0e10cSrcweir $dest_dir{$common_zip_file} = $common_dest; 1190cdf0e10cSrcweir $list_ref{$common_zip_file} = \@common_zip_list; 1191cdf0e10cSrcweir } 1192cdf0e10cSrcweir 1193cdf0e10cSrcweir my $ext = "%_EXT%"; 1194cdf0e10cSrcweir $ext = expand_macros($ext); 1195cdf0e10cSrcweir 1196cdf0e10cSrcweir my @zipfiles; 1197cdf0e10cSrcweir $zipfiles[0] = $platform_zip_file; 1198cdf0e10cSrcweir if ( $common_build ) { 1199cdf0e10cSrcweir push @zipfiles, ($common_zip_file); 1200cdf0e10cSrcweir } 1201cdf0e10cSrcweir foreach my $zip_file ( @zipfiles ) { 1202cdf0e10cSrcweir print "ZIP: updating $zip_file\n" if $opt_verbose; 1203cdf0e10cSrcweir next if ( $opt_check ); 1204cdf0e10cSrcweir 1205cdf0e10cSrcweir if ( $opt_delete ) { 1206cdf0e10cSrcweir if ( -e $zip_file ) { 1207cdf0e10cSrcweir unlink $zip_file or die "Error: can't remove file '$zip_file': $!"; 1208cdf0e10cSrcweir } 1209cdf0e10cSrcweir next; 1210cdf0e10cSrcweir } 1211cdf0e10cSrcweir 1212cdf0e10cSrcweir local $work_file = ""; 1213cdf0e10cSrcweir if ( $zip_file eq $common_zip_file) { 1214cdf0e10cSrcweir # Zip file in common tree: work on uniq copy to avoid collisions 1215cdf0e10cSrcweir $work_file = $zip_file; 1216cdf0e10cSrcweir $work_file =~ s/\.zip$//; 1217cdf0e10cSrcweir $work_file .= (sprintf('.%d-%d', $$, time())) . ".zip"; 1218cdf0e10cSrcweir die "Error: temp file $work_file already exists" if ( -e $work_file); 1219cdf0e10cSrcweir if ( -e $zip_file ) { 1220cdf0e10cSrcweir if ( -z $zip_file) { 1221cdf0e10cSrcweir # sometimes there are files of 0 byte size - remove them 1222cdf0e10cSrcweir unlink $zip_file or print_error("can't remove empty file '$zip_file': $!",0); 1223cdf0e10cSrcweir } else { 1224cdf0e10cSrcweir if ( ! copy($zip_file, $work_file)) { 1225cdf0e10cSrcweir # give a warning, not an error: 1226cdf0e10cSrcweir # we can zip from scratch instead of just updating the old zip file 1227cdf0e10cSrcweir print_warning("can't copy'$zip_file' into '$work_file': $!", 0); 1228cdf0e10cSrcweir unlink $work_file; 1229cdf0e10cSrcweir } 1230cdf0e10cSrcweir } 1231cdf0e10cSrcweir } 1232cdf0e10cSrcweir } else { 1233cdf0e10cSrcweir # No pre processing necessary, working directly on solver. 1234cdf0e10cSrcweir $work_file = $zip_file; 1235cdf0e10cSrcweir } 1236cdf0e10cSrcweir 1237cdf0e10cSrcweir # zip content has to be relative to $dest_dir 1238cdf0e10cSrcweir chdir($dest_dir{$zip_file}) or die "Error: cannot chdir into $dest_dir{$zip_file}"; 1239cdf0e10cSrcweir my $this_ref = $list_ref{$zip_file}; 1240cdf0e10cSrcweir open(ZIP, "| $zipexe -q -o -u -@ $work_file") or die "error opening zip file"; 1241cdf0e10cSrcweir foreach $file ( @$this_ref ) { 1242cdf0e10cSrcweir print "ZIP: adding $file to $zip_file\n" if $is_debug; 1243cdf0e10cSrcweir print ZIP "$file\n"; 1244cdf0e10cSrcweir } 1245cdf0e10cSrcweir close(ZIP); 1246cdf0e10cSrcweir fix_broken_cygwin_created_zips($work_file) if $^O eq "cygwin"; 1247cdf0e10cSrcweir 1248cdf0e10cSrcweir if ( $zip_file eq $common_zip_file) { 1249cdf0e10cSrcweir # rename work file back 1250cdf0e10cSrcweir if ( -e $work_file ) { 1251cdf0e10cSrcweir if ( -e $zip_file) { 1252cdf0e10cSrcweir # do some tricks to be fast. otherwise we may disturb other platforms 1253cdf0e10cSrcweir # by unlinking a file which just gets copied -> stale file handle. 1254cdf0e10cSrcweir my $buffer_file=$work_file . '_rm'; 1255cdf0e10cSrcweir rename($zip_file, $buffer_file) or warn "Warning: can't rename old zip file '$zip_file': $!"; 1256cdf0e10cSrcweir if (! rename($work_file, $zip_file)) { 1257cdf0e10cSrcweir print_error("can't rename temporary file to $zip_file: $!",0); 1258cdf0e10cSrcweir unlink $work_file; 1259cdf0e10cSrcweir } 1260cdf0e10cSrcweir unlink $buffer_file; 1261cdf0e10cSrcweir } else { 1262cdf0e10cSrcweir if (! rename($work_file, $zip_file)) { 1263cdf0e10cSrcweir print_error("can't rename temporary file to $zip_file: $!",0); 1264cdf0e10cSrcweir unlink $work_file; 1265cdf0e10cSrcweir } 1266cdf0e10cSrcweir } 1267cdf0e10cSrcweir } 1268cdf0e10cSrcweir } 1269cdf0e10cSrcweir } 1270cdf0e10cSrcweir} 1271cdf0e10cSrcweir 1272cdf0e10cSrcweirsub fix_broken_cygwin_created_zips 1273cdf0e10cSrcweir# add given extension to or strip it from stored path 1274cdf0e10cSrcweir{ 1275cdf0e10cSrcweir require Archive::Zip; import Archive::Zip; 1276cdf0e10cSrcweir my $zip_file = shift; 1277cdf0e10cSrcweir 1278cdf0e10cSrcweir $zip = Archive::Zip->new(); 1279cdf0e10cSrcweir unless ( $zip->read($work_file) == AZ_OK ) { 1280cdf0e10cSrcweir die "Error: can't open zip file '$zip_file' to fix broken cygwin file permissions"; 1281cdf0e10cSrcweir } 1282cdf0e10cSrcweir my $latest_member_mod_time = 0; 1283cdf0e10cSrcweir foreach $member ( $zip->members() ) { 1284cdf0e10cSrcweir my $attributes = $member->unixFileAttributes(); 1285cdf0e10cSrcweir $attributes &= ~0xFE00; 1286cdf0e10cSrcweir print $member->fileName() . ": " . sprintf("%lo", $attributes) if $is_debug; 1287cdf0e10cSrcweir $attributes |= 0x10; # add group write permission 1288cdf0e10cSrcweir print "-> " . sprintf("%lo", $attributes) . "\n" if $is_debug; 1289cdf0e10cSrcweir $member->unixFileAttributes($attributes); 1290cdf0e10cSrcweir if ( $latest_member_mod_time < $member->lastModTime() ) { 1291cdf0e10cSrcweir $latest_member_mod_time = $member->lastModTime(); 1292cdf0e10cSrcweir } 1293cdf0e10cSrcweir } 1294cdf0e10cSrcweir die "Error: can't overwrite zip file '$zip_file' for fixing permissions" unless $zip->overwrite() == AZ_OK; 1295cdf0e10cSrcweir utime($latest_member_mod_time, $latest_member_mod_time, $zip_file); 1296cdf0e10cSrcweir} 1297cdf0e10cSrcweir 1298cdf0e10cSrcweirsub get_tempfilename 1299cdf0e10cSrcweir{ 1300cdf0e10cSrcweir my $temp_dir = shift; 1301cdf0e10cSrcweir $temp_dir = ( -d '/tmp' ? '/tmp' : $ENV{TMPDIR} || $ENV{TEMP} || '.' ) 1302cdf0e10cSrcweir unless defined($temp_dir); 1303cdf0e10cSrcweir if ( ! -d $temp_dir ) { 1304cdf0e10cSrcweir die "no temp directory $temp_dir\n"; 1305cdf0e10cSrcweir } 1306cdf0e10cSrcweir my $base_name = sprintf( "%d-%di-%d", $$, time(), $tempcounter++ ); 1307cdf0e10cSrcweir return "$temp_dir/$base_name"; 1308cdf0e10cSrcweir} 1309cdf0e10cSrcweir 1310cdf0e10cSrcweirsub write_log 1311cdf0e10cSrcweir{ 1312cdf0e10cSrcweir my (%log_file, %file_date); 1313cdf0e10cSrcweir $log_file{\@log_list} = "%_DEST%/inc%_EXT%/$module/deliver.log"; 1314cdf0e10cSrcweir $log_file{\@common_log_list} = "%COMMON_DEST%/inc%_EXT%/$module/deliver.log"; 1315cdf0e10cSrcweir $file_date{\@log_list} = $logfiledate; 1316cdf0e10cSrcweir $file_date{\@common_log_list} = $commonlogfiledate; 1317cdf0e10cSrcweir 1318cdf0e10cSrcweir my @logs = ( \@log_list ); 1319cdf0e10cSrcweir push @logs, ( \@common_log_list ) if ( $common_build ); 1320cdf0e10cSrcweir foreach my $log ( @logs ) { 1321cdf0e10cSrcweir $log_file{$log} = expand_macros( $log_file{$log} ); 1322cdf0e10cSrcweir if ( $opt_delete ) { 1323cdf0e10cSrcweir print "LOG: removing $log_file{$log}\n" if $opt_verbose; 1324cdf0e10cSrcweir next if ( $opt_check ); 1325cdf0e10cSrcweir unlink $log_file{$log}; 1326cdf0e10cSrcweir } else { 1327cdf0e10cSrcweir print "LOG: writing $log_file{$log}\n" if $opt_verbose; 1328cdf0e10cSrcweir next if ( $opt_check ); 1329cdf0e10cSrcweir open( LOGFILE, "> $log_file{$log}" ) or warn "Error: could not open log file."; 1330cdf0e10cSrcweir foreach my $item ( @$log ) { 1331cdf0e10cSrcweir print LOGFILE "@$item\n"; 1332cdf0e10cSrcweir } 1333cdf0e10cSrcweir close( LOGFILE ); 1334cdf0e10cSrcweir utime($file_date{$log}, $file_date{$log}, $log_file{$log}); 1335cdf0e10cSrcweir } 1336cdf0e10cSrcweir push_on_ziplist( $log_file{$log} ) if $opt_zip; 1337cdf0e10cSrcweir } 1338cdf0e10cSrcweir return; 1339cdf0e10cSrcweir} 1340cdf0e10cSrcweir 1341cdf0e10cSrcweirsub check_dlst 1342cdf0e10cSrcweir{ 1343cdf0e10cSrcweir my %createddir; 1344cdf0e10cSrcweir my %destdir; 1345cdf0e10cSrcweir my %destfile; 1346cdf0e10cSrcweir # get all checkable actions to perform 1347cdf0e10cSrcweir foreach my $action ( @action_data ) { 1348cdf0e10cSrcweir my $path = expand_macros( $$action[1] ); 1349cdf0e10cSrcweir if ( $$action[0] eq 'mkdir' ) { 1350cdf0e10cSrcweir $createddir{$path} ++; 1351cdf0e10cSrcweir } elsif (( $$action[0] eq 'copy' ) || ( $$action[0] eq 'addincpath' )) { 1352cdf0e10cSrcweir my ($from, $to) = split(' ', $path); 1353cdf0e10cSrcweir my ($to_fname, $to_dir); 1354cdf0e10cSrcweir my $withwildcard = 0; 1355cdf0e10cSrcweir if ( $from =~ /[\*\?\[\]]/ ) { 1356cdf0e10cSrcweir $withwildcard = 1; 1357cdf0e10cSrcweir } 1358cdf0e10cSrcweir ($to_fname, $to_dir) = fileparse($to); 1359cdf0e10cSrcweir if ( $withwildcard ) { 1360cdf0e10cSrcweir if ( $to !~ /[\*\?\[\]]/ ) { 1361cdf0e10cSrcweir $to_dir = $to; 1362cdf0e10cSrcweir $to_fname =''; 1363cdf0e10cSrcweir } 1364cdf0e10cSrcweir } 1365cdf0e10cSrcweir $to_dir =~ s/[\\\/\s]$//; 1366cdf0e10cSrcweir $destdir{$to_dir} ++; 1367cdf0e10cSrcweir # Check: copy into non existing directory? 1368cdf0e10cSrcweir if ( ! $createddir{$to_dir} ) { 1369cdf0e10cSrcweir # unfortunately it is not so easy: it's OK if a subdirectory of $to_dir 1370cdf0e10cSrcweir # gets created, because mkpath creates the whole tree 1371cdf0e10cSrcweir foreach my $directory ( keys %createddir ) { 1372cdf0e10cSrcweir if ( $directory =~ /^\Q$to_dir\E[\\\/]/ ) { 1373cdf0e10cSrcweir $createddir{$to_dir} ++; 1374cdf0e10cSrcweir last; 1375cdf0e10cSrcweir } 1376cdf0e10cSrcweir } 1377cdf0e10cSrcweir print_warning("Possibly copying into directory without creating in before: '$to_dir'") 1378cdf0e10cSrcweir unless $createddir{$to_dir}; 1379cdf0e10cSrcweir } 1380cdf0e10cSrcweir # Check: overwrite file? 1381cdf0e10cSrcweir if ( ! $to ) { 1382cdf0e10cSrcweir if ( $destfile{$to} ) { 1383cdf0e10cSrcweir print_warning("Multiple entries copying to '$to'"); 1384cdf0e10cSrcweir } 1385cdf0e10cSrcweir $destfile{$to} ++; 1386cdf0e10cSrcweir } 1387cdf0e10cSrcweir } 1388cdf0e10cSrcweir } 1389cdf0e10cSrcweir} 1390cdf0e10cSrcweir 1391cdf0e10cSrcweirsub cleanup 1392cdf0e10cSrcweir{ 1393cdf0e10cSrcweir # remove empty directories 1394cdf0e10cSrcweir foreach my $path ( @dirlist ) { 1395cdf0e10cSrcweir $path = expand_macros($path); 1396cdf0e10cSrcweir if ( $opt_check ) { 1397cdf0e10cSrcweir print "RMDIR: $path\n" if $opt_verbose; 1398cdf0e10cSrcweir } else { 1399cdf0e10cSrcweir rmdir $path; 1400cdf0e10cSrcweir } 1401cdf0e10cSrcweir } 1402cdf0e10cSrcweir} 1403cdf0e10cSrcweir 1404cdf0e10cSrcweirsub delete_output 1405cdf0e10cSrcweir{ 1406cdf0e10cSrcweir my $output_path = expand_macros("../%__SRC%"); 1407cdf0e10cSrcweir if ( "$output_path" ne "../" ) { 1408cdf0e10cSrcweir if ( rmtree([$output_path], 0, 1) ) { 1409cdf0e10cSrcweir print "Deleted output tree.\n" if $opt_verbose; 1410cdf0e10cSrcweir } 1411cdf0e10cSrcweir else { 1412cdf0e10cSrcweir print_error("Error deleting output tree $output_path: $!",0); 1413cdf0e10cSrcweir } 1414cdf0e10cSrcweir } 1415cdf0e10cSrcweir else { 1416cdf0e10cSrcweir print_error("Output not deleted - INPATH is not set"); 1417cdf0e10cSrcweir } 1418cdf0e10cSrcweir} 1419cdf0e10cSrcweir 1420cdf0e10cSrcweirsub print_warning 1421cdf0e10cSrcweir{ 1422cdf0e10cSrcweir my $message = shift; 1423cdf0e10cSrcweir my $line = shift; 1424cdf0e10cSrcweir 1425cdf0e10cSrcweir print STDERR "$script_name: "; 1426cdf0e10cSrcweir if ( $dlst_file ) { 1427cdf0e10cSrcweir print STDERR "$dlst_file: "; 1428cdf0e10cSrcweir } 1429cdf0e10cSrcweir if ( $line ) { 1430cdf0e10cSrcweir print STDERR "line $line: "; 1431cdf0e10cSrcweir } 1432cdf0e10cSrcweir print STDERR "WARNING: $message\n"; 1433cdf0e10cSrcweir} 1434cdf0e10cSrcweir 1435cdf0e10cSrcweirsub print_error 1436cdf0e10cSrcweir{ 1437cdf0e10cSrcweir my $message = shift; 1438cdf0e10cSrcweir my $line = shift; 1439cdf0e10cSrcweir 1440cdf0e10cSrcweir print STDERR "$script_name: "; 1441cdf0e10cSrcweir if ( $dlst_file ) { 1442cdf0e10cSrcweir print STDERR "$dlst_file: "; 1443cdf0e10cSrcweir } 1444cdf0e10cSrcweir if ( $line ) { 1445cdf0e10cSrcweir print STDERR "line $line: "; 1446cdf0e10cSrcweir } 1447cdf0e10cSrcweir print STDERR "ERROR: $message\n"; 1448cdf0e10cSrcweir $error ++; 1449cdf0e10cSrcweir} 1450cdf0e10cSrcweir 1451cdf0e10cSrcweirsub print_stats 1452cdf0e10cSrcweir{ 1453cdf0e10cSrcweir print "Module '$module' delivered "; 1454cdf0e10cSrcweir if ( $error ) { 1455cdf0e10cSrcweir print "with errors\n"; 1456cdf0e10cSrcweir } else { 1457cdf0e10cSrcweir print "successfully."; 1458cdf0e10cSrcweir if ( $opt_delete ) { 1459cdf0e10cSrcweir print " $files_copied files removed,"; 1460cdf0e10cSrcweir } 1461cdf0e10cSrcweir else { 1462cdf0e10cSrcweir print " $files_copied files copied,"; 1463cdf0e10cSrcweir } 1464cdf0e10cSrcweir print " $files_unchanged files unchanged\n"; 1465cdf0e10cSrcweir } 1466cdf0e10cSrcweir} 1467cdf0e10cSrcweir 1468cdf0e10cSrcweirsub cleanup_and_die 1469cdf0e10cSrcweir{ 1470cdf0e10cSrcweir # clean up on unexpected termination 1471cdf0e10cSrcweir my $sig = shift; 1472cdf0e10cSrcweir if ( defined($temp_file) && -e $temp_file ) { 1473cdf0e10cSrcweir unlink($temp_file); 1474cdf0e10cSrcweir } 1475cdf0e10cSrcweir if ( defined($work_file) && -e $work_file ) { 1476cdf0e10cSrcweir unlink($work_file); 1477cdf0e10cSrcweir print STDERR "$work_file removed\n"; 1478cdf0e10cSrcweir } 1479cdf0e10cSrcweir 1480cdf0e10cSrcweir die "caught unexpected signal $sig, terminating ..."; 1481cdf0e10cSrcweir} 1482cdf0e10cSrcweir 1483cdf0e10cSrcweirsub usage 1484cdf0e10cSrcweir{ 1485cdf0e10cSrcweir my $exit_code = shift; 1486cdf0e10cSrcweir print STDERR "Usage:\ndeliver [OPTIONS] [DESTINATION-PATH]\n"; 1487cdf0e10cSrcweir print STDERR "Options:\n"; 1488cdf0e10cSrcweir print STDERR " -check just print what would happen, no actual copying of files\n"; 1489cdf0e10cSrcweir print STDERR " -checkdlst be verbose about (possible) d.lst bugs\n"; 1490cdf0e10cSrcweir print STDERR " -delete delete files (undeliver), use with care\n"; 1491cdf0e10cSrcweir print STDERR " -deloutput remove the output tree after copying\n"; 1492cdf0e10cSrcweir print STDERR " -dontdeletecommon do not delete common files (for -delete option)\n"; 1493cdf0e10cSrcweir print STDERR " -force copy even if not newer\n"; 1494cdf0e10cSrcweir print STDERR " -help print this message\n"; 1495cdf0e10cSrcweir if ( !defined($ENV{GUI}) || $ENV{GUI} ne 'WNT' ) { 1496cdf0e10cSrcweir print STDERR " -link hard link files into the solver to save disk space\n"; 1497cdf0e10cSrcweir } 1498cdf0e10cSrcweir print STDERR " -quiet be quiet, only report errors\n"; 1499cdf0e10cSrcweir print STDERR " -verbose be verbose\n"; 1500cdf0e10cSrcweir print STDERR " -zip additionally create zip files of delivered content\n"; 1501cdf0e10cSrcweir print STDERR "Options '-zip' and a destination-path are mutually exclusive.\n"; 1502cdf0e10cSrcweir print STDERR "Options '-check' and '-quiet' are mutually exclusive.\n"; 1503cdf0e10cSrcweir exit($exit_code); 1504cdf0e10cSrcweir} 1505cdf0e10cSrcweir 1506cdf0e10cSrcweir# vim: set ts=4 shiftwidth=4 expandtab syntax=perl: 1507