libsass-python/setup.py

294 lines
9.5 KiB
Python

import ast
import atexit
import os.path
import platform
import shutil
import subprocess
import sys
import tempfile
import distutils.cmd
import distutils.log
import distutils.sysconfig
from setuptools import Extension
from setuptools import 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 = fr'/DLIBSASS_VERSION="\"{libsass_version}\""'
else:
define = f'-DLIBSASS_VERSION="{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 OSError:
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 = f'cp3{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', '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'],
],
},
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 :: 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',
],
python_requires='>=3.6',
cmdclass=cmdclass,
)