diff --git a/doc/python/pages/building.rst b/doc/python/pages/building.rst index 7e81d42..e5cf629 100644 --- a/doc/python/pages/building.rst +++ b/doc/python/pages/building.rst @@ -131,6 +131,13 @@ containing location of all built libraries for use with Python setuptools: cd build/src/python/magnum python setup.py install # or python3, sudo might be needed +`Static build`_ +--------------- + +In case Corrade or Magnum is built with :dox:`CORRADE_BUILD_STATIC` / +:dox:`MAGNUM_BUILD_STATIC`, the corresponding bindings are compiled into a +single dynamic module instead of one module per Corrade/Magnum library. + `Running unit tests`_ --------------------- diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index d8d7b74..0b75b54 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -40,6 +40,8 @@ add_subdirectory(magnum) # CMake 3.12, so I need to do two passes, first replacing variables using # configure_file() and then replacing generator expressions with file(GENERATE) foreach(target + corrade + corrade_containers magnum_gl magnum_meshtools magnum_primitives diff --git a/src/python/corrade/CMakeLists.txt b/src/python/corrade/CMakeLists.txt index 6893a9f..ffe5da6 100644 --- a/src/python/corrade/CMakeLists.txt +++ b/src/python/corrade/CMakeLists.txt @@ -26,15 +26,35 @@ set(corrade_containers_SRCS containers.cpp) -pybind11_add_module(corrade_containers ${corrade_containers_SRCS}) -target_include_directories(corrade_containers PRIVATE ${PROJECT_SOURCE_DIR}/src/python) -target_link_libraries(corrade_containers PRIVATE - Corrade::Containers - Corrade::Utility) -set_target_properties(corrade_containers PROPERTIES - FOLDER "python/corrade" - OUTPUT_NAME "containers" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade) +# If Corrade is not built as static, compile the sub-libraries as separate +# modules +if(NOT CORRADE_BUILD_STATIC) + pybind11_add_module(corrade_containers ${corrade_containers_SRCS}) + target_include_directories(corrade_containers PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(corrade_containers PRIVATE + Corrade::Containers + Corrade::Utility) + set_target_properties(corrade_containers PROPERTIES + FOLDER "python/corrade" + OUTPUT_NAME "containers" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/corrade) + +# Otherwise put it all into one library so it's easier to install (which is the +# point of static builds). It also nicely avoids problems with multiply-defined +# global data. +else() + set(corrade_SRCS + corrade.cpp + ${corrade_containers_SRCS}) + + pybind11_add_module(corrade ${corrade_SRCS}) + target_include_directories(corrade PRIVATE ${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() file(GENERATE OUTPUT ${output_dir}/corrade/__init__.py INPUT ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py) diff --git a/src/python/corrade/__init__.py b/src/python/corrade/__init__.py index 917f2c4..a715e31 100644 --- a/src/python/corrade/__init__.py +++ b/src/python/corrade/__init__.py @@ -24,3 +24,23 @@ # """Root Corrade module""" + +import sys + +# 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 +# moment. +try: + from _corrade import * + + # 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 *` -- +# this is consistent with behavior in magnum +__all__ = [] diff --git a/src/python/corrade/bootstrap.h b/src/python/corrade/bootstrap.h index b87659e..cb73578 100644 --- a/src/python/corrade/bootstrap.h +++ b/src/python/corrade/bootstrap.h @@ -33,6 +33,8 @@ namespace corrade { using namespace Corrade; namespace py = pybind11; +void containers(py::module& m); + } #endif diff --git a/src/python/corrade/containers.cpp b/src/python/corrade/containers.cpp index 102e0dc..c8306a1 100644 --- a/src/python/corrade/containers.cpp +++ b/src/python/corrade/containers.cpp @@ -32,7 +32,9 @@ #include "corrade/PyArrayView.h" #include "corrade/PybindExtras.h" -namespace corrade { namespace { +namespace corrade { + +namespace { struct Slice { std::size_t start; @@ -401,6 +403,8 @@ template void mutableStridedArrayView3D(py::class_ + + 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. +*/ + +#include +#include + +#include "corrade/bootstrap.h" + +#ifndef CORRADE_BUILD_STATIC +#error this file should be compiled only in the static build +#endif + +namespace py = pybind11; + +PYBIND11_MODULE(_corrade, m) { + py::module containers = m.def_submodule("containers"); + corrade::containers(containers); +} diff --git a/src/python/magnum/CMakeLists.txt b/src/python/magnum/CMakeLists.txt index f0c5896..1920e84 100644 --- a/src/python/magnum/CMakeLists.txt +++ b/src/python/magnum/CMakeLists.txt @@ -24,7 +24,18 @@ # # *Not* REQUIRED -find_package(Magnum COMPONENTS GL Shaders SceneGraph MeshTools Primitives Trade) +find_package(Magnum COMPONENTS + GL + MeshTools + Primitives + SceneGraph + Shaders + Trade + + GlfwApplication + Sdl2Application + WindowlessEglApplication + WindowlessGlxApplication) set(magnum_SRCS magnum.cpp @@ -34,96 +45,163 @@ set(magnum_SRCS math.vectorfloat.cpp math.vectorintegral.cpp) +# Extra libraries to link to. Populated only in case of MAGNUM_BUILD_STATIC. +set(magnum_LIBS ) + +set(magnum_gl_SRCS + gl.cpp) + +set(magnum_meshtools_SRCS + meshtools.cpp) + +set(magnum_primitives_SRCS + primitives.cpp) + +set(magnum_scenegraph_SRCS + scenegraph.cpp + scenegraph.matrix.cpp + scenegraph.trs.cpp) + +set(magnum_shaders_SRCS + shaders.cpp) + +set(magnum_trade_SRCS + trade.cpp) + +# If Magnum is not built as static, compile the sub-libraries as separate +# modules +if(NOT MAGNUM_BUILD_STATIC) + if(Magnum_GL_FOUND) + pybind11_add_module(magnum_gl ${magnum_gl_SRCS}) + target_include_directories(magnum_gl PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_gl PRIVATE Magnum::GL) + set_target_properties(magnum_gl PROPERTIES + FOLDER "python" + OUTPUT_NAME "gl" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + + if(Magnum_MeshTools_FOUND) + pybind11_add_module(magnum_meshtools ${magnum_meshtools_SRCS}) + target_include_directories(magnum_meshtools PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_meshtools PRIVATE Magnum::MeshTools) + set_target_properties(magnum_meshtools PROPERTIES + FOLDER "python" + OUTPUT_NAME "meshtools" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + + if(Magnum_Primitives_FOUND) + pybind11_add_module(magnum_primitives ${magnum_primitives_SRCS}) + target_include_directories(magnum_primitives PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_primitives PRIVATE Magnum::Primitives) + set_target_properties(magnum_primitives PROPERTIES + FOLDER "python" + OUTPUT_NAME "primitives" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + + if(Magnum_SceneGraph_FOUND) + pybind11_add_module(magnum_scenegraph ${magnum_scenegraph_SRCS}) + target_include_directories(magnum_scenegraph PRIVATE + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_scenegraph PRIVATE Magnum::SceneGraph) + set_target_properties(magnum_scenegraph PROPERTIES + FOLDER "python" + OUTPUT_NAME "scenegraph" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + + if(Magnum_Shaders_FOUND) + pybind11_add_module(magnum_shaders ${magnum_shaders_SRCS}) + target_include_directories(magnum_shaders PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_shaders PRIVATE Magnum::Shaders) + set_target_properties(magnum_shaders PROPERTIES + FOLDER "python" + OUTPUT_NAME "shaders" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + + if(Magnum_Trade_FOUND) + pybind11_add_module(magnum_trade ${magnum_trade_SRCS}) + target_include_directories(magnum_trade PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + target_link_libraries(magnum_trade PRIVATE Magnum::Trade) + set_target_properties(magnum_trade PROPERTIES + FOLDER "python" + OUTPUT_NAME "trade" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) + endif() + +# Otherwise put it all into the core library so it's easier to install (which +# is the point of static builds). It also nicely avoids problems with +# multiply-defined global data. +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/staticconfigure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/staticconfigure.h) + + if(Magnum_GL_FOUND) + list(APPEND magnum_SRCS ${magnum_gl_SRCS}) + list(APPEND magnum_LIBS Magnum::GL) + endif() + + if(Magnum_MeshTools_FOUND) + list(APPEND magnum_SRCS ${magnum_meshtools_SRCS}) + list(APPEND magnum_LIBS Magnum::MeshTools) + endif() + + if(Magnum_Primitives_FOUND) + list(APPEND magnum_SRCS ${magnum_primitives_SRCS}) + list(APPEND magnum_LIBS Magnum::Primitives) + endif() + + if(Magnum_SceneGraph_FOUND) + list(APPEND magnum_SRCS ${magnum_scenegraph_SRCS}) + list(APPEND magnum_LIBS Magnum::SceneGraph) + endif() + + if(Magnum_Shaders_FOUND) + list(APPEND magnum_SRCS ${magnum_shaders_SRCS}) + list(APPEND magnum_LIBS Magnum::Shaders) + endif() + + if(Magnum_Trade_FOUND) + list(APPEND magnum_SRCS ${magnum_trade_SRCS}) + list(APPEND magnum_LIBS Magnum::Trade) + endif() + + if(Magnum_GlfwApplication_FOUND) + list(APPEND magnum_SRCS platform/glfw.cpp) + list(APPEND magnum_LIBS Magnum::GlfwApplication) + endif() + + if(Magnum_Sdl2Application_FOUND) + list(APPEND magnum_SRCS platform/sdl2.cpp) + list(APPEND magnum_LIBS Magnum::Sdl2Application) + endif() + + if(Magnum_WindowlessEglApplication_FOUND) + list(APPEND magnum_SRCS platform/egl.cpp) + list(APPEND magnum_LIBS Magnum::WindowlessEglApplication) + endif() + + if(Magnum_WindowlessGlxApplication_FOUND) + list(APPEND magnum_SRCS platform/glx.cpp) + list(APPEND magnum_LIBS Magnum::WindowlessGlxApplication) + endif() +endif() + pybind11_add_module(magnum ${magnum_SRCS}) -target_include_directories(magnum PRIVATE ${PROJECT_SOURCE_DIR}/src/python) -target_link_libraries(magnum PRIVATE Magnum::Magnum) +target_include_directories(magnum PRIVATE + ${PROJECT_SOURCE_DIR}/src # SceneGraph/Python.h for static build + ${PROJECT_SOURCE_DIR}/src/python + ${PROJECT_BINARY_DIR}/src/python) # for static build +target_link_libraries(magnum PRIVATE Magnum::Magnum ${magnum_LIBS}) set_target_properties(magnum PROPERTIES FOLDER "python" OUTPUT_NAME "_magnum" LIBRARY_OUTPUT_DIRECTORY ${output_dir}) -if(Magnum_GL_FOUND) - set(magnum_gl_SRCS - gl.cpp) - - pybind11_add_module(magnum_gl ${magnum_gl_SRCS}) - target_include_directories(magnum_gl PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_gl PRIVATE Magnum::GL) - set_target_properties(magnum_gl PROPERTIES - FOLDER "python" - OUTPUT_NAME "gl" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - -if(Magnum_MeshTools_FOUND) - set(magnum_meshtools_SRCS - meshtools.cpp) - - pybind11_add_module(magnum_meshtools ${magnum_meshtools_SRCS}) - target_include_directories(magnum_meshtools PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_meshtools PRIVATE Magnum::MeshTools) - set_target_properties(magnum_meshtools PROPERTIES - FOLDER "python" - OUTPUT_NAME "meshtools" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - -if(Magnum_Primitives_FOUND) - set(magnum_primitives_SRCS - primitives.cpp) - - pybind11_add_module(magnum_primitives ${magnum_primitives_SRCS}) - target_include_directories(magnum_primitives PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_primitives PRIVATE Magnum::Primitives) - set_target_properties(magnum_primitives PROPERTIES - FOLDER "python" - OUTPUT_NAME "primitives" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - -if(Magnum_SceneGraph_FOUND) - set(magnum_scenegraph_SRCS - scenegraph.cpp - scenegraph.matrix.cpp - scenegraph.trs.cpp) - - pybind11_add_module(magnum_scenegraph ${magnum_scenegraph_SRCS}) - target_include_directories(magnum_scenegraph PRIVATE - ${PROJECT_SOURCE_DIR}/src - ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_scenegraph PRIVATE Magnum::SceneGraph) - set_target_properties(magnum_scenegraph PROPERTIES - FOLDER "python" - OUTPUT_NAME "scenegraph" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - -if(Magnum_Shaders_FOUND) - set(magnum_shaders_SRCS - shaders.cpp) - - pybind11_add_module(magnum_shaders ${magnum_shaders_SRCS}) - target_include_directories(magnum_shaders PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_shaders PRIVATE Magnum::Shaders) - set_target_properties(magnum_shaders PROPERTIES - FOLDER "python" - OUTPUT_NAME "shaders" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - -if(Magnum_Trade_FOUND) - set(magnum_trade_SRCS - trade.cpp) - - pybind11_add_module(magnum_trade ${magnum_trade_SRCS}) - target_include_directories(magnum_trade PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - target_link_libraries(magnum_trade PRIVATE Magnum::Trade) - set_target_properties(magnum_trade PROPERTIES - FOLDER "python" - OUTPUT_NAME "trade" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum) -endif() - file(GENERATE OUTPUT ${output_dir}/magnum/__init__.py INPUT ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py) diff --git a/src/python/magnum/__init__.py b/src/python/magnum/__init__.py index efe0907..44102ee 100644 --- a/src/python/magnum/__init__.py +++ b/src/python/magnum/__init__.py @@ -33,6 +33,34 @@ from _magnum import * import sys sys.modules['magnum.math'] = math +# In case Magnum is built statically, the whole core project is put into +# _magnum. Then we need to do the same as above but for all modules. +for i in ['gl', 'meshtools', 'platform', 'primitives', 'scenegraph', 'shaders', 'trade']: + if i in globals(): sys.modules['magnum.' + i] = globals()[i] + +# Platform has subpackages +if 'platform' in globals(): + for i in ['glfw', 'sdl2', 'egl', 'glx']: + if hasattr(platform, i): sys.modules['magnum.platform.' + i] = getattr(platform, i) + + # Bring one application implementation directly into the platform module. + # The same logic is duplicated in platform/__init__.py. + if hasattr(platform, 'sdl2'): + platform.Application = platform.sdl2.Application + elif hasattr(platform, 'glfw'): + platform.Application = platform.glfw.Application + + # Same for windowless apps + if hasattr(platform, 'glx'): + platform.WindowlessApplication = platform.glx.WindowlessApplication + elif hasattr(platform, 'egl'): + platform.WindowlessApplication = platform.egl.WindowlessApplication + +# Scenegraph has subpackages +if 'scenegraph' in globals(): + for i in ['matrix', 'trs']: + sys.modules['magnum.scenegraph.' + i] = getattr(scenegraph, i) + __all__ = [ 'Deg', 'Rad', diff --git a/src/python/magnum/bootstrap.h b/src/python/magnum/bootstrap.h index 498a500..0960ffd 100644 --- a/src/python/magnum/bootstrap.h +++ b/src/python/magnum/bootstrap.h @@ -39,6 +39,21 @@ void mathVectorIntegral(py::module& root, py::module& m); void mathMatrixFloat(py::module& root); void mathMatrixDouble(py::module& root); +void gl(py::module& m); +void meshtools(py::module& m); +void primitives(py::module& m); +void scenegraph(py::module& m); +void shaders(py::module& m); +void trade(py::module& m); + +namespace platform { + void glfw(py::module& m); + void sdl2(py::module& m); + + void egl(py::module& m); + void glx(py::module& m); +} + } #endif diff --git a/src/python/magnum/gl.cpp b/src/python/magnum/gl.cpp index e8c2640..bad6aca 100644 --- a/src/python/magnum/gl.cpp +++ b/src/python/magnum/gl.cpp @@ -39,7 +39,7 @@ #include "magnum/NonDestructible.h" #include "magnum/PyMesh.h" -namespace magnum { namespace { +namespace magnum { void gl(py::module& m) { m.doc() = "OpenGL wrapping layer"; @@ -302,8 +302,10 @@ void gl(py::module& m) { } } -}} +} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(gl, m) { magnum::gl(m); } +#endif diff --git a/src/python/magnum/magnum.cpp b/src/python/magnum/magnum.cpp index 875299b..f9fff86 100644 --- a/src/python/magnum/magnum.cpp +++ b/src/python/magnum/magnum.cpp @@ -28,6 +28,10 @@ #include "magnum/bootstrap.h" +#ifdef MAGNUM_BUILD_STATIC +#include "magnum/staticconfigure.h" +#endif + namespace py = pybind11; namespace magnum { namespace { @@ -57,4 +61,68 @@ PYBIND11_MODULE(_magnum, m) { py::module math = m.def_submodule("math"); magnum::math(m, math); + + /* In case Magnum 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 MAGNUM_BUILD_STATIC + #ifdef Magnum_GL_FOUND + py::module gl = m.def_submodule("gl"); + magnum::gl(gl); + #endif + + #ifdef Magnum_SceneGraph_FOUND + py::module scenegraph = m.def_submodule("scenegraph"); + magnum::scenegraph(scenegraph); + #endif + + #ifdef Magnum_Trade_FOUND + py::module trade = m.def_submodule("trade"); + magnum::trade(trade); + #endif + + #ifdef Magnum_MeshTools_FOUND + /* Depends on trade and gl */ + py::module meshtools = m.def_submodule("meshtools"); + magnum::meshtools(meshtools); + #endif + + #ifdef Magnum_Primitives_FOUND + /* Depends on trade */ + py::module primitives = m.def_submodule("primitives"); + magnum::primitives(primitives); + #endif + + #ifdef Magnum_Shaders_FOUND + /* Depends on gl */ + py::module shaders = m.def_submodule("shaders"); + magnum::shaders(shaders); + #endif + + /* Keep the doc in sync with platform/__init__.py */ + py::module platform = m.def_submodule("platform"); + platform.doc() = "Platform-specific application and context creation"; + + #ifdef Magnum_GlfwApplication_FOUND + py::module glfw = platform.def_submodule("glfw"); + magnum::platform::glfw(glfw); + #endif + + #ifdef Magnum_Sdl2Application_FOUND + py::module sdl2 = platform.def_submodule("sdl2"); + magnum::platform::sdl2(sdl2); + #endif + + #ifdef Magnum_WindowlessEglApplication_FOUND + py::module egl = platform.def_submodule("egl"); + magnum::platform::egl(egl); + #endif + + #ifdef Magnum_WindowlessGlxApplication_FOUND + py::module glx = platform.def_submodule("glx"); + magnum::platform::glx(glx); + #endif + #endif } diff --git a/src/python/magnum/meshtools.cpp b/src/python/magnum/meshtools.cpp index 1a9ffdf..06e1a88 100644 --- a/src/python/magnum/meshtools.cpp +++ b/src/python/magnum/meshtools.cpp @@ -32,13 +32,17 @@ #include "magnum/bootstrap.h" #include "magnum/PyMesh.h" -namespace magnum { namespace { +namespace magnum { void meshtools(py::module& m) { m.doc() = "Mesh tools"; + #ifndef MAGNUM_BUILD_STATIC + /* These are a part of the same module in the static build, no need to + import (also can't import because there it's _magnum.*) */ py::module::import("magnum.gl"); py::module::import("magnum.trade"); + #endif m .def("compile", [](const Trade::MeshData2D& data) { @@ -49,8 +53,10 @@ void meshtools(py::module& m) { }, "Compile 3D mesh data"); } -}} +} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(meshtools, m) { magnum::meshtools(m); } +#endif diff --git a/src/python/magnum/platform/CMakeLists.txt b/src/python/magnum/platform/CMakeLists.txt index b345a2a..bb61f3f 100644 --- a/src/python/magnum/platform/CMakeLists.txt +++ b/src/python/magnum/platform/CMakeLists.txt @@ -23,51 +23,46 @@ # DEALINGS IN THE SOFTWARE. # -# *Not* REQUIRED -find_package(Magnum COMPONENTS - GlfwApplication - Sdl2Application - WindowlessEglApplication - WindowlessGlxApplication) +if(NOT MAGNUM_BUILD_STATIC) + if(Magnum_GlfwApplication_FOUND) + pybind11_add_module(magnum_platform_glfw glfw.cpp) + target_link_libraries(magnum_platform_glfw PRIVATE Magnum::GlfwApplication) + target_include_directories(magnum_platform_glfw PRIVATE ${CMAKE_SOURCE_DIR}/src/python) + set_target_properties(magnum_platform_glfw PROPERTIES + FOLDER "python/platform" + OUTPUT_NAME "glfw" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) + endif() -if(Magnum_GlfwApplication_FOUND) - pybind11_add_module(magnum_platform_glfw glfw.cpp) - target_link_libraries(magnum_platform_glfw PRIVATE Magnum::GlfwApplication) - target_include_directories(magnum_platform_glfw PRIVATE ${CMAKE_SOURCE_DIR}/src/python) - set_target_properties(magnum_platform_glfw PROPERTIES - FOLDER "python/platform" - OUTPUT_NAME "glfw" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) -endif() - -if(Magnum_Sdl2Application_FOUND) - pybind11_add_module(magnum_platform_sdl2 sdl2.cpp) - target_link_libraries(magnum_platform_sdl2 PRIVATE Magnum::Sdl2Application) - target_include_directories(magnum_platform_sdl2 PRIVATE ${CMAKE_SOURCE_DIR}/src/python) - set_target_properties(magnum_platform_sdl2 PROPERTIES - FOLDER "python/platform" - OUTPUT_NAME "sdl2" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) -endif() + if(Magnum_Sdl2Application_FOUND) + pybind11_add_module(magnum_platform_sdl2 sdl2.cpp) + target_link_libraries(magnum_platform_sdl2 PRIVATE Magnum::Sdl2Application) + target_include_directories(magnum_platform_sdl2 PRIVATE ${CMAKE_SOURCE_DIR}/src/python) + set_target_properties(magnum_platform_sdl2 PROPERTIES + FOLDER "python/platform" + OUTPUT_NAME "sdl2" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) + endif() -if(Magnum_WindowlessEglApplication_FOUND) - pybind11_add_module(magnum_platform_egl egl.cpp) - target_link_libraries(magnum_platform_egl PRIVATE Magnum::WindowlessEglApplication) - target_include_directories(magnum_platform_egl PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - set_target_properties(magnum_platform_egl PROPERTIES - FOLDER "python/platform" - OUTPUT_NAME "egl" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) -endif() + if(Magnum_WindowlessEglApplication_FOUND) + pybind11_add_module(magnum_platform_egl egl.cpp) + target_link_libraries(magnum_platform_egl PRIVATE Magnum::WindowlessEglApplication) + target_include_directories(magnum_platform_egl PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + set_target_properties(magnum_platform_egl PROPERTIES + FOLDER "python/platform" + OUTPUT_NAME "egl" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) + endif() -if(Magnum_WindowlessGlxApplication_FOUND) - pybind11_add_module(magnum_platform_glx glx.cpp) - target_link_libraries(magnum_platform_glx PRIVATE Magnum::WindowlessGlxApplication) - target_include_directories(magnum_platform_glx PRIVATE ${PROJECT_SOURCE_DIR}/src/python) - set_target_properties(magnum_platform_glx PROPERTIES - FOLDER "python/platform" - OUTPUT_NAME "glx" - LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) + if(Magnum_WindowlessGlxApplication_FOUND) + pybind11_add_module(magnum_platform_glx glx.cpp) + target_link_libraries(magnum_platform_glx PRIVATE Magnum::WindowlessGlxApplication) + target_include_directories(magnum_platform_glx PRIVATE ${PROJECT_SOURCE_DIR}/src/python) + set_target_properties(magnum_platform_glx PROPERTIES + FOLDER "python/platform" + OUTPUT_NAME "glx" + LIBRARY_OUTPUT_DIRECTORY ${output_dir}/magnum/platform) + endif() endif() file(GENERATE OUTPUT ${output_dir}/magnum/platform/__init__.py diff --git a/src/python/magnum/platform/__init__.py b/src/python/magnum/platform/__init__.py index 119801f..afb7f66 100644 --- a/src/python/magnum/platform/__init__.py +++ b/src/python/magnum/platform/__init__.py @@ -25,6 +25,9 @@ """Platform-specific application and context creation""" +# This logic is repeated in magnum's main __init__.py for static builds as +# there magnum.platform is a submodule inside the native _magnum module. + try: from .glx import WindowlessApplication except ImportError: # pragma: no cover diff --git a/src/python/magnum/platform/egl.cpp b/src/python/magnum/platform/egl.cpp index d59c10f..36ad680 100644 --- a/src/python/magnum/platform/egl.cpp +++ b/src/python/magnum/platform/egl.cpp @@ -29,9 +29,11 @@ #include "magnum/bootstrap.h" #include "magnum/platform/windowlessapplication.h" -namespace magnum { namespace platform { namespace { +namespace magnum { namespace platform { -int argc = 0; +namespace { + int argc = 0; +} void egl(py::module& m) { m.doc() = "EGL-based platform integration"; @@ -53,8 +55,10 @@ void egl(py::module& m) { windowlessapplication(windowlessEglApplication); } -}}} +}} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(egl, m) { magnum::platform::egl(m); } +#endif diff --git a/src/python/magnum/platform/glfw.cpp b/src/python/magnum/platform/glfw.cpp index 2a38fc6..f633f9a 100644 --- a/src/python/magnum/platform/glfw.cpp +++ b/src/python/magnum/platform/glfw.cpp @@ -29,9 +29,11 @@ #include "magnum/bootstrap.h" #include "magnum/platform/application.h" -namespace magnum { namespace platform { namespace { +namespace magnum { namespace platform { -int argc = 0; +namespace { + int argc = 0; +} void glfw(py::module& m) { m.doc() = "GLFW-based platform integration"; @@ -105,8 +107,10 @@ void glfw(py::module& m) { mouseMoveEvent(mouseMoveEvent_); } -}}} +}} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(glfw, m) { magnum::platform::glfw(m); } +#endif diff --git a/src/python/magnum/platform/glx.cpp b/src/python/magnum/platform/glx.cpp index 48c1ab1..2f4d091 100644 --- a/src/python/magnum/platform/glx.cpp +++ b/src/python/magnum/platform/glx.cpp @@ -29,9 +29,11 @@ #include "magnum/bootstrap.h" #include "magnum/platform/windowlessapplication.h" -namespace magnum { namespace platform { namespace { +namespace magnum { namespace platform { -int argc = 0; +namespace { + int argc = 0; +} void glx(py::module& m) { m.doc() = "GLX-based platform integration"; @@ -53,8 +55,10 @@ void glx(py::module& m) { windowlessapplication(windowlessGlxApplication); } -}}} +}} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(glx, m) { magnum::platform::glx(m); } +#endif diff --git a/src/python/magnum/platform/sdl2.cpp b/src/python/magnum/platform/sdl2.cpp index 5e94c8d..ed954ab 100644 --- a/src/python/magnum/platform/sdl2.cpp +++ b/src/python/magnum/platform/sdl2.cpp @@ -29,9 +29,11 @@ #include "magnum/bootstrap.h" #include "magnum/platform/application.h" -namespace magnum { namespace platform { namespace { +namespace magnum { namespace platform { -int argc = 0; +namespace { + int argc = 0; +} void sdl2(py::module& m) { m.doc() = "SDL2-based platform integration"; @@ -113,8 +115,10 @@ void sdl2(py::module& m) { mouseMoveEvent(mouseMoveEvent_); } -}}} +}} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(sdl2, m) { magnum::platform::sdl2(m); } +#endif diff --git a/src/python/magnum/primitives.cpp b/src/python/magnum/primitives.cpp index d16252f..8cc07ee 100644 --- a/src/python/magnum/primitives.cpp +++ b/src/python/magnum/primitives.cpp @@ -31,12 +31,16 @@ #include "magnum/bootstrap.h" -namespace magnum { namespace { +namespace magnum { void primitives(py::module& m) { m.doc() = "Primitive library"; + #ifndef MAGNUM_BUILD_STATIC + /* These are a part of the same module in the static build, no need to + import (also can't import because there it's _magnum.*) */ py::module::import("magnum.trade"); + #endif py::enum_{m, "SquareTextureCoords", "Whether to generate square texture coordinates"} .value("DONT_GENERATE", Primitives::SquareTextureCoords::DontGenerate) @@ -51,8 +55,10 @@ void primitives(py::module& m) { .def("square_wireframe", Primitives::squareWireframe, "Wireframe 2D square"); } -}} +} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(primitives, m) { magnum::primitives(m); } +#endif diff --git a/src/python/magnum/scenegraph.cpp b/src/python/magnum/scenegraph.cpp index e744db4..786bbf5 100644 --- a/src/python/magnum/scenegraph.cpp +++ b/src/python/magnum/scenegraph.cpp @@ -30,7 +30,9 @@ #include "magnum/scenegraph.h" -namespace magnum { namespace { +namespace magnum { + +namespace { template struct PyDrawable: SceneGraph::PyFeature> { explicit PyDrawable(SceneGraph::AbstractObject& object, SceneGraph::DrawableGroup* drawables): SceneGraph::PyFeature>{object, drawables} {} @@ -120,6 +122,8 @@ template void camera(py::class_ void vertexColor(NonDestructibleBase, GL::AbstractShaderProgram>& c) { /* Attributes */ @@ -60,10 +62,16 @@ template void vertexColor(NonDestructibleBase + + 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. +*/ + +/* Named magnum/staticconfigure.h to avoid it colliding with Magnum/configure.h + on case-insensitive filesystems */ + +#cmakedefine Magnum_GL_FOUND +#cmakedefine Magnum_MeshTools_FOUND +#cmakedefine Magnum_Primitives_FOUND +#cmakedefine Magnum_SceneGraph_FOUND +#cmakedefine Magnum_Shaders_FOUND +#cmakedefine Magnum_Trade_FOUND + +#cmakedefine Magnum_GlfwApplication_FOUND +#cmakedefine Magnum_Sdl2Application_FOUND +#cmakedefine Magnum_WindowlessEglApplication_FOUND +#cmakedefine Magnum_WindowlessGlxApplication_FOUND diff --git a/src/python/magnum/trade.cpp b/src/python/magnum/trade.cpp index 8afd331..6ae1803 100644 --- a/src/python/magnum/trade.cpp +++ b/src/python/magnum/trade.cpp @@ -29,7 +29,9 @@ #include "magnum/bootstrap.h" -namespace magnum { namespace { +namespace magnum { + +namespace { template void meshData(py::class_& c) { c @@ -37,6 +39,8 @@ template void meshData(py::class_& c) { .def("is_indexed", &T::isIndexed, "Whether the mesh is indexed"); } +} + void trade(py::module& m) { m.doc() = "Data format exchange"; @@ -46,8 +50,10 @@ void trade(py::module& m) { meshData(meshData3D); } -}} +} +#ifndef MAGNUM_BUILD_STATIC PYBIND11_MODULE(trade, m) { magnum::trade(m); } +#endif diff --git a/src/python/setup.py.cmake b/src/python/setup.py.cmake index 06494a9..b4fc8fa 100644 --- a/src/python/setup.py.cmake +++ b/src/python/setup.py.cmake @@ -30,8 +30,11 @@ from setuptools import setup, Extension, find_packages from setuptools.command.build_ext import build_ext extension_paths = { - # Filled in by cmake - 'corrade.containers': '$', + # 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 + # present. + '_corrade': '${corrade_file}', + 'corrade.containers': '${corrade_containers_file}', '_magnum': '$', 'magnum.gl': '${magnum_gl_file}', 'magnum.meshtools': '${magnum_meshtools_file}', @@ -45,6 +48,14 @@ extension_paths = { 'magnum.trade': '${magnum_trade_file}', } +packages = ['corrade', 'magnum'] + +# On dynamic builds, platform is a package with an __init__.py and submodules. +# On static builds, it's a submodule of magnum with everything present +# statically. +if '${MAGNUM_BUILD_STATIC}' != 'ON': + packages += ['magnum.platform'] + class TheExtensionIsAlreadyBuiltWhyThisHasToBeSoDamnComplicated(build_ext): def run(self): for ext in self.extensions: @@ -52,7 +63,7 @@ class TheExtensionIsAlreadyBuiltWhyThisHasToBeSoDamnComplicated(build_ext): setup( name='magnum', - packages=['corrade', 'magnum', 'magnum.platform'], + packages=packages, ext_modules=[Extension(name, sources=[]) for name, path in extension_paths.items() if path], cmdclass = { 'build_ext': TheExtensionIsAlreadyBuiltWhyThisHasToBeSoDamnComplicated