1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#!/usr/bin/env ruby
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
3dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2010 Apple Inc. All rights reserved.
4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#
5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Redistribution and use in source and binary forms, with or without
6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# modification, are permitted provided that the following conditions
7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# are met:
8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# 1. Redistributions of source code must retain the above copyright
9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#    notice, this list of conditions and the following disclaimer.
10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# 2. Redistributions in binary form must reproduce the above copyright
11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#    notice, this list of conditions and the following disclaimer in the
12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#    documentation and/or other materials provided with the distribution.
13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#
14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# THE POSSIBILITY OF SUCH DAMAGE.
25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
270617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenbase_directory = ENV['TARGET_BUILD_DIR'] or throw "Unable to find TARGET_BUILD_DIR in the environment!"
280617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenis_shallow_bundle = (ENV['SHALLOW_BUNDLE'] || "NO").upcase == "YES"
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockunless base_directory
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  throw "Unable to find TARGET_BUILD_DIR in the environment!"
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockDir.chdir base_directory
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$PERMITTED_INCLUDE_TYPES = { :public => [ :public ], :private => [ :public, :private ] }
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$HEADER_NAMES_TO_TYPE = { }
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$HEADERS_BY_TYPE = { :public => [], :private => [] }
40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$error_printed = false
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdef print_error msg
44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  $error_printed = true
45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  STDERR.puts "ERROR: #{msg}"
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
480617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsendef build_header_maps is_shallow_bundle
490617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen  current_version_path = is_shallow_bundle ? "" : "Versions/A/"
500617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen  all_headers = `find WebKit.framework/#{current_version_path}{,Private}Headers -type f -name '*.h'`.split
51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  all_headers.each do |header|
53dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if /\/Headers\/(.*)/.match(header)
54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      $HEADER_NAMES_TO_TYPE[$1] = :public
55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      $HEADERS_BY_TYPE[:public] << header
56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    elsif /\/PrivateHeaders\/(.*)/.match(header)
57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      $HEADER_NAMES_TO_TYPE[$1] = :private
58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      $HEADERS_BY_TYPE[:private] << header
59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else
60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      print_error "Unknown header type: #{header}"
61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    end
62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  end
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdef resolve_include(header, included_header, permitted_types)
66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  # Ignore includes that aren't in the typical framework style.
67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  return unless /<([^\/]+)\/(.*)>/.match(included_header)
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  framework, included_header_name = [$1, $2]
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  # Ignore includes that aren't related to other WebKit headers.
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  return unless framework =~ /^Web/
73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  # A header of any type including a WebCore header is a recipe for disaster.
75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  if framework == "WebCore"
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # <rdar://problem/7718826> WebKeyGenerator.h should not include a WebCore header
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if header =~ /\/WebKeyGenerator.h$/ and included_header_name == "WebCoreKeyGenerator.h"
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print_error "#{header} included #{included_header}!"
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return
81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  end
82dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  header_type = $HEADER_NAMES_TO_TYPE[included_header_name]
84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  if not header_type
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print_error "#{header} included #{included_header} but I could not find a header of that name!"
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  elsif not permitted_types.member?(header_type)
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print_error "#{header} included #{included_header} which is #{header_type}!"
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  end
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdef verify_includes(header, permitted_types)
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  File.open(header) do |file|
94dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    file.each_line do |line|
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      if /#(include|import) (.*)/.match(line)
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        resolve_include(header, $2, permitted_types)
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block      end
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    end
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  end
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1020617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsenbuild_header_maps is_shallow_bundle
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$HEADERS_BY_TYPE.each do |header_type, headers|
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  permitted_types = $PERMITTED_INCLUDE_TYPES[header_type]
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  headers.each do |header|
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    verify_includes header, permitted_types
108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  end
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockend
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockexit 1 if $error_printed
112