Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapper Update #749

Merged
merged 2 commits into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions wrap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,19 @@ configure_package_config_file(
INSTALL_INCLUDE_DIR
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})

message(STATUS "Package config : ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}")
# Set all the install paths
set(GTWRAP_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR})
set(GTWRAP_LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR})
set(GTWRAP_BIN_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN_DIR})
set(GTWRAP_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR})

# ##############################################################################
# Install the package

message(STATUS "CMake : ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}")
# Install CMake scripts to the standard CMake script directory.
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/gtwrapConfig.cmake
cmake/MatlabWrap.cmake cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake
DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/gtwrapConfig.cmake
cmake/MatlabWrap.cmake cmake/PybindWrap.cmake
cmake/GtwrapUtils.cmake DESTINATION "${GTWRAP_CMAKE_INSTALL_DIR}")

# Configure the include directory for matlab.h This allows the #include to be
# either gtwrap/matlab.h, wrap/matlab.h or something custom.
Expand All @@ -60,24 +62,26 @@ configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in

# Install the gtwrap python package as a directory so it can be found by CMake
# for wrapping.
message(STATUS "Lib path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
install(DIRECTORY gtwrap
DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
install(DIRECTORY gtwrap DESTINATION "${GTWRAP_LIB_INSTALL_DIR}")

# Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/gtwrap/pybind11` This
# will allow the gtwrapConfig.cmake file to load it later.
install(DIRECTORY pybind11
DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
install(DIRECTORY pybind11 DESTINATION "${GTWRAP_LIB_INSTALL_DIR}")

# Install wrapping scripts as binaries to `CMAKE_INSTALL_PREFIX/bin` so they can
# be invoked for wrapping. We use DESTINATION (instead of TYPE) so we can
# support older CMake versions.
message(STATUS "Bin path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN_DIR}")
install(PROGRAMS scripts/pybind_wrap.py scripts/matlab_wrap.py
DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN_DIR}")
DESTINATION "${GTWRAP_BIN_INSTALL_DIR}")

# Install the matlab.h file to `CMAKE_INSTALL_PREFIX/lib/gtwrap/matlab.h`.
message(
STATUS "Header path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}")
install(FILES matlab.h
DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}")
install(FILES matlab.h DESTINATION "${GTWRAP_INCLUDE_INSTALL_DIR}")

string(ASCII 27 Esc)
set(gtwrap "${Esc}[1;36mgtwrap${Esc}[m")
message(STATUS "${gtwrap} Package config : ${GTWRAP_CMAKE_INSTALL_DIR}")
message(STATUS "${gtwrap} version : ${PROJECT_VERSION}")
message(STATUS "${gtwrap} CMake path : ${GTWRAP_CMAKE_INSTALL_DIR}")
message(STATUS "${gtwrap} library path : ${GTWRAP_LIB_INSTALL_DIR}")
message(STATUS "${gtwrap} binary path : ${GTWRAP_BIN_INSTALL_DIR}")
message(STATUS "${gtwrap} header path : ${GTWRAP_INCLUDE_INSTALL_DIR}")
2 changes: 2 additions & 0 deletions wrap/gtwrap/interface_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
"""

import sys

import pyparsing

from .classes import *
from .declaration import *
from .enum import *
from .function import *
from .module import *
from .namespace import *
Expand Down
42 changes: 20 additions & 22 deletions wrap/gtwrap/interface_parser/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@

from typing import Iterable, List, Union

from pyparsing import Optional, ZeroOrMore, Literal
from pyparsing import Literal, Optional, ZeroOrMore

from .enum import Enum
from .function import ArgumentList, ReturnType
from .template import Template
from .tokens import (CLASS, COLON, CONST, IDENT, LBRACE, LPAREN, RBRACE,
RPAREN, SEMI_COLON, STATIC, VIRTUAL, OPERATOR)
from .type import TemplatedType, Type, Typename
from .tokens import (CLASS, COLON, CONST, IDENT, LBRACE, LPAREN, OPERATOR,
RBRACE, RPAREN, SEMI_COLON, STATIC, VIRTUAL)
from .type import TemplatedType, Typename
from .utils import collect_namespaces
from .variable import Variable


Expand Down Expand Up @@ -200,21 +202,6 @@ def __repr__(self) -> str:
)


def collect_namespaces(obj):
"""
Get the chain of namespaces from the lowest to highest for the given object.

Args:
obj: Object of type Namespace, Class or InstantiatedClass.
"""
namespaces = []
ancestor = obj.parent
while ancestor and ancestor.name:
namespaces = [ancestor.name] + namespaces
ancestor = ancestor.parent
return [''] + namespaces


class Class:
"""
Rule to parse a class defined in the interface file.
Expand All @@ -230,9 +217,13 @@ class Members:
"""
Rule for all the members within a class.
"""
rule = ZeroOrMore(Constructor.rule ^ StaticMethod.rule ^ Method.rule
^ Variable.rule ^ Operator.rule).setParseAction(
lambda t: Class.Members(t.asList()))
rule = ZeroOrMore(Constructor.rule #
^ StaticMethod.rule #
^ Method.rule #
^ Variable.rule #
^ Operator.rule #
^ Enum.rule #
).setParseAction(lambda t: Class.Members(t.asList()))

def __init__(self,
members: List[Union[Constructor, Method, StaticMethod,
Expand All @@ -242,6 +233,7 @@ def __init__(self,
self.static_methods = []
self.properties = []
self.operators = []
self.enums = []
for m in members:
if isinstance(m, Constructor):
self.ctors.append(m)
Expand All @@ -253,6 +245,8 @@ def __init__(self,
self.properties.append(m)
elif isinstance(m, Operator):
self.operators.append(m)
elif isinstance(m, Enum):
self.enums.append(m)

_parent = COLON + (TemplatedType.rule ^ Typename.rule)("parent_class")
rule = (
Expand All @@ -275,6 +269,7 @@ def __init__(self,
t.members.static_methods,
t.members.properties,
t.members.operators,
t.members.enums
))

def __init__(
Expand All @@ -288,6 +283,7 @@ def __init__(
static_methods: List[StaticMethod],
properties: List[Variable],
operators: List[Operator],
enums: List[Enum],
parent: str = '',
):
self.template = template
Expand All @@ -312,6 +308,8 @@ def __init__(
self.static_methods = static_methods
self.properties = properties
self.operators = operators
self.enums = enums

self.parent = parent

# Make sure ctors' names and class name are the same.
Expand Down
70 changes: 70 additions & 0 deletions wrap/gtwrap/interface_parser/enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
GTSAM Copyright 2010-2020, Georgia Tech Research Corporation,
Atlanta, Georgia 30332-0415
All Rights Reserved

See LICENSE for the license information

Parser class and rules for parsing C++ enums.

Author: Varun Agrawal
"""

from pyparsing import delimitedList

from .tokens import ENUM, IDENT, LBRACE, RBRACE, SEMI_COLON
from .type import Typename
from .utils import collect_namespaces


class Enumerator:
"""
Rule to parse an enumerator inside an enum.
"""
rule = (
IDENT("enumerator")).setParseAction(lambda t: Enumerator(t.enumerator))

def __init__(self, name):
self.name = name

def __repr__(self):
return "Enumerator: ({0})".format(self.name)


class Enum:
"""
Rule to parse enums defined in the interface file.

E.g.
```
enum Kind {
Dog,
Cat
};
```
"""

rule = (ENUM + IDENT("name") + LBRACE +
delimitedList(Enumerator.rule)("enumerators") + RBRACE +
SEMI_COLON).setParseAction(lambda t: Enum(t.name, t.enumerators))

def __init__(self, name, enumerators, parent=''):
self.name = name
self.enumerators = enumerators
self.parent = parent

def namespaces(self) -> list:
"""Get the namespaces which this class is nested under as a list."""
return collect_namespaces(self)

def cpp_typename(self):
"""
Return a Typename with the namespaces and cpp name of this
class.
"""
namespaces_name = self.namespaces()
namespaces_name.append(self.name)
return Typename(namespaces_name)

def __repr__(self):
return "Enum: {0}".format(self.name)
3 changes: 3 additions & 0 deletions wrap/gtwrap/interface_parser/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ def __init__(self,
# This means a tuple has been passed so we convert accordingly
elif len(default) > 1:
default = tuple(default.asList())
else:
# set to None explicitly so we can support empty strings
default = None
self.default = default

self.parent: Union[ArgumentList, None] = None
Expand Down
10 changes: 4 additions & 6 deletions wrap/gtwrap/interface_parser/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@

# pylint: disable=unnecessary-lambda, unused-import, expression-not-assigned, no-else-return, protected-access, too-few-public-methods, too-many-arguments

import sys

import pyparsing # type: ignore
from pyparsing import (ParserElement, ParseResults, ZeroOrMore,
cppStyleComment, stringEnd)
from pyparsing import ParseResults, ZeroOrMore, cppStyleComment, stringEnd

from .classes import Class
from .declaration import ForwardDeclaration, Include
from .enum import Enum
from .function import GlobalFunction
from .namespace import Namespace
from .template import TypedefTemplateInstantiation
Expand All @@ -44,7 +41,8 @@ class Module:
^ Class.rule #
^ TypedefTemplateInstantiation.rule #
^ GlobalFunction.rule #
^ Variable.rule #
^ Enum.rule #
^ Variable.rule #
^ Namespace.rule #
).setParseAction(lambda t: Namespace('', t.asList())) +
stringEnd)
Expand Down
4 changes: 3 additions & 1 deletion wrap/gtwrap/interface_parser/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from .classes import Class, collect_namespaces
from .declaration import ForwardDeclaration, Include
from .enum import Enum
from .function import GlobalFunction
from .template import TypedefTemplateInstantiation
from .tokens import IDENT, LBRACE, NAMESPACE, RBRACE
Expand Down Expand Up @@ -68,7 +69,8 @@ class Namespace:
^ Class.rule #
^ TypedefTemplateInstantiation.rule #
^ GlobalFunction.rule #
^ Variable.rule #
^ Enum.rule #
^ Variable.rule #
^ rule #
)("content") # BR
+ RBRACE #
Expand Down
1 change: 1 addition & 0 deletions wrap/gtwrap/interface_parser/tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"#include",
],
)
ENUM = Keyword("enum") ^ Keyword("enum class") ^ Keyword("enum struct")
NAMESPACE = Keyword("namespace")
BASIS_TYPES = map(
Keyword,
Expand Down
26 changes: 26 additions & 0 deletions wrap/gtwrap/interface_parser/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
GTSAM Copyright 2010-2020, Georgia Tech Research Corporation,
Atlanta, Georgia 30332-0415
All Rights Reserved

See LICENSE for the license information

Various common utilities.

Author: Varun Agrawal
"""


def collect_namespaces(obj):
"""
Get the chain of namespaces from the lowest to highest for the given object.

Args:
obj: Object of type Namespace, Class, InstantiatedClass, or Enum.
"""
namespaces = []
ancestor = obj.parent
while ancestor and ancestor.name:
namespaces = [ancestor.name] + namespaces
ancestor = ancestor.parent
return [''] + namespaces
2 changes: 2 additions & 0 deletions wrap/gtwrap/interface_parser/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ def __init__(self,
self.name = name
if default:
self.default = default[0]
else:
self.default = None

self.parent = parent

Expand Down
Loading