| 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..c1342cca02ef03a3e00b67f49bbbaecfb0e8d7a2
|
| --- /dev/null
|
| +++ b/tools/generate_library_loader/generate_library_loader.py
|
| @@ -0,0 +1,208 @@
|
| +#!/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) {
|
| + base::UnloadNativeLibrary(library_);
|
| + return false;
|
| + }
|
| +#else
|
| + this->%(function_name)s = &::%(function_name)s;
|
| +#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')
|
| +
|
| + # Create a unique prefix, e.g. for header guards.
|
| + unique_prefix = re.sub(r'[\W]', '_', options.output).upper();
|
| +
|
| + 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
|
| +
|
| + # 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
|
| +
|
| + # 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())
|
|
|