Browse Source

Complete overhaul of setup.py, README.md build and install instructions

- now works for linux, mac, (win to be tested)
- Removed a lot of unnecessary code and complexity
- Added logging
master
heck 5 years ago
parent
commit
d409cfacb5
  1. 42
      README.md
  2. 398
      setup.py

42
README.md

@ -1,11 +1,41 @@
There's a setup.py in pEpPythonAdapter/ # pEpPythonAdapter
In Python we've setup tools, so it's: ## Build Insttructions
python3 setup.py build These build instructions should work on:
python3 setup.py install * Linux
* MacOS
* Windows
### Build
To build against system wide pEp installation (libs/includes)
```bash
python3 setup.py build_ext
```
To build against a pEp installation in your home dir (libs/includes):
```bash
python3 setup.py build_ext --local
```
That is a Python concept. You can find more about it here: To build against a pEp installation in a custom installation root (libs/includes)
```bash
python3 setup.py build_ext --prefix=<path_to_your_install_root>
```
### Install
To install the extension module system wide, as root, run:
```bash
python3 setup.py install
```
https://docs.python.org/3/extending/building.html#building-c-and-c-extensions-with-distutils To install the extension module into you home dir
```bash
python3 setup.py install --user
```
To install the extension module into a custom destination
```bash
python3 setup.py install --prefix=<custom_destination_root>
```

398
setup.py

