Ejemplo n.º 1
0
def main():
    # type: () -> None
    parser = argparse.ArgumentParser()

    parser.add_argument("--genpybind-module", dest="module", required=True)
    parser.add_argument("--genpybind-parse", dest="executable", default="genpybind-parse")
    parser.add_argument("--genpybind-docstring", dest="docstring")
    parser.add_argument("--genpybind-include", nargs="+", dest="includes")
    parser.add_argument("--genpybind-isystem", nargs="+", dest="isystem")
    parser.add_argument("--genpybind-tag", nargs="+", dest="tags")
    parser.add_argument("--genpybind-from-ast", dest="from_ast")
    parser.add_argument('rest', nargs=argparse.REMAINDER)

    # args, rest_args = parser.parse_known_args()
    args = parser.parse_args()

    if args.from_ast:
        if args.rest:
            parser.error(
                "unexpected arguments with --genpybind-from-ast: {}".format(args.rest))
        translation_unit = TranslationUnit.from_ast_file(args.from_ast)
    else:
        name = tempfile.mkdtemp(prefix="genpybind")
        ast_file = os.path.join(name, "genpybind.ast")
        try:
            rest = args.rest[:]
            if rest[0] == "--":
                del rest[0]
            status = subprocess.call(
                [args.executable, "-output-file", ast_file] + rest, stdout=sys.stderr)
            if status != 0:
                parser.error("genpybind-parse returned status {} when called with\n{}".format(
                    status, rest))
            translation_unit = TranslationUnit.from_ast_file(ast_file)
        finally:
            shutil.rmtree(name)

    if translation_unit.diagnostics:
        for diag in translation_unit.diagnostics:
            print("//", diag.format())
            for diag_ in diag.children:
                print("//", "  ", diag_.format())

    toplevel_declarations = gather_declarations(translation_unit.cursor)

    print(expose_as(
        toplevel_declarations,
        module=args.module,
        doc=args.docstring,
        isystem=args.isystem,
        includes=args.includes,
        tags=args.tags,
    ))
Ejemplo n.º 2
0
 def test_fail_from_ast_file(self):
     path = os.path.join(kInputsDir, 'non-existent.ast')
     try:
         tu = TranslationUnit.from_ast_file(path)
     except TranslationUnitLoadError:
         tu = None
     self.assertEqual(tu, None)
Ejemplo n.º 3
0
def test_fail_from_ast_file():
    path = os.path.join(kInputsDir, 'non-existent.ast')
    try:
        tu = TranslationUnit.from_ast_file(path)
    except TranslationUnitLoadError:
        tu = None
    assert tu == None
Ejemplo n.º 4
0
def test_fail_from_ast_file():
    path = os.path.join(kInputsDir, 'non-existent.ast')
    try:
        tu = TranslationUnit.from_ast_file(path)
    except TranslationUnitLoadError:
        tu = None
    assert tu is None
def parse_files(list_of_files: List[str]) -> Tuple[Any, List[Any]]:
    """
    Use Clang to parse the provided list of files, and return
    a tuple of the Clang index, and the list of compiled ASTs
    (one for each compilation unit)
    """
    idx = Index.create()
    t_units = []  # type: List[Any]

    # To avoid parsing the files all the time, store the parsed ASTs
    # of each compilation unit in a cache.
    if not os.path.exists(".cache"):
        os.mkdir(".cache")
    for i, filename in enumerate(list_of_files):
        cache_filename = '.cache/' + os.path.basename(filename) + "_cache"
        # Have I parsed this file before?
        if os.path.exists(cache_filename):
            # Yes, load from cache
            try:
                t_units.append(
                    TranslationUnit.from_ast_file(
                        cache_filename, idx))
                print("[-] Loading cached AST for", filename)
            except TranslationUnitLoadError:
                print("[-] %3d%% Parsing " % (
                    100*(i+1)/len(list_of_files)) + filename)
                t_units.append(idx.parse(filename))
                t_units[-1].save(cache_filename)
        else:
            # No, parse it now.
            print("[-] %3d%% Parsing " % (
                100*(i+1)/len(list_of_files)) + filename)
            t_units.append(idx.parse(filename))
            t_units[-1].save(cache_filename)
    return idx, t_units
Ejemplo n.º 6
0
def parse_files(list_of_files: List[str]) -> Tuple[Any, List[Any]]:
    """
    Use Clang to parse the provided list of files.
    """
    idx = Index.create()
    t_units = []  # type: List[Any]

    # To avoid parsing the files all the time, store the parsed ASTs
    # of each compilation unit in a cache.
    if not os.path.exists(".cache"):
        os.mkdir(".cache")
    for i, filename in enumerate(list_of_files):
        cache_filename = '.cache/' + os.path.basename(filename) + "_cache"
        # Have I parsed this file before?
        if os.path.exists(cache_filename):
            # Yes, load from cache
            try:
                t_units.append(
                    TranslationUnit.from_ast_file(cache_filename, idx))
                logging.info("[-] Loading cached AST for %s", filename)
            except TranslationUnitLoadError:  # pragma: nocover
                logging.info("[-] %3d%% Parsing %s",
                             (100 * (i + 1) / len(list_of_files)),
                             filename)  # pragma: nocover
                t_units.append(idx.parse(filename))  # pragma: nocover
                t_units[-1].save(cache_filename)  # pragma: nocover
        else:
            # No, parse it now.
            logging.info("[-] %3d%% Parsing %s",
                         (100 * (i + 1) / len(list_of_files)), filename)
            # ...to adapt to: .... filename, args=['-I ...', '-D ...']
            t_units.append(idx.parse(filename))
            t_units[-1].save(cache_filename)
    return idx, t_units
Ejemplo n.º 7
0
def test_fail_from_ast_file():
    path = os.path.join(kInputsDir, 'non-existent.ast')
    try:
        index = Index.create()
        tu = TranslationUnit.from_ast_file(path, index=index)
    except TranslationUnitLoadError:
        tu = None
    assert tu == None
Ejemplo n.º 8
0
    def test_load_pathlike(self):
        """Ensure TranslationUnits can be constructed from saved files -
        PathLike variant."""
        tu = get_tu('int foo();')
        self.assertEqual(len(tu.diagnostics), 0)
        with save_tu(tu) as path:
            tu2 = TranslationUnit.from_ast_file(filename=path)
            self.assertEqual(len(tu2.diagnostics), 0)

            foo = get_cursor(tu2, 'foo')
            self.assertIsNotNone(foo)

            # Just in case there is an open file descriptor somewhere.
            del tu2
    def test_load_pathlike(self):
        """Ensure TranslationUnits can be constructed from saved files -
        PathLike variant."""
        tu = get_tu('int foo();')
        self.assertEqual(len(tu.diagnostics), 0)
        with save_tu(tu) as path:
            tu2 = TranslationUnit.from_ast_file(filename=str_to_path(path))
            self.assertEqual(len(tu2.diagnostics), 0)

            foo = get_cursor(tu2, 'foo')
            self.assertIsNotNone(foo)

            # Just in case there is an open file descriptor somewhere.
            del tu2
Ejemplo n.º 10
0
    def test_load(self):
        """Ensure TranslationUnits can be constructed from saved files."""

        tu = get_tu('int foo();')
        self.assertEqual(len(tu.diagnostics), 0)
        with save_tu(tu) as path:
            self.assertTrue(os.path.exists(path))
            self.assertGreater(os.path.getsize(path), 0)

            tu2 = TranslationUnit.from_ast_file(filename=path)
            self.assertEqual(len(tu2.diagnostics), 0)

            foo = get_cursor(tu2, 'foo')
            self.assertIsNotNone(foo)

            # Just in case there is an open file descriptor somewhere.
            del tu2
    def test_load(self):
        """Ensure TranslationUnits can be constructed from saved files."""

        tu = get_tu('int foo();')
        self.assertEqual(len(tu.diagnostics), 0)
        with save_tu(tu) as path:
            self.assertTrue(os.path.exists(path))
            self.assertGreater(os.path.getsize(path), 0)

            tu2 = TranslationUnit.from_ast_file(filename=path)
            self.assertEqual(len(tu2.diagnostics), 0)

            foo = get_cursor(tu2, 'foo')
            self.assertIsNotNone(foo)

            # Just in case there is an open file descriptor somewhere.
            del tu2
def test_load():
    """Ensure TranslationUnits can be constructed from saved files."""

    tu = get_tu('int foo();')
    assert len(tu.diagnostics) == 0
    path = save_tu(tu)

    assert os.path.exists(path)
    assert os.path.getsize(path) > 0

    tu2 = TranslationUnit.from_ast_file(filename=path)
    assert len(tu2.diagnostics) == 0

    foo = get_cursor(tu2, 'foo')
    assert foo is not None

    # Just in case there is an open file descriptor somewhere.
    del tu2

    os.unlink(path)
Ejemplo n.º 13
0
def test_load():
    """Ensure TranslationUnits can be constructed from saved files."""

    tu = get_tu('int foo();')
    assert len(tu.diagnostics) == 0
    path = save_tu(tu)

    assert os.path.exists(path)
    assert os.path.getsize(path) > 0

    tu2 = TranslationUnit.from_ast_file(filename=path)
    assert len(tu2.diagnostics) == 0

    foo = get_cursor(tu2, 'foo')
    assert foo is not None

    # Just in case there is an open file descriptor somewhere.
    del tu2

    os.unlink(path)
