Skip to content

Commit

Permalink
porting unix distribution script to cmake
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
  • Loading branch information
NikolajBjorner committed Jan 31, 2024
1 parent 28c44a6 commit 99ebbd6
Showing 1 changed file with 268 additions and 0 deletions.
268 changes: 268 additions & 0 deletions scripts/mk_unix_dist_cmake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
############################################
# Copyright (c) 2013 Microsoft Corporation
#
# Scripts for automatically generating
# Linux/OSX/BSD distribution zip files.
#
# Author: Leonardo de Moura (leonardo)
############################################

import os
import subprocess
import zipfile
import re
import getopt
import sys
import shutil
from mk_exception import *
from fnmatch import fnmatch

def getenv(name, default):
try:
return os.environ[name].strip(' "\'')
except:
return default

BUILD_DIR = 'build-dist'
DIST_DIR = 'dist'
VERBOSE = True
FORCE_MK = False
ASSEMBLY_VERSION = None
DOTNET_CORE_ENABLED = True
DOTNET_KEY_FILE = None
JAVA_ENABLED = True
JULIA_ENABLED = False
GIT_HASH = False
PYTHON_ENABLED = True
ARM64 = False
MAKEJOBS = getenv("MAKEJOBS", "24")

def set_verbose(flag):
global VERBOSE
VERBOSE = flag

def is_verbose():
return VERBOSE

def mk_dir(d):
if not os.path.exists(d):
if is_verbose():
print("Make directory", d)
os.makedirs(d)

def get_z3_name():
version = "4"
if ASSEMBLY_VERSION:
version = ASSEMBLY_VERSION
print("Assembly version:", version)
if GIT_HASH:
return 'z3-%s.%s' % (version, get_git_hash())
else:
return 'z3-%s' % (version)

def get_build_dir():
return BUILD_DIR

def get_build_dist():
return os.path.join(get_build_dir(), DIST_DIR)

def get_build_dist_path():
return os.path.join(get_build_dist(), get_z3_name())

def set_build_dir(path):
global BUILD_DIR
BUILD_DIR = os.path.expanduser(os.path.normpath(path))
mk_dir(BUILD_DIR)

def display_help():
print("mk_unix_dist_cmake.py: Z3 Unix distribution generator\n")
print("This script generates the zip files containing executables, shared objects, header files for Unix.")
print("It must be executed from the Z3 root directory.")
print("\nOptions:")
print(" -h, --help display this message.")
print(" -s, --silent do not print verbose messages.")
print(" -b <subdir>, --build=<subdir> subdirectory where Z3 will be built (default: build-dist).")
print(" -f, --force force script to regenerate Makefiles.")
print(" --version=<version> release version.")
print(" --assembly-version assembly version for dll")
print(" --nodotnet do not include .NET bindings in the binary distribution files.")
print(" --dotnet-key=<file> strongname sign the .NET assembly with the private key in <file>.")
print(" --nojava do not include Java bindings in the binary distribution files.")
print(" --nopython do not include Python bindings in the binary distribution files.")
print(" --julia build Julia bindings.")
print(" --githash include git hash in the Zip file.")
print(" --arm64 build for ARM64 architecture.")
exit(0)

# Parse configuration option for mk_make script
def parse_options():
global FORCE_MK, JAVA_ENABLED, JULIA_ENABLED, GIT_HASH, DOTNET_CORE_ENABLED, DOTNET_KEY_FILE, ASSEMBLY_VERSION, PYTHON_ENABLED, ARM64
path = BUILD_DIR
options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=',
'help',
'silent',
'force',
'nojava',
'nodotnet',
'dotnet-key=',
'assembly-version=',
'githash',
'nopython',
'julia',
'arm64'
])
for opt, arg in options:
if opt in ('-b', '--build'):
if arg == 'src':
raise MKException('The src directory should not be used to host the Makefile')
path = arg
elif opt in ('-s', '--silent'):
set_verbose(False)
elif opt in ('-h', '--help'):
display_help()
elif opt in ('-f', '--force'):
FORCE_MK = True
elif opt == '--nodotnet':
DOTNET_CORE_ENABLED = False
elif opt == '--assembly-version':
ASSEMBLY_VERSION = arg
elif opt == '--nopython':
PYTHON_ENABLED = False
elif opt == '--dotnet-key':
DOTNET_KEY_FILE = arg
elif opt == '--nojava':
JAVA_ENABLED = False
elif opt == '--julia':
JULIA_ENABLED = True
elif opt == '--githash':
GIT_HASH = True
elif opt == '--arm64':
ARM64 = True
else:
raise MKException("Invalid command line option '%s'" % opt)
set_build_dir(path)

