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

Unified 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, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: tools/generate_library_loader/generate_library_loader.py
diff --git a/tools/generate_library_loader/generate_library_loader.py b/tools/generate_library_loader/generate_library_loader.py
new file mode 100755
index 0000000000000000000000000000000000000000..403aebf7fc245a7fe94771f21faa80720b85f1de
--- /dev/null
+++ b/tools/generate_library_loader/generate_library_loader.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Creates a library loader (a header and implementation file),
+which is a wrapper for dlopen or direct linking with given library.
+
+The loader makes it possible to have the same client code for both cases,
+and also makes it easier to write code using dlopen (and also provides
+a standard way to do so, and limits the ugliness just to generated files).
+
+For more info refer to http://crbug.com/162733 .
+"""
+
+
+import optparse
+import os.path
+import re
+import sys
+
+
+HEADER_TEMPLATE = """// This is generated file. Do not modify directly.
+// Path to the code generator: %(generator_path)s .
+
+#ifndef %(unique_prefix)s_H_
+#define %(unique_prefix)s_H_
+
+%(wrapped_header_include)s
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#ifdef %(unique_prefix)s_DLOPEN
+#include "base/native_library.h"
+#endif
+
+class %(class_name)s {
+ public:
+ %(class_name)s();
+ ~%(class_name)s();
+
+ bool Load(const std::string& library_name) WARN_UNUSED_RESULT;
+
+%(member_decls)s
+
+ private:
+#ifdef %(unique_prefix)s_DLOPEN
+ base::NativeLibrary library_;
+#endif
+
+ bool loaded_;
+
+ DISALLOW_COPY_AND_ASSIGN(%(class_name)s);
+};
+
+#endif // %(unique_prefix)s_H_
+"""
+
+
+HEADER_MEMBER_TEMPLATE = """ typeof(&::%(function_name)s) %(function_name)s;
+"""
+
+
+IMPL_TEMPLATE = """// This is generated file. Do not modify directly.
+// Path to the code generator: %(generator_path)s .
+
+#include "%(generated_header_name)s"
+
+#include "base/file_path.h"
+#include "base/logging.h"
+
+%(class_name)s::%(class_name)s() : loaded_(false) {
+}
+
+%(class_name)s::~%(class_name)s() {
+#ifdef %(unique_prefix)s_DLOPEN
+ if (loaded_)
+ base::UnloadNativeLibrary(library_);
+#endif
+}
+
+bool %(class_name)s::Load(const std::string& library_name) {
+ if (loaded_) {
+ NOTREACHED();
+ return false;
+ }
+
+#ifdef %(unique_prefix)s_DLOPEN
+ library_ = base::LoadNativeLibrary(FilePath(library_name), NULL);
+ if (library_) {
+#endif
+
+%(member_init)s
+
+ loaded_ = true;
+ return true;
+#ifdef %(unique_prefix)s_DLOPEN
+ }
+
+ return false;
+#endif
+}
+"""
+
+IMPL_MEMBER_TEMPLATE = """
+#ifdef %(unique_prefix)s_DLOPEN
+ this->%(function_name)s =
+ reinterpret_cast<typeof(this->%(function_name)s)>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library_, "%(function_name)s"));
+ 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.
+ 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.
+ return false;
+ }
+#else
+ 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
+#endif
+"""
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('--name')
+ parser.add_option('--output')
+ parser.add_option('--header')
+
+ parser.add_option('--use-extern-c', action='store_true', default=False)
+ parser.add_option('--link-directly', type=int, default=0)
+
+ options, args = parser.parse_args()
+
+ if not options.name:
+ parser.error('Missing --name parameter')
+ if not options.output:
+ parser.error('Missing --output parameter')
+ if not options.header:
+ parser.error('Missing --header paramater')
+ if not args:
+ parser.error('No function names specified')
+
+ # Make sure we are always dealing with an absolute path
+ # to avoid issues caused by different relative path roots.
+ options.output = os.path.abspath(options.output)
+
+ # Create a unique prefix, e.g. for header guards.
+ 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.
+
+ member_decls = []
+ member_init = []
+ for fn in args:
+ member_decls += HEADER_MEMBER_TEMPLATE % {
+ 'function_name': fn,
+ 'unique_prefix': unique_prefix
+ }
+ member_init += IMPL_MEMBER_TEMPLATE % {
+ 'function_name': fn,
+ 'unique_prefix': unique_prefix
+ }
+
+ wrapped_header_include = '#include %s' % options.header
+
+ # Some libraries (e.g. libpci) have headers that cannot be included
+ # without extern "C", otherwise they cause the link to fail.
+ if options.use_extern_c:
+ 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.
+
+ # It seems cleaner just to have a single #define here and #ifdefs in bunch
+ # of places, rather than having a different set of templates, duplicating
+ # or complicating more code.
+ if options.link_directly == 0:
+ 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.
+
+ # Make it easier for people to find the code generator just in case.
+ # Doing it this way is more maintainable, because it's going to work
+ # even if file gets moved without updating the contents.
+ generator_path = os.path.abspath(__file__)
+
+ header_contents = HEADER_TEMPLATE % {
+ 'generator_path': generator_path,
+ 'unique_prefix': unique_prefix,
+ 'wrapped_header_include': wrapped_header_include,
+ 'class_name': options.name,
+ 'member_decls': ''.join(member_decls),
+ }
+
+ impl_contents = IMPL_TEMPLATE % {
+ 'generator_path': generator_path,
+ 'unique_prefix': unique_prefix,
+ 'generated_header_name': options.output + '.h',
+ 'class_name': options.name,
+ 'member_init': ''.join(member_init),
+ }
+
+ header_file = open(options.output + '.h', 'w')
+ try:
+ header_file.write(header_contents)
+ finally:
+ header_file.close()
+
+ impl_file = open(options.output + '.cc', 'w')
+ try:
+ impl_file.write(impl_contents)
+ finally:
+ impl_file.close()
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
« 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