CMake fragments are provided for an Automated generation of an end-user bindings package from a CMake-based project build. The bindings generated by rootcling, are ‘raw’ in the sense that:
cppyy
supports customization of the bindings via ‘Pythonization’ but
there is no automated way to load them.
These issues are addressed by the CMake support. This is a blend of Python packaging and CMake where CMake provides:
注意
The JIT needs to resolve linker symbols in order to call them through generated wrappers. Thus, any classes, functions, and data that will be used in Python need to be exported. This is the default behavior on Mac and Linux, but not on Windows. On that platform, use
__declspec(dllexport)
to explicitly export the classes and function you expect to call. CMake has simple
support for exporting all
C++ symbols.
Modern Python packaging usage is based on the ‘wheel’. This is places the onus on the creation of binary artifacts in the package on the distributor. In this case, this includes the platform-dependent steps necessary to compile the .cpp file.
The generated package also takes advantage of the __init__.py load-time mechanism to enhance the bindings:
Both of these need/can use the output of the
cppyy-generator
(included in the package) as well as other runtime support included in
cppyy
.
The CMake usage is via two modules:
Details of the usage of these modules is within the modules themselves, but here is a summary of the usage.
FindLibClang.cmake
sets the following variables:
LibClang_FOUND - True if libclang is found. LibClang_LIBRARY - Clang library to link against. LibClang_VERSION - Version number as a string (e.g. "3.9"). LibClang_PYTHON_EXECUTABLE - Compatible python version.
FindCppyy.cmake
sets the following variables:
Cppyy_FOUND - set to true if Cppyy is found Cppyy_DIR - the directory where Cppyy is installed Cppyy_EXECUTABLE - the path to the Cppyy executable Cppyy_INCLUDE_DIRS - Where to find the Cppyy header files. Cppyy_VERSION - the version number of the Cppyy backend.
and also defines the following functions:
cppyy_add_bindings - Generate a set of bindings from a set of header files. cppyy_find_pips - Return a list of available pip programs.
Generate a set of bindings from a set of header files. Somewhat like CMake’s add_library(), the output is a compiler target. In addition ancillary files are also generated to allow a complete set of bindings to be compiled, packaged and installed:
cppyy_add_bindings( pkg pkg_version author author_email [URL url] [LICENSE license] [LANGUAGE_STANDARD std] [LINKDEFS linkdef...] [IMPORTS pcm...] [GENERATE_OPTIONS option...] [COMPILE_OPTIONS option...] [INCLUDE_DIRS dir...] [LINK_LIBRARIES library...] [H_DIRS H_DIRSectory] H_FILES h_file...)
The bindings are based on https://cppyy.readthedocs.io/en/latest/ , and can be used as per the documentation provided via the cppyy.gbl namespace. First add the directory of the <pkg>.rootmap file to the LD_LIBRARY_PATH environment variable, then “import cppyy; from cppyy.gbl import <some-C++-entity>”.
Alternatively, use “import <pkg>”. This convenience wrapper supports “discovery” of the available C++ entities using, for example Python 3’s command line completion support.
The bindings are complete with a setup.py, supporting Wheel-based packaging, and a test.py supporting pytest/nosetest sanity test of the bindings.
The bindings are generated/built/packaged using 3 environments:
| Arguments and options | 描述 |
|---|---|
| pkg | The name of the package to generate. This can be either of the form “simplename” (e.g. “Akonadi”), or of the form “namespace.simplename” (e.g. “KF5.Akonadi”). |
| pkg_version | The version of the package. |
| 作者 | The name of the library author. |
| author_email | The email address of the library author. |
| URL url | The home page for the library. Default is “ https://pypi.python.org/pypi /<pkg>”. |
| LICENSE license | The license, default is “LGPL 2.0”. |
| LANGUAGE_STANDARD std | The version of C++ in use, “14” by default. |
| IMPORTS pcm | Files which contain previously-generated bindings which pkg depends on. |
| GENERATE_OPTIONS optio | Options which are to be passed into the rootcling command. For example, bindings which depend on Qt may need “-D__PIC__;-Wno-macro-redefined”. |
| LINKDEFS def |
Files or lines which contain extra #pragma content for the linkdef.h file used by rootcling. See
https://root.cern.ch/root/html/guides/users-guide/AddingaClass.html#the-linkdef.h-file
.
In lines, literal semi-colons must be escaped: “;”. |
| EXTRA_CODES code |
Files which contain extra code needed by the bindings. Customization is by routines named “c13n_<something>”; each such routine is passed the module for <pkg>:
:: code-block python
print(pkg_module.__dict__) The files and individual routines within files are processed in alphabetical order. |
| EXTRA_HEADERS hdr | Files which contain extra headers needed by the bindings. |
| EXTRA_PYTHONS py | Files which contain extra Python code needed by the bindings. |
| COMPILE_OPTIONS option | Options which are to be passed into the compile/link 命令。 |
| INCLUDE_DIRS dir | Include directories. |
| LINK_LIBRARIES library | Libraries to link against. |
| H_DIRS directory | Base directories for H_FILES. |
| H_FILES h_file | Header files for which to generate bindings in pkg. Absolute filenames, or filenames relative to H_DIRS. All definitions found directly in these files will contribute to the bindings. (NOTE: This means that if “forwarding headers” are present, the real “legacy” headers must be specified as H_FILES). All header files which contribute to a given C++ namespace should be grouped into a single pkg to ensure a 1-to-1 mapping with the implementing Python class. |
Returns via PARENT_SCOPE variables:
target The CMake target used to build. setup_py The setup.py script used to build or install pkg.
范例:
find_package(Qt5Core NO_MODULE)
find_package(KF5KDcraw NO_MODULE)
get_target_property(_H_DIRS KF5::KDcraw INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(_LINK_LIBRARIES KF5::KDcraw INTERFACE_LINK_LIBRARIES)
set(_LINK_LIBRARIES KF5::KDcraw ${_LINK_LIBRARIES})
include(${KF5KDcraw_DIR}/KF5KDcrawConfigVersion.cmake)
cppyy_add_bindings(
"KDCRAW" "${PACKAGE_VERSION}" "Shaheed" "srhaque@theiet.org"
LANGUAGE_STANDARD "14"
LINKDEFS "../linkdef_overrides.h"
GENERATE_OPTIONS "-D__PIC__;-Wno-macro-redefined"
INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS}
LINK_LIBRARIES ${_LINK_LIBRARIES}
H_DIRS ${_H_DIRS}
H_FILES "dcrawinfocontainer.h;kdcraw.h;rawdecodingsettings.h;rawfiles.h")
Return a list of available pip programs.