@ -1,284 +1,236 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# This file is under GNU Affero General Public License 3.0 # This file is under GNU Affero General Public License 3.0
# see LICENSE.txt # see LICENSE.txt
#
# For more debugging, export DISTUTILS_DEBUG=True
from __future__ import print_function from __future__ import print_function
import sys import sys
from sys import argv
import os import os
from os import environ from os import environ
from os.path import dirname, exists, join from os.path import join
import platform
from setuptools import setup, Extension from setuptools import setup, Extension
from glob import glob from glob import glob
import sysconfig
if sys.platform == 'winnt':
if sys.version_info[0] >= 3:
import winreg
else:
import _winreg as winreg
from setuptools.command.build_ext import build_ext from setuptools.command.build_ext import build_ext
verboseLevel = 0
if sys.version_info[0] < 3: def pEpLog(*msg):
FileNotFoundError = EnvironmentError if verboseLevel > 0:
import inspect
def find(fname, pathlist): msgstr = ''
for path in pathlist: separator = ' '
cand_fname = join(path, fname) for m in msg:
if exists(cand_fname): msgstr += str(m)
return path msgstr += separator
raise FileNotFoundError(fname) func = inspect.currentframe().f_back.f_code
print(func.co_filename + " : " + func.co_name + " : " + msgstr)
def append_once(lst, element):
if element not in lst:
lst.append(element)
def extend_once(lst, elements):
for element in elements:
if element not in lst:
lst.append(element)
def getPythonLibver():
g = sysconfig.get_config_vars()
sent = []
for template in (
'{cmd}{py_version_nodot}{abiflags}',
'{cmd}{py_version_nodot}',
'{cmd}{py_version_major}',
'{cmd}{py_version_major}{abiflags}',
'{cmd}'
):
val = template.format(
cmd = g['PYTHON'],
py_version_nodot = g['py_version_nodot'],
py_version_major = sys.version_info[0],
abiflags = g.get('ABIFLAGS', ''),
)
if val not in sent:
yield val
sent.append(val)
class BuildExtCommand(build_ext): class BuildExtCommand(build_ext):
# default_pyver = next( getPythonLibver() )
user_options = build_ext.user_options + [ user_options = build_ext.user_options + [
# ('boost-python=', None, 'Boost Python version to use (e.g. \'python34\')'), ('local', None, 'Use local pEp install in HOME/USERPROFILE for libs/includes'),
('local', None, 'Use local pEp install in HOME/USERPROFILE'), ('prefix=', None, 'Use local pEp install in prefix for libs/includes'),
('with-pEp-engine=', None, 'Path to pEp Engine source'),
('with-pEp-libadapter=', None, 'Path to pEp C++ Adapter Library source'),
('with-boost=', None, 'Path to Boost install prefix'),
('with-asn1c-share=', None, 'Path to installed ASN1C share directory'),
] ]
def windowsGetInstallLocation(): def initialize_options(self):
pEpLog("called")
build_ext.initialize_options(self)
self.local = None != environ.get('PER_USER_DIRECTORY')
self.prefix = getattr(self, "prefix=", None)
def windowsGetInstallLocation(self):
pEpLog("called")
# Note: should be installed to 'C:\Program Files (x86)' while a 32-bit distro # Note: should be installed to 'C:\Program Files (x86)' while a 32-bit distro
# TODO: Try desktop adapter location first, then COM server # TODO: Try desktop adapter location first, then COM server
# FIXME: This is wrong, we should chase the COM server, not the Outlook Plugin (even if they're in the same place) # FIXME: This is wrong, we should chase the COM server, not the Outlook Plugin (even if they're in the same place)
REG_PATH = "Software\\Microsoft\\Office\\Outlook\\Addins\\pEp" reg_path = "Software\\Microsoft\\Office\\Outlook\\Addins\\pEp"
KeyName = 'FileName'
regKey = None regKey = None
pEpLog("Registry Lookup:", reg_path, KeyName)
try: try:
regKey = winreg.OpenKey( regKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path, 0, winreg.KEY_READ)
winreg.HKEY_LOCAL_MACHINE, REG_PATH, 0, winreg.KEY_READ)
# Keys: Description, FileName, FriendlyName, LoadBehavior # Keys: Description, FileName, FriendlyName, LoadBehavior
com_server, regtype = winreg.QueryValueEx(regKey, 'FileName') com_server, regtype = winreg.QueryValueEx(regKey, KeyName)
winreg.CloseKey(regKey) winreg.CloseKey(regKey)
except WindowsError: except WindowsError:
pEpLog("Unknown Error")
com_server = None com_server = None
finally: finally:
if winreg: if winreg:
winreg.CloseKey(regKey) winreg.CloseKey(regKey)
# <install-base>\\bin\\COM_Server.exe # <install-base>\\bin\\COM_Server.exe
dirname = os.path.dirname dirname = os.path.dirname
return dirname( dirname( com_server ) ) ret = dirname(dirname(com_server))
pEpLog("Value:", ret)
def initialize_options(self): return ret
build_ext.initialize_options(self)
# self.boost_python = BuildExtCommand.default_pyver def get_build_info_winnt(self):
self.local = None != environ.get('PER_USER_DIRECTORY') home = environ.get('PER_USER_DIRECTORY') or environ.get('USERPROFILE')
self.with_pEp_engine = None sys_root = environ.get('SystemRoot')
self.with_pEp_libadapter = None profile_root = environ.get('AppData')
self.with_boost = None local_root = environ.get('LocalAppData')
self.with_asn1c_share = None inst_prefix = self.windowsGetInstallLocation()
sys_includes = [
join(inst_prefix, 'include'),
join(profile_root, 'pEp', 'include'),
join(local_root, 'pEp', 'include'),
join(sys_root, 'pEp', 'include'),
]
sys_libdirs = [
join(inst_prefix, 'bin'),
join(profile_root, 'pEp', 'bin'),
join(local_root, 'pEp', 'bin'),
join(sys_root, 'pEp', 'bin'),
]
libs = [
'pEpEngine',
'boost_python37-mt',
'boost_locale-mt'
]
return (home, sys_includes, sys_libdirs, libs)
def get_build_info_darwin(self):
home = environ.get('PER_USER_DIRECTORY') or environ.get('HOME')
sys_includes = [
'/opt/local/include',
'/usr/local/include',
'/Library/Frameworks/PrettyEasyPrivacy.framework/Versions/A/include',
'/usr/include',
]
sys_libdirs = [
'/opt/local/lib',
'/usr/local/lib',
'/Library/Frameworks/PrettyEasyPrivacy.framework/Versions/A/lib',
'/usr/lib',
]
libs = [
'pEpEngine',
'boost_python37-mt',
'boost_locale-mt'
]
return (home, sys_includes, sys_libdirs, libs)
def get_build_info_linux(self):
home = environ.get('PER_USER_DIRECTORY') or environ.get('HOME')
sys_includes = [
'/usr/local/include',
'/usr/include',
]
sys_libdirs = [
'/usr/local/lib',
'/usr/lib',
'/usr/lib/{}-linux-gnu'.format(platform.machine())
]
libs = [
'pEpEngine',
'boost_python3',
'boost_locale'
]
return (home, sys_includes, sys_libdirs, libs)
def finalize_options(self): def finalize_options(self):
pEpLog("called")
build_ext.finalize_options(self) build_ext.finalize_options(self)
# normalize paths given by user (expand tilde etc.) pEpLog("verbose: ", self.verbose)
for with_option in ('pEp_engine', 'pEp_libadapter', 'boost', 'asn1c_share'): pEpLog("local: ", self.local)
w_opt = 'with_' + with_option pEpLog("prefix: ", self.prefix)
w_val = getattr(self, w_opt) pEpLog("sys.platform: ", sys.platform)
if w_val != None:
setattr(self, w_opt, os.path.normpath(w_val)) global verboseLevel
verboseLevel = self.verbose
if sys.platform == 'darwin':
HOME = environ.get('PER_USER_DIRECTORY') or environ.get('HOME') # get build information for platform
PEPLIBNAME = 'libpEpEngine.dylib' if sys.platform == 'winnt':
LIBPEPA = 'libpEpAdapter.a' build_info = self.get_build_info_winnt()
BOOSTLIBNAME = 'libboost_{boost_python:s}-mt.dylib' elif sys.platform == 'darwin':
SYS_INCLUDES = [ build_info = self.get_build_info_darwin()
'/opt/local/include', # we prefer MacPorts over Homebrew (but support both) elif sys.platform == 'linux':
'/usr/local/include', build_info = self.get_build_info_linux()
'/Library/Frameworks/PrettyEasyPrivacy.framework/Versions/A/include',
join(environ["HOME"], 'include'),
'/usr/include',
]
SYS_SHARES = [
'/opt/local/share',
'/usr/local/share',
'/Library/Frameworks/PrettyEasyPrivacy.framework/Versions/A/share',
join(environ["HOME"], 'share'),
'/usr/share',
]
SYS_LIB_PREFIXES = [
'/opt/local/lib',
'/usr/local/lib',
'/Library/Frameworks/PrettyEasyPrivacy.framework/Versions/A/lib',
join(environ["HOME"], 'lib'),
'/usr/lib',
]
elif sys.platform == 'winnt':
HOME = environ.get('PER_USER_DIRECTORY') or environ.get('USERPROFILE')
SYS_ROOT = environ.get('SystemRoot')
PROFILE_ROOT = environ.get('AppData')
LOCAL_ROOT = environ.get('LocalAppData')
INST_PREFIX = windowsGetInstallLocation()
PEPLIBNAME = 'pEpEngine.dll'
LIBPEPA = 'libpEpAdapter.a'
BOOSTLIBNAME = 'boost_{boost_python:s}-mt.dll'
SYS_INCLUDES = [
join(INST_PREFIX, 'include'),
join(PROFILE_ROOT, 'pEp', 'include'),
join(LOCAL_ROOT, 'pEp', 'include'),
join(SYS_ROOT, 'pEp', 'include'),
]
SYS_SHARES = [
join(INST_PREFIX, 'share'),
join(PROFILE_ROOT, 'pEp', 'share'),
join(LOCAL_ROOT, 'pEp', 'share'),
join(SYS_ROOT, 'pEp', 'share'),
]
SYS_LIB_PREFIXES = [
join(INST_PREFIX, 'bin'),
join(PROFILE_ROOT, 'pEp', 'bin'),
join(LOCAL_ROOT, 'pEp', 'bin'),
join(SYS_ROOT, 'pEp', 'bin'),
]
else: else:
HOME = environ.get('PER_USER_DIRECTORY') or environ.get('HOME') pEpLog("Platform not supported:" + sys.platform)
PEPLIBNAME = 'pEpEngine.so' exit()
LIBPEPA = 'libpEpAdapter.a'
BOOSTLIBNAME = 'boost_{boost_python:s}-mt.so' (home, sys_includes, sys_libdirs, libs) = build_info
SYS_INCLUDES = ['/usr/local/pEp/include', '/usr/local/include', '/usr/include']
SYS_SHARES = ['/usr/local/pEp/share', '/usr/local/share', '/usr/share'] # Build the Includes -I and Library paths -L
SYS_LIB_PREFIXES = ['/usr/local/pEp/bin', '/usr/local/bin', '/usr/bin'] # Start empty
includes = []
use_local_incl = (self.local or os.path.isfile( libdirs = []
join(HOME, 'include', 'pEp', 'pEpEngine.h')) )
use_local_lib = (self.local or os.path.isfile( # Append home-dir
join(HOME, 'lib', PEPLIBNAME)) ) if self.local:
pEpLog("local mode")
INCLUDES = [ join(HOME, 'include') ] if use_local_incl else [] home_include=[ join(home, 'include') ]
INCLUDES.extend(SYS_INCLUDES) home_libdirs=[ join(home, 'lib') ]
SHARES = [ join(HOME, 'share') ] if use_local_incl else [] includes += home_include
SHARES.extend(SYS_SHARES) libdirs += home_libdirs
LIBS = [ join(HOME, 'lib') ] if use_local_lib else []
LIBS.extend(SYS_LIB_PREFIXES) # Append prefix-dir
if self.prefix:
if not self.with_pEp_engine: pEpLog("using prefix=",self.prefix)
ENGINE_INC = find( join('pEp', 'pEpEngine.h'), INCLUDES ) prefix_include=[ join(self.prefix, 'include') ]
ENGINE_LIB = find( PEPLIBNAME, LIBS ) prefix_libdirs=[ join(self.prefix, 'lib') ]
else: includes += prefix_include
if exists( join(self.with_pEp_engine, 'include', 'pEp') ): libdirs += prefix_libdirs
ENGINE_INC = find( join('pEp', 'pEpEngine.h'), (join(self.with_pEp_engine, 'include'),) )
ENGINE_LIB = find( PEPLIBNAME, (join(self.with_pEp_engine, 'lib'),) ) # Append default system dirs
else: includes += sys_includes
ENGINE_INC = find( 'pEpEngine.h', (join(self.with_pEp_engine, 'src'),) ) libdirs += sys_libdirs
ENGINE_LIB = find( PEPLIBNAME, (join(self.with_pEp_engine, 'src'),) )
# Compile flags
if not self.with_pEp_libadapter: compile_flags = ['-std=c++14']
LIBPEPA_INC = find( join('pEp', 'Adapter.hh'), INCLUDES ) if self.debug:
LIBPEPA_LIB = find( LIBPEPA, LIBS ) pEpLog("debug mode")
else: compile_flags += ['-O0', '-g', '-UNDEBUG']
if exists( join(self.with_pEp_libadapter, 'include', 'pEp') ):
LIBPEPA_INC = find( join('pEp', 'Adapter.hh'), (join(self.with_pEp_libadapter, 'include'),) )
LIBPEPA_LIB = find( LIBPEPA, (join(self.with_pEp_libadapter, 'lib'),) )
else:
LIBPEPA_INC = find( 'Adapter.hh', (join(self.with_pEp_libadapter, 'src'),) )
LIBPEPA_LIB = find( LIBPEPA, (join(self.with_pEp_libadapter, 'src'),) )
if not self.with_boost:
BOOST_INC = find( join('boost', 'system', 'config.hpp'), INCLUDES )
BOOST_LIB = None
e_ = None
for py in getPythonLibver():
f = BOOSTLIBNAME.format(boost_python=py)
try:
BOOST_LIB = find( f, LIBS )
break
except Exception as e:
if self.verbose:
print("Not found: " + f)
e_ = e if e_ is None else e_
if BOOST_LIB is None:
raise e_
else:
raise NotImplementedError("Building from Boost source not implemented yet") # FIXME
# BOOST_INC = find( join('boost', 'system', 'config.hpp'), (self.with_boost,) )
# BOOST_LIB = find( BOOSTLIBNAME, (self.with_boost,) )
if not self.with_asn1c_share:
ASN1C_INC = find( join('asn1c', 'asn_system.h'), SHARES )
else:
ASN1C_INC = find( join('asn1c', 'asn_system.h'), (self.with_asn1c_share,) )
if self.verbose:
print('ENGINE_INC=%s' % ENGINE_INC)
print('ENGINE_LIB=%s' % ENGINE_LIB)
print('LIBPEPA_INC=%s' % LIBPEPA_INC)
print('LIBPEPA_LIB=%s' % LIBPEPA_LIB)
print('BOOST_INC=%s' % BOOST_INC)
print('BOOST_LIB=%s' % BOOST_LIB)
print('ASN1C_INC=%s' % ASN1C_INC)
# Apply the build information
global module_pEp global module_pEp
extend_once( module_pEp.include_dirs, [ENGINE_INC, LIBPEPA_INC, BOOST_INC, ASN1C_INC] ) module_pEp.include_dirs = includes
extend_once( module_pEp.library_dirs, [ENGINE_LIB, LIBPEPA_LIB, BOOST_LIB] ) module_pEp.library_dirs = libdirs
extend_once( module_pEp.libraries, ['pEpEngine', 'boost_python37-mt', 'boost_locale-mt'] ) module_pEp.libraries = libs
module_pEp.extra_compile_args = compile_flags
if self.debug: pEpLog("Include Dirs:", module_pEp.include_dirs)
module_pEp.extra_compile_args = ['-O0', '-g', '-UNDEBUG', '-std=c++14'] pEpLog("Libs Dirs:", module_pEp.library_dirs)
else: pEpLog("Libraries:", module_pEp.libraries)
module_pEp.extra_compile_args = ['-std=c++14'] # FIXME pEpLog("Compile flags:", module_pEp.extra_compile_args)
def run(self): def run(self):
build_ext.run(self) build_ext.run(self)
# module_pEp global is referenced in BuildExtCommand if sys.platform == 'winnt':
module_pEp = Extension('pEp', if sys.version_info[0] >= 3:
sources = glob('src/*.cc'), import winreg
libraries = ['pEpEngine'], else:
# extra_compile_args = compile_args, import _winreg as winreg
# include_dirs = [ENGINE_INC, BOOST_INC, ASN1C_INC],
# library_dirs = [ENGINE_LIB, BOOST_LIB],
)
if sys.version_info[0] < 3:
FileNotFoundError = EnvironmentError
module_pEp = Extension(
'pEp',
sources = glob('src/*.cc'),
)
# "MAIN" Function
setup( setup(
name='pEp', name='pEp',
version='2.0', version='2.0',
description='p≡p for Python', description='p≡p for Python',
author="Volker Birk", author="Volker Birk",
author_email="vb@pep-project.org", author_email="vb@pep-project.org",
ext_modules=[module_pEp,], maintainer="Heck",
maintainer_email="heck@pep.foundation",
ext_modules=[module_pEp],
cmdclass={ cmdclass={
'build_ext': BuildExtCommand, 'build_ext': BuildExtCommand,
}, },

Loading…
Cancel
Save