Skip to content

Commit 9f8392b

Browse files
committed
Add ci
1 parent d2379a7 commit 9f8392b

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env python3
2+
3+
import shutil
4+
import subprocess
5+
import sys
6+
import os
7+
import urllib.request
8+
import json
9+
import argparse
10+
import tempfile
11+
import zipfile
12+
13+
ENV_FILE = ".z3env"
14+
15+
def is_command_available(cmd):
16+
return shutil.which(cmd) is not None
17+
18+
def install_with_yum():
19+
print("Detected yum. Installing clang...", file=sys.stderr)
20+
try:
21+
subprocess.run(['yum', 'install', '-y', 'clang'], check=True)
22+
print("clang installed successfully.", file=sys.stderr)
23+
except subprocess.CalledProcessError:
24+
print("Failed to install clang using yum.", file=sys.stderr)
25+
return
26+
27+
def install_with_apt():
28+
print("Detected apt. Installing llvm-dev, libclang-dev, and clang...", file=sys.stderr)
29+
try:
30+
subprocess.run(['apt', 'update'], check=True)
31+
subprocess.run(['apt', 'install', '-y', 'build-essential', 'libc6-dev', 'gcc-multilib'], check=True)
32+
print("Packages installed successfully via apt.", file=sys.stderr)
33+
except subprocess.CalledProcessError:
34+
print("Failed to install packages using apt.", file=sys.stderr)
35+
36+
def write_env_file(z3_header_path, z3_lib_path):
37+
with open(ENV_FILE, "w") as f:
38+
f.write(f"export Z3_SYS_Z3_HEADER={z3_header_path}\n")
39+
f.write(f"export LD_LIBRARY_PATH={z3_lib_path}")
40+
f.write(f"export Z3_PATH={z3_lib_path}/libz3.so")
41+
f.write(f"export RUSTFLAGS='-L native={z3_lib_path}'")
42+
print(f"\n✅ Z3 environment variables written to `{ENV_FILE}`.")
43+
print(f"👉 To load them into your shell, run:\n")
44+
print(f" source ./{ENV_FILE}\n")
45+
46+
def install_z3_glibc(target_platform):
47+
print(f"Fetching and installing Z3 Linux glibc build for target platform '{target_platform}'...", file=sys.stderr)
48+
49+
# GitHub API to fetch the latest release
50+
api_url = "https://api.github.com/repos/Z3Prover/z3/releases/latest"
51+
with urllib.request.urlopen(api_url) as response:
52+
data = json.loads(response.read().decode())
53+
54+
assets = data.get("assets", [])
55+
56+
# Define glibc build prefix based on target platform
57+
if target_platform == 'x86_64': # x64 architecture
58+
glibc_arch_prefix = "x64-glibc"
59+
elif target_platform == 'aarch64': # ARM64 architecture
60+
glibc_arch_prefix = "arm64-glibc"
61+
else:
62+
raise Exception(f"Unsupported target platform: {target_platform}")
63+
64+
# Search for the correct glibc build file in the release assets
65+
glibc_url = None
66+
for asset in assets:
67+
if glibc_arch_prefix in asset["name"] and asset["name"].endswith(".zip"):
68+
glibc_url = asset["browser_download_url"]
69+
break
70+
71+
if not glibc_url:
72+
raise Exception(f"Could not find a suitable Z3 glibc build for platform {target_platform}.")
73+
74+
# Download and extract the glibc build
75+
print(f"Downloading glibc build from {glibc_url}...", file=sys.stderr)
76+
with tempfile.TemporaryDirectory() as tmpdir:
77+
zip_path = os.path.join(tmpdir, "z3-glibc.zip")
78+
urllib.request.urlretrieve(glibc_url, zip_path)
79+
80+
print("Extracting Z3 glibc archive...", file=sys.stderr)
81+
with zipfile.ZipFile(zip_path, "r") as zip_ref:
82+
zip_ref.extractall(tmpdir)
83+
84+
# Find the extracted Z3 directory
85+
extracted_dirs = [d for d in os.listdir(tmpdir) if os.path.isdir(os.path.join(tmpdir, d))]
86+
if not extracted_dirs:
87+
raise Exception("Extraction failed or directory structure unexpected.")
88+
z3_dir = os.path.join(tmpdir, extracted_dirs[0])
89+
90+
# Set the include and lib directories
91+
include_dir = os.path.join(z3_dir, "include")
92+
lib_dir = os.path.join(z3_dir, "bin")
93+
94+
# Create a stable location for Z3
95+
stable_install_dir = "/usr/local/z3"
96+
subprocess.run(['mkdir', '-p', stable_install_dir], check=True)
97+
subprocess.run(['cp', '-r', include_dir, stable_install_dir], check=True)
98+
subprocess.run(['cp', os.path.join(lib_dir, 'libz3.so'), '/usr/local/lib/'], check=True)
99+
subprocess.run(['ldconfig'], check=True)
100+
101+
# Set paths for z3.h and libz3.so
102+
z3_header_path = os.path.join(stable_install_dir, "include", "z3.h")
103+
z3_lib_path = "/usr/local/lib"
104+
105+
# Write the paths to the environment file
106+
write_env_file(z3_header_path, z3_lib_path)
107+
108+
def main():
109+
parser = argparse.ArgumentParser(description="Install Z3 glibc build for a target platform.")
110+
parser.add_argument("target_platform", choices=["x86_64", "aarch64"],
111+
help="Target platform architecture (e.g., x86_64 or aarch64).")
112+
args = parser.parse_args()
113+
114+
# Check if 'yum' or 'apt' are available for optional package installation
115+
if is_command_available('yum'):
116+
install_with_yum()
117+
elif is_command_available('apt'):
118+
install_with_apt()
119+
else:
120+
print("❌ Neither yum nor apt found on this system.", file=sys.stderr)
121+
122+
# Install Z3 glibc build based on the target platform
123+
install_z3_glibc(args.target_platform)
124+
125+
if __name__ == "__main__":
126+
main()

0 commit comments

Comments
 (0)