Browse Source

python: expose corrade and magnum compilation defines.

pull/8/head
Vladimír Vondruš 7 years ago
parent
commit
c8e99ca086
  1. 46
      doc/python/conf.py
  2. 50
      doc/python/corrade.rst
  3. 15
      doc/python/magnum.rst
  4. 33
      doc/python/pages/api-conventions.rst
  5. 1
      src/python/CMakeLists.txt
  6. 31
      src/python/corrade/CMakeLists.txt
  7. 25
      src/python/corrade/__init__.py
  8. 85
      src/python/corrade/corrade.cpp
  9. 4
      src/python/magnum/__init__.py
  10. 47
      src/python/magnum/magnum.cpp
  11. 2
      src/python/setup.py.cmake

46
doc/python/conf.py

@ -22,10 +22,51 @@ import magnum.trade
# So the doc see everything # So the doc see everything
# TODO: use just +=, m.css should reorder this on its own # TODO: use just +=, m.css should reorder this on its own
corrade.__all__ = ['containers'] corrade.__all__ = ['containers', 'BUILD_STATIC', 'BUILD_MULTITHREADED', 'TARGET_UNIX', 'TARGET_APPLE', 'TARGET_IOS', 'TARGET_IOS_SIMULATOR', 'TARGET_WINDOWS', 'TARGET_WINDOWS_RT', 'TARGET_EMSCRIPTEN', 'TARGET_ANDROID']
magnum.__all__ = ['math', 'gl', 'meshtools', 'platform', 'primitives', 'shaders', 'scenegraph', 'trade'] + magnum.__all__ magnum.__all__ = ['math', 'gl', 'meshtools', 'platform', 'primitives', 'shaders', 'scenegraph', 'trade', 'BUILD_STATIC', 'TARGET_GL', 'TARGET_GLES', 'TARGET_GLES2', 'TARGET_WEBGL', 'TARGET_VK'] + magnum.__all__
# hide values of the preprocessor defines to avoid confusion by assigning a
# class without __repr__ to them
# TODO: more systematic solution directly in m.css
class DoNotPrintValue: pass
corrade.BUILD_STATIC = DoNotPrintValue()
corrade.BUILD_MULTITHREADED = DoNotPrintValue()
corrade.TARGET_UNIX = DoNotPrintValue()
corrade.TARGET_APPLE = DoNotPrintValue()
corrade.TARGET_IOS = DoNotPrintValue()
corrade.TARGET_IOS_SIMULATOR = DoNotPrintValue()
corrade.TARGET_WINDOWS = DoNotPrintValue()
corrade.TARGET_WINDOWS_RT = DoNotPrintValue()
corrade.TARGET_EMSCRIPTEN = DoNotPrintValue()
corrade.TARGET_ANDROID = DoNotPrintValue()
magnum.BUILD_STATIC = DoNotPrintValue()
magnum.TARGET_GL = DoNotPrintValue()
magnum.TARGET_GLES = DoNotPrintValue()
magnum.TARGET_GLES2 = DoNotPrintValue()
magnum.TARGET_WEBGL = DoNotPrintValue()
magnum.TARGET_VK = DoNotPrintValue()
# TODO ugh... can this be expressed directly in pybind? # TODO ugh... can this be expressed directly in pybind?
corrade.__annotations__ = {
'BUILD_STATIC': bool,
'BUILD_MULTITHREADED': bool,
'TARGET_UNIX': bool,
'TARGET_APPLE': bool,
'TARGET_IOS': bool,
'TARGET_IOS_SIMULATOR': bool,
'TARGET_WINDOWS': bool,
'TARGET_WINDOWS_RT': bool,
'TARGET_EMSCRIPTEN': bool,
'TARGET_ANDROID': bool
}
magnum.__annotations__ = {
'BUILD_STATIC': bool,
'TARGET_GL': bool,
'TARGET_GLES': bool,
'TARGET_GLES2': bool,
'TARGET_WEBGL': bool,
'TARGET_VK': bool
}
magnum.gl.__annotations__ = {} magnum.gl.__annotations__ = {}
magnum.gl.__annotations__['default_framebuffer'] = magnum.gl.DefaultFramebuffer magnum.gl.__annotations__['default_framebuffer'] = magnum.gl.DefaultFramebuffer
magnum.shaders.VertexColor2D.__annotations__ = {} magnum.shaders.VertexColor2D.__annotations__ = {}
@ -54,6 +95,7 @@ INPUT_PAGES = [
'../../../magnum-examples/doc/python/examples.rst' '../../../magnum-examples/doc/python/examples.rst'
] ]
INPUT_DOCS = [ INPUT_DOCS = [
'corrade.rst',
'corrade.containers.rst', 'corrade.containers.rst',
'magnum.rst', 'magnum.rst',

50
doc/python/corrade.rst

@ -0,0 +1,50 @@
..
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
..
.. roles used for all other docs
.. role:: cpp(code)
:language: c++
.. role:: py(code)
:language: py
.. role:: sh(code)
:language: sh
.. doctest setup
>>> from corrade import *
.. default-role:: ref
.. py:module:: corrade
:data BUILD_STATIC: Static library build
:data BUILD_MULTITHREADED: Multi-threaded build
:data TARGET_UNIX: Unix target
:data TARGET_APPLE: Apple target
:data TARGET_IOS: iOS target
:data TARGET_IOS_SIMULATOR: iOS simulator target
:data TARGET_WINDOWS: Windows target
:data TARGET_WINDOWS_RT: Windows RT target
:data TARGET_EMSCRIPTEN: Emscripten target
:data TARGET_ANDROID: Android target

15
doc/python/magnum.rst

@ -25,14 +25,13 @@
.. roles used for all other docs .. roles used for all other docs
.. role:: cpp(code)
:language: c++
.. role:: py(code)
:language: py
.. role:: sh(code)
:language: sh
.. doctest setup .. doctest setup
>>> from magnum import * >>> from magnum import *
.. default-role:: ref .. py:module:: magnum
:data BUILD_STATIC: Static library build
:data TARGET_GL: OpenGL interoperability
:data TARGET_GLES: OpenGL ES target
:data TARGET_GLES2: OpenGL ES 2.0 target
:data TARGET_WEBGL: WebGL target
:data TARGET_VK: Vulkan interoperability

33
doc/python/pages/api-conventions.rst

@ -44,8 +44,23 @@ Python API conventions
- constants and enums ``UPPERCASE``, again underscores omitted if it doesn't - constants and enums ``UPPERCASE``, again underscores omitted if it doesn't
hurt readability hurt readability
`Namespaces`_ `Preprocessor definitions`_
------------- ---------------------------
Exposed to Python as plain boolean constants, and only those that actually are
useful in a Python setting.
.. class:: m-table
=================================== ============================
C++ Python
=================================== ============================
:dox:`CORRADE_BUILD_MULTITHREADED` `corrade.BUILD_MULTITHREADED`
:dox:`MAGNUM_TARGET_GLES` `magnum.TARGET_GLES`
=================================== ============================
`Namespaces / modules`_
-----------------------
.. class:: m-table .. class:: m-table
@ -178,6 +193,20 @@ subnamespaces *do* have generic names. The :dox:`GL::version()` /
generic name isn't a problem, but you wouldn't find anything of similar generic name isn't a problem, but you wouldn't find anything of similar
genericity in the root namespace / module. genericity in the root namespace / module.
An exception to this rule is exposed preprocessor definitions --- these are
*not* pulled in when doing :py:`from magnum import *` as this would likely
cause conflicts (in particular, `BUILD_STATIC` is defined by Corrade as well).
Instead, you have to access them like this:
.. code:: py
import magnum
if magnum.TARGET_GLES2:
format = gl.TextureFormat.RGBA8
else:
format = gl.TextureFormat.R8
`Handling of alternate implementations`_ `Handling of alternate implementations`_
---------------------------------------- ----------------------------------------

1
src/python/CMakeLists.txt

@ -46,7 +46,6 @@ add_subdirectory(magnum)
# CMake 3.12, so I need to do two passes, first replacing variables using # CMake 3.12, so I need to do two passes, first replacing variables using
# configure_file() and then replacing generator expressions with file(GENERATE) # configure_file() and then replacing generator expressions with file(GENERATE)
foreach(target foreach(target
corrade
corrade_containers corrade_containers
magnum_gl magnum_gl
magnum_meshtools magnum_meshtools

31
src/python/corrade/CMakeLists.txt

@ -23,6 +23,12 @@
# DEALINGS IN THE SOFTWARE. # DEALINGS IN THE SOFTWARE.
# #
set(corrade_SRCS
corrade.cpp)
# Extra libraries to link to. Populated only in case of CORRADE_BUILD_STATIC.
set(corrade_LIBS )
set(corrade_containers_SRCS set(corrade_containers_SRCS
containers.cpp) containers.cpp)
@ -45,20 +51,19 @@ if(NOT CORRADE_BUILD_STATIC)
# point of static builds). It also nicely avoids problems with multiply-defined # point of static builds). It also nicely avoids problems with multiply-defined
# global data. # global data.
else() else()
set(corrade_SRCS list(APPEND corrade_SRCS ${corrade_containers_SRCS})
corrade.cpp list(APPEND corrade_LIBS Corrade::Containers)
${corrade_containers_SRCS})
pybind11_add_module(corrade SYSTEM ${corrade_SRCS})
target_include_directories(corrade PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
target_link_libraries(corrade PRIVATE Corrade::Utility ${corrade_LIBS})
set_target_properties(corrade PROPERTIES
FOLDER "python"
OUTPUT_NAME "_corrade"
LIBRARY_OUTPUT_DIRECTORY ${output_dir})
endif() endif()
pybind11_add_module(corrade SYSTEM ${corrade_SRCS})
target_include_directories(corrade PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/python)
target_link_libraries(corrade PRIVATE Corrade::Utility ${corrade_LIBS})
set_target_properties(corrade PROPERTIES
FOLDER "python"
OUTPUT_NAME "_corrade"
LIBRARY_OUTPUT_DIRECTORY ${output_dir})
file(GENERATE OUTPUT ${output_dir}/corrade/__init__.py file(GENERATE OUTPUT ${output_dir}/corrade/__init__.py
INPUT ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py) INPUT ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py)

25
src/python/corrade/__init__.py

@ -25,22 +25,21 @@
"""Root Corrade module""" """Root Corrade module"""
from _corrade import *
import sys import sys
# In case Corrade is built statically, the whole core project is put into # In case Corrade is built statically, the whole core project is put into
# _corrade. If corrade is built dynamically, there's no core library at the # _corrade. The following feels extremely hackish, but without that it wouldn't
# moment. # be possible to do `import corrade.containers`, which is weird
try: # (`from corrade import containers` works, tho, for whatever reason)
from _corrade import * for i in ['containers']:
if i in globals(): sys.modules['corrade.' + i] = globals()[i]
# The following feels extremely hackish, but without that it wouldn't be
# possible to do `import corrade.containers`, which is weird
# (`from corrade import containers` works, tho, for whatever reason)
for i in ['containers']:
if i in globals(): sys.modules['corrade.' + i] = globals()[i]
except ImportError:
pass
# Prevent all submodules being pulled in when saying `from corrade import *` -- # Prevent all submodules being pulled in when saying `from corrade import *` --
# this is consistent with behavior in magnum # this is consistent with behavior in magnum
__all__ = [] __all__ = [
# TARGET_*, BUILD_* are omitted as `from corrade import *` would pull them
# to globals and this would likely cause conflicts (magnum also defines
# BUILD_*)
]

85
src/python/corrade/corrade.cpp

@ -28,16 +28,93 @@
#include "corrade/bootstrap.h" #include "corrade/bootstrap.h"
#ifndef CORRADE_BUILD_STATIC
#error this file should be compiled only in the static build
#endif
namespace py = pybind11; namespace py = pybind11;
/* TODO: remove declaration when https://github.com/pybind/pybind11/pull/1863 /* TODO: remove declaration when https://github.com/pybind/pybind11/pull/1863
is released */ is released */
extern "C" PYBIND11_EXPORT PyObject* PyInit__corrade(); extern "C" PYBIND11_EXPORT PyObject* PyInit__corrade();
PYBIND11_MODULE(_corrade, m) { PYBIND11_MODULE(_corrade, m) {
m.doc() = "Root Corrade module";
m.attr("BUILD_STATIC") =
#ifdef CORRADE_BUILD_STATIC
true
#else
false
#endif
;
m.attr("BUILD_MULTITHREADED") =
#ifdef CORRADE_BUILD_MULTITHREADED
true
#else
false
#endif
;
m.attr("TARGET_APPLE") =
#ifdef CORRADE_TARGET_APPLE
true
#else
false
#endif
;
m.attr("TARGET_IOS") =
#ifdef CORRADE_TARGET_IOS
true
#else
false
#endif
;
m.attr("TARGET_IOS_SIMULATOR") =
#ifdef CORRADE_TARGET_IOS_SIMULATOR
true
#else
false
#endif
;
m.attr("TARGET_UNIX") =
#ifdef CORRADE_TARGET_UNIX
true
#else
false
#endif
;
m.attr("TARGET_WINDOWS") =
#ifdef CORRADE_TARGET_WINDOWS
true
#else
false
#endif
;
m.attr("TARGET_WINDOWS_RT") =
#ifdef CORRADE_TARGET_WINDOWS_RT
true
#else
false
#endif
;
m.attr("TARGET_EMSCRIPTEN") =
#ifdef CORRADE_TARGET_EMSCRIPTEN
true
#else
false
#endif
;
m.attr("TARGET_ANDROID") =
#ifdef CORRADE_TARGET_ANDROID
true
#else
false
#endif
;
/* Not exposing CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT as this
is a plugin itself and so if this works, plugin manager should too */
/* In case Corrade is a bunch of static libraries, put everything into a
single shared lib to make it easier to install (which is the point of
static builds) and avoid issues with multiply-defined global symbols.
These need to be defined in the order they depend on. */
#ifdef CORRADE_BUILD_STATIC
py::module containers = m.def_submodule("containers"); py::module containers = m.def_submodule("containers");
corrade::containers(containers); corrade::containers(containers);
#endif
} }

4
src/python/magnum/__init__.py

@ -91,4 +91,8 @@ __all__ = [
'PixelFormat', 'PixelStorage', 'PixelFormat', 'PixelStorage',
'ImageView1D', 'ImageView2D', 'ImageView3D', 'ImageView1D', 'ImageView2D', 'ImageView3D',
'MutableImageView1D', 'MutableImageView2D', 'MutableImageView3D' 'MutableImageView1D', 'MutableImageView2D', 'MutableImageView3D'
# TARGET_*, BUILD_* are omitted as `from magnum import *` would pull them
# to globals and this would likely cause conflicts (corrade also defines
# BUILD_*)
] ]

47
src/python/magnum/magnum.cpp

@ -133,6 +133,53 @@ template<class T> void imageViewFromMutable(py::class_<T, PyImageViewHolder<T>>&
} }
void magnum(py::module& m) { void magnum(py::module& m) {
m.attr("BUILD_STATIC") =
#ifdef MAGNUM_BUILD_STATIC
true
#else
false
#endif
;
m.attr("TARGET_GL") =
#ifdef MAGNUM_TARGET_GL
true
#else
false
#endif
;
m.attr("TARGET_GLES") =
#ifdef MAGNUM_TARGET_GLES
true
#else
false
#endif
;
m.attr("TARGET_GLES2") =
#ifdef MAGNUM_TARGET_GLES2
true
#else
false
#endif
;
/** @todo do we need TARGET_GLES3? i hope not */
m.attr("TARGET_WEBGL") =
#ifdef MAGNUM_TARGET_WEBGL
true
#else
false
#endif
;
/* TARGET_DESKTOP_GLES, TARGET_HEADLESS skipped as they make sense only
on native side (affecting what the builtin utilities use), not really in
Python */
m.attr("TARGET_VK") =
#ifdef MAGNUM_TARGET_VK
true
#else
false
#endif
;
py::enum_<MeshPrimitive>{m, "MeshPrimitive", "Mesh primitive type"} py::enum_<MeshPrimitive>{m, "MeshPrimitive", "Mesh primitive type"}
.value("POINTS", MeshPrimitive::Points) .value("POINTS", MeshPrimitive::Points)
.value("LINES", MeshPrimitive::Lines) .value("LINES", MeshPrimitive::Lines)

2
src/python/setup.py.cmake

@ -33,7 +33,7 @@ extension_paths = {
# Filled in by cmake. This works for both static and dynamic builds -- in # Filled in by cmake. This works for both static and dynamic builds -- in
# case a library is built statically, only the underscored name will be # case a library is built statically, only the underscored name will be
# present. # present.
'_corrade': '${corrade_file}', '_corrade': '$<TARGET_FILE:corrade>',
'corrade.containers': '${corrade_containers_file}', 'corrade.containers': '${corrade_containers_file}',
'_magnum': '$<TARGET_FILE:magnum>', '_magnum': '$<TARGET_FILE:magnum>',
'magnum.gl': '${magnum_gl_file}', 'magnum.gl': '${magnum_gl_file}',

Loading…
Cancel
Save