|
1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 # |
|
4 ############################################################################# |
|
5 ## |
|
6 ## Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
7 ## All rights reserved. |
|
8 ## Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
9 ## |
|
10 ## This file is part of the UI Extensions for Mobile. |
|
11 ## |
|
12 ## GNU Lesser General Public License Usage |
|
13 ## This file may be used under the terms of the GNU Lesser General Public |
|
14 ## License version 2.1 as published by the Free Software Foundation and |
|
15 ## appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
16 ## Please review the following information to ensure the GNU Lesser General |
|
17 ## Public License version 2.1 requirements will be met: |
|
18 ## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
19 ## |
|
20 ## In addition, as a special exception, Nokia gives you certain additional |
|
21 ## rights. These rights are described in the Nokia Qt LGPL Exception |
|
22 ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
23 ## |
|
24 ## If you have questions regarding the use of this file, please contact |
|
25 ## Nokia at developer.feedback@nokia.com. |
|
26 ## |
|
27 ############################################################################# |
|
28 |
|
29 import os |
|
30 import re |
|
31 import sys |
|
32 import shutil |
|
33 import optparse |
|
34 |
|
35 # ============================================================================ |
|
36 # Globals |
|
37 # ============================================================================ |
|
38 VERBOSE = False |
|
39 EXCLUDE = ["hbplugins", "hbservers", "3rdparty", "internal", "tsrc", "debug", "release"] |
|
40 COLLECTIONS = {"hbcore": "HbCore", |
|
41 "hbfeedback": "HbFeedback", |
|
42 "hbinput": "HbInput", |
|
43 "hbutils": "HbUtils", |
|
44 "hbwidgets": "HbWidgets"} |
|
45 |
|
46 # ============================================================================ |
|
47 # OptionParser |
|
48 # ============================================================================ |
|
49 class OptionParser(optparse.OptionParser): |
|
50 def __init__(self): |
|
51 optparse.OptionParser.__init__(self) |
|
52 self.add_option("-v", "--verbose", action="store_true", dest="verbose", |
|
53 help="print verbose information about each step of the sync process") |
|
54 |
|
55 group = optparse.OptionGroup(self, "Input/output options") |
|
56 self.add_option("-i", "--input", dest="inputdir", metavar="dir", |
|
57 help="specify the input <dir>") |
|
58 self.add_option("-o", "--output", dest="outputdir", metavar="dir", |
|
59 help="specify the output <dir>") |
|
60 self.add_option_group(group) |
|
61 |
|
62 self.set_defaults(verbose=VERBOSE) |
|
63 |
|
64 # ============================================================================ |
|
65 # Utils |
|
66 # ============================================================================ |
|
67 if not hasattr(os.path, "relpath"): |
|
68 def relpath(path, start=os.curdir): |
|
69 return path |
|
70 os.path.relpath = relpath |
|
71 |
|
72 def read_file(filepath): |
|
73 content = "" |
|
74 try: |
|
75 file = open(filepath, "r") |
|
76 content = file.read() |
|
77 file.close() |
|
78 except IOError, e: |
|
79 print(e) |
|
80 return content |
|
81 |
|
82 def write_file(filepath, content): |
|
83 try: |
|
84 file = open(filepath, "w") |
|
85 file.write(content) |
|
86 file.close() |
|
87 except IOError, e: |
|
88 print(e) |
|
89 |
|
90 def write_header(filepath, include): |
|
91 write_file(filepath, "#include \"%s\"\n" % include) |
|
92 |
|
93 # ============================================================================ |
|
94 # Component |
|
95 # ============================================================================ |
|
96 class Component: |
|
97 def __init__(self, name): |
|
98 self.name = name |
|
99 self.headers = list() |
|
100 self.privates = list() |
|
101 |
|
102 def read(self, path): |
|
103 entries = os.listdir(path) |
|
104 for entry in entries: |
|
105 entrypath = os.path.join(path, entry) |
|
106 if os.path.isdir(entrypath): |
|
107 self.read(entrypath) |
|
108 elif os.path.isfile(entrypath): |
|
109 if entry.endswith("_p_p.h"): |
|
110 continue |
|
111 elif entry.endswith("_p.h"): |
|
112 self.privates.append(entrypath) |
|
113 elif entry.endswith(".h"): |
|
114 self.headers.append(entrypath) |
|
115 |
|
116 def write(self, path): |
|
117 if len(self.headers) > 0: |
|
118 self._makedirs(path) |
|
119 self._write(path, self.headers, True) |
|
120 |
|
121 if len(self.privates) > 0: |
|
122 privpath = os.path.join(path, "private") |
|
123 self._makedirs(privpath) |
|
124 self._write(privpath, self.privates, False) |
|
125 |
|
126 def _write(self, path, headers, convenience): |
|
127 global VERBOSE |
|
128 if VERBOSE: |
|
129 print("INFO: Writing headers to '%s'" % path) |
|
130 for header in headers: |
|
131 filename = os.path.basename(header) |
|
132 filepath = os.path.join(path, filename) |
|
133 relpath = os.path.relpath(header, path) |
|
134 if VERBOSE: |
|
135 print("INFO:\t ==> %s" % os.path.basename(filepath)) |
|
136 write_header(filepath, relpath.replace("\\", "/")) |
|
137 if convenience: |
|
138 classes = list() |
|
139 content = read_file(header) |
|
140 for match in re.finditer("(?:class|namespace)\s+(?:HB_[^_]+_EXPORT\s+)?(Hb\w*)(\s*;)?", content): |
|
141 if not match.group(2): |
|
142 classes.append(match.group(1)) |
|
143 for match in re.finditer("#pragma hb_header\((\w+)\)", content): |
|
144 classes.append(match.group(1)) |
|
145 for cls in classes: |
|
146 filepath = os.path.join(path, cls) |
|
147 write_header(filepath, filename) |
|
148 |
|
149 def _makedirs(self, path): |
|
150 global VERBOSE |
|
151 if not os.path.exists(path): |
|
152 if VERBOSE: |
|
153 print("INFO: Creating include dir '%s'" % path) |
|
154 os.makedirs(path) |
|
155 |
|
156 # ============================================================================ |
|
157 # Collection |
|
158 # ============================================================================ |
|
159 class Collection: |
|
160 def __init__(self, name): |
|
161 self.name = name |
|
162 self.components = [] |
|
163 |
|
164 def read(self, path): |
|
165 global EXCLUDE |
|
166 for entry in os.listdir(path): |
|
167 entrypath = os.path.join(path, entry) |
|
168 if not entry in EXCLUDE and os.path.isdir(entrypath): |
|
169 component = Component(entry) |
|
170 component.read(entrypath) |
|
171 self.components.append(component) |
|
172 |
|
173 def write(self, path): |
|
174 global COLLECTIONS |
|
175 # include/hbcore |
|
176 includes = list() |
|
177 path = os.path.join(path, self.name) |
|
178 for component in self.components: |
|
179 component.write(path) |
|
180 for header in component.headers: |
|
181 includes.append("#include \"%s\"\n" % os.path.basename(header)) |
|
182 if self.name in COLLECTIONS: |
|
183 write_file(os.path.join(path, self.name + ".h"), "".join(includes)) |
|
184 write_header(os.path.join(path, COLLECTIONS[self.name]), self.name + ".h") |
|
185 |
|
186 # ============================================================================ |
|
187 # Package |
|
188 # ============================================================================ |
|
189 class Package: |
|
190 def __init__(self, name): |
|
191 self.path = name |
|
192 self.collections = list() |
|
193 |
|
194 def read(self, path): |
|
195 global EXCLUDE |
|
196 for entry in os.listdir(path): |
|
197 # hbcore, hbwidgets, hbutils... |
|
198 entrypath = os.path.join(path, entry) |
|
199 if not entry in EXCLUDE and os.path.isdir(entrypath): |
|
200 collection = Collection(entry) |
|
201 collection.read(entrypath) |
|
202 self.collections.append(collection) |
|
203 |
|
204 def write(self, path): |
|
205 for collection in self.collections: |
|
206 collection.write(path) |
|
207 |
|
208 # ============================================================================ |
|
209 # main() |
|
210 # ============================================================================ |
|
211 def main(): |
|
212 global VERBOSE |
|
213 |
|
214 parser = OptionParser() |
|
215 (options, args) = parser.parse_args() |
|
216 |
|
217 VERBOSE = options.verbose |
|
218 |
|
219 if not options.inputdir: |
|
220 options.inputdir = os.path.abspath(sys.path[0]) |
|
221 if os.path.basename(os.path.normpath(options.inputdir)) == "bin": |
|
222 options.inputdir = os.path.normpath(os.path.join(options.inputdir, os.pardir)) |
|
223 if not os.path.basename(os.path.normpath(options.inputdir)) == "src": |
|
224 options.inputdir = os.path.join(options.inputdir, "src") |
|
225 |
|
226 if not options.outputdir: |
|
227 options.outputdir = os.getcwd() |
|
228 if not os.path.basename(os.path.normpath(options.outputdir)) == "include": |
|
229 options.outputdir = os.path.join(options.outputdir, "include") |
|
230 |
|
231 if os.path.exists(options.outputdir): |
|
232 if VERBOSE: |
|
233 print("INFO: Removing include dir '%s'" % options.outputdir) |
|
234 shutil.rmtree(options.outputdir, ignore_errors=True) |
|
235 |
|
236 package = Package("hb") |
|
237 package.read(options.inputdir) |
|
238 package.write(options.outputdir) |
|
239 |
|
240 if __name__ == "__main__": |
|
241 main() |