Skip to content

Commit b9b7259

Browse files
committed
Use our own Z3 if available
1 parent 4d6991e commit b9b7259

File tree

5 files changed

+143
-6
lines changed

5 files changed

+143
-6
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ RUN mkdir -p /cache && ./pkgman.py \
5252
--exclude_libcxx \
5353
"--additional_paths=${BOOTSTRAP}/cmake/bin" \
5454
"--repository_path=${LIBRARIES}" \
55-
"--packages=llvm" && \
55+
"--packages=z3,llvm" && \
5656
rm -rf build && mkdir build && \
5757
rm -rf sources && mkdir sources && rm -rf /cache
5858

@@ -71,7 +71,7 @@ RUN mkdir -p /cache && ./pkgman.py \
7171
--verbose \
7272
"--additional_paths=${BOOTSTRAP}/cmake/bin:${LIBRARIES}/llvm/bin" \
7373
"--repository_path=${LIBRARIES}" \
74-
"--packages=cmake,google,xed,z3" && \
74+
"--packages=cmake,google,xed" && \
7575
rm -rf build && mkdir build && \
7676
rm -rf sources && mkdir sources && rm -rf /cache
7777

pkgman.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,13 @@ def main():
115115
print(("Repository path: " + args.repository_path))
116116

117117
if "llvm" in packages_to_install:
118+
if "z3" not in packages_to_install:
119+
properties["llvm_has_z3"] = False
120+
else:
121+
properties["llvm_has_z3"] = True
122+
# ensure "z3" is always first to install
123+
packages_to_install.remove("z3")
124+
packages_to_install.insert(0, "z3")
118125
if sys.platform == "win32":
119126
supported_llvm_version_list = [501]
120127
else:

pkgman/installers/common.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,20 @@ def common_installer_llvm(properties):
558558
print(" x Failed to patch LLVM")
559559
return False
560560

561+
if int(properties["llvm_version"]) <= 1000:
562+
print(" i Fixing LLVM's FindZ3.cmake")
563+
fz3_location = os.path.realpath(os.path.join(llvm_root_folder, "cmake", "modules", "FindZ3.cmake"))
564+
have_fz3 = os.path.exists(fz3_location)
565+
if have_fz3:
566+
src_file = os.path.join(PATCHES_DIR, "FindZ3.cmake")
567+
# overwrite the bad FindZ3.cmake with our version
568+
shutil.copyfile(src_file, fz3_location)
569+
570+
src_file = os.path.join(PATCHES_DIR, "testz3.cpp")
571+
tz3_location = os.path.realpath(os.path.join(llvm_root_folder, "cmake", "modules", "testz3.cpp"))
572+
shutil.copyfile(src_file, tz3_location)
573+
574+
561575
# create the build directory and compile the package
562576
llvm_build_path = os.path.realpath(os.path.join("build", "llvm-" + str(properties["llvm_version"])))
563577
if not os.path.isdir(llvm_build_path):
@@ -582,7 +596,12 @@ def common_installer_llvm(properties):
582596
cmake_command = ["cmake"] + get_env_compiler_settings() + get_cmake_build_type(debug) + ["-DCMAKE_INSTALL_PREFIX=" + destination_path,
583597
"-DCMAKE_CXX_STANDARD="+cppstd, "-DLLVM_TARGETS_TO_BUILD=" + arch_list,
584598
"-DLLVM_ENABLE_RTTI=ON", "-DLLVM_INCLUDE_EXAMPLES=OFF",
585-
"-DLLVM_INCLUDE_TESTS=OFF", "-DLLVM_ENABLE_Z3_SOLVER=OFF"]
599+
"-DLLVM_INCLUDE_TESTS=OFF"]
600+
601+
if properties["llvm_has_z3"]:
602+
cmake_command += ["-DLLVM_ENABLE_Z3_SOLVER=ON", "-DLLVM_Z3_INSTALL_DIR=" + os.path.join(repository_path, "z3")]
603+
else:
604+
cmake_command += ["-DLLVM_ENABLE_Z3_SOLVER=OFF"]
586605

587606
if properties["ccache"]:
588607
print(" i Enabling ccache on /cache ... ")
@@ -644,9 +663,7 @@ def common_installer_z3(properties):
644663
return False
645664

