Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
钟尚武
dlib
Commits
6c2811da
Commit
6c2811da
authored
Aug 28, 2015
by
Davis E. King
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #29 from dashesy/setup_py
Setup py
parents
f2868add
5c06db0e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
612 additions
and
0 deletions
+612
-0
.gitignore
.gitignore
+3
-0
MANIFEST.in
MANIFEST.in
+22
-0
setup.py
setup.py
+587
-0
No files found.
.gitignore
View file @
6c2811da
...
...
@@ -4,3 +4,6 @@
*.o
*.so
build
dist
*.egg-info/
MANIFEST.in
0 → 100644
View file @
6c2811da
#
# MANIFEST.in
#
# Manifest template for creating the dlib source distribution.
include MANIFEST.in
include setup.py
include README.txt
# sources
recursive-include dlib **
recursive-exclude dlib/test **
recursive-exclude dlib/build **
recursive-include docs **
recursive-include python_examples *.txt *.py *.bat
recursive-exclude python_examples/build **
recursive-include tools/python **
recursive-exclude tools/python/build **
# dlib package
recursive-include dist/dlib **
setup.py
0 → 100644
View file @
6c2811da
"""setup for the dlib project
Copyright (C) 2015 Ehsan Azar (dashesy@linux.com)
License: Boost Software License See LICENSE.txt for the full license.
To build the dlib:
python setup.py build
To build and install:
python setup.py install
To package the wheel:
python setup.py bdist_wheel
To repackage the previously built package as wheel (bypassing build):
python setup.py bdist_wheel --repackage
To install a develop version (egg with symbolic link):
python setup.py develop
To exclude/include certain options in the cmake config use --yes and --no:
for example:
--yes DLIB_NO_GUI_SUPPORT: will set -DDLIB_NO_GUI_SUPPORT=yes
--no DLIB_NO_GUI_SUPPORT: will set -DDLIB_NO_GUI_SUPPORT=no
Additional options:
--debug: makes a debug build
--cmake: path to specific cmake executable
--G or -G: name of a build system generator (equivalent of passing -G "name" to cmake)
"""
from
__future__
import
print_function
import
shutil
import
stat
import
errno
from
setuptools.command.bdist_egg
import
bdist_egg
as
_bdist_egg
from
setuptools.command.develop
import
develop
as
_develop
from
distutils.command.build_ext
import
build_ext
as
_build_ext
from
distutils.command.build
import
build
as
_build
from
distutils.errors
import
DistutilsSetupError
from
distutils.spawn
import
find_executable
from
distutils.sysconfig
import
get_python_inc
,
get_python_version
from
distutils
import
log
import
os
import
sys
from
setuptools
import
Extension
,
setup
import
platform
from
subprocess
import
Popen
,
PIPE
,
STDOUT
import
signal
from
threading
import
Thread
import
time
# change directory to this module path
try
:
this_file
=
__file__
except
NameError
:
this_file
=
sys
.
argv
[
0
]
this_file
=
os
.
path
.
abspath
(
this_file
)
if
os
.
path
.
dirname
(
this_file
):
os
.
chdir
(
os
.
path
.
dirname
(
this_file
))
script_dir
=
os
.
getcwd
()
def
_get_options
():
"""read arguments and creates options
"""
_cmake_path
=
find_executable
(
"cmake"
)
_cmake_extra
=
[]
_cmake_config
=
'Release'
_options
=
[]
opt_key
=
None
_generator_set
=
False
# if a build generator is set
argv
=
[
arg
for
arg
in
sys
.
argv
]
# take a copy
# parse commandline options and consume those we care about
for
opt_idx
,
arg
in
enumerate
(
argv
):
if
opt_key
==
'cmake'
:
_cmake_path
=
arg
elif
opt_key
==
'yes'
:
_cmake_extra
.
append
(
'-D{arg}=yes'
.
format
(
arg
=
arg
.
strip
()))
elif
opt_key
==
'no'
:
_cmake_extra
.
append
(
'-D{arg}=no'
.
format
(
arg
=
arg
.
strip
()))
elif
opt_key
==
'G'
:
_cmake_extra
+=
[
'-G'
,
arg
.
strip
()]
_generator_set
=
True
if
opt_key
:
sys
.
argv
.
remove
(
arg
)
opt_key
=
None
continue
# Keep -G to resemble cmake's
if
arg
==
'-G'
or
arg
.
lower
()
==
'--g'
:
opt_key
=
'G'
sys
.
argv
.
remove
(
arg
)
continue
if
not
arg
.
startswith
(
'--'
):
continue
opt
=
arg
[
2
:]
.
lower
()
if
opt
==
'cmake'
:
_cmake_path
=
None
opt_key
=
opt
sys
.
argv
.
remove
(
arg
)
continue
elif
opt
in
[
'yes'
,
'no'
]:
opt_key
=
opt
sys
.
argv
.
remove
(
arg
)
continue
custom_arg
=
True
if
opt
==
'debug'
:
_cmake_config
=
'Debug'
elif
opt
==
'release'
:
_cmake_config
=
'Release'
elif
opt
in
[
'repackage'
]:
_options
.
append
(
opt
)
else
:
custom_arg
=
False
if
custom_arg
:
sys
.
argv
.
remove
(
arg
)
return
_options
,
_cmake_config
,
_cmake_path
,
_cmake_extra
,
_generator_set
options
,
cmake_config
,
cmake_path
,
cmake_extra
,
generator_set
=
_get_options
()
def
reg_value
(
rk
,
rname
):
"""enumerate the subkeys in a registry key
:param rk: root key in registry
:param rname: name of the value we are interested in
"""
try
:
import
_winreg
as
winreg
except
ImportError
:
# noinspection PyUnresolvedReferences
import
winreg
count
=
0
try
:
while
True
:
name
,
value
,
_
=
winreg
.
EnumValue
(
rk
,
count
)
if
rname
==
name
:
return
value
count
+=
1
except
OSError
:
pass
return
None
def
enum_reg_key
(
rk
):
"""enumerate the subkeys in a registry key
:param rk: root key in registry
"""
try
:
import
_winreg
as
winreg
except
ImportError
:
# noinspection PyUnresolvedReferences
import
winreg
sub_keys
=
[]
count
=
0
try
:
while
True
:
name
=
winreg
.
EnumKey
(
rk
,
count
)
sub_keys
.
append
(
name
)
count
+=
1
except
OSError
:
pass
return
sub_keys
def
get_msvc_win64_generator
():
"""find the default MSVC generator but Win64
This logic closely matches cmake's resolution for default build generator.
Only we select the Win64 version of it.
"""
try
:
import
_winreg
as
winreg
except
ImportError
:
# noinspection PyUnresolvedReferences
import
winreg
known_vs
=
{
"6.0"
:
"Visual Studio 6"
,
"7.0"
:
"Visual Studio 7"
,
"7.1"
:
"Visual Studio 7 .NET 2003"
,
"8.0"
:
"Visual Studio 8 2005"
,
"9.0"
:
"Visual Studio 9 2008"
,
"10.0"
:
"Visual Studio 10 2010"
,
"11.0"
:
"Visual Studio 11 2012"
,
"12.0"
:
"Visual Studio 12 2013"
,
"14.0"
:
"Visual Studio 14 2015"
,
}
newest_vs
=
None
newest_ver
=
0
platform_arch
=
platform
.
architecture
()[
0
]
sam
=
winreg
.
KEY_WOW64_32KEY
+
winreg
.
KEY_READ
if
'64'
in
platform_arch
else
winreg
.
KEY_READ
for
vs
in
[
'VisualStudio
\\
'
,
'VCExpress
\\
'
,
'WDExpress
\\
'
]:
vs_key
=
"SOFTWARE
\\
Microsoft
\\
{vs}
\\
"
.
format
(
vs
=
vs
)
try
:
root_key
=
winreg
.
OpenKey
(
winreg
.
HKEY_LOCAL_MACHINE
,
vs_key
,
0
,
sam
)
except
OSError
:
continue
try
:
sub_keys
=
enum_reg_key
(
root_key
)
except
OSError
:
sub_keys
=
[]
winreg
.
CloseKey
(
root_key
)
if
not
sub_keys
:
continue
# look to see if we have InstallDir
for
sub_key
in
sub_keys
:
try
:
root_key
=
winreg
.
OpenKey
(
winreg
.
HKEY_LOCAL_MACHINE
,
vs_key
+
sub_key
,
0
,
sam
)
except
OSError
:
continue
ins_dir
=
reg_value
(
root_key
,
'InstallDir'
)
winreg
.
CloseKey
(
root_key
)
if
not
ins_dir
:
continue
gen_name
=
known_vs
.
get
(
sub_key
)
if
gen_name
is
None
:
# if it looks like a version number
try
:
ver
=
float
(
sub_key
)
except
ValueError
:
continue
gen_name
=
'Visual Studio
%
d'
%
int
(
ver
)
else
:
ver
=
float
(
sub_key
)
if
ver
>
newest_ver
:
newest_vs
=
gen_name
newest_ver
=
ver
if
newest_vs
:
return
[
'-G'
,
newest_vs
+
' Win64'
]
return
[]
try
:
from
Queue
import
Queue
,
Empty
except
ImportError
:
# noinspection PyUnresolvedReferences
from
queue
import
Queue
,
Empty
# python 3.x
_ON_POSIX
=
'posix'
in
sys
.
builtin_module_names
def
enqueue_output
(
out
,
queue
):
for
line
in
iter
(
out
.
readline
,
b
''
):
queue
.
put
(
line
)
out
.
close
()
def
_log_buf
(
buf
):
if
not
buf
:
return
buf
=
buf
.
decode
(
"latin-1"
)
buf
=
buf
.
rstrip
()
lines
=
buf
.
splitlines
()
for
line
in
lines
:
log
.
info
(
line
)
def
run_process
(
cmds
,
timeout
=
None
):
"""run a process asynchronously
:param cmds: list of commands to invoke on a shell e.g. ['make', 'install']
:param timeout: timeout in seconds (optional)
"""
# open process as its own session, and with no stdout buffering
p
=
Popen
(
cmds
,
stdout
=
PIPE
,
stderr
=
STDOUT
,
bufsize
=
1
,
close_fds
=
_ON_POSIX
,
preexec_fn
=
os
.
setsid
if
_ON_POSIX
else
None
)
q
=
Queue
()
t
=
Thread
(
target
=
enqueue_output
,
args
=
(
p
.
stdout
,
q
))
t
.
daemon
=
True
# thread dies with the program
t
.
start
()
_time
=
time
.
time
()
e
=
None
try
:
while
t
.
isAlive
():
try
:
buf
=
q
.
get
(
timeout
=.
1
)
except
Empty
:
buf
=
b
''
_log_buf
(
buf
)
elapsed
=
time
.
time
()
-
_time
if
timeout
and
elapsed
>
timeout
:
break
except
(
KeyboardInterrupt
,
SystemExit
)
as
e
:
# if user interrupted
pass
# noinspection PyBroadException
try
:
os
.
kill
(
p
.
pid
,
signal
.
SIGINT
)
except
(
KeyboardInterrupt
,
SystemExit
)
as
e
:
pass
except
:
pass
# noinspection PyBroadException
try
:
if
e
:
os
.
kill
(
p
.
pid
,
signal
.
SIGKILL
)
else
:
p
.
wait
()
except
(
KeyboardInterrupt
,
SystemExit
)
as
e
:
# noinspection PyBroadException
try
:
os
.
kill
(
p
.
pid
,
signal
.
SIGKILL
)
except
:
pass
except
:
pass
t
.
join
(
timeout
=
0.1
)
if
e
:
raise
e
return
p
.
returncode
def
readme
(
fname
):
"""Read text out of a file relative to setup.py.
"""
return
open
(
os
.
path
.
join
(
script_dir
,
fname
))
.
read
()
def
read_version
():
"""Read version information
"""
major
=
readme
(
'./docs/.current_release_number'
)
.
strip
()
minor
=
readme
(
'./docs/.current_minor_release_number'
)
.
strip
()
return
major
+
'.'
+
minor
def
rmtree
(
name
):
"""remove a directory and its subdirectories.
"""
def
remove_read_only
(
func
,
path
,
exc
):
excvalue
=
exc
[
1
]
if
func
in
(
os
.
rmdir
,
os
.
remove
)
and
excvalue
.
errno
==
errno
.
EACCES
:
os
.
chmod
(
path
,
stat
.
S_IRWXU
|
stat
.
S_IRWXG
|
stat
.
S_IRWXO
)
func
(
path
)
else
:
raise
shutil
.
rmtree
(
name
,
ignore_errors
=
False
,
onerror
=
remove_read_only
)
def
copy_file
(
src
,
dst
):
"""copy a single file and log
"""
log
.
info
(
"Copying file
%
s ->
%
s."
%
(
src
,
dst
))
shutil
.
copy2
(
src
,
dst
)
def
clean_dist
():
"""re-create the dist folder
"""
dist_dir
=
os
.
path
.
join
(
script_dir
,
"./dist"
)
if
os
.
path
.
exists
(
dist_dir
):
log
.
info
(
'Removing distribution directory
%
s'
%
dist_dir
)
rmtree
(
dist_dir
)
dist_dir
=
os
.
path
.
join
(
script_dir
,
"./dist/dlib"
)
try
:
os
.
makedirs
(
dist_dir
)
except
OSError
:
pass
# always start with a clean slate
clean_dist
()
# noinspection PyPep8Naming
class
build
(
_build
):
def
run
(
self
):
repackage
=
'repackage'
in
options
if
not
repackage
:
self
.
build_dlib
()
# this is where the extension examples go
dist_dir_examples
=
os
.
path
.
join
(
script_dir
,
"./dist/dlib/examples"
)
try
:
os
.
makedirs
(
dist_dir_examples
)
except
OSError
:
pass
# this is where the extension goes
dist_dir
=
os
.
path
.
join
(
script_dir
,
"./dist/dlib"
)
log
.
info
(
'Populating the distribution directory
%
s ...'
%
dist_dir
)
# create the module init files
with
open
(
os
.
path
.
join
(
dist_dir
,
'__init__.py'
),
'w'
)
as
f
:
# just so that we can `import dlib` and not `from dlib import dlib`
f
.
write
(
'from .dlib import *
\n
'
)
# add version here
f
.
write
(
'__version__ = {ver}
\n
'
.
format
(
ver
=
read_version
()))
with
open
(
os
.
path
.
join
(
dist_dir_examples
,
'__init__.py'
),
'w'
):
pass
# this is where the extension and Python examples are located
out_dir
=
os
.
path
.
join
(
script_dir
,
"./python_examples"
)
# these are the created artifacts we want to package
dll_ext
=
[
'.so'
]
if
sys
.
platform
==
"win32"
:
dll_ext
=
[
'.pyd'
,
'.dll'
]
ext_found
=
False
# manually copy everything to distribution folder with package hierarchy in mind
names
=
os
.
listdir
(
out_dir
)
for
name
in
names
:
srcname
=
os
.
path
.
join
(
out_dir
,
name
)
dstname
=
os
.
path
.
join
(
dist_dir
,
name
)
dstextname
=
os
.
path
.
join
(
dist_dir_examples
,
name
)
name
,
extension
=
os
.
path
.
splitext
(
name
.
lower
())
if
extension
in
[
'.py'
,
'.txt'
]:
copy_file
(
srcname
,
dstextname
)
elif
extension
in
dll_ext
:
if
name
.
startswith
(
'dlib'
):
ext_found
=
True
copy_file
(
srcname
,
dstname
)
if
not
ext_found
:
raise
DistutilsSetupError
(
"Cannot find built dlib extension module."
)
return
_build
.
run
(
self
)
@staticmethod
def
build_dlib
():
"""use cmake to build and install the extension
"""
if
cmake_path
is
None
:
raise
DistutilsSetupError
(
"Cannot find cmake in the path. Please specify its path with --cmake parameter."
)
platform_arch
=
platform
.
architecture
()[
0
]
log
.
info
(
"Detected Python architecture:
%
s"
%
platform_arch
)
# make sure build artifacts are generated for the version of Python currently running
cmake_extra_arch
=
[]
if
sys
.
version_info
>=
(
3
,
0
):
cmake_extra_arch
+=
[
'-DPYTHON3=yes'
]
if
platform_arch
==
'64bit'
and
sys
.
platform
==
"win32"
:
# 64bit build on Windows
if
not
generator_set
:
# see if we can deduce the 64bit default generator
cmake_extra_arch
+=
get_msvc_win64_generator
()
# help cmake to find Python library in 64bit Python in Windows
# because cmake is 32bit and cannot find PYTHON_LIBRARY from registry.
inc_dir
=
get_python_inc
()
cmake_extra_arch
+=
[
'-DPYTHON_INCLUDE_DIR={inc}'
.
format
(
inc
=
inc_dir
)]
# this imitates cmake in path resolution
py_ver
=
get_python_version
()
for
ext
in
[
py_ver
.
replace
(
"."
,
""
)
+
'.lib'
,
py_ver
+
'mu.lib'
,
py_ver
+
'm.lib'
,
py_ver
+
'u.lib'
]:
py_lib
=
os
.
path
.
abspath
(
os
.
path
.
join
(
inc_dir
,
'../libs/'
,
'python'
+
ext
))
if
os
.
path
.
exists
(
py_lib
):
cmake_extra_arch
+=
[
'-DPYTHON_LIBRARY={lib}'
.
format
(
lib
=
py_lib
)]
break
build_dir
=
os
.
path
.
join
(
script_dir
,
"./tools/python/build"
)
if
os
.
path
.
exists
(
build_dir
):
log
.
info
(
'Removing build directory
%
s'
%
build_dir
)
rmtree
(
build_dir
)
try
:
os
.
makedirs
(
build_dir
)
except
OSError
:
pass
# cd build
os
.
chdir
(
build_dir
)
log
.
info
(
'Configuring cmake ...'
)
cmake_cmd
=
[
cmake_path
,
".."
,
]
+
cmake_extra
+
cmake_extra_arch
if
run_process
(
cmake_cmd
):
raise
DistutilsSetupError
(
"cmake configuration failed!"
)
log
.
info
(
'Build using cmake ...'
)
cmake_cmd
=
[
cmake_path
,
"--build"
,
"."
,
"--config"
,
cmake_config
,
"--target"
,
"install"
,
]
if
run_process
(
cmake_cmd
):
raise
DistutilsSetupError
(
"cmake build failed!"
)
# cd back where setup awaits
os
.
chdir
(
script_dir
)
# noinspection PyPep8Naming
class
develop
(
_develop
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
_develop
.
__init__
(
self
,
*
args
,
**
kwargs
)
def
run
(
self
):
self
.
run_command
(
"build"
)
return
_develop
.
run
(
self
)
# noinspection PyPep8Naming
class
bdist_egg
(
_bdist_egg
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
_bdist_egg
.
__init__
(
self
,
*
args
,
**
kwargs
)
def
run
(
self
):
self
.
run_command
(
"build"
)
return
_bdist_egg
.
run
(
self
)
# noinspection PyPep8Naming
class
build_ext
(
_build_ext
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
_build_ext
.
__init__
(
self
,
*
args
,
**
kwargs
)
def
run
(
self
):
# cmake will do the heavy lifting, just pick up the fruits of its labour
pass
setup
(
name
=
'dlib'
,
version
=
read_version
(),
keywords
=
[
'dlib'
,
'Computer Vision'
,
'Machine Learning'
],
description
=
'A toolkit for making real world machine learning and data analysis applications'
,
long_description
=
readme
(
'./README.txt'
),
author
=
'Davis King'
,
author_email
=
'davis@dlib.net'
,
url
=
'https://github.com/davisking/dlib'
,
license
=
'Boost Software License'
,
packages
=
[
'dlib'
],
package_dir
=
{
''
:
'dist'
},
include_package_data
=
True
,
cmdclass
=
{
'build'
:
build
,
'build_ext'
:
build_ext
,
'bdist_egg'
:
bdist_egg
,
'develop'
:
develop
,
},
zip_safe
=
False
,
ext_modules
=
[
Extension
(
'dlib'
,
[])],
ext_package
=
'dlib'
,
classifiers
=
[
'Development Status :: 5 - Production/Stable'
,
'Intended Audience :: Science/Research'
,
'Intended Audience :: Developers'
,
'License :: OSI Approved :: Boost Software License (BSL)'
,
'Operating System :: MacOS :: MacOS X'
,
'Operating System :: POSIX'
,
'Operating System :: POSIX :: Linux'
,
'Operating System :: Microsoft'
,
'Operating System :: Microsoft :: Windows'
,
'Programming Language :: C++'
,
'Programming Language :: Python'
,
'Programming Language :: Python :: 2'
,
'Programming Language :: Python :: 2.6'
,
'Programming Language :: Python :: 2.7'
,
'Programming Language :: Python :: 3'
,
'Programming Language :: Python :: 3.4'
,
'Topic :: Scientific/Engineering'
,
'Topic :: Scientific/Engineering :: Image Recognition'
,
'Topic :: Software Development'
,
],
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment