Merge pull request #1360 from nanoric/autocxxparser
generator.binding:CXXParser:增加include路径的设置
This commit is contained in:
commit
901664c10a
16
binding/build.bat
Normal file
16
binding/build.bat
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@echo off
|
||||||
|
if "%VS150COMNTOOLS%"=="" (
|
||||||
|
echo Please run this batch file under "x64 Native Tools Command Prompt for VS 2017"
|
||||||
|
echo Read the doc!
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
@echo on
|
||||||
|
set binding_dir=%~dp0
|
||||||
|
cd %binding_dir%
|
||||||
|
|
||||||
|
rmdir /S /Q build
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -G "Visual Studio 15 2017 Win64" ..
|
||||||
|
msbuild vnpy_binding.sln /p:Configuration=Release /p:Platform=x64
|
@ -10,15 +10,21 @@
|
|||||||
> 在安装CMake的时候必须勾选将CMake加入PATH
|
> 在安装CMake的时候必须勾选将CMake加入PATH
|
||||||
> 在安装Visual Studio的时候必须勾选使用C++的桌面开发(Desktop Development with C++)
|
> 在安装Visual Studio的时候必须勾选使用C++的桌面开发(Desktop Development with C++)
|
||||||
|
|
||||||
## 编译步骤
|
## 一键编译
|
||||||
|
|
||||||
|
打开开始菜单-Visual Studio 2017-x64 Native Tools Command Prompt for VS 2017
|
||||||
|
将vnpy/binding/build.bat拖入弹出的控制台,回车运行即可。
|
||||||
|
|
||||||
|
|
||||||
|
## 手动编译
|
||||||
|
|
||||||
确保你安装好了Python3,CMake还有Visual Studio和C++编译环境,下载好[vnpy]并解压。
|
确保你安装好了Python3,CMake还有Visual Studio和C++编译环境,下载好[vnpy]并解压。
|
||||||
打开开始菜单-Visual Studio 2017-x64 Native Tools Command Prompt for VS 2017
|
打开开始菜单-Visual Studio 2017-x64 Native Tools Command Prompt for VS 2017
|
||||||
在弹出的控制台中运行以下命令:(假设你解压到C:\vnpy下)
|
在弹出的控制台中运行以下命令(将vnpy解压目录改为你将vnpy解压到的目录):
|
||||||
```bat
|
```bat
|
||||||
cd C:\vnpy
|
cd vnpy解压目录
|
||||||
mkdir binding/build
|
mkdir binding\build
|
||||||
cd binding/build
|
cd binding\build
|
||||||
cmake -G "Visual Studio 15 2017 Win64" ..
|
cmake -G "Visual Studio 15 2017 Win64" ..
|
||||||
msbuild vnpy_binding.sln /p:Configuration=Release /p:Platform=x64
|
msbuild vnpy_binding.sln /p:Configuration=Release /p:Platform=x64
|
||||||
```
|
```
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from autocxxpy.cxxparser import CXXParser, CXXParseResult
|
from autocxxpy.cxxparser import CXXFileParser, CXXParseResult
|
||||||
from autocxxpy.generator import GeneratorOptions
|
from autocxxpy.generator import GeneratorOptions
|
||||||
from autocxxpy.preprocessor import PreProcessorResult, PreProcessor
|
from autocxxpy.preprocessor import PreProcessorResult, PreProcessor
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class CtpAdaptor:
|
|||||||
self.md_header = md_header
|
self.md_header = md_header
|
||||||
|
|
||||||
def parse(self) -> GeneratorOptions:
|
def parse(self) -> GeneratorOptions:
|
||||||
r0: CXXParseResult = CXXParser(
|
r0: CXXParseResult = CXXFileParser(
|
||||||
[self.md_header, self.td_header]
|
[self.md_header, self.td_header]
|
||||||
).parse()
|
).parse()
|
||||||
r1: PreProcessorResult = PreProcessor(r0).process()
|
r1: PreProcessorResult = PreProcessor(r0).process()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional, Sequence
|
||||||
|
|
||||||
from .clang.cindex import (
|
from .clang.cindex import (
|
||||||
Config,
|
Config,
|
||||||
@ -168,16 +168,26 @@ class CXXParseResult(Namespace):
|
|||||||
macros: Dict[str, str] = field(default_factory=dict)
|
macros: Dict[str, str] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
class CXXFileParser:
|
class CXXParser:
|
||||||
def __init__(self, file_path: Optional[str], unsaved_files=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
file_path: Optional[str],
|
||||||
|
unsaved_files: Sequence[Sequence[str]] = None,
|
||||||
|
args: List[str] = None,
|
||||||
|
):
|
||||||
|
if args is None:
|
||||||
|
args = []
|
||||||
self.unsaved_files = unsaved_files
|
self.unsaved_files = unsaved_files
|
||||||
self.file_path = file_path
|
self.file_path = file_path
|
||||||
|
self.args = args
|
||||||
|
if "-std=c++11" not in self.args:
|
||||||
|
self.args.append("-std=c++11")
|
||||||
|
|
||||||
def parse(self) -> CXXParseResult:
|
def parse(self) -> CXXParseResult:
|
||||||
idx = Index.create()
|
idx = Index.create()
|
||||||
rs = idx.parse(
|
rs = idx.parse(
|
||||||
self.file_path,
|
self.file_path,
|
||||||
args="-std=c++11 ".split(" "),
|
args=self.args,
|
||||||
unsaved_files=self.unsaved_files,
|
unsaved_files=self.unsaved_files,
|
||||||
options=(
|
options=(
|
||||||
TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
|
TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
|
||||||
@ -189,27 +199,27 @@ class CXXFileParser:
|
|||||||
# todo: parse namespace
|
# todo: parse namespace
|
||||||
for c in rs.cursor.walk_preorder():
|
for c in rs.cursor.walk_preorder():
|
||||||
if c.kind == CursorKind.FUNCTION_DECL:
|
if c.kind == CursorKind.FUNCTION_DECL:
|
||||||
func = CXXFileParser._process_function(c)
|
func = CXXParser._process_function(c)
|
||||||
result.functions[func.name] = func
|
result.functions[func.name] = func
|
||||||
elif c.kind == CursorKind.ENUM_DECL:
|
elif c.kind == CursorKind.ENUM_DECL:
|
||||||
e = CXXFileParser._process_enum(c)
|
e = CXXParser._process_enum(c)
|
||||||
result.enums[e.name] = e
|
result.enums[e.name] = e
|
||||||
elif (
|
elif (
|
||||||
c.kind == CursorKind.CLASS_DECL
|
c.kind == CursorKind.CLASS_DECL
|
||||||
or c.kind == CursorKind.STRUCT_DECL
|
or c.kind == CursorKind.STRUCT_DECL
|
||||||
):
|
):
|
||||||
class_ = CXXFileParser._process_class(c)
|
class_ = CXXParser._process_class(c)
|
||||||
cname = class_.name
|
cname = class_.name
|
||||||
result.classes[cname] = class_
|
result.classes[cname] = class_
|
||||||
elif c.kind == CursorKind.VAR_DECL:
|
elif c.kind == CursorKind.VAR_DECL:
|
||||||
name, value = CXXFileParser._process_variable(c)
|
name, value = CXXParser._process_variable(c)
|
||||||
if value:
|
if value:
|
||||||
result.variables[name] = value
|
result.variables[name] = value
|
||||||
elif c.kind == CursorKind.TYPEDEF_DECL:
|
elif c.kind == CursorKind.TYPEDEF_DECL:
|
||||||
name, target = CXXFileParser._process_typedef(c)
|
name, target = CXXParser._process_typedef(c)
|
||||||
result.typedefs[name] = target
|
result.typedefs[name] = target
|
||||||
elif c.kind == CursorKind.MACRO_DEFINITION:
|
elif c.kind == CursorKind.MACRO_DEFINITION:
|
||||||
name, definition = CXXFileParser._process_macro_definition(c)
|
name, definition = CXXParser._process_macro_definition(c)
|
||||||
result.macros[name] = definition
|
result.macros[name] = definition
|
||||||
elif (
|
elif (
|
||||||
False
|
False
|
||||||
@ -226,7 +236,7 @@ class CXXFileParser:
|
|||||||
# ignore any body
|
# ignore any body
|
||||||
pass
|
pass
|
||||||
elif (
|
elif (
|
||||||
CXXFileParser._is_literal_cursor(c)
|
CXXParser._is_literal_cursor(c)
|
||||||
or c.kind == CursorKind.MACRO_INSTANTIATION
|
or c.kind == CursorKind.MACRO_INSTANTIATION
|
||||||
or c.kind == CursorKind.INCLUSION_DIRECTIVE
|
or c.kind == CursorKind.INCLUSION_DIRECTIVE
|
||||||
):
|
):
|
||||||
@ -297,12 +307,12 @@ class CXXFileParser:
|
|||||||
class_ = Class(name=c.displayname)
|
class_ = Class(name=c.displayname)
|
||||||
for ac in c.get_children():
|
for ac in c.get_children():
|
||||||
if ac.kind == CursorKind.CONSTRUCTOR:
|
if ac.kind == CursorKind.CONSTRUCTOR:
|
||||||
func = CXXFileParser._process_method(ac, class_)
|
func = CXXParser._process_method(ac, class_)
|
||||||
if func.is_virtual:
|
if func.is_virtual:
|
||||||
class_.is_polymorphic = True
|
class_.is_polymorphic = True
|
||||||
class_.constructors = func
|
class_.constructors = func
|
||||||
elif ac.kind == CursorKind.DESTRUCTOR:
|
elif ac.kind == CursorKind.DESTRUCTOR:
|
||||||
func = CXXFileParser._process_method(ac, class_)
|
func = CXXParser._process_method(ac, class_)
|
||||||
if func.is_virtual:
|
if func.is_virtual:
|
||||||
class_.is_polymorphic = True
|
class_.is_polymorphic = True
|
||||||
class_.destructor = func
|
class_.destructor = func
|
||||||
@ -310,7 +320,7 @@ class CXXFileParser:
|
|||||||
v = Variable(ac.spelling, ac.type.spelling)
|
v = Variable(ac.spelling, ac.type.spelling)
|
||||||
class_.variables[v.name] = v
|
class_.variables[v.name] = v
|
||||||
elif ac.kind == CursorKind.CXX_METHOD:
|
elif ac.kind == CursorKind.CXX_METHOD:
|
||||||
func = CXXFileParser._process_method(ac, class_)
|
func = CXXParser._process_method(ac, class_)
|
||||||
if func.is_virtual:
|
if func.is_virtual:
|
||||||
class_.is_polymorphic = True
|
class_.is_polymorphic = True
|
||||||
class_.functions[func.name].append(func)
|
class_.functions[func.name].append(func)
|
||||||
@ -339,8 +349,8 @@ class CXXFileParser:
|
|||||||
length = len(children)
|
length = len(children)
|
||||||
if length == 1:
|
if length == 1:
|
||||||
child = children[0]
|
child = children[0]
|
||||||
if CXXFileParser._is_literal_cursor(child):
|
if CXXParser._is_literal_cursor(child):
|
||||||
value = CXXFileParser._process_literal(child)
|
value = CXXParser._process_literal(child)
|
||||||
return c.spelling, value
|
return c.spelling, value
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"unable to process variable : %s %s", c.spelling, c.extent
|
"unable to process variable : %s %s", c.spelling, c.extent
|
||||||
@ -368,7 +378,7 @@ class CXXFileParser:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_source(token: Token, encoding="utf-8"):
|
def _get_source(token: Token, encoding="utf-8"):
|
||||||
return CXXFileParser._get_source_from_file(
|
return CXXParser._get_source_from_file(
|
||||||
token.location.file.name,
|
token.location.file.name,
|
||||||
token.extent.start.offset,
|
token.extent.start.offset,
|
||||||
token.extent.end.offset,
|
token.extent.end.offset,
|
||||||
@ -390,7 +400,7 @@ class CXXFileParser:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_literal_cursor(c: Cursor):
|
def _is_literal_cursor(c: Cursor):
|
||||||
return c.kind in CXXFileParser.LITERAL_KINDS
|
return c.kind in CXXParser.LITERAL_KINDS
|
||||||
# return str(c)[-9:-1] == 'LITERAL'
|
# return str(c)[-9:-1] == 'LITERAL'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -403,7 +413,7 @@ class CXXFileParser:
|
|||||||
elif c.kind == CursorKind.STRING_LITERAL:
|
elif c.kind == CursorKind.STRING_LITERAL:
|
||||||
return str(spelling)
|
return str(spelling)
|
||||||
elif c.kind == CursorKind.CHARACTER_LITERAL:
|
elif c.kind == CursorKind.CHARACTER_LITERAL:
|
||||||
return CXXFileParser.character_literal_to_int(spelling)
|
return CXXParser.character_literal_to_int(spelling)
|
||||||
elif c.kind == CursorKind.FLOATING_LITERAL:
|
elif c.kind == CursorKind.FLOATING_LITERAL:
|
||||||
return float(spelling)
|
return float(spelling)
|
||||||
logger.warning(
|
logger.warning(
|
||||||
@ -421,14 +431,26 @@ class CXXFileParser:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CXXParser(CXXFileParser):
|
class CXXFileParser(CXXParser):
|
||||||
def __init__(self, files: List[str]):
|
def __init__(
|
||||||
|
self,
|
||||||
|
files: Sequence[str],
|
||||||
|
include_paths: Sequence[str] = None,
|
||||||
|
args: List[str] = None,
|
||||||
|
):
|
||||||
|
if args is None:
|
||||||
|
args = []
|
||||||
|
if include_paths:
|
||||||
|
for include_path in include_paths:
|
||||||
|
args.append("-I" + include_path)
|
||||||
dummy_code = ""
|
dummy_code = ""
|
||||||
for file in files:
|
for file in files:
|
||||||
dummy_code += f'#include "{file}"\n'
|
dummy_code += f'#include "{file}"\n'
|
||||||
|
|
||||||
dummy_name = "dummy.cpp"
|
dummy_name = "dummy.cpp"
|
||||||
super().__init__(dummy_name, unsaved_files=[[dummy_name, dummy_code]])
|
super().__init__(
|
||||||
|
dummy_name, unsaved_files=[[dummy_name, dummy_code]], args=args
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
Config.set_library_path("")
|
Config.set_library_path("")
|
||||||
|
Loading…
Reference in New Issue
Block a user