CIRCT  20.0.0git
setup.py
Go to the documentation of this file.
1 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 # See https://llvm.org/LICENSE.txt for license information.
3 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 
5 # Build/install the circt-core python package.
6 # Note that this includes a relatively large build of LLVM (~2400 C++ files)
7 # and can take a considerable amount of time, especially with defaults.
8 # To install:
9 # pip install .
10 # To build a wheel:
11 # pip wheel .
12 #
13 # It is recommended to build with Ninja and ccache. To do so, set environment
14 # variables by prefixing to above invocations:
15 # CMAKE_GENERATOR=Ninja \
16 # CMAKE_C_COMPILER_LAUNCHER=ccache \
17 # CMAKE_CXX_COMPILER_LAUNCHER=ccache
18 #
19 # On CIs, it is often advantageous to re-use/control the CMake build directory.
20 # This can be set with the CIRCT_CMAKE_BUILD_DIR env var.
21 #
22 # By default, this will use the llvm-project submodule included with CIRCT.
23 # This can be overridden with the CIRCT_LLVM_DIR env var.
24 
25 import os
26 import platform
27 import shutil
28 import subprocess
29 import sys
30 import sysconfig
31 
32 from distutils.command.build import build as _build
33 from setuptools import find_namespace_packages, setup, Extension
34 from setuptools.command.build_ext import build_ext
35 from setuptools.command.build_py import build_py
36 
37 
38 # Build phase discovery is unreliable. Just tell it what phases to run.
40 
41  def run(self):
42  self.run_command("build_py")
43  self.run_command("build_ext")
44  self.run_command("build_scripts")
45 
46 
47 class CMakeExtension(Extension):
48 
49  def __init__(self, name, sourcedir=""):
50  Extension.__init__(self, name, sources=[])
51  self.sourcedirsourcedir = os.path.abspath(sourcedir)
52 
53 
54 class CMakeBuild(build_py):
55 
56  def run(self):
57  target_dir = self.build_lib
58  circt_dir = os.path.abspath(
59  os.path.join(os.path.dirname(__file__), "..", "..", ".."))
60  cmake_build_dir = os.getenv("CIRCT_CMAKE_BUILD_DIR")
61  if not cmake_build_dir:
62  cmake_build_dir = os.path.join(circt_dir, "build")
63  cmake_install_dir = os.path.join(cmake_build_dir, "..", "install")
64  llvm_dir = os.getenv("CIRCT_LLVM_DIR")
65  if not llvm_dir:
66  llvm_dir = os.path.join(circt_dir, "llvm", "llvm")
67 
68  # Use Ninja if available.
69  exist_ninja = shutil.which("ninja") is not None
70  cmake_generator = ["-G", "Ninja"] if exist_ninja else []
71 
72  # Use lld if available.
73  exist_lld = shutil.which("lld") is not None
74  cmake_linker = ["-DLLVM_USE_LINKER=lld"] if exist_lld else []
75  cmake_args = [
76  "-DCMAKE_BUILD_TYPE=Release", # not used on MSVC, but no harm
77  "-DCMAKE_INSTALL_PREFIX={}".format(os.path.abspath(cmake_install_dir)),
78  "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.14", # on OSX, min target for C++17
79  "-DPython3_EXECUTABLE={}".format(sys.executable.replace("\\", "/")),
80  "-DLLVM_ENABLE_PROJECTS=mlir",
81  "-DLLVM_EXTERNAL_PROJECTS=circt",
82  "-DLLVM_EXTERNAL_CIRCT_SOURCE_DIR={}".format(circt_dir),
83  "-DLLVM_TARGETS_TO_BUILD=host",
84  "-DMLIR_ENABLE_BINDINGS_PYTHON=ON",
85  "-DCIRCT_BINDINGS_PYTHON_ENABLED=ON",
86  "-DCIRCT_RELEASE_TAG_ENABLED=ON",
87  "-DCIRCT_RELEASE_TAG=firtool"
88  ] + cmake_linker + cmake_generator
89 
90  # HACK: CMake fails to auto-detect static linked Python installations, which
91  # happens to be what exists on manylinux. We detect this and give it a dummy
92  # library file to reference (which is checks exists but never gets
93  # used).
94  if platform.system() == "Linux":
95  python_libdir = sysconfig.get_config_var('LIBDIR')
96  python_library = sysconfig.get_config_var('LIBRARY')
97  if python_libdir and not os.path.isabs(python_library):
98  python_library = os.path.join(python_libdir, python_library)
99  if python_library and not os.path.exists(python_library):
100  print("Detected static linked python. Faking a library for cmake.")
101  fake_libdir = os.path.join(cmake_build_dir, "fake_python", "lib")
102  os.makedirs(fake_libdir, exist_ok=True)
103  fake_library = os.path.join(fake_libdir,
104  sysconfig.get_config_var('LIBRARY'))
105  subprocess.check_call(["ar", "q", fake_library])
106  cmake_args.append("-DPython3_LIBRARY:PATH={}".format(fake_library))
107 
108  os.makedirs(cmake_build_dir, exist_ok=True)
109  if os.path.exists(cmake_install_dir):
110  shutil.rmtree(cmake_install_dir)
111  cmake_cache_file = os.path.join(cmake_build_dir, "CMakeCache.txt")
112  if os.path.exists(cmake_cache_file):
113  os.remove(cmake_cache_file)
114  subprocess.check_call(["cmake", llvm_dir] + cmake_args, cwd=cmake_build_dir)
115  subprocess.check_call(
116  ["cmake", "--build", ".", "--target", "install-CIRCTPythonModules"],
117  cwd=cmake_build_dir)
118  if os.path.exists(target_dir):
119  os.remove(target_dir)
120  shutil.copytree(os.path.join(cmake_install_dir, "python_packages",
121  "circt_core"),
122  target_dir,
123  symlinks=False)
124 
125 
126 class NoopBuildExtension(build_ext):
127 
128  def build_extension(self, ext):
129  pass
130 
131 
132 setup(
133  name="circt",
134  version="0.0.1",
135  author="Mike Urbach",
136  author_email="mikeurbach@gmail.com",
137  description="CIRCT Python Bindings",
138  long_description="",
139  include_package_data=True,
140  ext_modules=[
141  CMakeExtension("circt._mlir_libs._mlir"),
142  CMakeExtension("circt._mlir_libs._circt"),
143  ],
144  cmdclass={
145  "build": CustomBuild,
146  "built_ext": NoopBuildExtension,
147  "build_py": CMakeBuild,
148  },
149  zip_safe=False,
150  packages=find_namespace_packages(include=[
151  "circt",
152  "circt.*",
153  ]),
154 )
def __init__(self, name, sourcedir="")
Definition: setup.py:49
def build_extension(self, ext)
Definition: setup.py:128
Definition: setup.py:1