646665
cmake_command = ["cmake"] + get_env_compiler_settings() + get_cmake_build_type(debug) + get_cmake_generator()
647-
cmake_command += ["-DCMAKE_CXX_STANDARD=11",
648-
"-DCMAKE_CXX_EXTENSIONS=ON",
649-
"-DZ3_BUILD_LIBZ3_SHARED=False",
666+
cmake_command += ["-DZ3_BUILD_LIBZ3_SHARED=False",
650667
"-DZ3_ENABLE_EXAMPLE_TARGETS=False",
651668
"-DZ3_BUILD_DOCUMENTATION=False",
652669
"-DZ3_BUILD_EXECUTABLE=True",

pkgman/patches/FindZ3.cmake

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
INCLUDE(CheckCXXSourceRuns)
2+
3+
# Function to check Z3's version
4+
function(check_z3_version z3_include z3_lib)
5+
# Get lib path
6+
get_filename_component(z3_lib_path ${z3_lib} PATH)
7+
8+
# Try to find a threading module in case Z3 was built with threading support.
9+
# Threads are required elsewhere in LLVM, but not marked as required here because
10+
# Z3 could have been compiled without threading support.
11+
find_package(Threads)
12+
set(z3_link_libs "-lz3" "${CMAKE_THREAD_LIBS_INIT}")
13+
14+
try_run(
15+
Z3_RETURNCODE
16+
Z3_COMPILED
17+
${CMAKE_BINARY_DIR}
18+
${CMAKE_SOURCE_DIR}/cmake/modules/testz3.cpp
19+
COMPILE_DEFINITIONS -I"${z3_include}"
20+
LINK_LIBRARIES -L${z3_lib_path} ${z3_link_libs}
21+
RUN_OUTPUT_VARIABLE SRC_OUTPUT
22+
)
23+
24+
if(Z3_COMPILED)
25+
string(REGEX REPLACE "([0-9]*\\.[0-9]*\\.[0-9]*)" "\\1"
26+
z3_version "${SRC_OUTPUT}")
27+
set(Z3_VERSION_STRING ${z3_version} PARENT_SCOPE)
28+
endif()
29+
endfunction(check_z3_version)
30+
31+
# Looking for Z3 in LLVM_Z3_INSTALL_DIR
32+
find_path(Z3_INCLUDE_DIR NAMES z3.h
33+
NO_DEFAULT_PATH
34+
PATHS ${LLVM_Z3_INSTALL_DIR}/include
35+
PATH_SUFFIXES libz3 z3
36+
)
37+
38+
find_library(Z3_LIBRARIES NAMES z3 libz3
39+
NO_DEFAULT_PATH
40+
PATHS ${LLVM_Z3_INSTALL_DIR}
41+
PATH_SUFFIXES lib bin
42+
)
43+
44+
# If Z3 has not been found in LLVM_Z3_INSTALL_DIR look in the default directories
45+
find_path(Z3_INCLUDE_DIR NAMES z3.h
46+
PATH_SUFFIXES libz3 z3
47+
)
48+
49+
find_library(Z3_LIBRARIES NAMES z3 libz3
50+
PATH_SUFFIXES lib bin
51+
)
52+
53+
# Searching for the version of the Z3 library is a best-effort task
54+
unset(Z3_VERSION_STRING)
55+
56+
# First, try to check it dynamically, by compiling a small program that
57+
# prints Z3's version
58+
if(Z3_INCLUDE_DIR AND Z3_LIBRARIES)
59+
# We do not have the Z3 binary to query for a version. Try to use
60+
# a small C++ program to detect it via the Z3_get_version() API call.
61+
check_z3_version(${Z3_INCLUDE_DIR} ${Z3_LIBRARIES})
62+
endif()
63+
64+
# If the dynamic check fails, we might be cross compiling: if that's the case,
65+
# check the version in the headers, otherwise, fail with a message
66+
if(NOT Z3_VERSION_STRING AND (CMAKE_CROSSCOMPILING AND
67+
Z3_INCLUDE_DIR AND
68+
EXISTS "${Z3_INCLUDE_DIR}/z3_version.h"))
69+
# TODO: print message warning that we couldn't find a compatible lib?
70+
71+
# Z3 4.8.1+ has the version is in a public header.
72+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
73+
z3_version_str REGEX "^#define[\t ]+Z3_MAJOR_VERSION[\t ]+.*")
74+
string(REGEX REPLACE "^.*Z3_MAJOR_VERSION[\t ]+([0-9]).*$" "\\1"
75+
Z3_MAJOR "${z3_version_str}")
76+
77+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
78+
z3_version_str REGEX "^#define[\t ]+Z3_MINOR_VERSION[\t ]+.*")
79+
string(REGEX REPLACE "^.*Z3_MINOR_VERSION[\t ]+([0-9]).*$" "\\1"
80+
Z3_MINOR "${z3_version_str}")
81+
82+
file(STRINGS "${Z3_INCLUDE_DIR}/z3_version.h"
83+
z3_version_str REGEX "^#define[\t ]+Z3_BUILD_NUMBER[\t ]+.*")
84+
string(REGEX REPLACE "^.*Z3_BUILD_VERSION[\t ]+([0-9]).*$" "\\1"
85+
Z3_BUILD "${z3_version_str}")
86+
87+
set(Z3_VERSION_STRING ${Z3_MAJOR}.${Z3_MINOR}.${Z3_BUILD})
88+
unset(z3_version_str)
89+
endif()
90+
91+
if(NOT Z3_VERSION_STRING)
92+
# Give up: we are unable to obtain a version of the Z3 library. Be
93+
# conservative and force the found version to 0.0.0 to make version
94+
# checks always fail.
95+
set(Z3_VERSION_STRING "0.0.0")
96+
endif()
97+
98+
# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if
99+
# all listed variables are TRUE
100+
include(FindPackageHandleStandardArgs)
101+
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3
102+
REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR
103+
VERSION_VAR Z3_VERSION_STRING)
104+
105+
mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES)

pkgman/patches/testz3.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <assert.h>
2+
#include <z3.h>
3+
int main() {
4+
unsigned int major, minor, build, rev;
5+
Z3_get_version(&major, &minor, &build, &rev);
6+
printf("%u.%u.%u", major, minor, build);
7+
return 0;
8+
}

0 commit comments

Comments
 (0)