From c6de8f3bb39f911cbb71a4f8c2259e04ba3f55e8 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Wed, 23 Aug 2017 14:20:53 +0200 Subject: [PATCH 1/2] Fix setup.py detail headers and add pip install tests to Travis The default `install_headers` from `distutils` flattens all the headers into a single directory -- `detail` subdirectory was lost. This commit fixes this by overriding the setup with a custom header installer. Tests are added to Travis to make sure `setup.py sdist` and `pip install` do not miss any headers and that the directory structure is preserved. [skip appveyor] --- .travis.yml | 9 ++++++++- MANIFEST.in | 2 +- setup.py | 20 +++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fd4162146d..55f1676be3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,8 @@ matrix: # Documentation build: - os: linux language: docs - env: DOCS STYLE LINT + env: DOCS STYLE LINT PIP + cache: false install: - export PATH="~/.local/bin:$PATH" - $PY_CMD -m pip install --user --upgrade sphinx sphinx_rtd_theme breathe flake8 pep8-naming @@ -76,6 +77,12 @@ matrix: - $PY_CMD -m sphinx -W -b html docs docs/.build - tools/check-style.sh - flake8 + - | + # Make sure setup.py distributes and installs all the headers + $PY_CMD setup.py sdist + $PY_CMD -m pip install --user -U ./dist/* + installed=$($PY_CMD -c "import pybind11; print(pybind11.get_include(True) + '/pybind11')") + diff -rq $installed ./include/pybind11 cache: directories: - $HOME/.local/bin diff --git a/MANIFEST.in b/MANIFEST.in index aa51d01100..6e57baeeef 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ -include include/pybind11/*.h +recursive-include include/pybind11 *.h include LICENSE README.md CONTRIBUTING.md diff --git a/setup.py b/setup.py index 51ab47d1a6..6e7a40a562 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ # Setup script for PyPI; use CMakeFile.txt to build extension modules from setuptools import setup +from distutils.command.install_headers import install_headers from pybind11 import __version__ import os @@ -17,7 +18,7 @@ 'include/pybind11/detail/descr.h', 'include/pybind11/detail/init.h', 'include/pybind11/detail/internals.h', - 'include/pybind11/detail/typeid.h' + 'include/pybind11/detail/typeid.h', 'include/pybind11/attr.h', 'include/pybind11/buffer_info.h', 'include/pybind11/cast.h', @@ -36,6 +37,22 @@ 'include/pybind11/stl_bind.h', ] + +class InstallHeaders(install_headers): + """Use custom header installer because the default one flattens subdirectories""" + def run(self): + if not self.distribution.headers: + return + + for header in self.distribution.headers: + subdir = os.path.dirname(os.path.relpath(header, 'include/pybind11')) + install_dir = os.path.join(self.install_dir, subdir) + self.mkpath(install_dir) + + (out, _) = self.copy_file(header, install_dir) + self.outfiles.append(out) + + setup( name='pybind11', version=__version__, @@ -47,6 +64,7 @@ packages=['pybind11'], license='BSD', headers=headers, + cmdclass=dict(install_headers=InstallHeaders), classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', From 21c3eda59cf23defc8efbed91d5b0a5ead65bdb1 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Wed, 23 Aug 2017 16:59:10 +0200 Subject: [PATCH 2/2] Fix missing user dir in `python -m pybind11 --includes` For the case of `pip install --user`, the header include dirs must also include `pybind11.get_include(True)`. [skip appveyor] --- pybind11/__main__.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/pybind11/__main__.py b/pybind11/__main__.py index c3832d7cab..9ef8378029 100644 --- a/pybind11/__main__.py +++ b/pybind11/__main__.py @@ -8,12 +8,18 @@ def print_includes(): - dirs = [sysconfig.get_path('include')] - if sysconfig.get_path('platinclude') not in dirs: - dirs.append(sysconfig.get_path('platinclude')) - if get_include() not in dirs: - dirs.append(get_include()) - print(' '.join('-I' + d for d in dirs)) + dirs = [sysconfig.get_path('include'), + sysconfig.get_path('platinclude'), + get_include(), + get_include(True)] + + # Make unique but preserve order + unique_dirs = [] + for d in dirs: + if d not in unique_dirs: + unique_dirs.append(d) + + print(' '.join('-I' + d for d in unique_dirs)) def main():