CIRCT  19.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 ESI runtime python package.
6 #
7 # To install:
8 # pip install .
9 # To build a wheel:
10 # pip wheel .
11 #
12 # It is recommended to build with Ninja and ccache. To do so, set environment
13 # variables by prefixing to above invocations:
14 # CMAKE_GENERATOR=Ninja CMAKE_CXX_COMPILER=clang++
15 #
16 # On CIs, it is often advantageous to re-use/control the CMake build directory.
17 # This can be set with the PYCDE_CMAKE_BUILD_DIR env var.
18 
19 import os
20 import platform
21 import shutil
22 import subprocess
23 import sys
24 import sysconfig
25 
26 from distutils.command.build import build as _build
27 from setuptools import find_namespace_packages, setup, Extension
28 from setuptools.command.build_ext import build_ext
29 from setuptools.command.build_py import build_py
30 
31 _thisdir = os.path.abspath(os.path.dirname(__file__))
32 
33 
34 # Build phase discovery is unreliable. Just tell it what phases to run.
36 
37  def run(self):
38  self.run_command("build_py")
39  self.run_command("build_ext")
40  self.run_command("build_scripts")
41 
42 
43 class CMakeExtension(Extension):
44 
45  def __init__(self, name, sourcedir=""):
46  Extension.__init__(self, name, sources=[])
47  self.sourcedirsourcedir = os.path.abspath(sourcedir)
48 
49 
50 class CMakeBuild(build_py):
51 
52  def run(self):
53  # Set up build dirs.
54  target_dir = os.path.abspath(self.build_lib)
55  cmake_build_dir = os.getenv("PYCDE_CMAKE_BUILD_DIR")
56  if not cmake_build_dir:
57  cmake_build_dir = os.path.abspath(
58  os.path.join(target_dir, "..", "cmake_build"))
59  src_dir = _thisdir
60 
61  os.makedirs(cmake_build_dir, exist_ok=True)
62  cmake_cache_file = os.path.join(cmake_build_dir, "CMakeCache.txt")
63  if os.path.exists(cmake_cache_file):
64  os.remove(cmake_cache_file)
65 
66  # Configure the build.
67  cfg = "Release"
68  cmake_args = [
69  "-DCMAKE_BUILD_TYPE={}".format(cfg), # not used on MSVC, but no harm
70  "-DCAPNP_PATH={}".format(os.getenv("CAPNP_PATH")),
71  "-DPython3_EXECUTABLE={}".format(sys.executable.replace("\\", "/")),
72  "-DWHEEL_BUILD=ON",
73  ]
74  cxx = os.getenv("CXX")
75  if cxx is not None:
76  cmake_args.append("-DCMAKE_CXX_COMPILER={}".format(cxx))
77 
78  cc = os.getenv("CC")
79  if cc is not None:
80  cmake_args.append("-DCMAKE_C_COMPILER={}".format(cc))
81 
82  if "CIRCT_EXTRA_CMAKE_ARGS" in os.environ:
83  cmake_args += os.environ["CIRCT_EXTRA_CMAKE_ARGS"].split(" ")
84 
85  # HACK: CMake fails to auto-detect static linked Python installations, which
86  # happens to be what exists on manylinux. We detect this and give it a dummy
87  # library file to reference (which is checks exists but never gets
88  # used).
89  if platform.system() == "Linux":
90  python_libdir = sysconfig.get_config_var('LIBDIR')
91  python_library = sysconfig.get_config_var('LIBRARY')
92  if python_libdir and not os.path.isabs(python_library):
93  python_library = os.path.join(python_libdir, python_library)
94  if python_library and not os.path.exists(python_library):
95  print("Detected static linked python. Faking a library for cmake.")
96  fake_libdir = os.path.join(cmake_build_dir, "fake_python", "lib")
97  os.makedirs(fake_libdir, exist_ok=True)
98  fake_library = os.path.join(fake_libdir,
99  sysconfig.get_config_var('LIBRARY'))
100  subprocess.check_call(["ar", "q", fake_library])
101  cmake_args.append("-DPython3_LIBRARY:PATH={}".format(fake_library))
102 
103  # Finally run the cmake configure.
104  subprocess.check_call(["cmake", src_dir] + cmake_args, cwd=cmake_build_dir)
105 
106  # Run the build.
107  subprocess.check_call([
108  "cmake",
109  "--build",
110  ".",
111  "--parallel",
112  "--target",
113  "ESIRuntime",
114  "esiquery",
115  "ESIPythonRuntime",
116  "EsiCosimDpiServer",
117  ],
118  cwd=cmake_build_dir)
119 
120  # Install the runtime directly into the target directory.
121  if os.path.exists(target_dir):
122  shutil.rmtree(target_dir)
123  subprocess.check_call([
124  "cmake", "--install", ".", "--prefix",
125  os.path.join(target_dir, "esiaccel"), "--component", "ESIRuntime"
126  ],
127  cwd=cmake_build_dir)
128 
129 
130 class NoopBuildExtension(build_ext):
131 
132  def build_extension(self, ext):
133  pass
134 
135 
136 setup(name="esiaccel",
137  include_package_data=True,
138  ext_modules=[
139  CMakeExtension("esiaccel.esiCppAccel"),
140  ],
141  cmdclass={
142  "build": CustomBuild,
143  "built_ext": NoopBuildExtension,
144  "build_py": CMakeBuild,
145  },
146  zip_safe=False,
147  packages=find_namespace_packages(include=[
148  "esiaccel",
149  "esiaccel.*",
150  ]))
def run(self)
Definition: setup.py:52
def __init__(self, name, sourcedir="")
Definition: setup.py:45
def run(self)
Definition: setup.py:37
def build_extension(self, ext)
Definition: setup.py:132
Definition: setup.py:1