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

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: another try 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) {
Mark Mentovai 2012/11/27 21:01:18 If you’re using the dlopen-at-runtime variant, a f
Paweł Hajdan Jr. 2012/11/27 22:27:24 Done.
115 base::UnloadNativeLibrary(library_);
Mark Mentovai 2012/11/27 21:01:18 Clear loaded_? Zero the function pointers?
Paweł Hajdan Jr. 2012/11/27 22:27:24 Done.
116 return false;
117 }
118 #else
119 this->%(function_name)s = &::%(function_name)s;
Mark Mentovai 2012/11/27 21:01:18 In this case, I think it’s better to just have the
Paweł Hajdan Jr. 2012/11/27 22:27:24 Hmm, what's the advantage? And then, should I also
Mark Mentovai 2012/11/27 23:09:11 Paweł Hajdan Jr. wrote:
Paweł Hajdan Jr. 2012/11/28 01:05:51 Not sure if that's worth it for possible weird int
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 # Make sure we are always dealing with an absolute path
145 # to avoid issues caused by different relative path roots.
146 options.output = os.path.abspath(options.output)
147
148 # Create a unique prefix, e.g. for header guards.
149 unique_prefix = re.sub(r'[\W]', '_', options.output).upper();
Mark Mentovai 2012/11/27 21:01:18 Because options.output is likely an absolute path
Paweł Hajdan Jr. 2012/11/27 22:27:24 Done.
150
151 member_decls = []
152 member_init = []
153 for fn in args:
154 member_decls += HEADER_MEMBER_TEMPLATE % {
155 'function_name': fn,
156 'unique_prefix': unique_prefix
157 }
158 member_init += IMPL_MEMBER_TEMPLATE % {
159 'function_name': fn,
160 'unique_prefix': unique_prefix
161 }
162
163 wrapped_header_include = '#include %s' % options.header
164
165 # Some libraries (e.g. libpci) have headers that cannot be included
166 # without extern "C", otherwise they cause the link to fail.
167 if options.use_extern_c:
168 wrapped_header_include = 'extern "C" {\n%s\n}\n' % wrapped_header_include
Mark Mentovai 2012/11/27 21:01:18 You’re losing a TODO in the existing code that sai
Paweł Hajdan Jr. 2012/11/27 22:27:24 Done.
169
170 # It seems cleaner just to have a single #define here and #ifdefs in bunch
171 # of places, rather than having a different set of templates, duplicating
172 # or complicating more code.
173 if options.link_directly == 0:
174 wrapped_header_include += '#define %s_DLOPEN\n' % unique_prefix
Mark Mentovai 2012/11/27 21:01:18 I don’t agree with this 100%. I think I’d be happi
Paweł Hajdan Jr. 2012/11/27 22:27:24 Done.
175
176 # Make it easier for people to find the code generator just in case.
177 # Doing it this way is more maintainable, because it's going to work
178 # even if file gets moved without updating the contents.
179 generator_path = os.path.abspath(__file__)
180
181 header_contents = HEADER_TEMPLATE % {
182 'generator_path': generator_path,
183 'unique_prefix': unique_prefix,
184 'wrapped_header_include': wrapped_header_include,
185 'class_name': options.name,
186 'member_decls': ''.join(member_decls),
187 }
188
189 impl_contents = IMPL_TEMPLATE % {
190 'generator_path': generator_path,
191 'unique_prefix': unique_prefix,
192 'generated_header_name': options.output + '.h',
193 'class_name': options.name,
194 'member_init': ''.join(member_init),
195 }
196
197 header_file = open(options.output + '.h', 'w')
198 try:
199 header_file.write(header_contents)
200 finally:
201 header_file.close()
202
203 impl_file = open(options.output + '.cc', 'w')
204 try:
205 impl_file.write(impl_contents)
206 finally:
207 impl_file.close()
208
209 return 0
210
211 if __name__ == '__main__':
212 sys.exit(main())
OLDNEW
« content/gpu/gpu_info_collector_linux.cc ('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