2022-04-08 14:02:29 -07:00
|
|
|
# pylint: disable=missing-class-docstring
|
2024-08-28 18:31:43 -07:00
|
|
|
from __future__ import annotations
|
2026-06-02 14:48:07 -07:00
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
import glob
|
2025-05-12 20:48:17 -07:00
|
|
|
import importlib
|
2024-07-01 17:16:43 -07:00
|
|
|
import importlib.resources
|
2017-06-12 17:37:05 -07:00
|
|
|
import os
|
|
|
|
|
import shutil
|
2022-04-08 14:02:29 -07:00
|
|
|
import subprocess
|
|
|
|
|
import sys
|
2017-06-12 17:37:05 -07:00
|
|
|
|
2026-06-02 14:48:07 -07:00
|
|
|
from distutils.command.build import build as st_build
|
2022-04-08 14:02:29 -07:00
|
|
|
from setuptools import Command, setup
|
2022-03-29 14:59:43 -07:00
|
|
|
from setuptools.command.develop import develop as st_develop
|
2022-03-16 17:36:57 -07:00
|
|
|
from setuptools.errors import LibError
|
2017-06-12 17:37:05 -07:00
|
|
|
|
2025-05-12 20:48:17 -07:00
|
|
|
# Import setuptools_rust to ensure an error is raised if not installed
|
|
|
|
|
try:
|
|
|
|
|
_ = importlib.import_module("setuptools_rust")
|
|
|
|
|
except ImportError as err:
|
|
|
|
|
raise Exception("angr requires setuptools-rust to build") from err
|
|
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
if sys.platform == "darwin":
|
2025-06-03 12:39:37 -07:00
|
|
|
library_file = "unicornlib.dylib"
|
2022-04-08 14:02:29 -07:00
|
|
|
elif sys.platform in ("win32", "cygwin"):
|
2025-06-03 12:39:37 -07:00
|
|
|
library_file = "unicornlib.dll"
|
2017-06-12 17:37:05 -07:00
|
|
|
else:
|
2025-06-03 12:39:37 -07:00
|
|
|
library_file = "unicornlib.so"
|
2017-06-12 17:37:05 -07:00
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
|
2025-06-03 12:39:37 -07:00
|
|
|
def build_unicornlib():
|
2017-06-12 17:37:05 -07:00
|
|
|
try:
|
2023-02-07 14:34:29 -07:00
|
|
|
importlib.import_module("pyvex")
|
2022-04-11 14:16:43 -07:00
|
|
|
except ImportError as e:
|
|
|
|
|
raise LibError("You must install pyvex before building angr") from e
|
|
|
|
|
|
2017-06-12 17:37:05 -07:00
|
|
|
env = os.environ.copy()
|
2022-04-08 14:02:29 -07:00
|
|
|
env_data = (
|
|
|
|
|
("PYVEX_INCLUDE_PATH", "pyvex", "include"),
|
|
|
|
|
("PYVEX_LIB_PATH", "pyvex", "lib"),
|
|
|
|
|
("PYVEX_LIB_FILE", "pyvex", "lib\\pyvex.lib"),
|
|
|
|
|
)
|
2017-06-12 17:37:05 -07:00
|
|
|
for var, pkg, fnm in env_data:
|
2024-07-01 17:16:43 -07:00
|
|
|
base = importlib.resources.files(pkg)
|
|
|
|
|
for child in fnm.split("\\"):
|
|
|
|
|
base = base.joinpath(child)
|
|
|
|
|
env[var] = str(base)
|
2017-06-12 17:37:05 -07:00
|
|
|
|
2022-06-10 03:09:25 -07:00
|
|
|
if sys.platform == "win32":
|
|
|
|
|
cmd = ["nmake", "/f", "Makefile-win"]
|
|
|
|
|
elif shutil.which("gmake") is not None:
|
|
|
|
|
cmd = ["gmake"]
|
2017-06-12 17:37:05 -07:00
|
|
|
else:
|
2022-06-10 03:09:25 -07:00
|
|
|
cmd = ["make"]
|
|
|
|
|
try:
|
2025-06-03 12:39:37 -07:00
|
|
|
subprocess.run(cmd, cwd="native/unicornlib", env=env, check=True)
|
2024-08-29 18:59:52 -07:00
|
|
|
except FileNotFoundError as err:
|
|
|
|
|
raise LibError("Couldn't find " + cmd[0] + " in PATH") from err
|
2022-06-10 03:09:25 -07:00
|
|
|
except subprocess.CalledProcessError as err:
|
2025-06-03 12:39:37 -07:00
|
|
|
raise LibError("Error while building unicornlib: " + str(err)) from err
|
2022-04-08 14:02:29 -07:00
|
|
|
|
|
|
|
|
shutil.rmtree("angr/lib", ignore_errors=True)
|
|
|
|
|
os.mkdir("angr/lib")
|
2025-06-03 12:39:37 -07:00
|
|
|
shutil.copy(os.path.join("native/unicornlib", library_file), "angr")
|
2017-06-12 17:37:05 -07:00
|
|
|
|
|
|
|
|
|
2026-07-22 03:03:40 -07:00
|
|
|
def build_protos():
|
|
|
|
|
proto_files = sorted(glob.glob("angr/protos/*.proto"))
|
|
|
|
|
cmd = [sys.executable, "-m", "grpc_tools.protoc", "-I.", "--python_out=.", *proto_files]
|
|
|
|
|
try:
|
|
|
|
|
subprocess.run(cmd, check=True)
|
|
|
|
|
except (FileNotFoundError, subprocess.CalledProcessError) as err:
|
|
|
|
|
raise LibError("Error while generating protobuf modules: " + str(err)) from err
|
|
|
|
|
|
|
|
|
|
|
2025-06-03 12:39:37 -07:00
|
|
|
def clean_unicornlib():
|
2022-04-08 14:02:29 -07:00
|
|
|
oglob = glob.glob("native/*.o")
|
|
|
|
|
oglob += glob.glob("native/*.obj")
|
|
|
|
|
oglob += glob.glob("native/*.so")
|
|
|
|
|
oglob += glob.glob("native/*.dll")
|
|
|
|
|
oglob += glob.glob("native/*.dylib")
|
2019-04-25 13:24:47 -07:00
|
|
|
for fname in oglob:
|
|
|
|
|
os.unlink(fname)
|
|
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
|
2022-03-29 14:59:43 -07:00
|
|
|
class build(st_build):
|
2017-06-12 17:37:05 -07:00
|
|
|
def run(self, *args):
|
2026-07-22 03:03:40 -07:00
|
|
|
self.execute(build_protos, (), msg="Generating protobuf modules")
|
2025-06-03 12:39:37 -07:00
|
|
|
self.execute(build_unicornlib, (), msg="Building unicornlib")
|
2022-03-16 17:36:57 -07:00
|
|
|
super().run(*args)
|
|
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
|
2025-06-03 12:39:37 -07:00
|
|
|
class clean(Command):
|
2022-03-16 17:36:57 -07:00
|
|
|
user_options = []
|
|
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
|
pass
|
2017-06-12 17:37:05 -07:00
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
def run(self):
|
2025-06-03 12:39:37 -07:00
|
|
|
self.execute(clean, (), msg="Cleaning unicornlib")
|
2022-04-08 14:02:29 -07:00
|
|
|
|
2019-04-25 13:24:47 -07:00
|
|
|
|
2022-03-29 14:59:43 -07:00
|
|
|
class develop(st_develop):
|
|
|
|
|
def run(self):
|
|
|
|
|
self.run_command("build")
|
|
|
|
|
super().run()
|
|
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
|
2017-06-12 17:37:05 -07:00
|
|
|
cmdclass = {
|
2022-04-08 14:02:29 -07:00
|
|
|
"build": build,
|
2025-06-03 12:39:37 -07:00
|
|
|
"clean_unicornlib": clean,
|
2022-04-08 14:02:29 -07:00
|
|
|
"develop": develop,
|
2017-06-12 17:37:05 -07:00
|
|
|
}
|
|
|
|
|
|
2022-10-06 15:02:53 -07:00
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from setuptools.command.editable_wheel import editable_wheel as st_editable_wheel
|
|
|
|
|
|
|
|
|
|
class editable_wheel(st_editable_wheel):
|
|
|
|
|
def run(self):
|
|
|
|
|
self.run_command("build")
|
|
|
|
|
super().run()
|
|
|
|
|
|
|
|
|
|
cmdclass["editable_wheel"] = editable_wheel
|
|
|
|
|
except ModuleNotFoundError:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
2022-04-08 14:02:29 -07:00
|
|
|
setup(cmdclass=cmdclass)
|