# Copyright (c) 2017 CEF Python, see the Authors file.# All rights reserved. Licensed under BSD 3-clause license.# Project website: https://github.com/cztomczak/cefpython"""Build the cefpython module, install package and run example.Before running you must first put cefpython ready CEF binaries andlibraries in the cefpython/build/ directory (create if doesn't exist).You have two options for obtaining these binaries and libraries.Option 1: Download upstream CEF binaries and libraries from cefpythonGitHub Releases page. These binaries are tagged eg. "v55-upstream".Extract the archive so that for example you have such a directory:cefpython/build/cef55_3.2883.1553.g80bd606_win32/ .Option 2: Use the automate.py tool. With this tool you can build CEFfrom sources or use ready binaries from Spotify Automated Builds.Usage:build.py VERSION [--rebuild-cpp] [--unittests] [--fast] [--clean] [--kivy][--hello-world] [--enable-profiling][--enable-line-tracing]Options:VERSION Version number eg. 50.0--unittests Run only unit tests. Do not run examples whilebuilding cefpython modules. Examples requireinteraction such as closing window before proceeding.--fast Fast mode--clean Clean C++ projects build files on Linux/Mac--kivy Run only Kivy example--hello-world Run only Hello World example--enable-profiling Enable cProfile profiling--enable-line-tracing Enable cProfile line tracing"""# --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED)# NOTE: When passing string command to subprocess functions you must# always use shell=True, otherwise on Linux error is thrown:# "No such file or directory". Always pass string commands to# subprocess functions with shell=True. If you pass a list of# arguments instead, then on Linux a "Segmentation fault" error# message is not shown. When passing a list of args to subprocess# function then you can't pass shell=True on Linux. If you pass# then it will execute args[0] and ignore others args.# NOTE 2: When calling os.system() returned value may be 256 when eg.# when running unit tests fail. If you pass 256 to sys.exit# an undefined result will occur. In my case on Linux it caused# that other script that called it sys.exit(256) was interpreted# for the script execute successfully. So never pass to sys.exit# a value returned from os.system. Check the value and call# sys.exit(1).# How to debug on Linux (OLD unsupported).# 1. Install "python-dbg" package# 2. Install "python-wxgtk2.8-dbg" package# 3. Run "python compile.py debug"# 4. In cygdb type "cy run"# 5. To display debug backtrace type "cy bt"# 6. More commands: http://docs.cython.org/src/userguide/debugging.htmlfrom common import *import copyimport sysimport osimport globimport shutilimport subprocessimport re# raw_input() was renamed to input() in Python 3try:# noinspection PyUnresolvedReferences# noinspection PyShadowingBuiltinsinput = raw_inputexcept NameError:pass# Command line args variablesSYS_ARGV_ORIGINAL = NoneVERSION = ""UNITTESTS = FalseDEBUG_FLAG = FalseFAST_FLAG = FalseCLEAN_FLAG = FalseKIVY_FLAG = FalseHELLO_WORLD_FLAG = FalseREBUILD_CPP = FalseENABLE_PROFILING = FalseENABLE_LINE_TRACING = False# First runFIRST_RUN = Falsedef main():command_line_args()print("[build.py] Python version: {ver} {arch}".format(ver=platform.python_version(), arch=ARCH_STR))print("[build.py] Python executable: %s" % sys.executable)print("[build.py] PYVERSION = %s" % PYVERSION)print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2)check_cython_version()check_directories()setup_environ()if os.path.exists(CEFPYTHON_API_HFILE):fix_cefpython_api_header_file()if WINDOWS:compile_cpp_projects_with_setuptools()elif MAC or LINUX:compile_cpp_projects_unix()else:print("[build.py] INFO: Looks like first run, as"" cefpython_py{pyver}.h is missing. Skip building"" C++ projects.".format(pyver=PYVERSION))global FIRST_RUNFIRST_RUN = Trueclear_cache()copy_and_fix_pyx_files()build_cefpython_module()fix_cefpython_api_header_file()install_and_run()def command_line_args():global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG, HELLO_WORLD_FLAG, \REBUILD_CPP, VERSION, UNITTESTSVERSION = get_version_from_command_line_args(__file__)# Other scripts called by this script expect that version number# is available in sys.argv, so don't remove it like it's done# for all other args starting with "--".if not VERSION:print(__doc__)sys.exit(1)print("[build.py] Parse command line arguments")global SYS_ARGV_ORIGINALSYS_ARGV_ORIGINAL = copy.copy(sys.argv)if "--unittests" in sys.argv:UNITTESTS = Trueprint("[build.py] Running examples disabled (--unittests)")sys.argv.remove("--unittests")if "--debug" in sys.argv:DEBUG_FLAG = Trueprint("[build.py] DEBUG mode On")sys.argv.remove("--debug")if "--fast" in sys.argv:# Fast mode doesn't delete C++ .o .a files.# Fast mode also disables optimization flags in setup/setup.py .FAST_FLAG = Trueprint("[build.py] FAST mode On")sys.argv.remove("--fast")if "--clean" in sys.argv:CLEAN_FLAG = Truesys.argv.remove("--clean")if "--kivy" in sys.argv:KIVY_FLAG = Trueprint("[build.py] KIVY example")sys.argv.remove("--kivy")if "--hello-world" in sys.argv:HELLO_WORLD_FLAG = Trueprint("[build.py] HELLO WORLD example")sys.argv.remove("--hello-world")# Rebuild c++ projectsif "--rebuild-cpp" in sys.argv:REBUILD_CPP = Trueprint("[build.py] REBUILD_CPP mode enabled")sys.argv.remove("--rebuild-cpp")global ENABLE_PROFILINGif "--enable-profiling" in sys.argv:print("[build.py] cProfile profiling enabled")ENABLE_PROFILING = Truesys.argv.remove("--enable-profiling")global ENABLE_LINE_TRACINGif "--enable-line-tracing" in sys.argv:print("[build.py] cProfile line tracing enabled")ENABLE_LINE_TRACING = Truesys.argv.remove("--enable-line-tracing")for arg in sys.argv:if arg.startswith("--"):print("ERROR: invalid arg {0}".format(arg))sys.exit(1)if len(sys.argv) <= 1:print(__doc__)sys.exit(1)print("[build.py] VERSION=%s" % VERSION)def check_cython_version():print("[build.py] Check Cython version")with open(os.path.join(TOOLS_DIR, "requirements.txt"), "rb") as fileobj:contents = fileobj.read().decode("utf-8")match = re.search(r"cython\s*==\s*([\d.]+)", contents,flags=re.IGNORECASE)assert match, "cython package not found in requirements.txt"require_version = match.group(1)try:import Cythonversion = Cython.__version__except ImportError:# noinspection PyUnusedLocalCython = Noneprint("[build.py] ERROR: Cython is not installed ({0} required)".format(require_version))sys.exit(1)if version != require_version:print("[build.py] ERROR: Wrong Cython version: {0}. Required: {1}".format(version, require_version))sys.exit(1)print("[build.py] Cython version: {0}".format(version))def check_directories():print("[build.py] Check directories")# Create directories if necessaryif not os.path.exists(CEFPYTHON_BINARY):os.makedirs(CEFPYTHON_BINARY)if not os.path.exists(BUILD_CEFPYTHON):os.makedirs(BUILD_CEFPYTHON)# Info if directory missingif not os.path.exists(CEF_BINARIES_LIBRARIES):prebuilt_name = get_cef_binaries_libraries_basename(OS_POSTFIX2)print("[build.py] ERROR: Couldn't find CEF prebuilt binaries and"" libraries: 'build/{prebuilt_dir}/'. Download it"" from GitHub released tagged eg. 'vXX-upstream` or download"" CEF binaries from Spotify Automated Builds and then run""`automate.py --prebuilt-cef`.".format(prebuilt_dir=prebuilt_name))sys.exit(1)# Check directories existassert os.path.exists(BUILD_DIR)assert os.path.exists(BUILD_CEFPYTHON)assert os.path.exists(CEF_BINARIES_LIBRARIES)assert os.path.exists(CEFPYTHON_BINARY)def setup_environ():"""Set environment variables. Set PATH so that it contains onlyminimum set of directories,to avoid any possible issues. Set Pythoninclude path. Set Mac compiler options. Etc."""print("[build.py] Setup environment variables")# PATHif WINDOWS:path = ["C:\\Windows\\system32","C:\\Windows","C:\\Windows\\System32\\Wbem",get_python_path(),]os.environ["PATH"] = os.pathsep.join(path)print("[build.py] environ PATH: {path}".format(path=os.environ["PATH"]))# INCLUDE env for vcproj buildif WINDOWS:if "INCLUDE" not in os.environ:os.environ["INCLUDE"] = ""os.environ["INCLUDE"] += os.pathsep + get_python_include_path()print("[build.py] environ INCLUDE: {include}".format(include=os.environ["INCLUDE"]))# LIB env for vcproj buildif WINDOWS:os.environ["AdditionalLibraryDirectories"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib")print("[build.py] environ AdditionalLibraryDirectories: {lib}".format(lib=os.environ["AdditionalLibraryDirectories"]))if LINUX or MAC:# Env variables for makefilesos.environ["PYTHON_INCLUDE"] = get_python_include_path()print("[build.py] PYTHON_INCLUDE: {python_include}".format(python_include=os.environ["PYTHON_INCLUDE"]))os.environ["CEF_CCFLAGS"] = "-std=gnu++11 -DNDEBUG -Wall -Werror -Wno-deprecated-declarations"if FAST_FLAG:os.environ["CEF_CCFLAGS"] += " -O0"else:os.environ["CEF_CCFLAGS"] += " -O3"os.environ["CEF_LINK_FLAGS"] = ""os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin")os.environ["CEF_LIB"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib")if LINUX:# TODO: Set CEF_CCFLAGS and CEF_LINK_FLAGS according to what is# in upstream cefclient, see cef/cmake/cef_variables.cmake.pass# Mac compiler optionsif MAC:os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"]os.environ["CC"] = "c++"os.environ["CXX"] = "c++"if ARCH32:raise Exception("Python 32-bit is not supported on Mac")os.environ["ARCHFLAGS"] = "-arch x86_64"os.environ["CEF_CCFLAGS"] += " -arch x86_64"os.environ["CEF_LINK_FLAGS"] += " -mmacosx-version-min=10.9"# -Wno-return-type-c-linkage to ignore:# > warning: 'somefunc' has C-linkage specified, but returns# > user-defined type 'sometype' which is incompatible with Cos.environ["CEF_CCFLAGS"] += " -Wno-return-type-c-linkage"# Compile against libc++ otherwise error "symbol not found"# with cef::logging::LogMessage symbol. Also include -lc++# and -lc++abi libraries.os.environ["CEF_CCFLAGS"] += " -stdlib=libc++"# See compile/link flags in upstream cefclientos.environ["CEF_CCFLAGS"] += (" -fno-strict-aliasing"" -fno-rtti"" -fno-threadsafe-statics"" -fobjc-call-cxx-cdtors"" -fvisibility=hidden"" -fvisibility-inlines-hidden")os.environ["CEF_LINK_FLAGS"] += (" -lc++"" -lc++abi"" -Wl,-search_paths_first"" -Wl,-ObjC"" -Wl,-pie"" -Wl,-dead_strip")def fix_cefpython_api_header_file():"""This function does two things: 1) Disable warnings in cefpythonAPI header file and 2) Make a copy named cefpython_pyXX_fixed.h,this copy will be used by C++ projects and its modification timewon't change every time you run build.py script, thus C++ won'trebuild each time."""# Fix cefpython_pyXX.h to disable this warning:# > warning: 'somefunc' has C-linkage specified, but returns# > user-defined type 'sometype' which is incompatible with C# On Mac this warning must be disabled using -Wno-return-type-c-linkage# flag in makefiles.print("[build.py] Fix cefpython API header file in the build_cefpython/"" directory")if not os.path.exists(CEFPYTHON_API_HFILE):assert not os.path.exists(CEFPYTHON_API_HFILE_FIXED)print("[build.py] cefpython API header file was not yet generated")return# Original contentswith open(CEFPYTHON_API_HFILE, "rb") as fo:contents = fo.read().decode("utf-8")# Pragma fix on Windowsif WINDOWS:pragma = "#pragma warning(disable:4190)"if pragma in contents:print("[build.py] cefpython API header file is already fixed")else:contents = ("%s\n\n" % pragma) + contentswith open(CEFPYTHON_API_HFILE, "wb") as fo:fo.write(contents.encode("utf-8"))print("[build.py] Save {filename}".format(filename=CEFPYTHON_API_HFILE))# Make a copy with a "_fixed" postfixif os.path.exists(CEFPYTHON_API_HFILE_FIXED):with open(CEFPYTHON_API_HFILE_FIXED, "rb") as fo:contents_fixed = fo.read().decode("utf-8")else:contents_fixed = ""# Resave fixed copy only if contents changed. Other scripts# depend on "modified time" of the "_fixed" file.if contents != contents_fixed:print("[build.py] Save cefpython_fixed.h")with open(CEFPYTHON_API_HFILE_FIXED, "wb") as fo:fo.write(contents.encode("utf-8"))def compile_cpp_projects_with_setuptools():"""Use setuptools to build static libraries / executable."""compile_cpp_projects = os.path.join(TOOLS_DIR, "build_cpp_projects.py")retcode = subprocess.call([sys.executable, compile_cpp_projects])if retcode != 0:print("[build.py] ERROR: Failed to compile C++ projects")sys.exit(1)# Copy subprocess executableprint("[build.py] Copy subprocess executable")shutil.copy(SUBPROCESS_EXE, CEFPYTHON_BINARY)def compile_cpp_projects_windows_DEPRECATED():"""DEPRECATED. Not used currently.Build C++ projects using .vcproj files."""# TODO: Remove code after setuptools compilation was tested for some timeprint("[build.py] Compile C++ projects")print("[build.py] ~~ Build CLIENT_HANDLER vcproj")vcproj = ("client_handler_py{pyver}_{os}.vcproj".format(pyver=PYVERSION, os=OS_POSTFIX2))vcproj = os.path.join(SRC_DIR, "client_handler", vcproj)build_vcproj_DEPRECATED(vcproj)print("[build.py] ~~ Build LIBCEFPYTHONAPP vcproj")vcproj = ("libcefpythonapp_py{pyver}_{os}.vcproj".format(pyver=PYVERSION, os=OS_POSTFIX2))vcproj = os.path.join(SRC_DIR, "subprocess", vcproj)build_vcproj_DEPRECATED(vcproj)print("[build.py] ~~ Build SUBPROCESS vcproj")vcproj = ("subprocess_{os}.vcproj".format(os=OS_POSTFIX2))vcproj = os.path.join(SRC_DIR, "subprocess", vcproj)ret = build_vcproj_DEPRECATED(vcproj)# Copy subprocess executablesubprocess_from = os.path.join(SUBPROCESS_DIR,"Release_{os}".format(os=OS_POSTFIX2),"subprocess_{os}.exe".format(os=OS_POSTFIX2))subprocess_to = os.path.join(CEFPYTHON_BINARY, "subprocess.exe")if os.path.exists(subprocess_to):os.remove(subprocess_to)if ret == 0:print("[build.py] Copy subprocess executable")# shutil.copy() will also copy Permission bitsshutil.copy(subprocess_from, subprocess_to)print("[build.py] ~~ Build CPP_UTILS vcproj")vcproj = ("cpp_utils_{os}.vcproj".format(os=OS_POSTFIX2))vcproj = os.path.join(SRC_DIR, "cpp_utils", vcproj)build_vcproj_DEPRECATED(vcproj)def build_vcproj_DEPRECATED(vcproj):"""DEPRECATED. Not used currently."""# TODO: Remove code after setuptools compilation was tested for some time# In VS2010 vcbuild.exe was replaced by msbuild.exe.# Ufortunately WinSDK 7.1 does not come with msbuild.exe,# so it would be required to install Visual Studio 2010,# and to support both 32-bit ad 64-bit compilations it# a non-express version would have to be installed, which# is not free. So to make it free open-source it was# required migrate to a new compilation system that uses# distutils/setuptools packages.# msbuild.exe flags:# /clp:disableconsolecolor# msbuild /p:BuildProjectReferences=false project.proj# MSBuild.exe MyProject.proj /t:buildVS2008_BUILD = ("%LocalAppData%\\Programs\\Common\\""Microsoft\\Visual C++ for Python\\9.0\\""VC\\bin\\amd64\\vcbuild.exe")VS2008_BUILD = VS2008_BUILD.replace("%LocalAppData%",os.environ["LOCALAPPDATA"])if PYVERSION == "27":args = list()args.append(VS2008_VCVARS)args.append(VS_PLATFORM_ARG)args.append("&&")args.append(VS2008_BUILD)args.append("/nocolor")args.append("/nologo")args.append("/nohtmllog")if REBUILD_CPP:args.append("/rebuild")args.append(vcproj)ret = subprocess.call(args, shell=True)if ret != 0:compile_ask_to_continue()return retelse:raise Exception("Only Python 2.7 32-bit is currently supported")def compile_ask_to_continue():# noinspection PyUnboundLocalVariablewhat = input("[build.py] make failed, 'y' to continue, Enter to stop: ")if what != "y":sys.exit(1)def clean_cpp_projects_unix():delete_files_by_pattern("{0}/*.o".format(CLIENT_HANDLER_DIR))delete_files_by_pattern("{0}/*.a".format(CLIENT_HANDLER_DIR))delete_files_by_pattern("{0}/*.o".format(SUBPROCESS_DIR))delete_files_by_pattern("{0}/*.a".format(SUBPROCESS_DIR))delete_files_by_pattern("{0}/subprocess".format(SUBPROCESS_DIR))delete_files_by_pattern("{0}/main_message_loop/*.o".format(SUBPROCESS_DIR))delete_files_by_pattern("{0}/*.o".format(CPP_UTILS_DIR))delete_files_by_pattern("{0}/*.a".format(CPP_UTILS_DIR))def compile_cpp_projects_unix():print("[build.py] Compile C++ projects")if CLEAN_FLAG:print("[build.py] Clean C++ projects (--clean flag passed)")clean_cpp_projects_unix()# Need to allow continuing even when make fails, as it may# fail because the "public" function declaration is not yet# in cefpython API header file, but for it to be generated we need# to run cython compiling, so in this case you continue even when# make fails and then run the compile.py script again and this time# make should succeed.# -- CLIENT_HANDLERprint("[build.py] ~~ Build CLIENT_HANDLER project")os.chdir(CLIENT_HANDLER_DIR)if not FAST_FLAG:subprocess.call("rm -f *.o *.a", shell=True)ret = subprocess.call("make -f Makefile", shell=True)if ret != 0:compile_ask_to_continue()# -- LIBCEFPYTHONAPPprint("[build.py] ~~ Build LIBCEFPYTHONAPP project")os.chdir(SUBPROCESS_DIR)if not FAST_FLAG:subprocess.call("rm -f *.o *.a", shell=True)subprocess.call("rm -f subprocess", shell=True)ret = subprocess.call("make -f Makefile-libcefpythonapp", shell=True)if ret != 0:compile_ask_to_continue()# -- SUBPROCESSprint("[build.py] ~~ Build SUBPROCESS project")ret = subprocess.call("make -f Makefile", shell=True)if ret != 0:compile_ask_to_continue()# Copy subprocess executablesubprocess_from = os.path.join(SUBPROCESS_DIR, "subprocess")subprocess_to = os.path.join(CEFPYTHON_BINARY, "subprocess")if os.path.exists(subprocess_from):# shutil.copy() will also copy Permission bitsshutil.copy(subprocess_from, subprocess_to)# -- CPP_UTILSprint("[build.py] ~~ Build CPP_UTILS project")os.chdir(CPP_UTILS_DIR)if not FAST_FLAG:subprocess.call("rm -f *.o *.a", shell=True)ret = subprocess.call("make -f Makefile", shell=True)if ret != 0:compile_ask_to_continue()def clear_cache():print("[build.py] Clean build cache")# Cache in CEFPYTHON_BINARY directory (eg. cefpython_linux64/)os.chdir(CEFPYTHON_BINARY)delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION, ext=MODULE_EXT))# Cache in build_cefpython/ directoryos.chdir(BUILD_CEFPYTHON)delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION, ext=MODULE_EXT))delete_files_by_pattern("./*.pyx")try:if not FAST_FLAG:# Cython's internal build/ directoryshutil.rmtree(os.path.join(BUILD_CEFPYTHON, "build"))except OSError:passdef copy_and_fix_pyx_files():print("[build.py] Copy and fix pyx files")# First, it copies all .pyx files from upper directory to setup/.# Then, fixes repeating of "include" statements in pyx files.# Only the mainfile needs to have "include" statements,# but we're using PyCharm and to get rid of "unresolved references"# and other errors displayed in pycharm we are adding "include"# statements in all of the pyx files.# I'm not 100% sure how includes work in Cython, but I suspect that# a few includes of the same file will include the same content more# than once, it should work, but function and variable definitions are# duplicated, it is some kind of overhead and it could lead to some# problems in the future, better to fix it now.# It also checks cdef & cpdef functions whether they are not missing# "except *", it is required to add it when returning non-python type.os.chdir(BUILD_CEFPYTHON)print("\n")mainfile_original = "cefpython.pyx"mainfile_newname = "cefpython_py{pyver}.pyx".format(pyver=PYVERSION)pyxfiles = glob.glob("../../src/*.pyx")if not len(pyxfiles):print("[build.py] ERROR: no .pyx files found in root")sys.exit(1)pyxfiles = [f for f in pyxfiles if f.find(mainfile_original) == -1]# Now, pyxfiles contains all pyx files except mainfile_original# (cefpython.pyx), we do not fix includes in mainfile.pyxfiles2 = glob.glob("../../src/handlers/*.pyx")if not len(pyxfiles2):print("[build.py] ERROR: no .pyx files found in handlers/")sys.exit(1)pyxfiles = pyxfiles + pyxfiles2# Remove old pyx filesoldpyxfiles = glob.glob("./*.pyx")print("[build.py] Clean pyx files in build_cefpython/")for pyxfile in oldpyxfiles:if os.path.exists(pyxfile):os.remove(pyxfile)# Copying pyxfiles and reading its contents.print("[build.py] Copy pyx files to build_cefpython/")# Copy cefpython.pyx and fix includes in cefpython.pyx, eg.:# include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx"shutil.copy("../../src/%s" % mainfile_original, "./%s" % mainfile_newname)with open("./%s" % mainfile_newname, "rb") as fo:content = fo.read().decode("utf-8")(content, subs) = re.subn(u"^include \"handlers/",u"include \"",content,flags=re.MULTILINE)# Add __version__ variable in cefpython.pyxprint("[build.py] Add __version__ variable to %s" % mainfile_newname)content = generate_cefpython_module_variables() + contentwith open("./%s" % mainfile_newname, "wb") as fo:fo.write(content.encode("utf-8"))print("[build.py] Fix %s includes in %s" % (subs, mainfile_newname))# Copy the rest of the filesprint("[build.py] Fix includes in other .pyx files")for pyxfile in pyxfiles:newfile = "./%s" % os.path.basename(pyxfile)shutil.copy(pyxfile, newfile)pyxfile = newfilewith open(pyxfile, "rb") as pyxfileopened:content = pyxfileopened.read().decode("utf-8")lineNumber = except_all_missing(content)if lineNumber:print("[build.py] WARNING: 'except *' missing"" in a cdef/cpdef function,"" in file %s on line %d"% (os.path.basename(pyxfile), lineNumber))sys.exit(1)# Do not remove the newline - so that line numbers# are exact with originals.(content, subs) = re.subn(u"^include[\\t ]+[\"'][^\"'\\n\\r]+[\"'][\\t ]*",u"",content,flags=re.MULTILINE)if subs:# print("[build.py] %s includes removed in: %s"# % (subs, os.path.basename(pyxfile)))passwith open(pyxfile, "wb") as pyxfileopened:pyxfileopened.write(content.encode("utf-8"))print("\n")def generate_cefpython_module_variables():"""Global variables that will be appended to cefpython.pyx sources."""ret = ('__version__ = "{0}"\n'.format(VERSION))version = get_cefpython_version()chrome_version = "{0}.{1}.{2}.{3}".format(version["CHROME_VERSION_MAJOR"], version["CHROME_VERSION_MINOR"],version["CHROME_VERSION_BUILD"], version["CHROME_VERSION_PATCH"])ret += ('__chrome_version__ = "{0}"\n'.format(chrome_version))ret += ('__cef_version__ = "{0}"\n'.format(version["CEF_VERSION"]))ret += ('__cef_api_hash_platform__ = "{0}"\n'.format(version["CEF_API_HASH_PLATFORM"]))ret += ('__cef_api_hash_universal__ = "{0}"\n'.format(version["CEF_API_HASH_UNIVERSAL"]))ret += ('__cef_commit_hash__ = "{0}"\n'.format(version["CEF_COMMIT_HASH"]))ret += ('__cef_commit_number__ = "{0}"\n'.format(version["CEF_COMMIT_NUMBER"]))return retdef except_all_missing(content):# This is not perfect, won't detect C++ custom types, but will find# the built-in types, templates and pointers.patterns = list()patterns.append(r"\bcp?def\s+""((int|short|long|double|char|unsigned|float|double|cpp_bool""|cpp_string|cpp_wstring|uintptr_t|void""|int32|uint32|int64|uint64""|int32_t|uint32_t|int64_t|uint64_t""|CefString)\s+)+""\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:")patterns.append(r"\bcp?def\s+"# A template ends with bracket: CefRefPtr[CefBrowser]# or a pointer ends with asterisk: CefBrowser*"[^\s]+[\]*]\s+""\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:")patterns.append(r"\bcp?def\s+"# A reference, eg. CefString&"[^\s]+&\s+""\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:")match = Nonefor pattern in patterns:match = re.search(pattern, content)if match:breakif match:lineNumber = (content.count("\n", 0, match.start()) + 1)return lineNumberdef build_cefpython_module():# if DEBUG_FLAG:# ret = subprocess.call("python-dbg setup.py build_ext --inplace"# " --cython-gdb", shell=True)print("[build.py] Execute cython_setup.py script")print("")os.chdir(BUILD_CEFPYTHON)enable_profiling = ""if ENABLE_PROFILING:enable_profiling = "--enable-profiling"enable_line_tracing = ""if ENABLE_LINE_TRACING:enable_line_tracing = "--enable-line-tracing"command = ("\"{python}\" {tools_dir}/cython_setup.py build_ext"" {enable_profiling} {enable_line_tracing}".format(python=sys.executable, tools_dir=TOOLS_DIR,enable_profiling=enable_profiling,enable_line_tracing=enable_line_tracing))if FAST_FLAG:command += " --fast"ret = subprocess.call(command, shell=True)# if DEBUG_FLAG:# shutil.rmtree("./../binaries_%s/cython_debug/" % BITS,# ignore_errors=True)# shutil.copytree("./cython_debug/",# "./../binaries_%s/cython_debug/" % BITS)# Remove .pyx filesoldpyxfiles = glob.glob("./*.pyx")print("")print("[build.py] Cleanup: remove pyx files in build_cefpython/")for pyxfile in oldpyxfiles:if os.path.exists(pyxfile):os.remove(pyxfile)# Check if built succeeded after pyx files were removedif ret != 0:if FIRST_RUN and os.path.exists(CEFPYTHON_API_HFILE):print("[build.py] INFO: looks like this was first run and"" building the cefpython module is expected to fail"" in such case due to cefpython API header file not"" being generated yet. Will re-run the build.py script"" programmatically now.")args = list()args.append("\"{python}\"".format(python=sys.executable))args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__)))assert os.path.basename(__file__) in sys.argv[0]args.extend(SYS_ARGV_ORIGINAL[1:])command = " ".join(args)print("[build.py] Running command: %s" % command)ret = subprocess.call(command, shell=True)# Always pass fixed value to sys.exit, read note at# the top of the script about os.system and sys.exit# issue.sys.exit(0 if ret == 0 else 1)else:print("[build.py] ERROR: failed to build the cefpython module")sys.exit(1)# Move the cefpython modulemodule_pattern = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION+"*",ext=MODULE_EXT)module_pattern = "./build/lib*/" + module_patternmove_file_by_pattern(module_pattern, os.path.join(CEFPYTHON_BINARY,MODULE_NAME))print("[build.py] DONE building the cefpython module")def move_file_by_pattern(pattern, move_to):assert len(pattern) > 2print("[build.py] Move file: {pattern} to {move_to}".format(pattern=pattern, move_to=move_to))files = glob.glob(pattern)assert(len(files) == 1)os.rename(files[0], move_to)def delete_files_by_pattern(pattern):assert len(pattern) > 2print("[build.py] Delete files by pattern: {pattern}".format(pattern=pattern))files = glob.glob(pattern)for f in files:os.remove(f)print("[build.py] Removed {0} files".format(len(files)))def delete_directories_by_pattern(pattern):assert len(pattern) > 2print("[build.py] Delete directories by pattern: {pattern}".format(pattern=pattern))paths = glob.glob(pattern)for path in paths:if os.path.isdir(path):shutil.rmtree(path)def install_and_run():# if DEBUG_FLAG:# os.chdir("./binaries_%s" % BITS)# subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True)print("[build.py] Install and run...")os.chdir(BUILD_DIR)# Setup installer directorysetup_basename = get_setup_installer_basename(VERSION, OS_POSTFIX2)setup_installer_dir = os.path.join(BUILD_DIR, setup_basename)# Delete setup installer directory if existsif os.path.exists(setup_installer_dir):delete_directory_reliably(setup_installer_dir)# Make setup installerprint("[build.py] Make setup installer")make_tool = os.path.join(TOOLS_DIR, "make_installer.py")command = ("\"{python}\" {make_tool} --version {version}".format(python=sys.executable,make_tool=make_tool,version=VERSION))ret = os.system(command)if ret != 0:print("[build.py] ERROR while making installer package")sys.exit(1)# Installprint("[build.py] Install the cefpython package")os.chdir(setup_installer_dir)command = ("\"{python}\" setup.py install".format(python=sys.executable))command = sudo_command(command, python=sys.executable)ret = os.system(command)if ret != 0:print("[build.py] ERROR while installing package")sys.exit(1)os.chdir(BUILD_DIR)# Delete setup installer directory after the package was installeddelete_directory_reliably(setup_installer_dir)# Run unittestsprint("[build.py] Run unittests")test_runner = os.path.join(UNITTESTS_DIR, "_test_runner.py")command = ("\"{python}\" {test_runner}".format(python=sys.executable,test_runner=test_runner))ret = os.system(command)if ret != 0:print("[build.py] ERROR while running unit tests")sys.exit(1)# Run examplesif not UNITTESTS:print("[build.py] Run examples")os.chdir(EXAMPLES_DIR)flags = ""if KIVY_FLAG:flags += " --kivy"if HELLO_WORLD_FLAG:flags += " --hello-world"run_examples = os.path.join(TOOLS_DIR, "run_examples.py")command = ("\"{python}\" {run_examples} {flags}".format(python=sys.executable,run_examples=run_examples,flags=flags))ret = os.system(command)if ret != 0:print("[build.py] ERROR while running examples")sys.exit(1)print("[build.py] Everything OK")def delete_directory_reliably(adir):assert len(adir) > 2assert os.path.isdir(adir)print("[build.py] Delete directory: {dir}".format(dir=adir.replace(ROOT_DIR, "")))if WINDOWS:# rmtree is vulnerable to race conditions. Sometimes# deleting directory fails with error:# >> OSError: [WinError 145] The directory is not empty:# >> 'C:\\github\\cefpython\\build\\cefpython3_56.2_win64\\build\\# >> lib\\cefpython3'shutil.rmtree(adir, ignore_errors=True)else:# On Linux sudo might be required to delete directory, as this# might be a setup installer directory with package installed# using sudo and in such case files were created with sudo.command = "rm -rf {dir}".format(dir=adir)command = sudo_command(command, python=sys.executable)os.system(command)if __name__ == "__main__":main()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。