Ejemplo n.º 14
0
def main(prog_path, libclang_path, api_header, pch_dst, api_casts_dst, namespace_filter, function_filter, namespace_dst, *libclang_args):
	accept_from = set(namespace_filter.split(" "))
	valid_function_prefixes = set(function_filter.split(" "))
	
	Config.set_library_file(libclang_path)
	index = Index.create(excludeDecls=True)
	# We should really want to use a compilation database here, except that it's only supported by makefiles...
	tu = TranslationUnit.from_ast_file(pch_dst, index)

	filt = FFIFilter(lambda s: s[0] in accept_from,
		lambda x: any([x.displayname.startswith(prefix) for prefix in valid_function_prefixes]),
		solve_template_base_config(index, pch_dst))
	
	code_gen = CodeGen(prog_path,
						pre_hook = lambda: ("namespace %s {" % (namespace_dst,), 4),
						post_hook = lambda indent: "}")
	
	with open(api_casts_dst, 'w') as out_handle:
		from os.path import abspath
		out_handle.write(code_gen(api_header, filt.exposed_types, filt.emit_table_for_TU(tu.cursor)))
Ejemplo n.º 15
0
def _ast_files_to_callinfo(directory):
    index = Index(conf.lib.clang_createIndex(False, True))

    # don't list comprehend so we can get better error reporting
    units = []
    for path in _ast_files(directory):
        try:
            units.append((os.path.abspath(path),
                          TranslationUnit.from_ast_file(path, index)))
        except Exception as e:
            print("error parsing {}, python clang version might be different"
                  "from compiled clang version?".format(path))
            print(e.args)
            print(e.message)
            raise

    ci = CallInfo()

    for path, tu in units:
        for cursor in tu.cursor.get_children():
            # seems hacky, probably misses c++ cases
            # stuff from includes has the include's filename
            if ((cursor.kind == CursorKind.VAR_DECL) and
                (cursor.location.file.name == tu.spelling)):
                ci.add_global(cursor)

    for path, tu in units:
        # WARNING: this will fail silently and unexpectedly if
        # the version of clang that generated the .ast files is
        # different from the python clang library
        sys.stderr.write("  processing ast file {}\n".format(path))
        sys.stderr.flush()
        for cursor in tu.cursor.get_children():
            if (cursor.kind == CursorKind.FUNCTION_DECL or
                cursor.kind == CursorKind.VAR_DECL):
                decl = ci.add_decl(cursor)
                ci.walk_decl(cursor, decl)
    return ci
Ejemplo n.º 16
0
def main():
    # type: () -> None
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "--genpybind-module",
        dest="module",
        required=True,
        help="name of the extension module (cf. PYBIND11_MODULE)")
    parser.add_argument(
        "--genpybind-parse",
        dest="executable",
        default="genpybind-parse",
        help="name of the tool used to extend/amend the abstract syntax tree")
    parser.add_argument(
        "--genpybind-docstring",
        dest="docstring",
        help="docstring of the extension module (cf. PYBIND11_MODULE)")
    parser.add_argument(
        "--genpybind-include",
        nargs="+",
        dest="includes",
        help="includes to add to the generated bindings file (added in \"\"")
    parser.add_argument(
        "--genpybind-isystem",
        nargs="+",
        dest="isystem",
        help="includes to add to the generated bindings file (added in <>)")
    parser.add_argument(
        "--genpybind-tag",
        nargs="+",
        dest="tags",
        help=
        "generate bindings for tagged parts; otherwise tagged parts will be omitted from binding generation"
    )
    parser.add_argument(
        "--genpybind-from-ast",
        dest="from_ast",
        help=
        "read from already generated abstract syntax tree instead of calling genpybind-parse"
    )
    parser.add_argument("--genpybind-output-files",
                        dest="output_files",
                        required=True,
                        help="Comma-separated list of output file names.")
    parser.add_argument(
        'rest',
        nargs=argparse.REMAINDER,
        help=
        "arguments to genpybind-parse; also including compiler flags for the regular processing of the translation unit corresponding to the header file"
    )

    # args, rest_args = parser.parse_known_args()
    args = parser.parse_args()

    if args.from_ast:
        if args.rest:
            parser.error(
                "unexpected arguments with --genpybind-from-ast: {}".format(
                    args.rest))
        translation_unit = TranslationUnit.from_ast_file(args.from_ast)
    else:
        name = tempfile.mkdtemp(prefix="genpybind")
        ast_file = os.path.join(name, "genpybind.ast")
        try:
            rest = args.rest[:]
            if rest[0] == "--":
                del rest[0]
            status = subprocess.call(
                [args.executable, "-output-file", ast_file] + rest,
                stdout=sys.stderr)
            if status != 0:
                parser.error(
                    "genpybind-parse returned status {} when called with\n{}".
                    format(status, rest))
            translation_unit = TranslationUnit.from_ast_file(ast_file)
        finally:
            shutil.rmtree(name)

    if translation_unit.diagnostics:
        for diag in translation_unit.diagnostics:
            print("//", diag.format())
            for diag_ in diag.children:
                print("//", "  ", diag_.format())

    toplevel_declarations = gather_declarations(translation_unit.cursor)

    expose_as(
        toplevel_declarations,
        module=args.module,
        doc=args.docstring,
        isystem=args.isystem,
        includes=args.includes,
        tags=args.tags,
        output_files=args.output_files.split(','),
    )