libsass-python/setup.py

299 lines
9.7 KiB
Python

#!/usr/bin/env python
from __future__ import print_function
import ast
import atexit
import distutils.cmd
import distutils.log
import distutils.sysconfig
import os.path
import platform
import shutil
import subprocess
import sys
import tempfile
from setuptools import Extension, setup
MACOS_FLAG = ['-mmacosx-version-min=10.7']
FLAGS_POSIX = [
'-fPIC', '-std=gnu++0x', '-Wall', '-Wno-parentheses', '-Werror=switch',
]
FLAGS_CLANG = ['-c', '-O3'] + FLAGS_POSIX + ['-stdlib=libc++']
LFLAGS_POSIX = ['-fPIC', '-lstdc++']
LFLAGS_CLANG = ['-fPIC', '-stdlib=libc++']
sources = ['_sass.c']
headers = []
if sys.platform == 'win32':
extra_compile_args = ['/Od', '/EHsc', '/MT']
extra_link_args = []
elif platform.system() == 'Darwin':
extra_compile_args = FLAGS_CLANG + MACOS_FLAG
extra_link_args = LFLAGS_CLANG + MACOS_FLAG
elif platform.system() in {'FreeBSD', 'OpenBSD'}:
extra_compile_args = FLAGS_CLANG
extra_link_args = LFLAGS_CLANG
else:
extra_compile_args = FLAGS_POSIX
extra_link_args = LFLAGS_POSIX
if platform.system() in {'Darwin', 'FreeBSD', 'OpenBSD'}:
os.environ.setdefault('CC', 'clang')
os.environ.setdefault('CXX', 'clang++')
orig_customize_compiler = distutils.sysconfig.customize_compiler
def customize_compiler(compiler):
orig_customize_compiler(compiler)
compiler.compiler[0] = os.environ['CC']
compiler.compiler_so[0] = os.environ['CXX']
compiler.compiler_cxx[0] = os.environ['CXX']
compiler.linker_so[0] = os.environ['CXX']
return compiler
distutils.sysconfig.customize_compiler = customize_compiler
if os.environ.get('SYSTEM_SASS', False):
libraries = ['sass']
include_dirs = []
else:
LIBSASS_SOURCE_DIR = os.path.join('libsass', 'src')
if (
not os.path.isfile(os.path.join('libsass', 'Makefile')) and
os.path.isdir('.git')
):
print(file=sys.stderr)
print('Missing the libsass sumbodule. Try:', file=sys.stderr)
print(' git submodule update --init', file=sys.stderr)
print(file=sys.stderr)
exit(1)
# Determine the libsass version from the git checkout
if os.path.exists(os.path.join('libsass', '.git')):
out = subprocess.check_output((
'git', '-C', 'libsass', 'describe',
'--abbrev=4', '--dirty', '--always', '--tags',
))
with open('.libsass-upstream-version', 'wb') as libsass_version_file:
libsass_version_file.write(out)
# The version file should always exist at this point
with open('.libsass-upstream-version', 'rb') as libsass_version_file:
libsass_version = libsass_version_file.read().decode('UTF-8').strip()
if sys.platform == 'win32':
# This looks wrong, but is required for some reason :(
define = r'/DLIBSASS_VERSION="\"{}\""'.format(libsass_version)
else:
define = '-DLIBSASS_VERSION="{}"'.format(libsass_version)
for directory in (
os.path.join('libsass', 'src'),
os.path.join('libsass', 'include'),
):
for pth, _, filenames in os.walk(directory):
for filename in filenames:
filename = os.path.join(pth, filename)
if filename.endswith(('.c', '.cpp')):
sources.append(filename)
elif filename.endswith('.h'):
headers.append(filename)
if sys.platform == 'win32':
from distutils.msvc9compiler import get_build_version
vscomntools_env = 'VS{}{}COMNTOOLS'.format(
int(get_build_version()),
int(get_build_version() * 10) % 10,
)
try:
os.environ[vscomntools_env] = os.environ['VS140COMNTOOLS']
except KeyError:
distutils.log.warn(
'You probably need Visual Studio 2015 (14.0) '
'or higher',
)
from distutils import msvccompiler, msvc9compiler
if msvccompiler.get_build_version() < 14.0:
msvccompiler.get_build_version = lambda: 14.0
if get_build_version() < 14.0:
msvc9compiler.get_build_version = lambda: 14.0
msvc9compiler.VERSION = 14.0
elif platform.system() in {'Darwin', 'FreeBSD', 'OpenBSD'}:
# Dirty workaround to avoid link error...
# Python distutils doesn't provide any way
# to configure different flags for each cc and c++.
cencode_path = os.path.join(LIBSASS_SOURCE_DIR, 'cencode.c')
cencode_body = ''
with open(cencode_path) as f:
cencode_body = f.read()
with open(cencode_path, 'w') as f:
f.write(
'#ifdef __cplusplus\n'
'extern "C" {\n'
'#endif\n',
)
f.write(cencode_body)
f.write(
'#ifdef __cplusplus\n'
'}\n'
'#endif\n',
)
@atexit.register
def restore_cencode():
if os.path.isfile(cencode_path):
with open(cencode_path, 'w') as f:
f.write(cencode_body)
libraries = []
include_dirs = [os.path.join('.', 'libsass', 'include')]
extra_compile_args.append(define)
# Py_LIMITED_API does not work for pypy
# https://foss.heptapod.net/pypy/pypy/issues/3173
if not hasattr(sys, 'pypy_version_info'):
py_limited_api = True
define_macros = [('Py_LIMITED_API', None)]
else:
py_limited_api = False
define_macros = []
sass_extension = Extension(
'_sass',
sorted(sources),
include_dirs=include_dirs,
depends=headers,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
libraries=libraries,
py_limited_api=py_limited_api,
define_macros=define_macros,
)
def version(sass_filename='sass.py'):
with open(sass_filename) as f:
tree = ast.parse(f.read(), sass_filename)
for node in tree.body:
if isinstance(node, ast.Assign) and len(node.targets) == 1:
target, = node.targets
if isinstance(target, ast.Name) and target.id == '__version__':
return node.value.s
def readme():
try:
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as f:
return f.read()
except IOError:
pass
class upload_doc(distutils.cmd.Command):
"""Uploads the documentation to GitHub pages."""
description = __doc__
user_options = []
def initialize_options(self):
if sys.version_info < (3,):
raise SystemExit('upload_doc must be run with python 3')
def finalize_options(self):
pass
def run(self):
path = tempfile.mkdtemp()
build = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'build', 'sphinx', 'html',
)
os.chdir(path)
os.system(
'git clone -b gh-pages --depth 5 '
'git@github.com:sass/libsass-python.git .',
)
os.system('git rm -r .')
os.system('touch .nojekyll')
os.system('cp -r ' + build + '/* .')
os.system('git stage .')
os.system('git commit -a -m "Documentation updated."')
os.system('git push origin gh-pages')
shutil.rmtree(path)
cmdclass = {'upload_doc': upload_doc}
if sys.version_info >= (3,) and platform.python_implementation() == 'CPython':
try:
import wheel.bdist_wheel
except ImportError:
pass
else:
class bdist_wheel(wheel.bdist_wheel.bdist_wheel):
def finalize_options(self):
self.py_limited_api = 'cp3{}'.format(sys.version_info[1])
super().finalize_options()
cmdclass['bdist_wheel'] = bdist_wheel
setup(
name='libsass',
description='Sass for Python: '
'A straightforward binding of libsass for Python.',
long_description=readme(),
version=version(),
ext_modules=[sass_extension],
packages=['sassutils'],
py_modules=['pysassc', 'sass', 'sassc', 'sasstests'],
package_data={
'': [
'README.rst',
'test/*.sass',
],
},
license='MIT License',
author='Hong Minhee',
author_email='minhee' '@' 'dahlia.kr',
url='https://sass.github.io/libsass-python/',
download_url='https://github.com/sass/libsass-python/releases',
entry_points={
'distutils.commands': [
'build_sass = sassutils.distutils:build_sass',
],
'distutils.setup_keywords': [
'sass_manifests = sassutils.distutils:validate_manifests',
],
'console_scripts': [
['pysassc = pysassc:main'],
# TODO: remove `sassc` entry (#134)
['sassc = sassc:main'],
],
},
install_requires=['six'],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: C',
'Programming Language :: C++',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Programming Language :: Python :: Implementation :: Stackless',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Topic :: Software Development :: Code Generators',
'Topic :: Software Development :: Compilers',
],
cmdclass=cmdclass,
)