459 lines
17 KiB
Python
Executable File
459 lines
17 KiB
Python
Executable File
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
|
|
import os
|
|
import sys
|
|
import platform
|
|
import subprocess
|
|
from distutils.core import setup, Command
|
|
from distutils.extension import Extension
|
|
from distutils.command.build_ext import build_ext
|
|
from distutils.version import StrictVersion, LooseVersion
|
|
from efl import __version__, __version_info__ as vers
|
|
|
|
script_path = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
# python-efl version (change in efl/__init__.py)
|
|
RELEASE = __version__
|
|
VERSION = "%d.%d" % (vers[0], vers[1] if vers[2] < 99 else vers[1] + 1)
|
|
|
|
# dependencies
|
|
CYTHON_MIN_VERSION = "0.21"
|
|
# CYTHON_BLACKLIST = ("0.21.1", "0.21.2") # only used if py3
|
|
EFL_MIN_VER = RELEASE
|
|
ELM_MIN_VER = RELEASE
|
|
|
|
# Add git commit count for dev builds
|
|
if vers[2] == 99:
|
|
try:
|
|
call = subprocess.Popen(["git", "rev-list", "--count", "HEAD"],
|
|
stdout=subprocess.PIPE)
|
|
out, err = call.communicate()
|
|
count = out.decode("utf-8").strip()
|
|
RELEASE += "a" + count
|
|
except Exception:
|
|
RELEASE += "a0"
|
|
|
|
|
|
# XXX: Force default visibility. See phab T504
|
|
if os.getenv("CFLAGS") is not None and "-fvisibility=" in os.environ["CFLAGS"]:
|
|
os.environ["CFLAGS"] += " -fvisibility=default"
|
|
|
|
|
|
# === Sphinx ===
|
|
try:
|
|
from sphinx.setup_command import BuildDoc
|
|
except ImportError:
|
|
class BuildDoc(Command):
|
|
description = "build docs using sphinx, that must be installed."
|
|
version = ""
|
|
release = ""
|
|
user_options = []
|
|
|
|
def initialize_options(self):
|
|
pass
|
|
|
|
def finalize_options(self):
|
|
pass
|
|
|
|
def run(self):
|
|
print("Error: sphinx not found")
|
|
|
|
|
|
# === pkg-config ===
|
|
def pkg_config(name, require, min_vers=None):
|
|
try:
|
|
sys.stdout.write("Checking for " + name + ": ")
|
|
|
|
call = subprocess.Popen(["pkg-config", "--modversion", require],
|
|
stdout=subprocess.PIPE)
|
|
out, err = call.communicate()
|
|
ver = out.decode("utf-8").strip()
|
|
|
|
if min_vers is not None:
|
|
assert (LooseVersion(ver) >= LooseVersion(min_vers)) is True
|
|
|
|
call = subprocess.Popen(["pkg-config", "--cflags", require],
|
|
stdout=subprocess.PIPE)
|
|
out, err = call.communicate()
|
|
cflags = out.decode("utf-8").split()
|
|
|
|
call = subprocess.Popen(["pkg-config", "--libs", require],
|
|
stdout=subprocess.PIPE)
|
|
out, err = call.communicate()
|
|
libs = out.decode("utf-8").split()
|
|
|
|
sys.stdout.write("OK, found " + ver + "\n")
|
|
|
|
cflags = list(set(cflags))
|
|
|
|
return (cflags, libs)
|
|
except (OSError, subprocess.CalledProcessError):
|
|
raise SystemExit("Did not find " + name + " with 'pkg-config'.")
|
|
except (AssertionError):
|
|
raise SystemExit("%s version mismatch. Found: %s Needed %s" % (
|
|
name, ver, min_vers))
|
|
|
|
|
|
# === setup.py clean_generated_files command ===
|
|
class CleanGenerated(Command):
|
|
description = "Clean C and html files generated by Cython"
|
|
user_options = []
|
|
|
|
def initialize_options(self):
|
|
pass
|
|
|
|
def finalize_options(self):
|
|
pass
|
|
|
|
def run(self):
|
|
for lib in ("eo", "evas", "ecore", "ecore_x", "edje", "emotion",
|
|
"elementary", "ethumb", "dbus_mainloop", "utils"):
|
|
lib_path = os.path.join(script_path, "efl", lib)
|
|
for root, dirs, files in os.walk(lib_path):
|
|
for f in files:
|
|
if f.endswith((".c", ".html")) and f != "e_dbus.c":
|
|
self.remove(os.path.join(root, f))
|
|
|
|
def remove(self, fullpath):
|
|
print("removing %s" % fullpath.replace(script_path, "").lstrip('/'))
|
|
os.remove(fullpath)
|
|
|
|
|
|
# === setup.py uninstall command ===
|
|
RECORD_FILE = "installed_files-%d.%d.txt" % sys.version_info[:2]
|
|
class Uninstall(Command):
|
|
description = 'remove all the installed files recorded at installation time'
|
|
user_options = []
|
|
|
|
def initialize_options(self):
|
|
pass
|
|
|
|
def finalize_options(self):
|
|
pass
|
|
|
|
def remove_entry(self, entry):
|
|
if os.path.isfile(entry):
|
|
try:
|
|
print("removing file %s" % entry)
|
|
os.unlink(entry)
|
|
except OSError as e:
|
|
error(e)
|
|
|
|
directory = os.path.dirname(entry)
|
|
while os.listdir(directory) == []:
|
|
try:
|
|
print("removing empty directory %s" % directory)
|
|
os.rmdir(directory)
|
|
except OSError as e:
|
|
error(e)
|
|
directory = os.path.dirname(directory)
|
|
|
|
def run(self):
|
|
if not os.path.exists(RECORD_FILE):
|
|
print('ERROR: No %s file found!' % RECORD_FILE)
|
|
else:
|
|
for entry in open(RECORD_FILE).read().split():
|
|
self.remove_entry(entry)
|
|
|
|
|
|
# === setup.py test command ===
|
|
class Test(Command):
|
|
description = 'Run all the available unit tests using efl in build/'
|
|
user_options = []
|
|
|
|
def initialize_options(self):
|
|
pass
|
|
|
|
def finalize_options(self):
|
|
pass
|
|
|
|
def run(self):
|
|
import unittest
|
|
|
|
sys.path.insert(0, "build/lib.%s-%s-%d.%d" % (
|
|
platform.system().lower(), platform.machine(),
|
|
sys.version_info[0], sys.version_info[1]))
|
|
if "efl" in sys.modules:
|
|
del sys.modules["efl"]
|
|
|
|
loader = unittest.TestLoader()
|
|
suite = loader.discover('./tests')
|
|
runner = unittest.TextTestRunner(verbosity=1, buffer=True)
|
|
result = runner.run(suite)
|
|
|
|
|
|
# === use cython or pre-generated C files ===
|
|
USE_CYTHON = False
|
|
if os.getenv("DISABLE_CYTHON") is not None:
|
|
USE_CYTHON = False
|
|
elif os.getenv("ENABLE_CYTHON") is not None:
|
|
USE_CYTHON = True
|
|
elif not os.path.exists(os.path.join(script_path, "efl/eo/efl.eo.c")):
|
|
USE_CYTHON = True
|
|
elif os.path.exists(os.path.join(script_path, "Makefile")):
|
|
USE_CYTHON = True
|
|
|
|
|
|
ext_modules = []
|
|
py_modules = []
|
|
packages = ["efl"]
|
|
|
|
if set(("build", "build_ext", "install", "bdist", "sdist")) & set(sys.argv):
|
|
sys.stdout.write("Python-EFL: %s\n" % RELEASE)
|
|
|
|
# === Python ===
|
|
sys.stdout.write("Checking for Python: ")
|
|
py_ver = sys.version_info
|
|
py_ver = "%s.%s.%s" % (py_ver[0], py_ver[1], py_ver[2])
|
|
if sys.hexversion < 0x020600f0:
|
|
raise SystemExit("too old. Found: %s Need at least 2.6.0" % py_ver)
|
|
else:
|
|
sys.stdout.write("OK, found %s\n" % py_ver)
|
|
|
|
# === Cython ===
|
|
sys.stdout.write("Checking for Cython: ")
|
|
if USE_CYTHON:
|
|
# check if cython is installed
|
|
try:
|
|
from Cython.Distutils import Extension, build_ext
|
|
from Cython.Build import cythonize
|
|
import Cython.Compiler.Options
|
|
except ImportError:
|
|
raise SystemExit("not found! Needed >= %s" % (CYTHON_MIN_VERSION))
|
|
|
|
# check min version
|
|
if LooseVersion(Cython.__version__) < LooseVersion(CYTHON_MIN_VERSION):
|
|
raise SystemExit("too old! Found %s Needed %s" % (
|
|
Cython.__version__, CYTHON_MIN_VERSION))
|
|
|
|
# Cython PyMethod_New() is broken for py3! blacklisted
|
|
# if sys.version_info[0] > 2 and Cython.__version__ in CYTHON_BLACKLIST:
|
|
# raise SystemExit("found %s, it's broken! Need another release" %
|
|
# Cython.__version__)
|
|
|
|
sys.stdout.write("OK, found %s\n" % Cython.__version__)
|
|
module_suffix = ".pyx"
|
|
# Stop compilation on first error
|
|
Cython.Compiler.Options.fast_fail = True
|
|
# Generates HTML files with annotated source
|
|
Cython.Compiler.Options.annotate = False
|
|
# Set to False to disable docstrings
|
|
Cython.Compiler.Options.docstrings = True
|
|
|
|
else:
|
|
sys.stdout.write("not needed, using pre-generated C files\n")
|
|
module_suffix = ".c"
|
|
|
|
# === Eina ===
|
|
eina_cflags, eina_libs = pkg_config('Eina', 'eina', EFL_MIN_VER)
|
|
|
|
# === Eo ===
|
|
eo_cflags, eo_libs = pkg_config('Eo', 'eo', EFL_MIN_VER)
|
|
eo_ext = Extension("eo", ["efl/eo/efl.eo" + module_suffix],
|
|
define_macros=[
|
|
('EFL_BETA_API_SUPPORT', 1),
|
|
('EFL_EO_API_SUPPORT', 1)
|
|
],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=eo_cflags,
|
|
extra_link_args=eo_libs + eina_libs
|
|
)
|
|
ext_modules.append(eo_ext)
|
|
|
|
# === Utilities ===
|
|
utils_ext = [
|
|
Extension("utils.deprecated", ["efl/utils/deprecated" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=eina_cflags,
|
|
extra_link_args=eina_libs),
|
|
Extension("utils.conversions", ["efl/utils/conversions" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=eo_cflags,
|
|
extra_link_args=eo_libs + eina_libs),
|
|
Extension("utils.logger", ["efl/utils/logger" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=eina_cflags,
|
|
extra_link_args=eina_libs),
|
|
]
|
|
ext_modules.extend(utils_ext)
|
|
py_modules.append("efl.utils.setup")
|
|
packages.append("efl.utils")
|
|
|
|
# === Evas ===
|
|
evas_cflags, evas_libs = pkg_config('Evas', 'evas', EFL_MIN_VER)
|
|
evas_ext = Extension("evas", ["efl/evas/efl.evas" + module_suffix],
|
|
define_macros=[
|
|
('EFL_BETA_API_SUPPORT', 1),
|
|
('EFL_EO_API_SUPPORT', 1)
|
|
],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=evas_cflags,
|
|
extra_link_args=evas_libs + eina_libs + eo_libs)
|
|
ext_modules.append(evas_ext)
|
|
|
|
# === Ecore ===
|
|
ecore_cflags, ecore_libs = pkg_config('Ecore', 'ecore', EFL_MIN_VER)
|
|
ecore_file_cflags, ecore_file_libs = pkg_config('EcoreFile', 'ecore-file',
|
|
EFL_MIN_VER)
|
|
ecore_ext = Extension("ecore", ["efl/ecore/efl.ecore" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=list(set(ecore_cflags +
|
|
ecore_file_cflags)),
|
|
extra_link_args=ecore_libs + ecore_file_libs +
|
|
eina_libs + evas_libs)
|
|
ext_modules.append(ecore_ext)
|
|
|
|
# === Ecore X ===
|
|
try:
|
|
ecore_input_cflags, ecore_input_libs = pkg_config('EcoreInput',
|
|
'ecore-input',
|
|
EFL_MIN_VER)
|
|
ecore_x_cflags, ecore_x_libs = pkg_config('EcoreX', 'ecore-x',
|
|
EFL_MIN_VER)
|
|
except SystemExit:
|
|
pass
|
|
else:
|
|
ecore_x_ext = Extension("ecore_x",
|
|
["efl/ecore_x/efl.ecore_x" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=list(set(ecore_cflags +
|
|
ecore_file_cflags +
|
|
ecore_x_cflags +
|
|
ecore_input_cflags)),
|
|
extra_link_args=ecore_libs + ecore_file_libs +
|
|
ecore_x_libs + ecore_input_libs +
|
|
eina_libs + evas_libs)
|
|
ext_modules.append(ecore_x_ext)
|
|
|
|
# === Ethumb ===
|
|
ethumb_cflags, ethumb_libs = pkg_config('Ethumb', 'ethumb', EFL_MIN_VER)
|
|
ethumb_ext = Extension("ethumb", ["efl/ethumb/efl.ethumb" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=ethumb_cflags,
|
|
extra_link_args=ethumb_libs + eina_libs)
|
|
ext_modules.append(ethumb_ext)
|
|
|
|
ethumb_client_cflags, ethumb_client_libs = pkg_config(
|
|
'Ethumb_Client', 'ethumb_client', EFL_MIN_VER)
|
|
ethumb_client_ext = Extension("ethumb_client",
|
|
["efl/ethumb/efl.ethumb_client" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=ethumb_client_cflags,
|
|
extra_link_args=ethumb_client_libs + eina_libs)
|
|
ext_modules.append(ethumb_client_ext)
|
|
|
|
# === Edje ===
|
|
edje_cflags, edje_libs = pkg_config('Edje', 'edje', EFL_MIN_VER)
|
|
edje_ext = Extension("edje", ["efl/edje/efl.edje" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=edje_cflags,
|
|
extra_link_args=edje_libs + eina_libs + evas_libs)
|
|
ext_modules.append(edje_ext)
|
|
|
|
# === Edje_Edit ===
|
|
edje_edit_ext = Extension("edje_edit",
|
|
["efl/edje/efl.edje_edit" + module_suffix],
|
|
define_macros=[('EDJE_EDIT_IS_UNSTABLE_AND_I_KNOW_ABOUT_IT', None)],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=edje_cflags,
|
|
extra_link_args=edje_libs + eina_libs + evas_libs)
|
|
ext_modules.append(edje_edit_ext)
|
|
|
|
# === Emotion ===
|
|
emotion_cflags, emotion_libs = pkg_config('Emotion', 'emotion', EFL_MIN_VER)
|
|
emotion_ext = Extension("emotion",
|
|
["efl/emotion/efl.emotion" + module_suffix],
|
|
include_dirs=['include/'],
|
|
extra_compile_args=emotion_cflags,
|
|
extra_link_args=emotion_libs +
|
|
eina_libs + evas_libs)
|
|
ext_modules.append(emotion_ext)
|
|
|
|
# === dbus mainloop integration ===
|
|
dbus_cflags, dbus_libs = pkg_config('DBus', 'dbus-python', "0.83.0")
|
|
dbus_ml_ext = Extension("dbus_mainloop",
|
|
["efl/dbus_mainloop/dbus_mainloop" + module_suffix,
|
|
"efl/dbus_mainloop/e_dbus.c"],
|
|
extra_compile_args=list(set(dbus_cflags + ecore_cflags)),
|
|
extra_link_args=dbus_libs + ecore_libs)
|
|
ext_modules.append(dbus_ml_ext)
|
|
|
|
# === Elementary ===
|
|
elm_cflags, elm_libs = pkg_config('Elementary', 'elementary', ELM_MIN_VER)
|
|
e = Extension("elementary.__init__",
|
|
["efl/elementary/__init__" + module_suffix],
|
|
define_macros=[
|
|
('EFL_BETA_API_SUPPORT', 1),
|
|
('EFL_EO_API_SUPPORT', 1)
|
|
],
|
|
include_dirs=["include/"],
|
|
extra_compile_args=elm_cflags,
|
|
extra_link_args=elm_libs + eina_libs + eo_libs + evas_libs)
|
|
ext_modules.append(e)
|
|
|
|
packages.append("efl.elementary")
|
|
|
|
# Cythonize all the external modules (if needed)
|
|
if USE_CYTHON:
|
|
ext_modules = cythonize(ext_modules,
|
|
include_path=["include"],
|
|
compiler_directives={
|
|
#"c_string_type": "unicode",
|
|
#"c_string_encoding": "utf-8",
|
|
"embedsignature": True,
|
|
"binding": True,
|
|
})
|
|
|
|
|
|
setup(
|
|
name="python-efl",
|
|
fullname="Python bindings for Enlightenment Foundation Libraries",
|
|
description="Python bindings for Enlightenment Foundation Libraries",
|
|
long_description=open(os.path.join(script_path, 'README')).read(),
|
|
version=RELEASE,
|
|
author='Davide Andreoli, Kai Huuhko, and others',
|
|
author_email="dave@gurumeditation.it, kai.huuhko@gmail.com",
|
|
contact="Enlightenment developer mailing list",
|
|
contact_email="enlightenment-devel@lists.sourceforge.net",
|
|
url="http://www.enlightenment.org",
|
|
license="GNU Lesser General Public License (LGPL)",
|
|
keywords="efl wrapper binding enlightenment eo evas ecore edje emotion elementary ethumb",
|
|
classifiers=[
|
|
'Development Status :: 5 - Production/Stable',
|
|
'Environment :: X11 Applications',
|
|
'Environment :: Console :: Framebuffer',
|
|
'Intended Audience :: End Users/Desktop',
|
|
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
|
|
'Operating System :: POSIX',
|
|
'Programming Language :: C',
|
|
'Programming Language :: Cython',
|
|
'Programming Language :: Python :: 2',
|
|
'Programming Language :: Python :: 3',
|
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
|
'Topic :: Software Development :: User Interfaces',
|
|
'Topic :: Software Development :: Widget Sets',
|
|
],
|
|
cmdclass={
|
|
'test': Test,
|
|
'build_doc': BuildDoc,
|
|
'clean_generated_files': CleanGenerated,
|
|
'uninstall': Uninstall,
|
|
'build_ext': build_ext,
|
|
},
|
|
command_options={
|
|
'build_doc': {
|
|
'version': ('setup.py', VERSION),
|
|
'release': ('setup.py', RELEASE),
|
|
},
|
|
'install': {
|
|
'record': ('setup.py', RECORD_FILE),
|
|
},
|
|
},
|
|
packages=packages,
|
|
ext_package="efl",
|
|
ext_modules=ext_modules,
|
|
py_modules=py_modules,
|
|
)
|