Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: tools/generate_library_loader/generate_library_loader.py

Issue 11415138: Linux: create a library loader code generator for dlopen and use it for libpci. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """
7 Creates a library loader (a header and implementation file),
8 which is a wrapper for dlopen or direct linking with given library.
9
10 The loader makes it possible to have the same client code for both cases,
11 and also makes it easier to write code using dlopen (and also provides
12 a standard way to do so, and limits the ugliness just to generated files).
13
14 For more info refer to http://crbug.com/162733 .
15 """
16
17
18 import optparse
19 import os.path
20 import re
21 import sys
22
23
24 HEADER_TEMPLATE = """// This is generated file. Do not modify directly.
25 // Path to the code generator: %(generator_path)s .
26
27 #ifndef %(unique_prefix)s_H_
28 #define %(unique_prefix)s_H_
29
30 %(wrapped_header_include)s
31
32 #include <string>
33
34 #include "base/basictypes.h"
35 #include "base/compiler_specific.h"
36 #ifdef %(unique_prefix)s_DLOPEN
37 #include "base/native_library.h"
38 #endif
39
40 class %(class_name)s {
41 public:
42 %(class_name)s();
43 ~%(class_name)s();
44
45 bool Load(const std::string& library_name) WARN_UNUSED_RESULT;
46
47 %(member_decls)s
48
49 private:
50 #ifdef %(unique_prefix)s_DLOPEN
51 base::NativeLibrary library_;
52 #endif
53
54 bool loaded_;
55
56 DISALLOW_COPY_AND_ASSIGN(%(class_name)s);
57 };
58
59 #endif // %(unique_prefix)s_H_
60 """
61
62
63 HEADER_MEMBER_TEMPLATE = """ typeof(&::%(function_name)s) %(function_name)s;
64 """
65
66
67 IMPL_TEMPLATE = """// This is generated file. Do not modify directly.
68 // Path to the code generator: %(generator_path)s .
69
70 #include "%(generated_header_name)s"
71
72 #include "base/file_path.h"
73 #include "base/logging.h"
74
75 %(class_name)s::%(class_name)s() : loaded_(false) {
76 }
77
78 %(class_name)s::~%(class_name)s() {
79 #ifdef %(unique_prefix)s_DLOPEN
80 if (loaded_)
81 base::UnloadNativeLibrary(library_);
82 #endif
83 }
84
85 bool %(class_name)s::Load(const std::string& library_name) {
86 if (loaded_) {
87 NOTREACHED();
88 return false;
89 }
90
91 #ifdef %(unique_prefix)s_DLOPEN
92 library_ = base::LoadNativeLibrary(FilePath(library_name), NULL);
93 if (library_) {
94 #endif
95
96 %(member_init)s
97
98 loaded_ = true;
99 return true;
100 #ifdef %(unique_prefix)s_DLOPEN
101 }
102
103 return false;
104 #endif
105 }
106 """
107
108 IMPL_MEMBER_TEMPLATE = """
109 #ifdef %(unique_prefix)s_DLOPEN
110 this->%(function_name)s =
111 reinterpret_cast<typeof(this->%(function_name)s)>(
112 base::GetFunctionPointerFromNativeLibrary(
113 library_, "%(function_name)s"));
114 if (!this->%(function_name)s) {
115 base::UnloadNativeLibrary(library_);
116 return false;
117 }
118 #else
119 this->%(function_name)s = &::%(function_name)s;
120 #endif
121 """
122
123
124 def main():
125 parser = optparse.OptionParser()
126 parser.add_option('--name')
127 parser.add_option('--output')
128 parser.add_option('--header')
129
130 parser.add_option('--use-extern-c', action='store_true', default=False)
131 parser.add_option('--link-directly', type=int, default=0)
132
133 options, args = parser.parse_args()
134
135 if not options.name:
136 parser.error('Missing --name parameter')
137 if not options.output:
138 parser.error('Missing --output parameter')
139 if not options.header:
140 parser.error('Missing --header paramater')
141 if not args:
142 parser.error('No function names specified')
143
144 # Create a unique prefix, e.g. for header guards.
145 unique_prefix = re.sub(r'[\W]', '_', options.output).upper();
146
147 member_decls = []
148 member_init = []
149 for fn in args:
150 member_decls += HEADER_MEMBER_TEMPLATE % {
151 'function_name': fn,
152 'unique_prefix': unique_prefix
153 }
154 member_init += IMPL_MEMBER_TEMPLATE % {
155 'function_name': fn,
156 'unique_prefix': unique_prefix
157 }
158
159 wrapped_header_include = '#include %s' % options.header
160
161 # Some libraries (e.g. libpci) have headers that cannot be included
162 # without extern "C", otherwise they cause the link to fail.
163 if options.use_extern_c:
164 wrapped_header_include = 'extern "C" {\n%s\n}\n' % wrapped_header_include
165
166 # It seems cleaner just to have a single #define here and #ifdefs in bunch
167 # of places, rather than having a different set of templates, duplicating
168 # or complicating more code.
169 if options.link_directly == 0:
170 wrapped_header_include += '#define %s_DLOPEN\n' % unique_prefix
171
172 # Make it easier for people to find the code generator just in case.
173 # Doing it this way is more maintainable, because it's going to work
174 # even if file gets moved without updating the contents.
175 generator_path = os.path.abspath(__file__)
176
177 header_contents = HEADER_TEMPLATE % {
178 'generator_path': generator_path,
179 'unique_prefix': unique_prefix,
180 'wrapped_header_include': wrapped_header_include,
181 'class_name': options.name,
182 'member_decls': ''.join(member_decls),
183 }
184
185 impl_contents = IMPL_TEMPLATE % {
186 'generator_path': generator_path,
187 'unique_prefix': unique_prefix,
188 'generated_header_name': options.output + '.h',
189 'class_name': options.name,
190 'member_init': ''.join(member_init),
191 }
192
193 header_file = open(options.output + '.h', 'w')
194 try:
195 header_file.write(header_contents)
196 finally:
197 header_file.close()
198
199 impl_file = open(options.output + '.cc', 'w')
200 try:
201 impl_file.write(impl_contents)
202 finally:
203 impl_file.close()
204
205 return 0
206
207 if __name__ == '__main__':
208 sys.exit(main())
OLDNEW
« build/linux/system.gyp ('K') | « content/gpu/gpu_info_collector_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698