about summary refs log tree commit diff stats
path: root/setup.py
diff options
context:
space:
mode:
Diffstat (limited to 'setup.py')
-rw-r--r--setup.py61
1 files changed, 58 insertions, 3 deletions
diff --git a/setup.py b/setup.py
index 4b149772..a20cf9a1 100644
--- a/setup.py
+++ b/setup.py
@@ -7,14 +7,20 @@ from distutils.sysconfig import get_python_lib, get_config_vars
 from distutils.dist import DistributionMetadata
 from distutils.command.install_data import install_data
 from tempfile import TemporaryFile
+import fnmatch
 import io
 import os
 import platform
-from shutil import copy2
+from shutil import copy2, copyfile, rmtree
 import sys
+import tempfile
+import atexit
 
 is_win = platform.system() == "Windows"
 is_mac = platform.system() == "Darwin"
+is_64bit = platform.architecture()[0] == "64bit"
+if is_win:
+    import winreg
 
 def set_extension_compile_args(extension):
     rel_lib_path = extension.name.replace('.', '/')
@@ -22,7 +28,6 @@ def set_extension_compile_args(extension):
     lib_name = abs_lib_path + '.so'
     extension.extra_link_args = [ '-Wl,-install_name,' + lib_name]
 
-
 class smart_install_data(install_data):
     """Replacement for distutils.command.install_data to handle
     configuration files location.
@@ -35,6 +40,48 @@ class smart_install_data(install_data):
         ]
         return install_data.run(self)
 
+def win_get_llvm_reg():
+    REG_PATH = "SOFTWARE\\LLVM\\LLVM"
+    try:
+      return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, REG_PATH, 0, winreg.KEY_READ | winreg.KEY_WOW64_32KEY)
+    except FileNotFoundError:
+      pass
+    return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, REG_PATH, 0, winreg.KEY_READ)
+  
+def win_find_clang_path():
+    try:
+        with win_get_llvm_reg() as rkey:
+            return winreg.QueryValueEx(rkey, None)[0]
+    except FileNotFoundError:
+        return None
+
+def win_use_clang():
+    # Recent (>= 8 ?) LLVM versions does not ship anymore a cl.exe binary in
+    # the msbuild-bin directory. Thus, we need to
+    # * copy-paste bin/clang-cl.exe into a temporary directory
+    # * rename it to cl.exe
+    # * add that path first in %Path%
+    # * clean this mess on exit
+    # We could use the build directory created by distutils for this, but it
+    # seems non trivial to gather
+    # (https://stackoverflow.com/questions/12896367/reliable-way-to-get-the-build-directory-from-within-setup-py).
+    clang_path = win_find_clang_path()
+    if clang_path is None:
+        return False
+    tmpdir = tempfile.mkdtemp(prefix="llvm")
+    copyfile(os.path.join(clang_path, "bin", "clang-cl.exe"), os.path.join(tmpdir, "cl.exe"))
+    os.environ['Path'] = "%s;%s" % (tmpdir, os.environ["Path"])
+    atexit.register(lambda dir_: rmtree(dir_), tmpdir)
+
+    return True
+
+win_force_clang = False
+if is_win and is_64bit:
+    # We do not change to clang if under 32 bits, because even with Clang we
+    # don't have uint128_t with the 32 bits ABI.
+    win_force_clang = win_use_clang()
+    if not win_force_clang:
+        print("Warning: couldn't find a Clang/LLVM installation. Some runtime functions needed by the jitter won't be compiled.")
 
 def buil_all():
     packages=[
@@ -153,6 +200,9 @@ def buil_all():
         Extension("miasm.jitter.Jitllvm",
                   ["miasm/jitter/Jitllvm.c",
                    "miasm/jitter/bn.c",
+                   "miasm/runtime/udivmodti4.c",
+                   "miasm/runtime/divti3.c",
+                   "miasm/runtime/udivti3.c"
                   ]),
         Extension("miasm.jitter.Jitgcc",
                   ["miasm/jitter/Jitgcc.c",
@@ -164,6 +214,10 @@ def buil_all():
         # Force setuptools to use whatever msvc version installed
         os.environ['MSSdk'] = '1'
         os.environ['DISTUTILS_USE_SDK'] = '1'
+        if win_force_clang:
+            march = "-m64" if is_64bit else "-m32"
+            for extension in ext_modules_all:
+                extension.extra_compile_args = [march]
     elif is_mac:
         for extension in ext_modules_all:
             set_extension_compile_args(extension)
@@ -248,7 +302,8 @@ def buil_all():
         for lib in libs:
             filename = os.path.basename(lib)
             dst = os.path.join(build_base, lib_dirname, "miasm", "jitter")
-            if filename not in ["VmMngr.lib", "Jitgcc.lib", "Jitllvm.lib"]:
+            # Windows built libraries may have a name like VmMngr.cp38-win_amd64.lib
+            if not any([fnmatch.fnmatch(filename, pattern) for pattern in ["VmMngr.*lib", "Jitgcc.*lib", "Jitllvm.*lib"]]):
                 dst = os.path.join(dst, "arch")
             dst = os.path.join(dst, filename)
             if not os.path.isfile(dst):