def call_vcvarsall_bat(self): import struct from setuptools.msvc import msvc14_get_vc_env arch = "x64" if struct.calcsize("P") * 8 == 64 else "x86" vc_env = msvc14_get_vc_env(arch) self._compiler_env.update(vc_env)
def get_msvc_env(): global _msvc_env arch_name = prefs['codegen.cpp.msvc_architecture'] if arch_name == '': bits = struct.calcsize('P') * 8 if bits == 64: arch_name = 'x86_amd64' else: arch_name = 'x86' # Manual specification of vcvarsall.bat location by the user vcvars_loc = prefs['codegen.cpp.msvc_vars_location'] if vcvars_loc: vcvars_cmd = '"{vcvars_loc}" {arch_name}'.format(vcvars_loc=vcvars_loc, arch_name=arch_name) return None, vcvars_cmd # Search for MSVC environemtn if not already cached if _msvc_env is None: try: _msvc_env = msvc.msvc14_get_vc_env(arch_name) except distutils.errors.DistutilsPlatformError: raise IOError("Cannot find Microsoft Visual Studio, You " "can try to set the path to vcvarsall.bat " "via the codegen.cpp.msvc_vars_location " "preference explicitly.") return _msvc_env, None
def locate_vcredist_dir(): """Locate vcredist directory and add it to $PATH Adding it to $PATH is required to run executables that link libzmq to find e.g. msvcp140.dll """ from setuptools import msvc try: from setuptools._distutils.util import get_platform except ImportError: from distutils.util import get_platform vcvars = msvc.msvc14_get_vc_env(get_platform()) try: vcruntime = vcvars["py_vcruntime_redist"] except KeyError: warn(f"platform={get_platform()}, vcvars=") pprint(vcvars, stream=sys.stderr) warn( "Failed to get py_vcruntime_redist via vcvars, may need to set it in %PATH%" ) return None redist_dir, dll = os.path.split(vcruntime) # add redist dir to $PATH so that it can be found os.environ["PATH"] += os.pathsep + redist_dir return redist_dir
def get_environment(): from setuptools.msvc import (msvc9_query_vcvarsall, EnvironmentInfo, msvc14_get_vc_env) py_version = sys.version_info[:2] if py_version >= (3, 5): env = msvc14_get_vc_env(ARCH) msbuild_version = 14.0 env_info = EnvironmentInfo(ARCH) msbuild_path = _find_file('MSBuild.exe', env_info.MSBuild[0])[0] sdks = ('10.0', '8.1', '8.1A', '8.0', '8.0A') solution_dest = 'vs2015' elif (3, 5) > py_version >= (3, 3): env = msvc9_query_vcvarsall(10.0, ARCH) msbuild_version = 4.0 msbuild_path = _get_reg_value('MSBuild\\4.0', 'MSBuildOverrideTasksPath') if msbuild_path: msbuild_path = _find_file('MSBuild.exe', msbuild_path)[0] sdks = ('7.1', '7.0A') solution_dest = 'vs2010' elif (3, 3) > py_version >= (2, 6): env = msvc9_query_vcvarsall(9.0, ARCH) msbuild_version = 4.0 msbuild_path = _get_reg_value('MSBuild\\4.0', 'MSBuildOverrideTasksPath') if msbuild_path: msbuild_path = _find_file('MSBuild.exe', msbuild_path)[0] sdks = ('6.1', '6.1A', '6.0A') solution_dest = 'vs2008' else: raise RuntimeError( 'This library does not support python versions < 2.6') for sdk in sdks: sdk_version = _get_reg_value('Microsoft SDKs\\Windows\\v' + sdk, 'ProductVersion') if sdk_version: sdk_installation_folder = _get_reg_value( 'Microsoft SDKs\\Windows\\v' + sdk, 'InstallationFolder') target_platform = sdk_version os.environ['WindowsSdkDir'] = sdk_installation_folder break else: raise RuntimeError('Unable to locate suitable SDK %s' % (sdks, )) platform_toolset, tools_version = TOOLSETS[msbuild_version] return (env, msbuild_version, msbuild_path, sdk_installation_folder, target_platform, platform_toolset, tools_version, solution_dest)
def get_msvc_env(): global _msvc_env from setuptools import msvc import distutils vcvars_loc = prefs['codegen.cpp.msvc_vars_location'] if vcvars_loc: return vcvars_loc, None arch_name = prefs['codegen.cpp.msvc_architecture'] if arch_name == '': bits = struct.calcsize('P') * 8 if bits == 64: arch_name = 'x86_amd64' else: arch_name = 'x86' if _msvc_env is None: try: # This will fail on Python 2 with an AttributError _msvc_env = msvc.msvc14_get_vc_env(arch_name) except (distutils.errors.DistutilsPlatformError, AttributeError): # Use the old way of searching for MSVC # FIXME: Remove this when we remove Python 2 support # and require Visual Studio 2015? for version in range(16, 8, -1): fname = msvc.msvc9_find_vcvarsall(version) if fname: vcvars_loc = fname break if vcvars_loc == '': raise IOError("Cannot find Microsoft Visual Studio, You " "can try to set the path to vcvarsall.bat " "via the codegen.cpp.msvc_vars_location " "preference explicitly.") if vcvars_loc: vcvars_cmd = '"{vcvars_loc}" {arch_name}'.format(vcvars_loc=vcvars_loc, arch_name=arch_name) else: vcvars_cmd = None return _msvc_env, vcvars_cmd
def build_extension(self, ext): if self.distribution.lief_test: log.info("LIEF tests enabled!") fullname = self.get_ext_fullname(ext.name) jobs = self.parallel if self.parallel else 1 cmake_args = ["-DLIEF_FORCE_API_EXPORTS=ON", "-DLIEF_PYTHON_API=on"] build_temp = self.build_temp cmake_library_output_directory = os.path.abspath( os.path.dirname(build_temp)) cfg = 'RelWithDebInfo' if self.debug else 'Release' is64 = sys.maxsize > 2**32 # Ninja ? build_with_ninja = False if self.has_ninja() and self.distribution.ninja: build_with_ninja = True if build_with_ninja: cmake_args += ["-G", "Ninja"] cmake_args += [ '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}'.format( cmake_library_output_directory), '-DPYTHON_EXECUTABLE={}'.format(sys.executable), '-DLIEF_PYTHON_API=on', ] # LIEF options # ============ if self.distribution.lief_test: cmake_args += ["-DLIEF_TESTS=on"] if self.distribution.lief_no_json: log.info("LIEF JSON module disabled") cmake_args += ["-DLIEF_ENABLE_JSON=off"] if self.distribution.lief_no_logging: log.info("LIEF logging module disabled") cmake_args += ["-DLIEF_LOGGING=off"] if self.distribution.doc: log.info("LIEF documentation enabled") cmake_args += ["-DLIEF_DOC=on"] if self.debug: log.info("LIEF enables DEBUG messages") cmake_args += ["-DLIEF_LOGGING_DEBUG=on"] else: cmake_args += ["-DLIEF_LOGGING_DEBUG=off"] if self.distribution.lief_no_cache: cmake_args += ["-DLIEF_USE_CCACHE=off"] # Setup spdlog configuration flags if # the user provides --spdlog-dir if self.distribution.spdlog_dir is not None: cmake_args.append("-DLIEF_EXTERNAL_SPDLOG=ON") cmake_args.append("-Dspdlog_DIR={}".format( self.distribution.spdlog_dir)) if self.distribution.lief_config_extra is not None and len( self.distribution.lief_config_extra) > 0: args = self.distribution.lief_config_extra.replace("\n", "") args = map(lambda a: a.strip(), args.split(";")) cmake_args += list(args) # Main formats # ============ if self.distribution.lief_no_elf: log.info("LIEF ELF module disabled") cmake_args += ["-DLIEF_ELF=off"] if self.distribution.lief_no_pe: log.info("LIEF PE module disabled") cmake_args += ["-DLIEF_PE=off"] if self.distribution.lief_no_macho: log.info("LIEF MACH-O module disabled") cmake_args += ["-DLIEF_MACHO=off"] # Android formats # =============== if self.distribution.lief_no_oat or self.distribution.lief_no_android: log.info("LIEF OAT module disabled") cmake_args += ["-DLIEF_OAT=off"] if self.distribution.lief_no_dex or self.distribution.lief_no_android: log.info("LIEF DEX module disabled") cmake_args += ["-DLIEF_DEX=off"] if self.distribution.lief_no_vdex or self.distribution.lief_no_android: log.info("LIEF VDEX module disabled") cmake_args += ["-DLIEF_VDEX=off"] if self.distribution.lief_no_art or self.distribution.lief_no_android: log.info("LIEF ART module disabled") cmake_args += ["-DLIEF_ART=off"] build_args = ['--config', cfg] env = os.environ if os.getenv("CXXFLAGS", None) is not None: cmake_args += [ '-DCMAKE_CXX_FLAGS={}'.format(os.getenv("CXXFLAGS")), ] if os.getenv("CFLAGS", None) is not None: cmake_args += [ '-DCMAKE_C_FLAGS={}'.format(os.getenv("CFLAGS")), ] if platform.system() == "Windows": from setuptools import msvc cmake_args += [ '-DCMAKE_BUILD_TYPE={}'.format(cfg), '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format( cfg.upper(), cmake_library_output_directory), '-DLIEF_USE_CRT_RELEASE=MT', ] if build_with_ninja: arch = 'x64' if is64 else 'x86' ninja_env = msvc.msvc14_get_vc_env(arch) env.update(ninja_env) else: cmake_args += ['-A', 'x64'] if is64 else ['-A', 'win32'] build_args += ['--', '/m'] else: cmake_args += ['-DCMAKE_BUILD_TYPE={}'.format(cfg)] if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) log.info("Platform: %s", platform.system()) log.info("Wheel library: %s", self.get_ext_fullname(ext.name)) # 1. Configure configure_cmd = ['cmake', ext.sourcedir] + cmake_args log.info(" ".join(configure_cmd)) subprocess.check_call(configure_cmd, cwd=self.build_temp, env=env) # 2. Build targets = { 'python_bindings': 'pyLIEF', } if self.distribution.sdk: targets['sdk'] = "package" if self.distribution.doc: targets['doc'] = "lief-doc" if platform.system() == "Windows": if self.distribution.lief_test: subprocess.check_call(configure_cmd, cwd=self.build_temp, env=env) if build_with_ninja: subprocess.check_call( ['cmake', '--build', '.', '--target', "all"] + build_args, cwd=self.build_temp, env=env) else: subprocess.check_call( ['cmake', '--build', '.', '--target', "ALL_BUILD"] + build_args, cwd=self.build_temp, env=env) subprocess.check_call( ['cmake', '--build', '.', '--target', "check-lief"] + build_args, cwd=self.build_temp, env=env) else: subprocess.check_call([ 'cmake', '--build', '.', '--target', targets['python_bindings'] ] + build_args, cwd=self.build_temp, env=env) if 'sdk' in targets: subprocess.check_call( ['cmake', '--build', '.', '--target', targets['sdk']] + build_args, cwd=self.build_temp, env=env) else: if build_with_ninja: if self.distribution.lief_test: subprocess.check_call(configure_cmd, cwd=self.build_temp) subprocess.check_call(['ninja'], cwd=self.build_temp) subprocess.check_call(['ninja', "check-lief"], cwd=self.build_temp) else: subprocess.check_call( ['ninja', targets['python_bindings']], cwd=self.build_temp, env=env) if 'sdk' in targets: subprocess.check_call(['ninja', targets['sdk']], cwd=self.build_temp, env=env) if 'doc' in targets: try: subprocess.check_call(['ninja', targets['doc']], cwd=self.build_temp, env=env) except Exception as e: log.error("Documentation failed: %s" % e) else: log.info("Using {} jobs".format(jobs)) if self.distribution.lief_test: subprocess.check_call(configure_cmd, cwd=self.build_temp) subprocess.check_call( ['make', '-j', str(jobs), "all"], cwd=self.build_temp) subprocess.check_call( ['make', '-j', str(jobs), "check-lief"], cwd=self.build_temp) else: subprocess.check_call( ['make', '-j', str(jobs), targets['python_bindings']], cwd=self.build_temp, env=env) if 'sdk' in targets: subprocess.check_call( ['make', '-j', str(jobs), targets['sdk']], cwd=self.build_temp, env=env) if 'doc' in targets: try: subprocess.check_call( ['make', '-j', str(jobs), targets['doc']], cwd=self.build_temp, env=env) except Exception as e: log.error("Documentation failed: %s" % e) pylief_dst = os.path.join( self.build_lib, self.get_ext_filename(self.get_ext_fullname(ext.name))) libsuffix = pylief_dst.split(".")[-1] pylief_path = os.path.join(cmake_library_output_directory, "{}.{}".format(PACKAGE_NAME, libsuffix)) if platform.system() == "Windows": pylief_base = pathlib.Path( cmake_library_output_directory) / "Release" / "api" / "python" pylief_path = pylief_base / "Release" / "{}.{}".format( PACKAGE_NAME, libsuffix) if not pylief_path.is_file(): pylief_path = pylief_base / "{}.{}".format( PACKAGE_NAME, libsuffix) pylief_path = pylief_path.as_posix() if not os.path.exists(self.build_lib): os.makedirs(self.build_lib) log.info("Copying {} into {}".format(pylief_path, pylief_dst)) copy_file(pylief_path, pylief_dst, verbose=self.verbose, dry_run=self.dry_run) # SDK # === if self.distribution.sdk: sdk_path = list( pathlib.Path(self.build_temp).rglob("LIEF-*.{}".format( self.sdk_suffix()))) if len(sdk_path) == 0: log.error("Unable to find SDK archive") sys.exit(1) sdk_path = str(sdk_path.pop()) sdk_output = str(pathlib.Path(CURRENT_DIR) / "build") copy_file(sdk_path, sdk_output, verbose=self.verbose, dry_run=self.dry_run)
def bundle_libzmq_extension(self): bundledir = "bundled" ext_modules = self.distribution.ext_modules if ext_modules and any(m.name == 'zmq.libzmq' for m in ext_modules): # I've already been run return line() info("Using bundled libzmq") # fetch sources for libzmq extension: if not os.path.exists(bundledir): os.makedirs(bundledir) fetch_libzmq(bundledir) stage_platform_hpp(pjoin(bundledir, 'zeromq')) sources = [pjoin('buildutils', 'initlibzmq.cpp')] sources.extend([ src for src in glob(pjoin(bundledir, 'zeromq', 'src', '*.cpp')) # exclude draft ws transport files if not os.path.basename(src).startswith(("ws_", "wss_")) ]) includes = [pjoin(bundledir, 'zeromq', 'include')] if bundled_version < (4, 2, 0): tweetnacl = pjoin(bundledir, 'zeromq', 'tweetnacl') tweetnacl_sources = glob(pjoin(tweetnacl, 'src', '*.c')) randombytes = pjoin(tweetnacl, 'contrib', 'randombytes') if sys.platform.startswith('win'): tweetnacl_sources.append(pjoin(randombytes, 'winrandom.c')) else: tweetnacl_sources.append(pjoin(randombytes, 'devurandom.c')) sources += tweetnacl_sources includes.append(pjoin(tweetnacl, 'src')) includes.append(randombytes) else: # >= 4.2 sources += glob(pjoin(bundledir, 'zeromq', 'src', 'tweetnacl.c')) # construct the Extensions: libzmq = Extension( 'zmq.libzmq', sources=sources, include_dirs=includes, ) # register the extension: # doing this here means we must be run # before finalize_options in build_ext self.distribution.ext_modules.insert(0, libzmq) # use tweetnacl to provide CURVE support libzmq.define_macros.append(('ZMQ_HAVE_CURVE', 1)) libzmq.define_macros.append(('ZMQ_USE_TWEETNACL', 1)) # select polling subsystem based on platform if sys.platform == "darwin" or "bsd" in sys.platform: libzmq.define_macros.append(('ZMQ_USE_KQUEUE', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_KQUEUE', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) elif 'linux' in sys.platform: libzmq.define_macros.append(('ZMQ_USE_EPOLL', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_EPOLL', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) elif sys.platform.startswith('win'): libzmq.define_macros.append(('ZMQ_USE_SELECT', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_SELECT', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_SELECT', 1)) else: # this may not be sufficiently precise libzmq.define_macros.append(('ZMQ_USE_POLL', 1)) libzmq.define_macros.append(('ZMQ_IOTHREADS_USE_POLL', 1)) libzmq.define_macros.append(('ZMQ_POLL_BASED_ON_POLL', 1)) if sys.platform.startswith('win'): # include defines from zeromq msvc project: libzmq.define_macros.append(('FD_SETSIZE', 16384)) libzmq.define_macros.append(('DLL_EXPORT', 1)) libzmq.define_macros.append(('_CRT_SECURE_NO_WARNINGS', 1)) # When compiling the C++ code inside of libzmq itself, we want to # avoid "warning C4530: C++ exception handler used, but unwind # semantics are not enabled. Specify /EHsc". if self.compiler_type == 'msvc': libzmq.extra_compile_args.append('/EHsc') elif self.compiler_type == 'mingw32': libzmq.define_macros.append(('ZMQ_HAVE_MINGW32', 1)) # And things like sockets come from libraries that must be named. libzmq.libraries.extend( ['rpcrt4', 'ws2_32', 'advapi32', 'iphlpapi']) # bundle MSCVP redist if self.config['bundle_msvcp']: from setuptools import msvc from setuptools._distutils.util import get_platform vcvars = msvc.msvc14_get_vc_env(get_platform()) try: vcruntime = vcvars["py_vcruntime_redist"] except KeyError: warn(f"platform={get_platform()}, vcvars=") pprint(vcvars, stream=sys.stderr) # fatal error if env set, warn otherwise msg = fatal if os.environ.get("PYZMQ_BUNDLE_CRT") else warn msg("Failed to get py_vcruntime_redist via vcvars, not bundling MSVCP" ) redist_dir, dll = os.path.split(vcruntime) to_bundle = [ pjoin(redist_dir, dll.replace('vcruntime', name)) for name in ('msvcp', 'concrt') ] for src in to_bundle: dest = localpath('zmq', basename(src)) info("Copying %s -> %s" % (src, dest)) # copyfile to avoid permission issues shutil.copyfile(src, dest) else: libzmq.include_dirs.append(bundledir) # check if we need to link against Realtime Extensions library cc = new_compiler(compiler=self.compiler_type) customize_compiler(cc) cc.output_dir = self.build_temp if not sys.platform.startswith(('darwin', 'freebsd')): line() info("checking for timer_create") if not cc.has_function('timer_create'): info("no timer_create, linking librt") libzmq.libraries.append('rt') else: info("ok") # copy the header files to the source tree. bundledincludedir = pjoin('zmq', 'include') if not os.path.exists(bundledincludedir): os.makedirs(bundledincludedir) if not os.path.exists(pjoin(self.build_lib, bundledincludedir)): os.makedirs(pjoin(self.build_lib, bundledincludedir)) for header in glob(pjoin(bundledir, 'zeromq', 'include', '*.h')): shutil.copyfile(header, pjoin(bundledincludedir, basename(header))) shutil.copyfile( header, pjoin(self.build_lib, bundledincludedir, basename(header))) # update other extensions, with bundled settings self.config['libzmq_extension'] = True self.init_settings_from_config() self.save_config('config', self.config)
from distutils.util import get_platform from distutils.msvccompiler import get_build_version from setuptools import msvc p = get_platform() v = get_build_version() if v >= 14.0: print(p, v, msvc.msvc14_get_vc_env(p)) else: print(p, v, msvc.msvc9_find_vcvarsall(v))
def get_environment_from_setup_tools(arch): from setuptools.msvc import msvc14_get_vc_env msvc_env = msvc14_get_vc_env(arch) return {k.upper(): v for k, v in msvc_env.items()}
CPACK_PATH = CMAKE_PATH.parent / "cpack.exe" if not CPACK_PATH.is_file(): print("Can't find cpack.exe at: {}".format(CPACK_PATH), file=sys.stderr) sys.exit(1) CPACK_BIN = CPACK_PATH.as_posix() BUILD_PATH.mkdir(exist_ok=True) BUILD_STATIC_PATH.mkdir(exist_ok=True) BUILD_SHARED_PATH.mkdir(exist_ok=True) is64 = sys.maxsize > 2**32 arch = 'x64' if is64 else 'x86' ninja_env = msvc.msvc14_get_vc_env(arch) env.update(ninja_env) cmake_config_static = [ "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release", "-DBUILD_SHARED_LIBS=off", "-DLIEF_PYTHON_API=off", "-DLIEF_INSTALL_COMPILED_EXAMPLES=on", "-DLIEF_USE_CRT_RELEASE=MT", ] cmake_config_shared = [ "-G", "Ninja", "-DCMAKE_BUILD_TYPE=Release", "-DBUILD_SHARED_LIBS=on",
#!/usr/bin/env python3 import pprint from setuptools import msvc from setuptools._distutils.util import get_platform plat = get_platform() print(f"platform: {plat}") vcvars = msvc.msvc14_get_vc_env(plat) print("vcvars:") pprint.pprint(vcvars)