Skip to content
Snippets Groups Projects
Commit 1880d248 authored by Andrews Sobral's avatar Andrews Sobral
Browse files

Improved python installation. Added pybgs on PyPI. Added BGS_PYTHON_ONLY on the cmake file.

parent a2bcf4ba
Branches
Tags
No related merge requests found
...@@ -8,8 +8,22 @@ if(NOT DEFINED BGS_PYTHON_SUPPORT) ...@@ -8,8 +8,22 @@ if(NOT DEFINED BGS_PYTHON_SUPPORT)
elseif() elseif()
# add_definitions(-DBGS_PYTHON_SUPPORT) # add_definitions(-DBGS_PYTHON_SUPPORT)
endif() endif()
# cmake -D BGS_PYTHON_ONLY=ON ..
if(NOT DEFINED BGS_PYTHON_ONLY)
set(BGS_PYTHON_ONLY OFF)
elseif()
# add_definitions(-DBGS_PYTHON_ONLY)
endif()
# cmake -D BGS_CORE_STATIC=ON ..
if(NOT DEFINED BGS_CORE_STATIC)
set(BGS_CORE_STATIC OFF)
elseif()
# add_definitions(-DBGS_CORE_STATIC)
endif()
message(STATUS "") message(STATUS "")
message(STATUS "BGSLIBRARY WITH PYTHON SUPPORT: ${BGS_PYTHON_SUPPORT}") message(STATUS "BGS_PYTHON_SUPPORT: ${BGS_PYTHON_SUPPORT}")
message(STATUS "BGS_PYTHON_ONLY: ${BGS_PYTHON_ONLY}")
message(STATUS "BGS_CORE_STATIC: ${BGS_CORE_STATIC}")
# cmake -D BGS_PYTHON_SUPPORT=ON -D BGS_PYTHON_VERSION=3 .. # cmake -D BGS_PYTHON_SUPPORT=ON -D BGS_PYTHON_VERSION=3 ..
if(NOT DEFINED BGS_PYTHON_VERSION) if(NOT DEFINED BGS_PYTHON_VERSION)
...@@ -146,8 +160,10 @@ if(BGS_PYTHON_SUPPORT) ...@@ -146,8 +160,10 @@ if(BGS_PYTHON_SUPPORT)
message(STATUS "NUMPY_INCLUDE_DIR: ${NUMPY_INCLUDE_DIR}\n") message(STATUS "NUMPY_INCLUDE_DIR: ${NUMPY_INCLUDE_DIR}\n")
endif() endif()
file(GLOB main_src src/*.cpp src/*.c) if(NOT BGS_PYTHON_ONLY)
file(GLOB main_inc src/*.h src/*.hpp) file(GLOB main_src src/*.cpp src/*.c)
file(GLOB main_inc src/*.h src/*.hpp)
endif()
file(GLOB_RECURSE utils_src src/utils/*.cpp src/utils/*.c) file(GLOB_RECURSE utils_src src/utils/*.cpp src/utils/*.c)
file(GLOB_RECURSE utils_inc src/utils/*.h src/utils/*.hpp) file(GLOB_RECURSE utils_inc src/utils/*.h src/utils/*.hpp)
...@@ -177,16 +193,20 @@ if(${OpenCV_VERSION} VERSION_LESS 2.4.3) ...@@ -177,16 +193,20 @@ if(${OpenCV_VERSION} VERSION_LESS 2.4.3)
list(REMOVE_ITEM bgs_src ${gmg}) list(REMOVE_ITEM bgs_src ${gmg})
endif() endif()
add_library(bgslibrary_core SHARED ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc}) if(BGS_CORE_STATIC)
# generates the export header bgslibrary_core_EXPORTS.h automatically add_library(bgslibrary_core STATIC ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
include(GenerateExportHeader) elseif()
GENERATE_EXPORT_HEADER(bgslibrary_core add_library(bgslibrary_core SHARED ${bgs_src} ${tools_src} ${utils_src} ${bgs_inc} ${tools_inc} ${utils_inc})
BASE_NAME bgslibrary_core # generates the export header bgslibrary_core_EXPORTS.h automatically
EXPORT_MACRO_NAME bgslibrary_core_EXPORTS include(GenerateExportHeader)
EXPORT_FILE_NAME bgslibrary_core_EXPORTS.h GENERATE_EXPORT_HEADER(bgslibrary_core
STATIC_DEFINE BGSLIBRARY_CORE_EXPORTS_BUILT_AS_STATIC) BASE_NAME bgslibrary_core
target_link_libraries(bgslibrary_core ${OpenCV_LIBS}) EXPORT_MACRO_NAME bgslibrary_core_EXPORTS
set_property(TARGET bgslibrary_core PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc}) EXPORT_FILE_NAME bgslibrary_core_EXPORTS.h
STATIC_DEFINE BGSLIBRARY_CORE_EXPORTS_BUILT_AS_STATIC)
target_link_libraries(bgslibrary_core ${OpenCV_LIBS})
set_property(TARGET bgslibrary_core PROPERTY PUBLIC_HEADER ${bgs_inc} ${tools_inc} ${utils_inc})
endif()
if(BGS_PYTHON_SUPPORT) if(BGS_PYTHON_SUPPORT)
#add_library(bgs_python SHARED ${bgs_src} ${tools_src}) #add_library(bgs_python SHARED ${bgs_src} ${tools_src})
...@@ -223,9 +243,11 @@ endif() ...@@ -223,9 +243,11 @@ endif()
# endif() # endif()
#endif() #endif()
add_executable(bgslibrary ${main_src} ${main_inc}) if(NOT BGS_PYTHON_ONLY)
target_link_libraries(bgslibrary ${OpenCV_LIBS} bgslibrary_core) add_executable(bgslibrary ${main_src} ${main_inc})
# set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs) target_link_libraries(bgslibrary ${OpenCV_LIBS} bgslibrary_core)
# set_target_properties(bgslibrary PROPERTIES OUTPUT_NAME bgs)
endif()
if(UNIX AND BGS_PYTHON_SUPPORT) if(UNIX AND BGS_PYTHON_SUPPORT)
execute_process( execute_process(
...@@ -244,24 +266,26 @@ if(UNIX AND BGS_PYTHON_SUPPORT) ...@@ -244,24 +266,26 @@ if(UNIX AND BGS_PYTHON_SUPPORT)
#install(TARGETS bgs_python DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}) #install(TARGETS bgs_python DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
endif() endif()
install(TARGETS bgslibrary_core if(NOT BGS_PYTHON_ONLY)
bgslibrary install(TARGETS bgslibrary_core
RUNTIME DESTINATION bin COMPONENT app bgslibrary
LIBRARY DESTINATION lib COMPONENT runtime RUNTIME DESTINATION bin COMPONENT app
ARCHIVE DESTINATION lib COMPONENT runtime LIBRARY DESTINATION lib COMPONENT runtime
#PUBLIC_HEADER DESTINATION include/bgslibrary COMPONENT dev ARCHIVE DESTINATION lib COMPONENT runtime
FRAMEWORK DESTINATION "/Library/Frameworks" #PUBLIC_HEADER DESTINATION include/bgslibrary COMPONENT dev
) FRAMEWORK DESTINATION "/Library/Frameworks"
)
if(UNIX) if(UNIX)
# to avoid: error while loading shared libraries: libbgslibrary_core.so # to avoid: error while loading shared libraries: libbgslibrary_core.so
message(STATUS "You might need to run:") message(STATUS "You might need to run:")
message(STATUS "$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib") message(STATUS "$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib")
message(STATUS "$ export LD_LIBRARY_PATH") message(STATUS "$ export LD_LIBRARY_PATH")
message(STATUS "after 'make install' to avoid error while loading libbgslibrary_core\n") message(STATUS "after 'make install' to avoid error while loading libbgslibrary_core\n")
endif() endif()
if(WIN32) if(WIN32)
message(STATUS "You might need to add ${CMAKE_CURRENT_BINARY_DIR} to your PATH to be able to run your applications.") message(STATUS "You might need to add ${CMAKE_CURRENT_BINARY_DIR} to your PATH to be able to run your applications.")
message(STATUS "> set PATH=%PATH%;${CMAKE_CURRENT_BINARY_DIR}\n") message(STATUS "> set PATH=%PATH%;${CMAKE_CURRENT_BINARY_DIR}\n")
endif()
endif() endif()
include *.txt
prune src
recursive-include src/algorithms *.*
recursive-include src/tools *.*
recursive-include src/utils *.*
prune wrapper
recursive-include wrapper/python *.*
recursive-include modules *.*
recursive-include pybgs *.*
prune build
prune dist
prune tools
prune test
prune gui
prune examples
prune docs
prune dataset
prune config
prune cmake-modules
prune _dist
prune _wiki
prune _opencv_cmake
...@@ -3,6 +3,10 @@ To build the bgslibrary: ...@@ -3,6 +3,10 @@ To build the bgslibrary:
python setup.py build python setup.py build
To build and install: To build and install:
python setup.py install python setup.py install
To install using pip:
pip install .
To install using PyPI:
pip install pybgs
To package the wheel (after pip installing twine and wheel): To package the wheel (after pip installing twine and wheel):
python setup.py bdist_wheel python setup.py bdist_wheel
To upload the binary wheel to PyPi To upload the binary wheel to PyPi
...@@ -11,88 +15,184 @@ To upload the source distribution to PyPi ...@@ -11,88 +15,184 @@ To upload the source distribution to PyPi
python setup.py sdist python setup.py sdist
twine upload dist/pybgs-*.tar.gz twine upload dist/pybgs-*.tar.gz
""" """
import os import os, re, sys, shutil, pathlib, platform, subprocess
import re
import sys
import platform
import subprocess
from setuptools import setup, find_packages, Extension from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext from setuptools.command.build_ext import build_ext
from setuptools.command.install_lib import install_lib
from setuptools.command.install_scripts import install_scripts
from distutils.command.install_data import install_data
from distutils.version import LooseVersion from distutils.version import LooseVersion
#import datetime PACKAGE_NAME = "pybgs"
#now = datetime.datetime.now()
#
#pkg_properties={}
#with open('.properties') as fp:
# for line in fp:
# if '=' in line:
# name, value = line.replace('\n','').split('=', 1)
# if "SNAPSHOT" in value:
# dev_version = "." + now.strftime("%y%m%d%H%M") + ".dev"
# value = value.replace("-SNAPSHOT", dev_version)
# pkg_properties[name] = value
class CMakeExtension(Extension): class CMakeExtension(Extension):
def __init__(self, name, sourcedir=''): def __init__(self, name, sourcedir=''):
Extension.__init__(self, name, sources=[]) Extension.__init__(self, name, sources=[])
self.sourcedir = os.path.abspath(sourcedir) self.sourcedir = os.path.abspath(sourcedir)
class InstallCMakeLibsData(install_data):
"""
Just a wrapper to get the install data into the egg-info
class CMakeBuild(build_ext): Listing the installed files in the egg-info guarantees that
all of the package files will be uninstalled when the user
uninstalls your package through pip
"""
def run(self): def run(self):
try: """
out = subprocess.check_output(['cmake', '--version']) Outfiles are the libraries that were built using cmake
except OSError: """
raise RuntimeError("CMake must be installed to build the following extensions: " + # There seems to be no other way to do this; I tried listing the
", ".join(e.name for e in self.extensions)) # libraries during the execution of the InstallCMakeLibs.run() but
# setuptools never tracked them, seems like setuptools wants to
# track the libraries through package data more than anything...
# help would be appriciated
self.outfiles = self.distribution.data_files
class InstallCMakeLibs(install_lib):
"""
Get the libraries from the parent distribution, use those as the outfiles
if platform.system() == "Windows": Skip building anything; everything is already built, forward libraries to
cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1)) the installation step
if cmake_version < '3.10.0': """
raise RuntimeError("CMake >= 3.10.0 is required on Windows") def run(self):
"""
Copy libraries from the bin directory and place them as appropriate
"""
self.announce("Moving library files", level=3)
# We have already built the libraries in the previous build_ext step
self.skip_build = True
if hasattr(self.distribution, 'bin_dir'):
bin_dir = self.distribution.bin_dir
else:
bin_dir = os.path.join(self.build_dir)
# Depending on the files that are generated from your cmake
# build chain, you may need to change the below code, such that
# your files are moved to the appropriate location when the installation
# is run
libs = [os.path.join(bin_dir, _lib) for _lib in
os.listdir(bin_dir) if
os.path.isfile(os.path.join(bin_dir, _lib)) and
os.path.splitext(_lib)[1] in [".dll", ".so"]
and not (_lib.startswith("python") or _lib.startswith(PACKAGE_NAME))]
for lib in libs:
shutil.move(lib, os.path.join(self.build_dir,
os.path.basename(lib)))
# Mark the libs for installation, adding them to
# distribution.data_files seems to ensure that setuptools' record
# writer appends them to installed-files.txt in the package's egg-info
#
# Also tried adding the libraries to the distribution.libraries list,
# but that never seemed to add them to the installed-files.txt in the
# egg-info, and the online recommendation seems to be adding libraries
# into eager_resources in the call to setup(), which I think puts them
# in data_files anyways.
#
# What is the best way?
# These are the additional installation files that should be
# included in the package, but are resultant of the cmake build
# step; depending on the files that are generated from your cmake
# build chain, you may need to modify the below code
self.distribution.data_files = [os.path.join(self.install_dir,
os.path.basename(lib))
for lib in libs]
# Must be forced to run after adding the libs to data_files
self.distribution.run_command("install_data")
super().run()
for ext in self.extensions: class InstallCMakeScripts(install_scripts):
self.build_extension(ext) """
Install the scripts in the build dir
"""
def run(self):
"""
Copy the required directory to the build directory and super().run()
"""
self.announce("Moving scripts files", level=3)
# Scripts were already built in a previous step
self.skip_build = True
bin_dir = self.distribution.bin_dir
scripts_dirs = [os.path.join(bin_dir, _dir) for _dir in
os.listdir(bin_dir) if
os.path.isdir(os.path.join(bin_dir, _dir))]
for scripts_dir in scripts_dirs:
shutil.move(scripts_dir,
os.path.join(self.build_dir,
os.path.basename(scripts_dir)))
# Mark the scripts for installation, adding them to
# distribution.scripts seems to ensure that the setuptools' record
# writer appends them to installed-files.txt in the package's egg-info
self.distribution.scripts = scripts_dirs
super().run()
class BuildCMakeExt(build_ext):
"""
Builds using cmake instead of the python setuptools implicit build
"""
def run(self):
"""
Perform build_cmake before doing the 'normal' stuff
"""
for extension in self.extensions:
self.build_cmake(extension)
super().run()
def build_extension(self, ext): def build_cmake(self, extension: Extension):
"""
The steps required to build the extension
"""
self.announce("Preparing the build environment", level=3)
build_dir = pathlib.Path(self.build_temp)
extension_path = pathlib.Path(self.get_ext_fullpath(extension.name))
os.makedirs(build_dir, exist_ok=True)
os.makedirs(extension_path.parent.absolute(), exist_ok=True)
python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1]) python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1])
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, # Now that the necessary directories are created, build
'-DPYTHON_EXECUTABLE=' + sys.executable, self.announce("Configuring cmake project", level=3)
cmake_args = ['-DPYTHON_EXECUTABLE=' + sys.executable,
'-DBGS_CORE_STATIC=ON',
'-DBGS_PYTHON_SUPPORT=ON', '-DBGS_PYTHON_SUPPORT=ON',
'-DBGS_PYTHON_ONLY=ON',
'-DBGS_PYTHON_VERSION=' + python_version] '-DBGS_PYTHON_VERSION=' + python_version]
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
self.spawn(['cmake', '-H'+extension.sourcedir, '-B'+self.build_temp]+ cmake_args)
cfg = 'Debug' if self.debug else 'Release' self.announce("Building binaries", level=3)
build_args = ['--config', cfg] self.spawn(["cmake", "--build", self.build_temp,
"--config", "Release", '--', '-j8'])
if platform.system() == "Windows": # Build finished, now copy the files into the copy directory
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] # The copy directory is the parent directory of the extension (.pyd)
if sys.maxsize > 2**32: self.announce("Moving built python module", level=3)
cmake_args += ['-A', 'x64'] bin_dir = os.path.join(build_dir)
build_args += ['--', '/m'] self.distribution.bin_dir = bin_dir
else: pyd_path = [os.path.join(bin_dir, _pyd) for _pyd in
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] os.listdir(bin_dir) if
build_args += ['--', '-j8'] os.path.isfile(os.path.join(bin_dir, _pyd)) and
os.path.splitext(_pyd)[0].startswith(PACKAGE_NAME) and
os.path.splitext(_pyd)[1] in [".pyd", ".so"]][0]
shutil.move(pyd_path, extension_path)
env = os.environ.copy() # After build_ext is run, the following commands will run:
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), #
self.distribution.get_version()) # install_lib
if not os.path.exists(self.build_temp): # install_scripts
os.makedirs(self.build_temp) #
subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env) # These commands are subclassed above to avoid pitfalls that
subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp) # setuptools tries to impose when installing these, as it usually
print() # wants to build those libs and scripts as well or move them to a
# different place. See comments above for additional information
with open("README.md", "r") as fh: with open("README.md", "r") as fh:
long_description = fh.read() long_description = fh.read()
setup( setup(
name='pybgs', name='pybgs',
version='3.0.0', version='3.0.0.post0',
#version=pkg_properties["version"],
author='Andrews Sobral', author='Andrews Sobral',
author_email='andrewssobral@gmail.com', author_email='andrewssobral@gmail.com',
url='https://github.com/andrewssobral/bgslibrary', url='https://github.com/andrewssobral/bgslibrary',
...@@ -100,10 +200,14 @@ setup( ...@@ -100,10 +200,14 @@ setup(
description='Python wrapper for bgslibrary using pybind11 and CMake', description='Python wrapper for bgslibrary using pybind11 and CMake',
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
ext_modules=[CMakeExtension('src')], ext_modules=[CMakeExtension(name='pybgs', sourcedir='.')],
cmdclass=dict(build_ext=CMakeBuild), cmdclass={
'build_ext': BuildCMakeExt,
'install_data': InstallCMakeLibsData,
'install_lib': InstallCMakeLibs,
#'install_scripts': InstallCMakeScripts
},
zip_safe=False, zip_safe=False,
#packages=find_packages('pybgs'), packages=find_packages(),
#package_dir={'':'pybgs'},
keywords=['BGSLibrary', 'Background Subtraction', 'Computer Vision', 'Machine Learning'], keywords=['BGSLibrary', 'Background Subtraction', 'Computer Vision', 'Machine Learning'],
) )
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment