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# checkdeliver.pl - compare delivered files on solver with those on SRC_ROOT
29cdf0e10cSrcweir#
30cdf0e10cSrcweir
31cdf0e10cSrcweiruse strict;
32cdf0e10cSrcweiruse Getopt::Long;
33cdf0e10cSrcweiruse File::stat;
34cdf0e10cSrcweiruse IO::Handle;
35cdf0e10cSrcweir
36cdf0e10cSrcweiruse lib ("$ENV{SOLARENV}/bin/modules");
37cdf0e10cSrcweir
38cdf0e10cSrcweir#### globals #####
39cdf0e10cSrcweir
40cdf0e10cSrcweirmy $err              = 0;
41cdf0e10cSrcweirmy $srcrootdir       = '';
42cdf0e10cSrcweirmy $solverdir        = '';
43cdf0e10cSrcweirmy $platform         = '';
44cdf0e10cSrcweirmy $logfile          = '';
45cdf0e10cSrcweirmy $milestoneext     = '';
46cdf0e10cSrcweirmy $local_env        = 0;
47cdf0e10cSrcweirmy @exceptionmodlist = (
48cdf0e10cSrcweir                        "postprocess",
49cdf0e10cSrcweir                        "instset.*native",
50cdf0e10cSrcweir                        "smoketest.*native",
51cdf0e10cSrcweir                        "testautomation",
52cdf0e10cSrcweir                        "testgraphical"
53cdf0e10cSrcweir                       ); # modules not yet delivered
54cdf0e10cSrcweir
55cdf0e10cSrcweir#### main #####
56cdf0e10cSrcweir
57cdf0e10cSrcweirprint_logged("checkdeliver.pl - checking delivered binaries\n");
58cdf0e10cSrcweir
59cdf0e10cSrcweirget_globals();                                  # get global variables
60cdf0e10cSrcweirmy $deliverlists_ref = get_deliver_lists();     # get deliver log files
61cdf0e10cSrcweirforeach my $listfile ( @$deliverlists_ref ) {
62cdf0e10cSrcweir    $err += check( $listfile );                 # check delivered files
63cdf0e10cSrcweir}
64cdf0e10cSrcweirprint_logged("OK\n") if ( ! $err );
65cdf0e10cSrcweirexit $err;
66cdf0e10cSrcweir
67cdf0e10cSrcweir#### subroutines ####
68cdf0e10cSrcweir
69cdf0e10cSrcweirsub get_globals
70cdf0e10cSrcweir# set global variables using environment variables and command line options
71cdf0e10cSrcweir{
72cdf0e10cSrcweir    my $help;
73cdf0e10cSrcweir
74cdf0e10cSrcweir    # set global variables according to environnment
75cdf0e10cSrcweir    $platform      = $ENV{INPATH};
76cdf0e10cSrcweir    $srcrootdir    = $ENV{SOURCE_ROOT_DIR};
77cdf0e10cSrcweir    $solverdir     = $ENV{SOLARVERSION};
78cdf0e10cSrcweir    $milestoneext  = $ENV{UPDMINOREXT};
79cdf0e10cSrcweir
80cdf0e10cSrcweir    # override environment with command line options
81cdf0e10cSrcweir    GetOptions('help' => \$help,
82cdf0e10cSrcweir               'l=s'  => \$logfile,
83cdf0e10cSrcweir               'p=s'  => \$platform
84cdf0e10cSrcweir    ) or usage (1);
85cdf0e10cSrcweir
86cdf0e10cSrcweir    if ( $help ) {
87cdf0e10cSrcweir        usage(0);
88cdf0e10cSrcweir    }
89cdf0e10cSrcweir
90cdf0e10cSrcweir    #do some sanity checks
91cdf0e10cSrcweir    if ( ! ( $platform && $srcrootdir && $solverdir ) ) {
92cdf0e10cSrcweir        die "Error: please set environment\n";
93cdf0e10cSrcweir    }
94cdf0e10cSrcweir    if ( ! -d $solverdir ) {
95cdf0e10cSrcweir        die "Error: cannot find solver directory '$solverdir'\n";
96cdf0e10cSrcweir    }
97cdf0e10cSrcweir
98cdf0e10cSrcweir    # Check for local env., taken from solenv/bin/modules/installer/control.pm
99cdf0e10cSrcweir    # In this case the content of SOLARENV starts with the content of SOL_TMP
100cdf0e10cSrcweir    my $solarenv = "";
101cdf0e10cSrcweir    my $sol_tmp;
102cdf0e10cSrcweir    if ( $ENV{'SOLARENV'} ) {
103cdf0e10cSrcweir        $solarenv = $ENV{'SOLARENV'};
104cdf0e10cSrcweir    }
105cdf0e10cSrcweir    if ( $ENV{'SOL_TMP'} ) {
106cdf0e10cSrcweir        $sol_tmp = $ENV{'SOL_TMP'};
107cdf0e10cSrcweir    }
108cdf0e10cSrcweir    if ( defined $sol_tmp && ( $solarenv =~ /^\s*\Q$sol_tmp\E/ )) {
109cdf0e10cSrcweir        # Content of SOLARENV starts with the content of SOL_TMP: Local environment
110cdf0e10cSrcweir        $local_env = 1;
111cdf0e10cSrcweir    }
112cdf0e10cSrcweir}
113cdf0e10cSrcweir
114cdf0e10cSrcweirsub get_deliver_lists
115cdf0e10cSrcweir# find deliver log files on solver
116cdf0e10cSrcweir{
117cdf0e10cSrcweir    my @files;
118cdf0e10cSrcweir    my $pattern = "$solverdir/$platform/inc";
119cdf0e10cSrcweir    $pattern .= "$milestoneext" if ( $milestoneext );
120cdf0e10cSrcweir    $pattern .= "/*/deliver.log";
121cdf0e10cSrcweir
122cdf0e10cSrcweir    @files = glob( $pattern );
123cdf0e10cSrcweir    # do not check modules not yet built
124cdf0e10cSrcweir    foreach my $exceptionpattern ( @exceptionmodlist ) {
125cdf0e10cSrcweir        @files = grep ! /\/$exceptionpattern\//, @files;
126cdf0e10cSrcweir    }
127cdf0e10cSrcweir    if ( ! @files ) {
128cdf0e10cSrcweir        print_logged( "Error: cannot find deliver log files\n" );
129cdf0e10cSrcweir        exit 1;
130cdf0e10cSrcweir    }
131cdf0e10cSrcweir    return \@files;
132cdf0e10cSrcweir}
133cdf0e10cSrcweir
134cdf0e10cSrcweirsub check
135cdf0e10cSrcweir# reads deliver log file given as parameter and compares pairs of files listed there.
136cdf0e10cSrcweir{
137cdf0e10cSrcweir    my $listname = shift;
138cdf0e10cSrcweir    my $error = 0;
139cdf0e10cSrcweir    my %delivered;
140cdf0e10cSrcweir    my $module;
141cdf0e10cSrcweir    my $repository;
142cdf0e10cSrcweir    STDOUT->autoflush(1);
143cdf0e10cSrcweir    # which module are we checking?
144cdf0e10cSrcweir    if ( $listname =~ /\/([\w-]+?)\/deliver\.log$/o) {
145cdf0e10cSrcweir        $module = $1;
146cdf0e10cSrcweir    } else {
147cdf0e10cSrcweir        print_logged( "Error: cannot determine module name from \'$listname\'\n" );
148cdf0e10cSrcweir        return 1;
149cdf0e10cSrcweir    }
150cdf0e10cSrcweir
151cdf0e10cSrcweir    if ( -z $listname ) {
152cdf0e10cSrcweir        print_logged( "Warning: empty deliver log file \'$listname\'. Module '$module' not delivered correctly?\n\n" );
153cdf0e10cSrcweir        return 0;
154cdf0e10cSrcweir    }
155cdf0e10cSrcweir
156cdf0e10cSrcweir    # read deliver log file
157cdf0e10cSrcweir    if ( ! open( DELIVERLOG, "< $listname" ) ) {
158cdf0e10cSrcweir        print_logged( "Error: cannot open file \'$listname\'\n$!" );
159cdf0e10cSrcweir        exit 2;
160cdf0e10cSrcweir    }
161cdf0e10cSrcweir    while ( <DELIVERLOG> ) {
162cdf0e10cSrcweir        next if ( /^LINK / );
163cdf0e10cSrcweir        # What's this modules' repository?
164cdf0e10cSrcweir        if ( /COPY\s+(.+?)\/$module\/prj\/build.lst/ ) {
165cdf0e10cSrcweir#        if ( /COPY (\w[\w\s-]*?)\/$module\/prj\/build.lst/ ) {
166cdf0e10cSrcweir            $repository = $1;
167cdf0e10cSrcweir        }
168cdf0e10cSrcweir        # For now we concentrate on binaries, located in 'bin' or 'lib' and 'misc/build/<...>/[bin|lib]'.
169cdf0e10cSrcweir        next if ( (! /\/$module\/$platform\/[bl]i[nb]\//) && (! /\/$module\/$platform\/misc\/build\//));
170cdf0e10cSrcweir        next if (! /[bl]i[nb]/);
171cdf0e10cSrcweir        next if ( /\.html$/ );
172cdf0e10cSrcweir        chomp;
173cdf0e10cSrcweir        if ( /^\w+? (\S+) (\S+)\s*$/o ) {
174cdf0e10cSrcweir            my $origin = $1;
175cdf0e10cSrcweir            $delivered{$origin} = $2;
176cdf0e10cSrcweir        } else {
177cdf0e10cSrcweir            print_logged( "Warning: cannot parse \'$listname\' line\n\'$_\'\n" );
178cdf0e10cSrcweir        }
179cdf0e10cSrcweir    }
180cdf0e10cSrcweir    close( DELIVERLOG );
181cdf0e10cSrcweir
182cdf0e10cSrcweir    if ( ! $repository ) {
183cdf0e10cSrcweir        print_logged( "Error parsing \'$listname\': cannot determine repository. Module '$module' not delivered correctly?\n\n" );
184cdf0e10cSrcweir        $error ++;
185cdf0e10cSrcweir        return $error;
186cdf0e10cSrcweir    }
187cdf0e10cSrcweir
188cdf0e10cSrcweir    my $path = "$srcrootdir/$repository/$module";
189cdf0e10cSrcweir    # is module physically accessible?
190cdf0e10cSrcweir    # there are valid use cases where we build against a prebuild solver whithout having
191cdf0e10cSrcweir    # all modules at disk
192cdf0e10cSrcweir    my $canread = is_moduledirectory( $path );
193cdf0e10cSrcweir    if ( ! $canread ) {
194cdf0e10cSrcweir        # do not bother about non existing modules in local environment
195cdf0e10cSrcweir        # or on childworkspaces
196cdf0e10cSrcweir        if (( $local_env ) || ( $ENV{CWS_WORK_STAMP} )) {
197cdf0e10cSrcweir            return $error;
198cdf0e10cSrcweir        }
199cdf0e10cSrcweir        # in a master build it is considered an error to have deliver leftovers
200cdf0e10cSrcweir        # from non exising (removed) modules
201cdf0e10cSrcweir        print_logged( "Error: module '$module' not found.\n" );
202cdf0e10cSrcweir        $error++;
203cdf0e10cSrcweir        return $error;
204cdf0e10cSrcweir    }
205cdf0e10cSrcweir    if ( $canread == 2 ) {
206cdf0e10cSrcweir        # module is linked and not built, no need for checking
207cdf0e10cSrcweir        # should not happen any more nowadays ...
208cdf0e10cSrcweir        return $error;
209cdf0e10cSrcweir    }
210cdf0e10cSrcweir
211cdf0e10cSrcweir    # compare all delivered files with their origin
212cdf0e10cSrcweir    # no strict 'diff' allowed here, as deliver may alter files (hedabu, strip, ...)
213cdf0e10cSrcweir    foreach my $file ( sort keys %delivered ) {
214cdf0e10cSrcweir        my $ofile = "$srcrootdir/$file";
215cdf0e10cSrcweir        my $sfile = "$solverdir/$delivered{$file}";
216cdf0e10cSrcweir        if ( $milestoneext ) {
217cdf0e10cSrcweir            # deliver log files do not contain milestone extension on solver
218cdf0e10cSrcweir            $sfile =~ s/\/$platform\/(...)\//\/$platform\/$1$milestoneext\//;
219cdf0e10cSrcweir        }
220cdf0e10cSrcweir        my $orgfile_stats = stat($ofile);
221cdf0e10cSrcweir        next if ( -d _ );  # compare files, not directories
222cdf0e10cSrcweir        my $delivered_stats = lstat($sfile);
223cdf0e10cSrcweir        next if ( -d _ );  # compare files, not directories
224cdf0e10cSrcweir        if ( $^O !~ /^MSWin/ ) {
225cdf0e10cSrcweir            # windows does not know about links.
226cdf0e10cSrcweir            # Therefore lstat() is not a lstat, and the following check would break
227cdf0e10cSrcweir            next if ( -l _ );  # compare files, not links
228cdf0e10cSrcweir        }
229cdf0e10cSrcweir
230cdf0e10cSrcweir        if ( $orgfile_stats && $delivered_stats ) {
231cdf0e10cSrcweir            # Stripping (on unix like platforms) and signing (for windows)
232cdf0e10cSrcweir            # changes file size. Therefore we have to compare for file dates.
233cdf0e10cSrcweir            # File modification time also can change after deliver, f.e. by
234cdf0e10cSrcweir            # rebasing, but only increase. It must not happen that a file on
235cdf0e10cSrcweir            # solver is older than it's source.
236cdf0e10cSrcweir            if ( ( $orgfile_stats->mtime - $delivered_stats->mtime ) gt 1 ) {
237cdf0e10cSrcweir                print_logged( "Error: " );
238cdf0e10cSrcweir                print_logged( "delivered file is older than it's source '$ofile' '$sfile'\n" );
239cdf0e10cSrcweir                $error ++;
240cdf0e10cSrcweir            }
241cdf0e10cSrcweir        } elsif ( !$orgfile_stats && $delivered_stats ) {
242cdf0e10cSrcweir            # This is not an error if we have a solver and did not build the
243cdf0e10cSrcweir            # module!
244cdf0e10cSrcweir        } elsif ( !$orgfile_stats && !$delivered_stats ) {
245cdf0e10cSrcweir            # This is not necessarily an error.
246cdf0e10cSrcweir            # Instead, this seems to be an error of the deliver.log file.
247cdf0e10cSrcweir        } else {
248cdf0e10cSrcweir            print_logged( "Error: no such file '$ofile'\n" ) if ( ! $orgfile_stats );
249cdf0e10cSrcweir            print_logged( "Error: no such file '$sfile'\n" ) if ( ! $delivered_stats );
250cdf0e10cSrcweir            $error ++;
251cdf0e10cSrcweir        }
252cdf0e10cSrcweir    }
253cdf0e10cSrcweir    if ( $error ) {
254cdf0e10cSrcweir        print_logged( "$error errors found: Module '$module' not delivered correctly?\n\n" );
255cdf0e10cSrcweir    }
256cdf0e10cSrcweir    STDOUT->autoflush(0);
257cdf0e10cSrcweir    return $error;
258cdf0e10cSrcweir}
259cdf0e10cSrcweir
260cdf0e10cSrcweirsub is_moduledirectory
261cdf0e10cSrcweir# Test whether we find a module having a d.lst file at a given path.
262cdf0e10cSrcweir# Return value: 1: path is valid directory
263cdf0e10cSrcweir#               2: path.link is a valid link
264cdf0e10cSrcweir#               0: module not found
265cdf0e10cSrcweir{
266cdf0e10cSrcweir    my $dirname = shift;
267cdf0e10cSrcweir    if ( -e "$dirname/prj/d.lst" ) {
268cdf0e10cSrcweir        return 1;
269cdf0e10cSrcweir    } elsif ( -e "$dirname.link/prj/d.lst" ) {
270cdf0e10cSrcweir        return 2
271cdf0e10cSrcweir    } else {
272cdf0e10cSrcweir        return 0;
273cdf0e10cSrcweir    }
274cdf0e10cSrcweir}
275cdf0e10cSrcweir
276cdf0e10cSrcweirsub print_logged
277cdf0e10cSrcweir# Print routine.
278cdf0e10cSrcweir# If a log file name is specified with '-l' option, print_logged() prints to that file
279cdf0e10cSrcweir# as well as to STDOUT. If '-l' option is not set, print_logged() just writes to STDOUT
280cdf0e10cSrcweir{
281cdf0e10cSrcweir    my $message = shift;
282cdf0e10cSrcweir    print "$message";
283cdf0e10cSrcweir    if ( $logfile ) {
284cdf0e10cSrcweir        open ( LOGFILE, ">> $logfile" ) or die "Can't open logfile '$logfile'\n";
285cdf0e10cSrcweir        print LOGFILE "$message";
286cdf0e10cSrcweir        close ( LOGFILE) ;
287cdf0e10cSrcweir    }
288cdf0e10cSrcweir}
289cdf0e10cSrcweir
290cdf0e10cSrcweir
291cdf0e10cSrcweirsub usage
292cdf0e10cSrcweir# print usage message and exit
293cdf0e10cSrcweir{
294cdf0e10cSrcweir    my $retval = shift;
295cdf0e10cSrcweir    print STDERR "Usage: checkdeliver.pl [-h] [-p <platform>]\n";
296cdf0e10cSrcweir    print STDERR "Compares delivered files on solver with original ones in build tree\n";
297cdf0e10cSrcweir    print STDERR "Options:\n";
298cdf0e10cSrcweir    print STDERR "    -h              print this usage message\n";
299cdf0e10cSrcweir    print STDERR "    -p platform     specify platform\n";
300cdf0e10cSrcweir
301cdf0e10cSrcweir    exit $retval;
302cdf0e10cSrcweir}
303cdf0e10cSrcweir
304