#!/usr/bin/perl # Copyright (C) 2006, 2007, 2008, 2010, 2011 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. # "check-for-inappropriate-objc-class-names" script for WebKit Open Source Project # Intended to be invoked from an Xcode build step to check if a framework # defines any Objective-C class whose name does not have one of the prefixes # the framework is allowed to use. use warnings; use strict; use File::Basename; sub touch($); my @allowedPrefixes = @ARGV; # Xcode will automatically link ObjC binaries against libarclite in some cases, which defines a class called __ARCLite__. push(@allowedPrefixes, "__ARCLite"); die "No allowed prefixes passed on the command line" if !@allowedPrefixes; my $arch = $ENV{'CURRENT_ARCH'}; my $target = $ENV{'TARGET_NAME'}; my $variant = $ENV{'CURRENT_VARIANT'}; my $coverageBuild = $ENV{'WEBKIT_COVERAGE_BUILD'}; my $executablePath = "$ENV{'TARGET_BUILD_DIR'}/$ENV{'EXECUTABLE_PATH'}"; my $buildTimestampPath = $ENV{'TARGET_TEMP_DIR'} . "/" . basename($0) . join('-', @allowedPrefixes) . ".timestamp"; my $buildTimestampAge = -M $buildTimestampPath; my $executablePathAge = -M $executablePath; my $scriptAge = -M $0; my $pattern = "^(" . join('|', @allowedPrefixes) . ")"; my $sawError = 0; if (!defined $executablePathAge || !defined $buildTimestampAge || $executablePathAge < $buildTimestampAge || $scriptAge < $buildTimestampAge) { if (!open NM, "(nm -Ujp '$executablePath' | sed 's/^/STDOUT:/') 2>&1 |") { print "ERROR: Could not open $executablePath\n"; $sawError = 1; next; } my @badNames; while () { if (/^STDOUT:/) { next unless /^STDOUT:_OBJC_CLASS_\$_/; chomp; my $className = substr($_, 21); push(@badNames, $className) unless $className =~ /$pattern/; } else { print STDERR if $_ ne "nm: no name list\n"; } } close NM; # begin PLATFORM(IOS) # On iOS put exceptions in place for existing bad names. Future bad names will # be caught and should be fixed immediately. Fixing these is covered by: # Fix Inappropriate Objective-C Class Names found by build phase my %exceptions = ( # WebCore "WKQuadObject" => 1, "LegacyTileCacheTombstone" => 1, "LegacyTileHostLayer" => 1, "LegacyTileLayer" => 1, "WAKResponder" => 1, "NSCursor" => 1, "WAKClipView" => 1, "WAKScrollView" => 1, "WAKView" => 1, "WAKWindow" => 1, ); my @realBadNames; for my $className (@badNames) { push(@realBadNames, $className) unless exists($exceptions{$className}); } @badNames = @realBadNames; # end PLATFORM(IOS) if (@badNames) { my $shortName = $executablePath; $shortName =~ s/.*\///; print "ERROR: $shortName defines one or more Objective-C classes with inappropriate names. ($executablePath)\n"; for my $className (@badNames) { print "ERROR: Inappropriate Objective-C class name: $className.\n"; } if (@allowedPrefixes > 1) { print "ERROR: Objective-C class names in $target must have one of these prefixes: " . join(", ", map('"' . $_ . '"', @allowedPrefixes)) . ".\n"; } else { print "ERROR: Objective-C class names in $target must have the prefix \"" . $allowedPrefixes[0] . "\".\n"; } $sawError = 1; } } if ($sawError and !$coverageBuild) { unlink $executablePath; exit 1; } touch($buildTimestampPath); exit 0; sub touch($) { my ($path) = @_; open(TOUCH, ">", $path) or die "$!"; close(TOUCH); }