def check_output(cmd):
out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
if out != None:
enc = sys.getdefaultencoding()
if enc != None: return out.decode(enc).rstrip('\r\n')
else: return out.rstrip('\r\n')
else:
return ""

def get_git_hash():
try:
branch = check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])
r = check_output(['git', 'show-ref', '--abbrev=12', 'refs/heads/%s' % branch])
except:
raise MKException("Failed to retrieve git hash")
ls = r.split(' ')
if len(ls) != 2:
raise MKException("Unexpected git output " + r)
return ls[0]

# Create a build directory using CMake
def mk_build_dir():
build_path = get_build_dir()
if not os.path.exists(build_path) or FORCE_MK:
mk_dir(build_path)
cmds = []
cmds.append(f"cd {build_path}")
cmd = []
cmd.append("cmake -S .")
if DOTNET_CORE_ENABLED:
cmd.append(' -DZ3_BUILD_DOTNET_BINDINGS=ON')
if JAVA_ENABLED:
cmd.append(' -DZ3_BUILD_JAVA_BINDINGS=ON')
cmd.append(' -DZ3_INSTALL_JAVA_BINDINGS=ON')
cmd.append(' -DZ3_JAVA_JAR_INSTALLDIR=java')
cmd.append(' -DZ3_JAVA_JNI_LIB_INSTALLDIR=bin/java')
if PYTHON_ENABLED:
cmd.append(' -DZ3_BUILD_PYTHON_BINDINGS=ON')
cmd.append(' -DZ3_INSTALL_PYTHON_BINDINGS=ON')
cmd.append(' -DCMAKE_INSTALL_PYTHON_PKG_DIR=bin/python')
if JULIA_ENABLED:
cmd.append(' -DZ3_BUILD_JULIA_BINDINGS=ON')
cmd.append(' -DZ3_INSTALL_JULIA_BINDINGS=ON')
if GIT_HASH:
git_hash = get_git_hash()
cmd.append(' -DGIT_HASH=' + git_hash)
cmd.append(' -DZ3_USE_LIB_GMP=OFF')
cmd.append(' -DZ3_BUILD_LIBZ3_SHARED=ON')
cmd.append(' -DCMAKE_BUILD_TYPE=RelWithDebInfo')
cmd.append(' -DCMAKE_INSTALL_PREFIX=' + get_build_dist_path())
cmd.append(' -G "Ninja"')
cmd.append(' ..\n')
cmds.append("".join(cmd))
print("CMAKE commands:", cmds)
sys.stdout.flush()
if exec_cmds(cmds) != 0:
raise MKException("failed to run commands")

def exec_cmds(cmds):
cmd_file = 'z3_tmp.sh'
f = open(cmd_file, 'w')
for cmd in cmds:
f.write(cmd)
f.write('\n')
f.close()
res = 0
try:
res = subprocess.call(['sh', cmd_file])
except:
res = 1
try:
os.remove(cmd_file)
except:
pass
return res

def build_z3():
if is_verbose():
print("build z3")
build_dir = get_build_dir()
cmds = []
cmds.append('cd %s' % build_dir)
cmds.append('ninja install')
if exec_cmds(cmds) != 0:
raise MKException("Failed to make z3")

def mk_zip():
build_dist = get_build_dist_path()
dist_name = get_z3_name()
old = os.getcwd()
try:
if is_verbose():
print("dist path", build_dist)
mk_dir(build_dist)
zfname = '%s.zip' % dist_name
zipout = zipfile.ZipFile(zfname, 'w', zipfile.ZIP_DEFLATED)
os.chdir(get_build_dist())
for root, dirs, files in os.walk("."):
for f in files:
if is_verbose():
print("adding ", os.path.join(root, f))
zipout.write(os.path.join(root, f))
if is_verbose():
print("Generated '%s'" % zfname)
except:
pass
os.chdir(old)

def cp_license():
if is_verbose():
print("copy licence")
path = get_build_dist_path()
mk_dir(path)
shutil.copy("LICENSE.txt", path)

# Entry point
def main():
parse_options()
mk_build_dir()
build_z3()
cp_license()
mk_zip()

main()

0 comments on commit 99ebbd6

Please sign in to comment.