15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#!/usr/bin/perl
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 1.  Redistributions of source code must retain the above copyright
10fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch#     notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 2.  Redistributions in binary form must reproduce the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     notice, this list of conditions and the following disclaimer in the
13fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch#     documentation and/or other materials provided with the distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#     its contributors may be used to endorse or promote products derived
16fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch#     from this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# "check-for-global-initializers" script for WebKit Open Source Project
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# Intended to be invoked from an Xcode build step to check if there are
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)# any global initializers in a target.
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use warnings;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use strict;
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)use File::Basename;
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub touch($);
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub demangle($);
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $arch = $ENV{'CURRENT_ARCH'};
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $configuration = $ENV{'CONFIGURATION'};
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $target = $ENV{'TARGET_NAME'};
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $variant = $ENV{'CURRENT_VARIANT'};
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $coverageBuild = $ENV{'WEBKIT_COVERAGE_BUILD'};
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $debugRoot = $ENV{'WEBKIT_DEBUG_ROOT'};
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$arch = $ENV{'NATIVE_ARCH'} if !$arch; # for Xcode 2.1, which does not have CURRENT_ARCH
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)$variant = "normal" if !$variant; # for Xcode 2.1, which does not have CURRENT_VARIANT
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $executablePath = "$ENV{'TARGET_BUILD_DIR'}/$ENV{'EXECUTABLE_PATH'}";
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $buildTimestampPath = $ENV{'TARGET_TEMP_DIR'} . "/" . basename($0) . ".timestamp";
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $buildTimestampAge = -M $buildTimestampPath;
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $scriptAge = -M $0;
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $list = $ENV{"LINK_FILE_LIST_${variant}_${arch}"};
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if (!open LIST, $list) {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    print "ERROR: Could not open $list\n";
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    exit 1;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my @files = <LIST>;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)chomp @files;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)close LIST;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)my $sawError = 0;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)for my $file (sort @files) {
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (defined $buildTimestampAge && $buildTimestampAge < $scriptAge) {
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        my $fileAge = -M $file;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        next if defined $fileAge && $fileAge > $buildTimestampAge;
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!open NM, "(nm '$file' | sed 's/^/STDOUT:/') 2>&1 |") {
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        print "ERROR: Could not open $file\n";
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $sawError = 1;
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        next;
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $sawGlobal = 0;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my @globals;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (<NM>) {
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (/^STDOUT:/) {
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            my $line = $_;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ($line =~ /__GLOBAL__I(.+)$/) {
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                $sawGlobal = 1;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                push(@globals, demangle($1));
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            print STDERR if $_ ne "nm: no name list\n";
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close NM;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ($sawGlobal) {
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        my $shortName = $file;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $shortName =~ s/.*\///;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        # Special cases for files that have initializers in debug builds.
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if ($configuration eq "Debug" or $variant eq "debug" or $debugRoot) {
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ($target eq "JavaScriptCore") {
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "AllInOneFile.o";
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Opcode.o";
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Structure.o";
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "nodes.o";
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ($target eq "WebCore") {
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "BidiRun.o";
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "CachedPage.o";
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "CachedResource.o";
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "FEGaussianBlur.o";
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Frame.o";
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "JSCustomSQLTransactionCallback.o";
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "JSLazyEventListener.o";
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Node.o";
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Page.o";
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "Range.o";
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "RenderObject.o";
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "SVGElementInstance.o";
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "SubresourceLoader.o";
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "XMLHttpRequest.o";
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ($target eq "WebKit") {
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "HostedNetscapePluginStream.o";
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "NetscapePluginInstanceProxy.o";
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if ($target eq "WebKit2") {
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "WebContext.o";
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "WebFrame.o";
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "WebPage.o";
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next if $shortName eq "WebPageProxy.o";
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        print "ERROR: $shortName has one or more global initializers in it! ($file), near @globals\n";
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        $sawError = 1;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)if ($sawError and !$coverageBuild) {
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unlink $executablePath;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    exit 1;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)touch($buildTimestampPath);
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exit 0;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub touch($)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($path) = @_;
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    open(TOUCH, ">", $path) or die "$!";
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close(TOUCH);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)sub demangle($)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my ($symbol) = @_;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!open FILT, "c++filt $symbol |") {
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        print "ERROR: Could not open c++filt\n";
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    my $result = <FILT>;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    close FILT;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    chomp $result;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return $result;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
168