5 from shutil import copyfile, rmtree
8 from setuptools import setup, Extension
9 from distutils.command.clean import clean as clean_cmd
11 # a technique to build a shared library on windows
12 from distutils.command.build_ext import build_ext
14 build_ext.get_export_symbols = lambda x, y: []
17 PACKAGE_DIR = "liblinear"
18 PACKAGE_NAME = "liblinear-official"
20 cpp_dir = "cpp-source"
21 # should be consistent with dynamic_lib_name in liblinear/liblinear.py
22 dynamic_lib_name = "clib"
24 # sources to be included to build the shared library
26 path.join("blas", "daxpy.c"),
27 path.join("blas", "ddot.c"),
28 path.join("blas", "dnrm2.c"),
29 path.join("blas", "dscal.c"),
34 path.join("blas", "blas.h"),
35 path.join("blas", "blasp.h"),
42 license_source = path.join("..", "COPYRIGHT")
43 license_file = "LICENSE"
44 license_name = "BSD-3-Clause"
46 kwargs_for_extension = {
47 "sources": [path.join(cpp_dir, f) for f in source_codes],
48 "depends": [path.join(cpp_dir, f) for f in headers],
49 "include_dirs": [cpp_dir],
54 if sys.platform == "win32":
55 kwargs_for_extension.update(
57 "define_macros": [("_WIN64", ""), ("_CRT_SECURE_NO_DEPRECATE", "")],
58 "extra_link_args": ["-DEF:{}\linear.def".format(cpp_dir)],
63 def create_cpp_source():
64 for f in source_codes + headers:
65 src_file = path.join("..", f)
66 tgt_file = path.join(cpp_dir, f)
67 # ensure blas directory is created
68 os.makedirs(path.dirname(tgt_file), exist_ok=True)
69 copyfile(src_file, tgt_file)
72 class CleanCommand(clean_cmd):
75 to_be_removed = ["build/", "dist/", "MANIFEST", cpp_dir, "{}.egg-info".format(PACKAGE_NAME), license_file]
76 to_be_removed += glob("./{}/{}.*".format(PACKAGE_DIR, dynamic_lib_name))
77 for root, dirs, files in os.walk(os.curdir, topdown=False):
78 if "__pycache__" in dirs:
79 to_be_removed.append(path.join(root, "__pycache__"))
80 to_be_removed += [f for f in files if f.endswith(".pyc")]
82 for f in to_be_removed:
83 print("remove {}".format(f))
92 if not path.exists(cpp_dir):
95 if not path.exists(license_file):
96 copyfile(license_source, license_file)
98 with open("README") as f:
99 long_description = f.read()
103 packages=[PACKAGE_DIR],
105 description="Python binding of LIBLINEAR",
106 long_description=long_description,
107 long_description_content_type="text/plain",
108 author="ML group @ National Taiwan University",
109 author_email="cjlin@csie.ntu.edu.tw",
110 url="https://www.csie.ntu.edu.tw/~cjlin/liblinear",
111 license=license_name,
112 install_requires=["scipy"],
115 "{}.{}".format(PACKAGE_DIR, dynamic_lib_name), **kwargs_for_extension
118 cmdclass={"clean": CleanCommand},