README.rst 9.84 KB
Newer Older
Joe Snyder's avatar
Joe Snyder committed
1
2
3
4
5
6
Wrapper Generator
==================

This repository contains the first set of Python code which could be used to
automatically generate PyBin11 code from C++ files with proper annotation.

Joe Snyder's avatar
Joe Snyder committed
7
8
9
10
**CAUTION**: The content, structure, and API of this repository are still under
development.  No guarantees of backwards compatibility are given for the
functionality.

Joe Snyder's avatar
Joe Snyder committed
11
12
13
14
15
16
License
+++++++

This repository is distributed under the OSI-approved BSD 3-clause License.
See Copyright.txt_ for details.

17
18
19
Program execution
+++++++++++++++++

Joe Snyder's avatar
Joe Snyder committed
20
Prerequisites
Joe Snyder's avatar
Joe Snyder committed
21
22
---------------

Joe Snyder's avatar
Joe Snyder committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
All instructions below assume that a Python3 environment is available.

CMake
#####

The CMake-based portion of the tool requires CMake 3.12 or greater.
Download or build CMake: https://cmake.org/

CastXML
#######

A version of the CastXML tool is required for this program to run.  It, likely, can
be downloaded from your Linux package management system. For Ubuntu, the command looks
like this::
Joe Snyder's avatar
Joe Snyder committed
37

38
39
  sudo apt install castxml

Joe Snyder's avatar
Joe Snyder committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
If it is not available, a selection of binary distributions can be found on the
`data.kitware.com`_ website.

Python Libraries
################

The repository contains a requirements.txt file which can be provided to the
PIP program to install all required Python Libraries.  Execute::

    pip install -r requirements.txt

to install the other required programs.

Preparing C++ code
------------------

The setup for the C++ code to be wrapped is simple. Each C++ directory with content
to be wrapped should contain a file named ``wrapper_input.yml``.
This content should describe the classes, "free" functions
(functions that are not a part of a class), and non-typed enumerations.

This information follows a certain structure.  This structure has three reserved key
tags: ``classes``, ``functions``, and ``enums``.  Any tag not found within one of these
structures, is considered a namespace for the code to be found under::

  <namespace>:
    classes:
      <class_name>:
        <class_data>,
      <class_2_name>:
        <class_2_data>
    functions:
      <function_name>:
        <function_data>
    <namespace_2>:
      enums:

Each type of object within the reserved tags requires different pieces of information:

    +-----------------------------+---------------------------------+
    |           C++ Object        |      Required YAML pieces       |
    +=============================+=================================+
    |           Class             | file:  <str>                    |
    |                             |   Path to file with class       |
    |                             +---------------------------------+
    |                             | inst: []                        |
    |                             |   List of instantiation types   |
    |                             |   for class.                    |
    |                             |   Leave blank for non-templated |
    +-----------------------------+---------------------------------+
    |        Function             | file:  <str>                    |
    |                             |   Path to file with function    |
    |                             +---------------------------------+
    |                             | is_template: <bool>             |
    |                             |  "true" if function is template |
    |                             |  "false" otherwise              |
    |                             +---------------------------------+
    |                             | inst: []                        |
    |                             |   List of instantiation types   |
    |                             |   for function, if is_template  |
    |                             |   is true                       |
    +-----------------------------+---------------------------------+
    |        Enumeration          | file:  <str>                    |
    |                             |   Path to file with enumeration |
    +-----------------------------+---------------------------------+

For an example of a correctly written object, see `wrapper_input.yml`_ in the ``example`` directory.

Execution
---------
110

Joe Snyder's avatar
Joe Snyder committed
111
112
via CMake
##########
113

Joe Snyder's avatar
Joe Snyder committed
114
The recommended path for the usage of this tool is via CMake.
115

Joe Snyder's avatar
Joe Snyder committed
116
117
Setup
%%%%%
Joe Snyder's avatar
Joe Snyder committed
118

