# # Copyright (c) 2018 Microsoft Corporation # # 1. copy over dlls # 2. copy over libz3.dll for the different architectures # 3. copy over Microsoft.Z3.dll from suitable distribution # 4. copy nuspec file from packages # 5. call nuget pack # 6. sign package import json import os import zipfile import sys import os.path import shutil import subprocess def mk_dir(d): if not os.path.exists(d): os.makedirs(d) os_info = { 'x64-ubuntu-latest' : ('so', 'linux-x64'), 'x64-ubuntu-18' : ('so', 'linux-x64'), 'x64-ubuntu-20' : ('so', 'linux-x64'), 'x64-ubuntu-22' : ('so', 'linux-x64'), 'x64-glibc-2.35' : ('so', 'linux-x64'), 'x64-win' : ('dll', 'win-x64'), 'x86-win' : ('dll', 'win-x86'), 'x64-osx' : ('dylib', 'osx-x64'), 'debian' : ('so', 'linux-x64') } # Nuget not supported for ARM #'arm-glibc-2.35' : ('so', 'linux-arm64'), #'arm64-osx' : ('dylib', 'osx-arm64'), def classify_package(f, arch): for os_name in os_info: if os_name in f: ext, dst = os_info[os_name] return os_name, f[:-4], ext, dst print("Could not classify", f) return None def replace(src, dst): try: os.remove(dst) except: shutil.move(src, dst) def unpack(packages, symbols, arch): # unzip files in packages # out # +- runtimes # +- win-x64 # +- win-x86 # +- linux-x64 # +- osx-x64 # + tmp = "tmp" if not symbols else "tmpsym" for f in os.listdir(packages): print(f) if f.endswith(".zip") and classify_package(f, arch): os_name, package_dir, ext, dst = classify_package(f, arch) path = os.path.abspath(os.path.join(packages, f)) zip_ref = zipfile.ZipFile(path, 'r') zip_ref.extract(f"{package_dir}/bin/libz3.{ext}", f"{tmp}") mk_dir(f"out/runtimes/{dst}/native") replace(f"{tmp}/{package_dir}/bin/libz3.{ext}", f"out/runtimes/{dst}/native/libz3.{ext}") if "x64-win" in f or "x86-win" in f: mk_dir("out/lib/netstandard2.0/") if symbols: zip_ref.extract(f"{package_dir}/bin/libz3.pdb", f"{tmp}") replace(f"{tmp}/{package_dir}/bin/libz3.pdb", f"out/runtimes/{dst}/native/libz3.pdb") files = ["Microsoft.Z3.dll", "Microsoft.Z3.pdb", "Microsoft.Z3.xml"] for b in files: file1 = f"{package_dir}/bin/{b}" file2 = f"{package_dir}/bin/netstandard2.0/{b}" found_path = False # check that file1 exists in zip_ref: try: zip_ref.extract(file1, f"{tmp}") replace(f"{tmp}/{file1}", f"out/lib/netstandard2.0/{b}") found_path = True except: pass try: zip_ref.extract(file2, f"{tmp}") replace(f"{tmp}/{file2}", f"out/lib/netstandard2.0/{b}") found_path = True except: pass if not found_path: print(f"Could not find file path {file1} nor {file2}") def mk_targets(source_root): mk_dir("out/build") shutil.copy(f"{source_root}/src/api/dotnet/Microsoft.Z3.targets.in", "out/build/Microsoft.Z3.targets") def mk_icon(source_root): mk_dir("out/content") shutil.copy(f"{source_root}/resources/icon.jpg", "out/content/icon.jpg") # shutil.copy(f"{source_root}/src/api/dotnet/README.md", "out/content/README.md") def create_nuget_spec(version, repo, branch, commit, symbols, arch): arch = f".{arch}" if arch == "x86" else "" contents = """ Microsoft.Z3{4} {0} Microsoft Z3 is a satisfiability modulo theories solver from Microsoft Research. Linux Dependencies: libgomp.so.1 installed © Microsoft Corporation. All rights reserved. smt constraint solver theorem prover content/icon.jpg https://github.com/Z3Prover/z3 MIT true en """.format(version, repo, branch, commit, arch) print(contents) sym = "sym." if symbols else "" file = f"out/Microsoft.Z3{arch}.{sym}nuspec" print(file) with open(file, 'w') as f: f.write(contents) class Env: def __init__(self, argv): self.packages = argv[1] self.version = argv[2] self.repo = argv[3] self.branch = argv[4] self.commit = argv[5] self.source_root = argv[6] self.symbols = False self.arch = "x64" if len(argv) > 7 and "symbols" == argv[7]: self.symbols = True if len(argv) > 8: self.arch = argv[8] def create(self): mk_dir(self.packages) unpack(self.packages, self.symbols, self.arch) mk_targets(self.source_root) mk_icon(self.source_root) create_nuget_spec(self.version, self.repo, self.branch, self.commit, self.symbols, self.arch) def main(): env = Env(sys.argv) print(env.packages) env.create() main()