zbar icon indicating copy to clipboard operation
zbar copied to clipboard

update setup.py for bug fixing

Open wqh17101 opened this issue 4 years ago • 4 comments

we should update setup.py as below to support building .whl

#!/usr/bin/env python
from setuptools import setup
from distutils.extension import Extension

setup(
    name = 'zbar',
    version = '0.23.1',
    author = 'Jeff Brown',
    author_email = '[email protected]',
    url = 'https://github.com/mchehab/zbar',
    description = 'read barcodes from images or video',
    license = 'LGPL',
    long_description = open('README').read(),
    classifiers = [
        'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'Environment :: Console',
        'Environment :: X11 Applications',
        'Environment :: Win32 (MS Windows)',
        'Operating System :: POSIX',
        'Operating System :: Unix',
        'Operating System :: Microsoft :: Windows',
        'Topic :: Communications',
        'Topic :: Multimedia :: Graphics',
        'Topic :: Software Development :: Libraries',
    ],
    ext_modules = [
        Extension('zbar', [
                'zbarmodule.c',
                'enum.c',
                'exception.c',
                'symbol.c',
                'symbolset.c',
                'symboliter.c',
                'image.c',
                'processor.c',
                'imagescanner.c',
                'decoder.c',
                'scanner.c',
                ],
            libraries = [ 'zbar' ],
            include_dirs = ['../include']
        ),
    ],
)

wqh17101 avatar Feb 01 '21 11:02 wqh17101

First i want to build the wheel with libzbar so that we can upload it to pypi and easy to install. Second, using a pythonic way to wrap zbar maybe better such as what pyzbar did.

wqh17101 avatar Feb 03 '21 09:02 wqh17101

for the first thing, we can modify the setup.py like below

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys

from setuptools import Extension
from setuptools import find_packages
from setuptools import setup

CUR_DIR = os.path.realpath(os.path.dirname(__file__))
zbar_init_path = os.path.join(CUR_DIR, "zbar_init")
SYS_MAP = {"msys": ["msys-zbar", ".dll"],
           "win32": ["libzbar", ".dll"],
           "linux": ["libzbar", ".so"],
           "gnu": ["libzbar", ".so"]}
SYSTEM_KEY = [x for x in SYS_MAP.keys() if x.startswith(sys.platform)]
SYSTEM_KEY = SYSTEM_KEY[0] if SYSTEM_KEY else ""
LIB_PATTERN = SYS_MAP.get(SYSTEM_KEY, [])


def get_lib_path(lib_dir, lib_pattern):
    """

    :param lib_dir:
    :param lib_pattern: [prefix,postfix]
    :return:
    """
    path = ""
    if os.path.isdir(lib_dir) and lib_pattern:
        file_list = os.listdir(lib_dir)
        start, end = lib_pattern
        for f in file_list:
            if f.startswith(start) and f.endswith(end):
                path = os.path.join(lib_dir, f)
    return path


LIB_PATH = get_lib_path(zbar_init_path, LIB_PATTERN)
WITH_LIB = bool(LIB_PATH)
print("#####")
print("setup zbar {} zbar lib".format("with" if WITH_LIB else "without"))
print("#####")
setup(
    name='zbar',
    version='0.23.1',
    author='Jeff Brown',
    author_email='[email protected]',
    url='https://github.com/mchehab/zbar',
    description='read barcodes from images or video',
    license='LGPL',
    long_description=open('README').read(),
    classifiers=[
        'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'Environment :: Console',
        'Environment :: X11 Applications',
        'Environment :: Win32 (MS Windows)',
        'Operating System :: POSIX',
        'Operating System :: Unix',
        'Operating System :: Microsoft :: Windows',
        'Topic :: Communications',
        'Topic :: Multimedia :: Graphics',
        'Topic :: Software Development :: Libraries',
    ],
    packages=find_packages() if WITH_LIB else [],
    package_data={"zbar_init": [os.path.basename(LIB_PATH)]} if WITH_LIB else {},
    ext_modules=[
        Extension('zbar', [
            'zbarmodule.c',
            'enum.c',
            'exception.c',
            'symbol.c',
            'symbolset.c',
            'symboliter.c',
            'image.c',
            'processor.c',
            'imagescanner.c',
            'decoder.c',
            'scanner.c',
        ],
                  libraries=['zbar'],
                  include_dirs=['../include']
                  ),
    ],
)

