CIRCT 24.0.0git
Loading...
Searching...
No Matches
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# For CI, it can be useful or required to place limits on especially the number
26# of allowed linker jobs. When using Ninja, this limit can be specified with the
27# CIRCT_PARALLEL_LINK_JOBS env var (passed through as -DLLVM_PARALLEL_LINK_JOBS).
28
29import os
30import platform
31import shutil
32import subprocess
33import sys
34import sysconfig
35
36from distutils.command.build import build as _build
37from setuptools import find_namespace_packages, setup, Extension
38from setuptools.command.build_ext import build_ext
39from setuptools.command.build_py import build_py
40
41
42# Build phase discovery is unreliable. Just tell it what phases to run.
44
45 def run(self):
46 self.run_command("build_py")
47 self.run_command("build_ext")
48 self.run_command("build_scripts")
49
50
51class CMakeExtension(Extension):
52
53 def __init__(self, name, sourcedir=""):
54 Extension.__init__(self, name, sources=[])
55 self.sourcedir = os.path.abspath(sourcedir)
56
57
58class CMakeBuild(build_py):
59
60 def run(self):
61 target_dir = self.build_lib
62 circt_dir = os.path.abspath(
63 os.path.join(os.path.dirname(__file__), "..", "..", ".."))
64 cmake_build_dir = os.getenv("CIRCT_CMAKE_BUILD_DIR")
65 if not cmake_build_dir:
66 cmake_build_dir = os.path.join(circt_dir, "build")
67 cmake_install_dir = os.path.join(cmake_build_dir, "..", "install")
68 llvm_dir = os.getenv("CIRCT_LLVM_DIR")
69 if not llvm_dir:
70 llvm_dir = os.path.join(circt_dir, "llvm", "llvm")
71
72 # Use Ninja if available.
73 exist_ninja = shutil.which("ninja") is not None
74 cmake_generator = ["-G", "Ninja"] if exist_ninja else []
75
76 # Use lld if available.
77 exist_lld = shutil.which("lld") is not None
78 cmake_linker = ["-DLLVM_USE_LINKER=lld"] if exist_lld else []
79
80 # Optionally cap the number of concurrent link jobs.
81 link_jobs = os.getenv("CIRCT_PARALLEL_LINK_JOBS")
82 cmake_link_jobs = ["-DLLVM_PARALLEL_LINK_JOBS={}".format(int(link_jobs))
83 ] if link_jobs else []
84
85 cmake_args = [
86 "-DCMAKE_BUILD_TYPE=Release", # not used on MSVC, but no harm
87 "-DCMAKE_INSTALL_PREFIX={}".format(os.path.abspath(cmake_install_dir)),
88 # Use the minimum macOS deployment target that supports all c++17
89 # features.
90 #
91 # See: Notes column of https://developer.apple.com/xcode/cpp/#c++17
92 "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15",
93 "-DPython3_EXECUTABLE={}".format(sys.executable.replace("\\", "/")),
94 "-DLLVM_ENABLE_PROJECTS=mlir",
95 "-DLLVM_EXTERNAL_PROJECTS=circt",
96 "-DLLVM_EXTERNAL_CIRCT_SOURCE_DIR={}".format(circt_dir),
97 "-DLLVM_TARGETS_TO_BUILD=host",
98 "-DMLIR_ENABLE_BINDINGS_PYTHON=ON",
99 "-DMLIR_BINDINGS_PYTHON_NB_DOMAIN=circt",
100 "-DCIRCT_BINDINGS_PYTHON_ENABLED=ON",
101 "-DCIRCT_RELEASE_TAG_ENABLED=ON",
102 "-DCIRCT_RELEASE_TAG=firtool"
103 ] + cmake_link_jobs + cmake_linker + cmake_generator
104
105 # HACK: CMake fails to auto-detect static linked Python installations, which
106 # happens to be what exists on manylinux. We detect this and give it a dummy
107 # library file to reference (which is checks exists but never gets
108 # used).
109 if platform.system() == "Linux":
110 python_libdir = sysconfig.get_config_var('LIBDIR')
111 python_library = sysconfig.get_config_var('LIBRARY')
112 if python_libdir and not os.path.isabs(python_library):
113 python_library = os.path.join(python_libdir, python_library)
114 if python_library and not os.path.exists(python_library):
115 print("Detected static linked python. Faking a library for cmake.")
116 fake_libdir = os.path.join(cmake_build_dir, "fake_python", "lib")
117 os.makedirs(fake_libdir, exist_ok=True)
118 fake_library = os.path.join(fake_libdir,
119 sysconfig.get_config_var('LIBRARY'))
120 subprocess.check_call(["ar", "q", fake_library])
121 cmake_args.append("-DPython3_LIBRARY:PATH={}".format(fake_library))
122
123 os.makedirs(cmake_build_dir, exist_ok=True)
124 if os.path.exists(cmake_install_dir):
125 shutil.rmtree(cmake_install_dir)
126 cmake_cache_file = os.path.join(cmake_build_dir, "CMakeCache.txt")
127 if os.path.exists(cmake_cache_file):
128 os.remove(cmake_cache_file)
129 subprocess.check_call(["cmake", llvm_dir] + cmake_args, cwd=cmake_build_dir)
130 subprocess.check_call(
131 ["cmake", "--build", ".", "--target", "install-CIRCTPythonModules"],
132 cwd=cmake_build_dir)
133 if os.path.exists(target_dir):
134 os.remove(target_dir)
135 shutil.copytree(os.path.join(cmake_install_dir, "python_packages",
136 "circt_core"),
137 target_dir,
138 symlinks=False)
139
140
141class NoopBuildExtension(build_ext):
142
143 def build_extension(self, ext):
144 pass
145
146
147setup(
148 name="circt",
149 version="0.0.1",
150 author="Mike Urbach",
151 author_email="mikeurbach@gmail.com",
152 description="CIRCT Python Bindings",
153 long_description="",
154 include_package_data=True,
155 ext_modules=[
156 CMakeExtension("circt._mlir_libs._mlir"),
157 CMakeExtension("circt._mlir_libs._circt"),
158 ],
159 cmdclass={
160 "build": CustomBuild,
161 "build_ext": NoopBuildExtension,
162 "build_py": CMakeBuild,
163 },
164 zip_safe=False,
165 packages=find_namespace_packages(include=[
166 "circt",
167 "circt.*",
168 ]),
169)
static void print(TypedAttr val, llvm::raw_ostream &os)
__init__(self, name, sourcedir="")
Definition setup.py:53
Definition setup.py:1