Metadata-Version: 2.1
Name: cmake-build-extension
Version: 0.2.0
Summary: Setuptools extension to build and package CMake projects
Home-page: https://github.com/diegoferigo/cmake-build-extension
Author: Diego Ferigo
Author-email: dgferigo@gmail.com
License: MIT
Description: # cmake-build-extension
        
        [![Version](https://img.shields.io/pypi/v/cmake-build-extension.svg)](https://pypi.org/project/cmake-build-extension/)
        [![Python versions](https://img.shields.io/pypi/pyversions/cmake-build-extension.svg)](https://pypi.org/project/cmake-build-extension/)
        [![Status](https://img.shields.io/pypi/status/cmake-build-extension.svg)](https://pypi.org/project/cmake-build-extension/)
        [![Format](https://img.shields.io/pypi/format/cmake-build-extension.svg)](https://pypi.org/project/cmake-build-extension/)
        [![License](https://img.shields.io/pypi/l/cmake-build-extension.svg)](https://pypi.org/project/cmake-build-extension/)
        [![Python CI/CD](https://github.com/diegoferigo/cmake-build-extension/workflows/Python%20CI/CD/badge.svg)](https://github.com/diegoferigo/cmake-build-extension/actions)
        
        Setuptools extension to build and package CMake projects.
        
        A project `MyProject` with C++ files that can be compiled with CMake (here `MyClass.{h,cpp}`) 
        and a Python package (here `my_python_package`) can be structured as follows:
        
        ```
        myproject/
        |-- CMakeLists.txt
        |-- include
        |   `-- MyClass.h
        |-- python
        |   `-- my_python_package
        |       `-- __init__.py
        |-- setup.py
        `-- src
            `-- MyClass.cpp
        ```
        
        The C++ and Python could be independent, even though this hybrid setup usually
        applies to project that want to provide Python bindings of the C++ libraries.
        
        This extension enables the following:
        
        - Streamlines the interaction of Python packaging and CMake.
        - Enables building and packaging a generic CMake project through `setuptools`.
        - Simplifies distributing and consuming C++ / Python hybrid projects.
        
        The following lines of the `setup.py` script add a `build_ext` step to the pipeline that
        compiles and installs the CMake project in the root of the resulting Python package:
        
        ```python
        from setuptools import find_packages, setup
        from cmake_build_extension import BuildExtension, CMakeExtension
        
        setup(
            name="my-python-package",
            packages=find_packages("python"),
            package_dir={'': "python"},
            # ...
            ext_modules=[
                CMakeExtension(name="MyProject",
                               install_prefix="my_python_package",
                               cmake_configure_options=[
                                   "-DBUILD_SHARED_LIBS:BOOL=OFF",
                               ]),
            ],
            cmdclass=dict(build_ext=BuildExtension),
        )
        ```
        
        Note: If CMake also exports the targets, downstream projects can import them by 
        adding the directory of the installed Python package to `CMAKE_PREFIX_PATH`.
        
        The resulting Python install tree will be something similar to what follows:
        
        ```
        site-packages/
        `-- my_python_package
            |-- __init__.py
            `-- lib
                |-- cmake
                |   |-- MyProject.cmake
                |   |-- MyProjectTargets.cmake
                |   `-- MyProjectVersion.cmake
                `-- libMyProject.so
        ```
        
        This way, if the C++ project also includes Python bindings, they can be generated by your favourite tool
        and handled with CMake. This is often convenient since CMake typically has powerful modules that
        simplify the building process, especially for big projects.
        
        Check out [`examples/swig`](examples/swig) for a minimal working example.
        
        ## Usage
        
        Once both CMake project and `setup.py` are correctly configured, the following
        commands can be used:
        
        ```bash
        # Install with pip
        pip install .
        pip install --editable .
        
        # Install with setup.py
        python setup.py install .
        python setup.py develop .
        
        # Install with pip passing custom CMake options
        pip install --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" .
        
        # Install with setup.py passing custom CMake options
        python setup.py install build_ext -D"BAR=Foo;VAR=TRUE"
        
        # Create wheel with pip
        pip wheel -w dist .
        
        # Create wheel with setup.py
        python setup.py bdist_wheel
        
        # Create wheel with setup.py passing custom CMake options
        python setup.py bdist_wheel build_ext -D"BAR=Foo;VAR=TRUE"
        ```
        
        If the Python project is compliant with PEP517 and PEP518, `pip` will use an isolated environment.
        Note that CMake's `find_package` will still find resources from the filesystem and it will
        not be isolated. 
        
        ## Caveats
        
        - Beyond distributing a hybrid C++ / Python project through, e.g., PyPI, this extension simplifies including the exported CMake project in the resulting wheel. This is dependent on how the CMake project is configured and whether it installs in the prefix the [exported targets](https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets) alongside to shared libraries and headers. If everything is in place, the `manylinux*` guidelines could still work against you. In fact, wheels supporting `manylinux2010|manylinux2014` are built [with gcc4](https://www.python.org/dev/peps/pep-0599/#the-manylinux2014-policy) that does not support the new C++11 ABIs. In few words, this means that the exported libraries bundled with the wheel cannot be imported in a downstream project using relatevely new C++ standards! For more details visit [robotology/idyntree#776](https://github.com/robotology/idyntree/issues/776). Luckily, the situation changed thanks to the finalization of [PEP600](https://www.python.org/dev/peps/pep-0600/), i.e. `manylinux2_24` :tada: If you build a PEP600 compliant wheel (nowadays compatible with most of the commonly used distributions), your exported CMake project bundled in the wheel can be successfully imported by either standalone C++ downstream projects by simply configuring `CMAKE_INSTALL_PREFIX=/path/to/site-packages/<package_name>`, or from other projects using `cmake_build_extension` using the [cmake_depends_on](https://github.com/diegoferigo/cmake-build-extension/blob/69fc8c23ce065fd1830e74094bd7c090e44b3e4d/src/cmake_build_extension/cmake_extension.py#L30) option ([example](https://github.com/robotology/gym-ignition/blob/4a95c80271c6277821ad60990eb664e7c3092042/setup.py#L73)).
        
Keywords: setuptools extension cmake build package pypi
Platform: any
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Archiving :: Packaging
Requires-Python: >=3.6
Description-Content-Type: text/markdown