And then we can move the .so to ./zbar_initand rename to libzbar.so if we want to build a wheel with .so to migrate conveniently. After that we meet a problem that how can python find the libzbar.so in the wheel. so that i make a init module to load it explicitly. like below

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
from ctypes import CDLL

SYS_MAP = {"msys": ["msys-zbar", ".dll"],
           "win32": ["libzbar", ".dll"],
           "linux": ["libzbar", ".so"],
           "gnu": ["libzbar", ".so"]}
SYSTEM_KEY = [x for x in SYS_MAP.keys() if x.startswith(sys.platform)]
SYSTEM_KEY = SYSTEM_KEY[0] if SYSTEM_KEY else ""
LIB_PATTERN = SYS_MAP.get(SYSTEM_KEY, [])
print("system platform is {}".format(SYSTEM_KEY)
      if SYSTEM_KEY else "No valid zbar lib in this whl for {}".format(sys.platform))


def get_lib_path(lib_dir, lib_pattern):
    """

    :param lib_dir: 
    :param lib_pattern: [prefix,postfix] 
    :return: 
    """
    path = ""
    if os.path.isdir(lib_dir) and lib_pattern:
        file_list = os.listdir(lib_dir)
        start, end = lib_pattern
        for f in file_list:
            if f.startswith(start) and f.endswith(end):
                path = os.path.join(lib_dir, f)
    return path


CUR_DIR = os.path.realpath(os.path.dirname(__file__))
ZBAR_LIB_PATH = get_lib_path(CUR_DIR, LIB_PATTERN)
try:
    import zbar
except ImportError as err:
    print("warning : {}".format(err))
    print("warning : Fail to get so or dll in the default path")
    print("try to load {} ".format(ZBAR_LIB_PATH))
    CDLL(ZBAR_LIB_PATH)
    import zbar

if you have libzar in your environment, you can use

import zbar
print(zbar.version())

to check whether it works.

if you don`t have libzar ,and install a wheel with libzbar.so you can use

from zbar_init import zbar
print(zbar.version())

to check

wqh17101 avatar Feb 03 '21 10:02 wqh17101

For this to work, we need to first define how a zbar-lite will work properly:

  1. a new configure.ac option is needed in order to enable/disable such feature;
  2. a new test to be run with make tests should test the functionality provided by the new python modules;
  3. it doesn't make sense to copy source files. Instead, ./configure --with-zbar-lite should be setting the makefiles to properly build it;
  4. any new functions that may be needed for this to work should be inside the already-existing ZBar libraries, as we don't want the same symbols to be added on both libzbar and on a libzbar-lite that would contain a sub/superset of libzbar;
  5. whatever is needed for setup.py, it should never include config.h, Makefile or any other symbol produced by autotools, as this would be a mess to maintain and probably useless for the user, as their enviroment will be different than the ones used by developers;
  6. Let's try to use the same version number for zbar-lite, as keeping a different one for it is a maintainance nightmare.

mchehab avatar Feb 15 '21 09:02 mchehab

  1. The version number of zbar-lite is a software number,and libzbar version is a core version number. These are two differnt things. Whenever i add some new feature by Python to zbar-lite, it should not update the core version for core code of zbar is not changed. In the other hand, if java add some new feature, i don`t think my zbar-lite version should be changed, because nothing changed for Python

wqh17101 avatar Feb 15 '21 13:02 wqh17101