python: Fix vpath builds, fix distcheck.

* lang/python/gpgme-h-clean.py: Delete file.
* lang/python/MANIFEST.in: Adapt accordingly.
* lang/python/Makefile.am (EXTRA_DIST): Likewise.
(COPY_FILES_GPG): Bring variable back.
(copystamp): Copy files.
(clean-local): Delete copied files.
(install-exec-local): Do not create and install list of installed
files.
(uninstall-local): Instead, create some explicit rules to uninstall
the extension.
* lang/python/setup.py.in: Parse arguments.  Locate files either in
the source directory, or in the build base directory.  Inline the code
from 'gpgme-h-clean.py'.  Copy 'helpers.c', add source directory as
include directory.

Fixes-commit: 801d7d8c5d
Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2017-04-03 15:44:14 +02:00
parent 801d7d8c5d
commit e7d9c0c3d7
No known key found for this signature in database
GPG Key ID: DD1A52F9DA8C9020
4 changed files with 92 additions and 75 deletions

View File

@ -1,4 +1,4 @@
recursive-include examples *.py recursive-include examples *.py
include gpgme-h-clean.py gpgme.i include gpgme.i
include helpers.c helpers.h private.h include helpers.c helpers.h private.h
recursive-include gpg *.py recursive-include gpg *.py

View File

@ -21,12 +21,20 @@ EXTRA_DIST = \
MANIFEST.in \ MANIFEST.in \
gpgme.i \ gpgme.i \
helpers.c helpers.h private.h \ helpers.c helpers.h private.h \
gpgme-h-clean.py \
examples \ examples \
gpg gpg
SUBDIRS = . tests SUBDIRS = . tests
COPY_FILES_GPG = \
$(srcdir)/gpg/callbacks.py \
$(srcdir)/gpg/constants \
$(srcdir)/gpg/core.py \
$(srcdir)/gpg/errors.py \
$(srcdir)/gpg/__init__.py \
$(srcdir)/gpg/results.py \
$(srcdir)/gpg/util.py
.PHONY: prepare .PHONY: prepare
prepare: copystamp prepare: copystamp
@ -35,12 +43,14 @@ prepare: copystamp
copystamp: copystamp:
ln -sf "$(abs_top_srcdir)/src/data.h" . ln -sf "$(abs_top_srcdir)/src/data.h" .
ln -sf "$(abs_top_builddir)/config.h" . ln -sf "$(abs_top_builddir)/config.h" .
if test $(srcdir) != . ; then cp -R $(COPY_FILES_GPG) gpg ; fi
touch $@ touch $@
all-local: copystamp all-local: copystamp
set -e ; set $(PYTHONS); for VERSION in $(PYTHON_VERSIONS); do \ set -e ; set $(PYTHONS); for VERSION in $(PYTHON_VERSIONS); do \
PYTHON="$$1" ; shift ; \ PYTHON="$$1" ; shift ; \
CFLAGS="$(CFLAGS)" \ CFLAGS="$(CFLAGS)" \
srcdir="$(srcdir)" \
abs_top_builddir="$(abs_top_builddir)" \ abs_top_builddir="$(abs_top_builddir)" \
$$PYTHON setup.py build --verbose --build-base=python$${VERSION}-gpg ; \ $$PYTHON setup.py build --verbose --build-base=python$${VERSION}-gpg ; \
done done
@ -48,6 +58,7 @@ all-local: copystamp
python$(PYTHON_VERSION)-gpg/dist/gpg-$(VERSION).tar.gz.asc: copystamp python$(PYTHON_VERSION)-gpg/dist/gpg-$(VERSION).tar.gz.asc: copystamp
$(MKDIR_P) python$(PYTHON_VERSION)-gpg-dist $(MKDIR_P) python$(PYTHON_VERSION)-gpg-dist
CFLAGS="$(CFLAGS)" \ CFLAGS="$(CFLAGS)" \
srcdir="$(srcdir)" \
abs_top_builddir="$(abs_top_builddir)" \ abs_top_builddir="$(abs_top_builddir)" \
$(PYTHON) setup.py sdist --verbose --dist-dir=python$(PYTHON_VERSION)-gpg-dist \ $(PYTHON) setup.py sdist --verbose --dist-dir=python$(PYTHON_VERSION)-gpg-dist \
--manifest=python$(PYTHON_VERSION)-gpg-dist/MANIFEST --manifest=python$(PYTHON_VERSION)-gpg-dist/MANIFEST
@ -73,6 +84,12 @@ CLEANFILES = copystamp \
# permissions. # permissions.
clean-local: clean-local:
rm -rf -- build rm -rf -- build
if test $(srcdir) != . ; then \
find gpg -type d ! -perm -200 -exec chmod u+w {} ';' ; \
for FILE in $(COPY_FILES_GPG); do \
rm -rf -- gpg/$$(basename $$FILE) ; \
done \
fi
for VERSION in $(PYTHON_VERSIONS); do \ for VERSION in $(PYTHON_VERSIONS); do \
find python$${VERSION}-gpg -type d ! -perm -200 -exec chmod u+w {} ';' ; \ find python$${VERSION}-gpg -type d ! -perm -200 -exec chmod u+w {} ';' ; \
rm -rf -- python$${VERSION}-gpg ; \ rm -rf -- python$${VERSION}-gpg ; \
@ -81,20 +98,18 @@ clean-local:
install-exec-local: install-exec-local:
set -e ; set $(PYTHONS); for VERSION in $(PYTHON_VERSIONS); do \ set -e ; set $(PYTHONS); for VERSION in $(PYTHON_VERSIONS); do \
PYTHON="$$1" ; shift ; \ PYTHON="$$1" ; shift ; \
srcdir="$(srcdir)" \
abs_top_builddir="$(abs_top_builddir)" \ abs_top_builddir="$(abs_top_builddir)" \
$$PYTHON setup.py \ $$PYTHON setup.py \
build \ build \
--build-base=python$${VERSION}-gpg \ --build-base=python$${VERSION}-gpg \
install \ install \
--prefix "$(DESTDIR)$(prefix)" \ --prefix "$(DESTDIR)$(prefix)" \
--record files.txt \
--verbose ; \ --verbose ; \
cat files.txt >> install_files.txt ; \
rm files.txt ; \
done done
$(MKDIR_P) "$(DESTDIR)$(pythondir)/gpg"
mv install_files.txt "$(DESTDIR)$(pythondir)/gpg"
uninstall-local: uninstall-local:
xargs < "$(DESTDIR)$(pythondir)/gpg/install_files.txt" -- rm -rf -- GV=$$(echo $(VERSION) | tr - _); for PV in $(PYTHON_VERSIONS); do \
rm -rf -- "$(DESTDIR)$(pythondir)/gpg" rm -rf -- "$(DESTDIR)$(prefix)/lib/python$$PV/site-packages/gpg" \
"$(DESTDIR)$(prefix)/lib/python$$PV/site-packages/gpg-$$GV-py$$PV.egg-info" ; \
done

