Created
November 24, 2014 19:11
-
-
Save gubatron/fee44631a73cb57af275 to your computer and use it in GitHub Desktop.
libtorrent python binding setup.py to build on MacOSX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from distutils import sysconfig | |
from distutils.core import setup, Extension | |
import os | |
import platform | |
import sys | |
import shutil | |
import multiprocessing | |
import subprocess | |
def parse_cmd(cmdline, prefix, keep_prefix = False): | |
ret = [] | |
for token in cmdline.split(): | |
if token[:len(prefix)] == prefix: | |
if keep_prefix: | |
ret.append(token) | |
else: | |
ret.append(token[len(prefix):]) | |
return ret | |
def arch(): | |
if platform.system() != 'Darwin': return [] | |
a = os.uname()[4] | |
if a == 'Power Macintosh': a = 'ppc' | |
return ['-arch', a] | |
def target_specific(): | |
if platform.system() != 'Darwin': return [] | |
# on mavericks, clang will fail when unknown arguments are | |
# passed in. python distutils will pass in arguments it doesn't | |
# know about | |
return ['-Wno-error=unused-command-line-argument-hard-error-in-future'] | |
def get_boost_root_path(): | |
if 'BOOST_ROOT' in os.environ: | |
return os.environ['BOOST_ROOT'] | |
raise 'Error: Please set your BOOST_ROOT environment variable.' | |
def get_boost_lib_path(): | |
if 'BOOST_LIB_PATH' in os.environ: | |
return os.environ['BOOST_LIB_PATH'] | |
return os.path.join(get_boost_root_path(), 'stage', 'lib') | |
def copy_libtorrent_shared_library_here(): | |
'''on mac, the libtorrent.dylib is called libtorrent.dylib.x.y.z, we bring it to this folder | |
and rename it to libtorrent.dylib, and we'll add this scripts folder as part of the link path''' | |
libtorrent_source_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)),'..','..')) | |
p = os.popen('find %s | grep dylib' % (libtorrent_source_path)) | |
dylib_list = p.readlines() | |
p.close() | |
if len(dylib_list) == 1: | |
print dylib_list[0].strip() | |
shutil.copyfile(dylib_list[0].strip(),'libtorrent.dylib') | |
def get_libtorrent_shared_library_path(): | |
libtorrent_source_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)),'..','..')) | |
p = os.popen('find %s | grep dylib' % (libtorrent_source_path)) | |
dylib_list = p.readlines() | |
p.close() | |
if len(dylib_list) == 1: | |
return os.path.dirname(dylib_list[0]).strip() | |
if len(dylib_list) == 0: | |
raise "Could not find libtorrent's libtorrent.dylib file. Please build libtorrent shared library first." | |
def get_boost_library_names_available(): | |
'''returns a list of all the boost .dylib filenames stripped off their "lib" prefix and ".dylib" extension''' | |
boost_lib_folder = os.path.join(get_boost_root_path(),'stage','lib') | |
boost_lib_files = os.listdir(boost_lib_folder) | |
boost_library_names = [libname[3:-6] for libname in boost_lib_files if libname.endswith('dylib')] | |
return boost_library_names | |
def get_DMACRO_compile_parameters(): | |
# -D<macro> parameters | |
D_FLAGS = ['TORRENT_USE_OPENSSL', | |
'WITH_SHIPPED_GEOIP_H', | |
'BOOST_ASIO_HASH_MAP_BUCKETS=1021', | |
'BOOST_EXCEPTION_DISABLE', | |
'BOOST_ASIO_ENABLE_CANCELIO', | |
'BOOST_ASIO_DYN_LINK', | |
'TORRENT_LINKING_SHARED'] | |
D_FLAGS_PARAMETERS = '-D' + ' -D'.join(D_FLAGS) | |
return D_FLAGS_PARAMETERS | |
def get_library_name_parameters(): | |
# -l<library_name> parameters | |
all_boost_dylibs = get_boost_library_names_available() | |
# we only care about boost_system and boost_python, but we don't know if they were | |
# built with the '-mt' suffix or not | |
boost_needed_libraries = [libname for libname in all_boost_dylibs | |
if libname.startswith('boost_system') or | |
libname.startswith('boost_python')] | |
LIBRARIES = ['ssl','crypto'] + boost_needed_libraries | |
LIBRARIES_FLAGS_PARAMETERS = '-l' + ' -l'.join(LIBRARIES) | |
return LIBRARIES_FLAGS_PARAMETERS | |
def get_include_path_parameters(): | |
# -I<include_path> parameters | |
I_PATHS = ['/usr/local/include', | |
os.path.join(get_boost_root_path(),'boost'), | |
'../../include'] | |
I_PATHS_PARAMETERS = '-I' + ' -I'.join(I_PATHS) | |
return I_PATHS_PARAMETERS | |
def get_link_path_parameters(): | |
# -L<link_path> parameters | |
LINK_PATHS = ['/usr/local/lib', | |
get_boost_lib_path(), | |
'./'] | |
#get_libtorrent_shared_library_path()] | |
LINK_PATHS_PARAMETERS = '-L' + ' -L'.join(LINK_PATHS) | |
return LINK_PATHS_PARAMETERS | |
def get_mac_extra_cmd(): | |
compile_flags = [get_DMACRO_compile_parameters(), | |
get_include_path_parameters(), | |
get_mac_ld_flags(), | |
get_library_name_parameters()] | |
return ' ' + ' '.join(compile_flags) | |
def get_mac_ld_flags(): | |
return ' ' + get_link_path_parameters() | |
try: | |
if platform.system() != 'Darwin': | |
with open('compile_flags') as _file: | |
extra_cmd = _file.read() | |
else: | |
extra_cmd = get_mac_extra_cmd() | |
except Exception, e: | |
print e | |
extra_cmd = None | |
try: | |
if platform.system() != 'Darwin': | |
with open('link_flags') as _file: | |
ldflags = _file.read() | |
else: | |
# we copy the shared library from the libtorrent | |
# build folder into here as libtorrent.dylib | |
# and will add the current folder as one of the | |
# build paths. | |
copy_libtorrent_shared_library_here() | |
ldflags = get_mac_ld_flags() | |
except: | |
ldflags = None | |
ext = None | |
packages = None | |
if '--bjam' in sys.argv or ldflags == None or extra_cmd == None: | |
if '--bjam' in sys.argv: | |
del sys.argv[sys.argv.index('--bjam')] | |
if not '--help' in sys.argv \ | |
and not '--help-commands' in sys.argv: | |
toolset = '' | |
file_ext = '.so' | |
if platform.system() == 'Windows': | |
# msvc 9.0 (2008) is the official windows compiler for python 2.6 | |
# http://docs.python.org/whatsnew/2.6.html#build-and-c-api-changes | |
toolset = ' msvc-9.0' | |
file_ext = '.pyd' | |
parallell_builds = ' -j%d' % multiprocessing.cpu_count() | |
# build libtorrent using bjam and build the installer with distutils | |
cmdline = 'bjam boost=source link=static geoip=static boost-link=static release optimization=space stage_module --abbreviate-paths' + toolset + parallell_builds | |
print(cmdline) | |
if os.system(cmdline) != 0: | |
print('build failed') | |
sys.exit(1) | |
try: os.mkdir('build') | |
except: pass | |
try: shutil.rmtree('build/lib') | |
except: pass | |
try: os.mkdir('build/lib') | |
except: pass | |
try: os.mkdir('libtorrent') | |
except: pass | |
shutil.copyfile('libtorrent' + file_ext, 'build/lib/libtorrent' + file_ext) | |
packages = ['libtorrent'] | |
else: | |
source_list = os.listdir(os.path.join(os.path.dirname(__file__), "src")) | |
source_list = [os.path.join("src", s) for s in source_list if s.endswith(".cpp")] | |
ext = [Extension('libtorrent', | |
sources = source_list, | |
language='c++', | |
include_dirs = parse_cmd(extra_cmd, '-I'), | |
library_dirs = parse_cmd(extra_cmd, '-L'), | |
extra_link_args = ldflags.split() + arch(), | |
extra_compile_args = parse_cmd(extra_cmd, '-D', True) + arch() \ | |
+ target_specific(), | |
libraries = ['torrent'] + parse_cmd(extra_cmd, '-l'))] | |
setup(name = 'python-libtorrent', | |
version = '1.0.2', | |
author = 'Arvid Norberg', | |
author_email = 'arvid@rasterbar.com', | |
description = 'Python bindings for libtorrent-rasterbar', | |
long_description = 'Python bindings for libtorrent-rasterbar', | |
url = 'http://libtorrent.org', | |
platforms = [platform.system() + '-' + platform.machine()], | |
license = 'BSD', | |
packages = packages, | |
ext_modules = ext | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As of November 2014, the
/bindings/python/setup.py
on the libtorrent codebase is broken for MacOSX, I've updated the script to dinamically find the include paths, link paths and libraries required to build the python bindings on MacOSX.Just replace the
bindings/python/setup.py
with this version and issuepython setup.py bdist
and you should be good to go. (This script assumes you have builtboost
from sources and that you've set up yourBOOST_ROOT
environment variable. Setting up theBOOST_LIB_PATH
helps too but it's not necessary for the script to build the bindings)