Joe Snyder's avatar
Joe Snyder committed
119
120
121
By utilizing the ``find_package`` utility, the created macros and functions can be
introduced into the environment.  This repository contains the
``AutoPyBind11Config.cmake`` file which is the targe of the following command::
Joe Snyder's avatar
Joe Snyder committed
122

Joe Snyder's avatar
Joe Snyder committed
123
  find_package(AutoPyBind11)
Joe Snyder's avatar
Joe Snyder committed
124

Joe Snyder's avatar
Joe Snyder committed
125
126
127
128
After this command is found, one additional command will be used to acquire PyBind11 via the
``FetchContent`` module::

    autopybind11_fetch_build_pybind11()
Joe Snyder's avatar
Joe Snyder committed
129

Joe Snyder's avatar
Joe Snyder committed
130
131
Add Library
%%%%%%%%%%%
Joe Snyder's avatar
Joe Snyder committed
132

Joe Snyder's avatar
Joe Snyder committed
133
134
135
136
137
To add a library for the written PyBind11 code, we use the ``autopybind11_add_module``
function.  This function does the work of setting custom commands to generate
the PyBind11 code and adds a library to CMake which contains the PyBind11 code., and then
This command should be written once for each ``wrapper_input.yml`` file in the repository.
The command has the following structure::
Joe Snyder's avatar
Joe Snyder committed
138

Joe Snyder's avatar
Joe Snyder committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
    autopybind11_add_module(<name> YAML_INPUT <path_to>/wrapper_input.yml
                        DESTINATION <path_to_output>
                        LINK_LIBRARIES <library_1> <library_2>
                        [CONFIG_INPUT <path_to>/config.yml])

Only the ``CONFIG_INPUT`` flag is optional.  The file given to that argument can be used
to customize the templates used to create the PyBind11 CPP code.  The default templates
can be found in `text_blocks.py`_
An example of the function invocation is here::

    autopybind11_add_module("example" YAML_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/wrapper_input.yml
                            DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
                            LINK_LIBRARIES wrapper_example)

via Python
##########
Joe Snyder's avatar
Joe Snyder committed
155
156
157
This script assumes that Python 3.* is used.
The Python script has help for the arguments::

Joe Snyder's avatar
Joe Snyder committed
158
    $ python3 autopybind11.py -h
Joe Snyder's avatar
Joe Snyder committed
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
    usage: autopybind11.py [-h] [-o OUTPUT_DIR] -y YAML_PATH --module_name
                           MODULE_NAME [-g CASTXML_PATH] [-cg CONFIG_DIR]
                           [--no-generation] [-rs RSP_PATH] [-pm]
                           [--common_cpp_body_fmt COMMON_CPP_BODY_FMT]
                           [--class_info_body_fmt CLASS_INFO_BODY_FMT]
                           [--init_fun_signature_fmt INIT_FUN_SIGNATURE_FMT]
                           [--init_fun_forward_fmt INIT_FUN_FORWARD_FMT]
                           [--cppbody_fmt CPPBODY_FMT]
                           [--module_cpp_fmt MODULE_CPP_FMT]
                           [--member_func_fmt MEMBER_FUNC_FMT]
                           [--constructor_fmt CONSTRUCTOR_FMT]
                           [--member_func_arg_fmt MEMBER_FUNC_ARG_FMT]
                           [--public_member_var_fmt PUBLIC_MEMBER_VAR_FMT]
                           [--private_member_var_fmt PRIVATE_MEMBER_VAR_FMT]
                           [--member_reference_fmt MEMBER_REFERENCE_FMT]
                           [--overload_template_fmt OVERLOAD_TEMPLATE_FMT]
                           [--wrap_header_fmt WRAP_HEADER_FMT]
                           [--operator_fmt OPERATOR_FMT]
                           [--call_operator_fmt CALL_OPERATOR_FMT]
                           [--enum_header_fmt ENUM_HEADER_FMT]
                           [--enum_val_fmt ENUM_VAL_FMT]

    Args that start with '--' (eg. -o) can also be set in a config file (specified
    via -cg). The config file uses YAML syntax and must represent a YAML 'mapping'
    (for details, see http://learn.getgrav.org/advanced/yaml). If an arg is
    specified in more than one place, then commandline values override config file
    values which override defaults.
Joe Snyder's avatar
Joe Snyder committed
186
187
188

    optional arguments:
      -h, --help            show this help message and exit
Joe Snyder's avatar
Joe Snyder committed
189
      -o OUTPUT_DIR, --output OUTPUT_DIR
tao558's avatar
tao558 committed
190
      -y YAML_PATH, --input_yaml YAML_PATH
Joe Snyder's avatar
Joe Snyder committed
191
192
193
                            Path to input YAML file of objects to process
      --module_name MODULE_NAME
                            Desired name of the output PyBind11 module
Joe Snyder's avatar
Joe Snyder committed
194
195
      -g CASTXML_PATH, --castxml-path CASTXML_PATH
                            Path to castxml
Tom Osika's avatar
Tom Osika committed
196
      -cg CONFIG_DIR, --config-path CONFIG_DIR
Tom Osika's avatar
Tom Osika committed
197
                            config file path
Joe Snyder's avatar
Joe Snyder committed
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
      --no-generation, -n   Only print name of files to be generated
      -rs RSP_PATH, --input_response RSP_PATH
      -pm, --private_members
      --common_cpp_body_fmt COMMON_CPP_BODY_FMT
      --class_info_body_fmt CLASS_INFO_BODY_FMT
      --init_fun_signature_fmt INIT_FUN_SIGNATURE_FMT
      --init_fun_forward_fmt INIT_FUN_FORWARD_FMT
      --cppbody_fmt CPPBODY_FMT
      --module_cpp_fmt MODULE_CPP_FMT
      --member_func_fmt MEMBER_FUNC_FMT
      --constructor_fmt CONSTRUCTOR_FMT
      --member_func_arg_fmt MEMBER_FUNC_ARG_FMT
      --public_member_var_fmt PUBLIC_MEMBER_VAR_FMT
      --private_member_var_fmt PRIVATE_MEMBER_VAR_FMT
      --member_reference_fmt MEMBER_REFERENCE_FMT
      --overload_template_fmt OVERLOAD_TEMPLATE_FMT
      --wrap_header_fmt WRAP_HEADER_FMT
      --operator_fmt OPERATOR_FMT
      --call_operator_fmt CALL_OPERATOR_FMT
      --enum_header_fmt ENUM_HEADER_FMT
      --enum_val_fmt ENUM_VAL_FMT

This is useful for some small testing. But since a Python call would be needed to wrap each input file, we recommend
using the CMake system above.
Joe Snyder's avatar
Joe Snyder committed
222

223
224
225
226
227
228
229
230
Style Checking / Linting
-------------------------

This repository uses the pycodestyle_ tool for linting and style checking which
can be installed via the ``pip`` program.
The program should be run at the top level so that the ``setup.cfg`` in the
repository is available. An example run is as follows::

Joe Snyder's avatar
Joe Snyder committed
231
  $ pycodestyle autopybind11.py
232

Joe Snyder's avatar
Joe Snyder committed
233
234
235
236
237
or setup a CMake build system and execute the ``WG_Linter`` test::

  $ ctest -R WG_Linter -VV

.. _pycodestyle: https://pypi.org/project/pycodestyle/
Joe Snyder's avatar
Joe Snyder committed
238
.. _Copyright.txt: Copyright.txt
Joe Snyder's avatar
Joe Snyder committed
239
240
241
.. _`data.kitware.com`: https://data.kitware.com/#folder/57b5de948d777f10f2696370
.. _`text_blocks.py`: text_blocks.py
.. _`wrapper_input.yml`: example/wrapper_input.yml