View File

@ -1,53 +0,0 @@
#!/usr/bin/env python
# Copyright (C) 2016 g10 Code GmbH
# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from __future__ import absolute_import, print_function, unicode_literals
del absolute_import, print_function, unicode_literals
import sys, re
if len(sys.argv) != 2:
sys.stderr.write("Usage: %s path/to/[gpgme|gpg-error].h\n" % sys.argv[0])
sys.exit(1)
deprec_func = re.compile(r'^(.*typedef.*|.*\(.*\)|[^#]+\s+.+)'
+ r'\s*_GPGME_DEPRECATED(_OUTSIDE_GPGME)?\(.*\);\s*',
re.S)
line_break = re.compile(';|\\$|\\x0c|^\s*#|{');
if 'gpgme.h' in sys.argv[1]:
gpgme = open(sys.argv[1])
tmp = gpgme.readline()
text = ''
while tmp:
text += re.sub(' class ', ' _py_obsolete_class ', tmp)
if line_break.search(tmp):
if not deprec_func.search(text):
sys.stdout.write(text)
text = ''
tmp = gpgme.readline()
sys.stdout.write(text)
gpgme.close()
else:
filter_re = re.compile(r'GPG_ERR_[^ ]* =')
rewrite_re = re.compile(r' *(.*) = .*')
for line in open(sys.argv[1]):
if not filter_re.search(line):
continue
print(rewrite_re.sub(r'%constant long \1 = \1;', line.strip()))

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (C) 2016 g10 Code GmbH # Copyright (C) 2016-2017 g10 Code GmbH
# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> # Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
@ -19,11 +19,18 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from distutils.core import setup, Extension from distutils.core import setup, Extension
import argparse
import os, os.path, sys import os, os.path, sys
import glob import glob
import re
import shutil import shutil
import subprocess import subprocess
# We parse a subset of the arguments.
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--build-base', default='')
options, _ = parser.parse_known_args()
# Out-of-tree build of the gpg bindings. # Out-of-tree build of the gpg bindings.
gpg_error_config = ["gpg-error-config"] gpg_error_config = ["gpg-error-config"]
gpgme_config_flags = ["--thread=pthread"] gpgme_config_flags = ["--thread=pthread"]
@ -31,6 +38,7 @@ gpgme_config = ["gpgme-config"] + gpgme_config_flags
gpgme_h = "" gpgme_h = ""
include_dirs = [os.getcwd()] include_dirs = [os.getcwd()]
library_dirs = [] library_dirs = []
vpath_build = os.environ.get('srcdir', '.') != '.'
in_tree = False in_tree = False
extra_swig_opts = [] extra_swig_opts = []
extra_macros = dict() extra_macros = dict()
@ -133,6 +141,14 @@ if uname_s.startswith("MINGW32"):
library_dirs.append(os.path.join(tgt, item)) library_dirs.append(os.path.join(tgt, item))
break break
def in_srcdir(name):
return os.path.join(os.environ.get("srcdir", ""), name)
def in_build_base(name):
return os.path.join(options.build_base, name)
def up_to_date(source, target):
return (os.path.exists(target)
and os.path.getmtime(source) <= os.path.getmtime(target))
# We build an Extension using SWIG, which generates a Python module. # We build an Extension using SWIG, which generates a Python module.
# By default, the 'build_py' step is run before 'build_ext', and # By default, the 'build_py' step is run before 'build_ext', and
# therefore the generated Python module is not copied into the build # therefore the generated Python module is not copied into the build
@ -143,25 +159,60 @@ if uname_s.startswith("MINGW32"):
from distutils.command.build import build from distutils.command.build import build
class BuildExtFirstHack(build): class BuildExtFirstHack(build):
def _generate_gpgme_h(self, source_name, sink_name):
if up_to_date(source_name, sink_name):
return
deprec_func = re.compile(r'^(.*typedef.*|.*\(.*\)|[^#]+\s+.+)'
+ r'\s*_GPGME_DEPRECATED(_OUTSIDE_GPGME)?\(.*\);\s*',
re.S)
line_break = re.compile(';|\\$|\\x0c|^\s*#|{')
with open(sink_name, "w") as sink, open(source_name) as source:
text = ''
for line in source:
text += re.sub(' class ', ' _py_obsolete_class ', line)
if line_break.search(line):
if not deprec_func.search(text):
sink.write(text)
text = ''
sink.write(text)
def _generate_errors_i(self, source_name, sink_name):
if up_to_date(source_name, sink_name):
return
filter_re = re.compile(r'GPG_ERR_[^ ]* =')
rewrite_re = re.compile(r' *(.*) = .*')
with open(sink_name, "w") as sink, open(source_name) as source:
for line in source:
if not filter_re.search(line):
continue
sink.write(rewrite_re.sub(r'%constant long \1 = \1;'+'\n', line.strip()))
def _generate(self): def _generate(self):
print("Building python gpg module using {} and {}.".format(gpgme_h, gpg_error_h)) print("Building python gpg module using {} and {}.".format(gpgme_h, gpg_error_h))
# Cleanup gpgme.h from deprecated functions and typedefs. # Cleanup gpgme.h from deprecated functions and typedefs.
# Keep timestamp to avoid rebuild
if not os.path.exists(self.build_base): if not os.path.exists(self.build_base):
os.makedirs(self.build_base) os.makedirs(self.build_base)
for src, dst in ( self._generate_gpgme_h(gpgme_h, in_build_base("gpgme.h"))
(gpgme_h, os.path.join(self.build_base, "gpgme.h")), self._generate_errors_i(gpg_error_h, in_build_base("errors.i"))
(gpg_error_h, os.path.join(self.build_base, "errors.i"))
): # Keep timestamp to avoid rebuild
subprocess.check_call([sys.executable, "gpgme-h-clean.py", src], for source, target in ((gpgme_h, in_build_base("gpgme.h")),
stdout=open(dst, "w")) (gpg_error_h, in_build_base("errors.i"))):
shutil.copystat(src, dst) if not up_to_date(source, target):
shutil.copystat(source, target)
# Copy due to http://bugs.python.org/issue2624 # Copy due to http://bugs.python.org/issue2624
# Avoid creating in srcdir # Avoid creating in srcdir
shutil.copy2("gpgme.i", self.build_base) for source, target in ((in_srcdir(n), in_build_base(n))
for n in ('gpgme.i', 'helpers.c')):
if not up_to_date(source, target):
shutil.copy2(source, target)
def run(self): def run(self):
self._generate() self._generate()
@ -171,14 +222,18 @@ class BuildExtFirstHack(build):
os.makedirs(os.path.join(self.build_lib, "gpg")) os.makedirs(os.path.join(self.build_lib, "gpg"))
swig_sources.append(os.path.join(self.build_base, 'gpgme.i')) swig_sources.append(os.path.join(self.build_base, 'gpgme.i'))
swig_opts.extend(['-I' + self.build_base, '-outdir', os.path.join(self.build_lib, 'gpg')]) swig_opts.extend(['-I' + self.build_base,
'-I' + in_srcdir('.'),
'-outdir', os.path.join(self.build_lib, 'gpg')])
if vpath_build:
include_dirs.append(in_srcdir('.'))
include_dirs.append(self.build_base) include_dirs.append(self.build_base)
self.run_command('build_ext') self.run_command('build_ext')
build.run(self) build.run(self)
py3 = [] if sys.version_info.major < 3 else ['-py3'] py3 = [] if sys.version_info.major < 3 else ['-py3']
swig_sources = ['helpers.c'] swig_sources = [in_build_base('helpers.c')]
swig_opts = ['-threads'] + py3 + extra_swig_opts swig_opts = ['-threads'] + py3 + extra_swig_opts
swige = Extension("gpg._gpgme", swige = Extension("gpg._gpgme",
sources = swig_sources, sources = swig_sources,