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  # Use the minimum macOS deployment target that supports all c++17
79  # features.
80  #
81  # See: Notes column of https://developer.apple.com/xcode/cpp/#c++17
82  "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15",
83  "-DPython3_EXECUTABLE={}".format(sys.executable.replace("\\", "/")),
84  "-DLLVM_ENABLE_PROJECTS=mlir",
85  "-DLLVM_EXTERNAL_PROJECTS=circt",
86  "-DLLVM_EXTERNAL_CIRCT_SOURCE_DIR={}".format(circt_dir),
87  "-DLLVM_TARGETS_TO_BUILD=host",
88  "-DMLIR_ENABLE_BINDINGS_PYTHON=ON",
89  "-DCIRCT_BINDINGS_PYTHON_ENABLED=ON",
90  "-DCIRCT_RELEASE_TAG_ENABLED=ON",
91  "-DCIRCT_RELEASE_TAG=firtool"
92  ] + cmake_linker + cmake_generator
93 
94  # HACK: CMake fails to auto-detect static linked Python installations, which
95  # happens to be what exists on manylinux. We detect this and give it a dummy
96  # library file to reference (which is checks exists but never gets
97  # used).
98  if platform.system() == "Linux":
99  python_libdir = sysconfig.get_config_var('LIBDIR')
100  python_library = sysconfig.get_config_var('LIBRARY')
101  if python_libdir and not os.path.isabs(python_library):
102  python_library = os.path.join(python_libdir, python_library)
103  if python_library and not os.path.exists(python_library):
104  print("Detected static linked python. Faking a library for cmake.")
105  fake_libdir = os.path.join(cmake_build_dir, "fake_python", "lib")
106  os.makedirs(fake_libdir, exist_ok=True)
107  fake_library = os.path.join(fake_libdir,
108  sysconfig.get_config_var('LIBRARY'))
109  subprocess.check_call(["ar", "q", fake_library])
110  cmake_args.append("-DPython3_LIBRARY:PATH={}".format(fake_library))
111 
112  os.makedirs(cmake_build_dir, exist_ok=True)
113  if os.path.exists(cmake_install_dir):
114  shutil.rmtree(cmake_install_dir)
115  cmake_cache_file = os.path.join(cmake_build_dir, "CMakeCache.txt")
116  if os.path.exists(cmake_cache_file):
117  os.remove(cmake_cache_file)
118  subprocess.check_call(["cmake", llvm_dir] + cmake_args, cwd=cmake_build_dir)
119  subprocess.check_call(
120  ["cmake", "--build", ".", "--target", "install-CIRCTPythonModules"],
121  cwd=cmake_build_dir)
122  if os.path.exists(target_dir):
123  os.remove(target_dir)
124  shutil.copytree(os.path.join(cmake_install_dir, "python_packages",
125  "circt_core"),
126  target_dir,
127  symlinks=False)
128 
129 
130 class NoopBuildExtension(build_ext):
131 
132  def build_extension(self, ext):
133  pass
134 
135 
136 setup(
137  name="circt",
138  version="0.0.1",
139  author="Mike Urbach",
140  author_email="mikeurbach@gmail.com",
141  description="CIRCT Python Bindings",
142  long_description="",
143  include_package_data=True,
144  ext_modules=[
145  CMakeExtension("circt._mlir_libs._mlir"),
146  CMakeExtension("circt._mlir_libs._circt"),
147  ],
148  cmdclass={
149  "build": CustomBuild,
150  "built_ext": NoopBuildExtension,
151  "build_py": CMakeBuild,
152  },
153  zip_safe=False,
154  packages=find_namespace_packages(include=[
155  "circt",
156  "circt.*",
157  ]),
158 )
def __init__(self, name, sourcedir="")
Definition: setup.py:49
def build_extension(self, ext)
Definition: setup.py:132
Definition: setup.py:1