diff --git a/src/client_handler/setup.py b/src/client_handler/setup.py new file mode 100644 index 00000000..7d14e2af --- /dev/null +++ b/src/client_handler/setup.py @@ -0,0 +1,100 @@ +import os +import sys +import struct +import platform +from setuptools import setup + +COMPILE_FLAGS = ['-flto', '-std=gnu++11', '-g', '-Wall', + '-fPIC', '-Werror'] + +LINK_FLAGS = ['-flto', '-Wl,-rpath,.'] + +if len(sys.argv) > 1 and "--fast" in sys.argv: + sys.argv.remove("--fast") + # Fast mode disables optimization flags + FAST = True + print("FAST mode On") +else: + FAST = False + # Fix "ImportError ... undefined symbol ..." caused by CEF's include/base/ + # headers by adding the -flto flag (Issue #230). Unfortunately -flto + # prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/6687630/ + COMPILE_FLAGS += ['-fdata-sections', '-ffunction-sections'] + LINK_FLAGS += ['-Wl,--gc-sections'] + + +# Architecture and OS postfixes +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") +OS_POSTFIX2 = "unknown" +if OS_POSTFIX == "win": + OS_POSTFIX2 = "win32" if ARCH32 else "win64" +elif OS_POSTFIX == "mac": + OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" +elif OS_POSTFIX == "linux": + OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + +# Directories +CLIENT_HANDLER_DIR = os.path.abspath(os.path.dirname(__file__)) +SRC_DIR = os.path.abspath(os.path.join(CLIENT_HANDLER_DIR, "..")) + +# Python version string: "27" or "32". +PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) + + +client_handler_src = [ + 'client_handler.cpp', 'cookie_visitor.cpp', 'resource_handler.cpp', + 'web_request_client.cpp', 'string_visitor.cpp', 'request_context_handler.cpp', + 'task.cpp', 'x11.cpp', 'context_menu_handler.cpp', 'display_handler.cpp', + 'download_handler.cpp', 'focus_handler.cpp', 'js_dialog_handler.cpp', + 'keyboard_handler.cpp', 'lifespan_handler.cpp', 'load_handler.cpp', + 'render_handler.cpp', 'request_handler.cpp' +] + +if OS_POSTFIX.startswith('mac'): + client_handler_src.append('util_mac.mm') + + +setup( + name='client_handler', + libraries=[('client_handler', dict( + sources=[os.path.join(CLIENT_HANDLER_DIR, src) for src in client_handler_src], + include_dirs=[ + r'./../', + r'./../common/', + r'/usr/include/python2.7', + r'/usr/include/gtk-2.0', + r'/usr/include/gtk-unix-print-2.0', + r'/usr/include/glib-2.0', + r'/usr/include/cairo', + r'/usr/include/pango-1.0', + r'/usr/include/gdk-pixbuf-2.0', + r'/usr/include/atk-1.0', + r'/usr/lib/x86_64-linux-gnu/gtk-2.0/include', + r'/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/x86_64-linux-gnu/glib-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/i386-linux-gnu/glib-2.0/include', + r'/usr/lib64/gtk-2.0/include', + r'/usr/lib64/gtk-unix-print-2.0', + r'/usr/lib64/glib-2.0/include', + r'/usr/lib/gtk-2.0/include', + r'/usr/lib/gtk-2.0/gtk-unix-print-2.0', + r'/usr/lib/glib-2.0/include', + ], + + # library_dirs=library_dirs, + + # Static libraries only. Order is important, if library A depends on B, + # then B must be included before A. + # libraries=libs, + + extra_compile_args=COMPILE_FLAGS, + extra_link_args=LINK_FLAGS, + ))], +) diff --git a/src/cpp_utils/setup.py b/src/cpp_utils/setup.py new file mode 100644 index 00000000..553dd6f9 --- /dev/null +++ b/src/cpp_utils/setup.py @@ -0,0 +1,85 @@ +import os +import sys +import struct +import platform +from setuptools import setup + +COMPILE_FLAGS = ['-flto', '-std=gnu++11', '-g', '-Wall', + '-Werror'] + +LINK_FLAGS = ['-flto', '-Wl,-rpath,.'] + +if len(sys.argv) > 1 and "--fast" in sys.argv: + sys.argv.remove("--fast") + # Fast mode disables optimization flags + FAST = True + print("FAST mode On") +else: + FAST = False + # Fix "ImportError ... undefined symbol ..." caused by CEF's include/base/ + # headers by adding the -flto flag (Issue #230). Unfortunately -flto + # prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/6687630/ + COMPILE_FLAGS += ['-fdata-sections', '-ffunction-sections'] + LINK_FLAGS += ['-Wl,--gc-sections'] + + +# Architecture and OS postfixes +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") +OS_POSTFIX2 = "unknown" +if OS_POSTFIX == "win": + OS_POSTFIX2 = "win32" if ARCH32 else "win64" +elif OS_POSTFIX == "mac": + OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" +elif OS_POSTFIX == "linux": + OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + +# Directories +CPP_UTILS_DIR = os.path.abspath(os.path.dirname(__file__)) +SRC_DIR = os.path.abspath(os.path.join(CPP_UTILS_DIR, "..")) + +# Python version string: "27" or "32". +PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) + + +libcpp_utils_src = [ + 'PaintBuffer.cpp' +] + +setup( + name='libcpp_utils', + libraries=[('cpp_utils', dict( + sources = [os.path.join(CPP_UTILS_DIR, src) for src in libcpp_utils_src], + include_dirs=[ + r'./../', + r'./../common/', + r'/usr/include/python2.7', + r'/usr/include/gtk-2.0', + r'/usr/include/gtk-unix-print-2.0', + r'/usr/include/glib-2.0', + r'/usr/include/cairo', + r'/usr/include/pango-1.0', + r'/usr/include/gdk-pixbuf-2.0', + r'/usr/include/atk-1.0', + r'/usr/lib/x86_64-linux-gnu/gtk-2.0/include', + r'/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/x86_64-linux-gnu/glib-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/i386-linux-gnu/glib-2.0/include', + r'/usr/lib64/gtk-2.0/include', + r'/usr/lib64/gtk-unix-print-2.0', + r'/usr/lib64/glib-2.0/include', + r'/usr/lib/gtk-2.0/include', + r'/usr/lib/gtk-2.0/gtk-unix-print-2.0', + r'/usr/lib/glib-2.0/include', + ], + + extra_compile_args=COMPILE_FLAGS, + extra_link_args=LINK_FLAGS, + ))], +) diff --git a/src/linux/compile.py b/src/linux/compile.py index 6eb2da74..3721abbe 100644 --- a/src/linux/compile.py +++ b/src/linux/compile.py @@ -108,17 +108,19 @@ SETUP_DIR = os.path.abspath(os.path.join(LINUX_DIR, "setup")) CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) -CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cefpython_"+OS_POSTFIX2)) +CEF_BINARY = os.environ.get('CEF_BINARY') +if not CEF_BINARY or not os.path.exists(CEF_BINARY): + CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) # Create directories if necessary if not os.path.exists(CEFPYTHON_BINARY): - os.mkdir(CEFPYTHON_BINARY) + os.makedirs(CEFPYTHON_BINARY) # Check directories -assert os.path.exists(CEF_BINARY) -assert os.path.exists(CEFPYTHON_BINARY) +assert os.path.exists(CEF_BINARY), "%s missing" % CEF_BINARY +assert os.path.exists(CEFPYTHON_BINARY), "%s missing" % CEFPYTHON_BINARY print("Compiling C++ projects") @@ -129,49 +131,52 @@ # fails and then run the compile.py script again and this time # make should succeed. +def run_setuptools_build_ext(): + ret = subprocess.call("{python} setup.py build_ext --inplace {fast}" + .format(python=sys.executable, + fast=('--fast' if FAST_FLAG else '')), shell=True) + return check_ret(ret) + +def run_setuptools_build_lib(): + ret = subprocess.call("{python} setup.py build_clib --build-clib='.' {fast}" + .format(python=sys.executable, + fast=('' if FAST_FLAG else '--force')), shell=True) + return check_ret(ret) + +def check_ret(ret): + if ret != 0: + what = input("%s build failed, press 'y' to continue, 'n' to stop: " % os.path.basename('.')) + if what != "y": + sys.exit(1) + + return ret + # -------- CPP_UTILS_DIR os.chdir(CPP_UTILS_DIR) if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) + subprocess.call("rm -rf *.o *.a build", shell=True) + +run_setuptools_build_lib() -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - # noinspection PyUnboundLocalVariable - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) # -------- CLIENT_HANDLER_DIR os.chdir(CLIENT_HANDLER_DIR) if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) + subprocess.call("rm -rf *.o *.a build", shell=True) -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) +run_setuptools_build_lib() # -------- SUBPROCESS_DIR os.chdir(SUBPROCESS_DIR) if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) + subprocess.call("rm -rf *.o *.a build", shell=True) subprocess.call("rm -f subprocess", shell=True) -ret = subprocess.call("make -f Makefile-libcefpythonapp", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) +run_setuptools_build_ext() -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) subprocess_exe = os.path.join(CEFPYTHON_BINARY, "subprocess") if os.path.exists("./subprocess"): # .copy() will also copy Permission bits @@ -215,15 +220,7 @@ with open("__version__.pyx", "w") as fo: fo.write('__version__ = "{}"\n'.format(VERSION)) -# if DEBUG_FLAG: -# ret = subprocess.call("python-dbg setup.py build_ext --inplace" -# " --cython-gdb", shell=True) -if FAST_FLAG: - ret = subprocess.call("{python} setup.py build_ext --inplace --fast" - .format(python=sys.executable), shell=True) -else: - ret = subprocess.call("{python} setup.py build_ext --inplace" - .format(python=sys.executable), shell=True) +ret = run_setuptools_build_ext() # if DEBUG_FLAG: # shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, diff --git a/src/linux/setup/setup.py b/src/linux/setup/setup.py index d06a688f..c4025407 100644 --- a/src/linux/setup/setup.py +++ b/src/linux/setup/setup.py @@ -1,4 +1,4 @@ -from distutils.core import setup +from setuptools import setup # Use "Extension" from Cython.Distutils so that "cython_directives" works. # from distutils.extension import Extension from Cython.Distutils import build_ext, Extension diff --git a/src/subprocess/Makefile b/src/subprocess/Makefile deleted file mode 100644 index fcaad726..00000000 --- a/src/subprocess/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# -g - extra debug information -# -O1 - more precise backtraces -# -fPIC - required when using -shared option, required for use with Cython -# -Wall - show important warnings -# -Werror - treat warnings as errors - -UNAME_S = $(shell uname -s) -INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ - -I/usr/include/gtk-2.0 \ - -I/usr/include/gtk-unix-print-2.0 \ - -I/usr/include/glib-2.0 \ - -I/usr/include/cairo \ - -I/usr/include/pango-1.0 \ - -I/usr/include/gdk-pixbuf-2.0 \ - -I/usr/include/atk-1.0 \ - -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include \ - -I/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0 \ - -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \ - -I/usr/lib/i386-linux-gnu/gtk-2.0/include \ - -I/usr/lib/i386-linux-gnu/gtk-unix-print-2.0 \ - -I/usr/lib/i386-linux-gnu/glib-2.0/include \ - -I/usr/lib64/gtk-2.0/include \ - -I/usr/lib64/gtk-unix-print-2.0 \ - -I/usr/lib64/glib-2.0/include \ - -I/usr/lib/gtk-2.0/include \ - -I/usr/lib/gtk-2.0/gtk-unix-print-2.0 \ - -I/usr/lib/glib-2.0/include - -ifeq ($(UNAME_S), Linux) - LIB_DIRS = -L./../../build/cef_linux64/bin \ - -L./../../build/cef_linux32/bin \ - -L./../../build/cef_linux64/lib \ - -L./../../build/cef_linux32/lib -else ifeq ($(UNAME_S), Darwin) - LIB_DIRS = -L./../../build/cef_mac64/bin \ - -L./../../build/cef_mac32/bin \ - -L./../../build/cef_mac64/lib \ - -L./../../build/cef_mac32/lib -endif - -ifeq ($(UNAME_S), Linux) - CPP_FILES = print_handler_gtk.cpp - LIBS = -lgobject-2.0 -lglib-2.0 -lgtk-x11-2.0 -else - CPP_FILES = - LIBS = -endif - -CCFLAGS = -g -std=gnu++11 -Wall -Werror -DRENDERER_PROCESS $(CEF_CCFLAGS) - - -subprocess: - # -fPIC is required only for libraries included by Cython. - @echo [SUBPROCESS] Building the 'subprocess' executable - g++ $(CCFLAGS) $(INC) $(LIB_DIRS) main.cpp cefpython_app.cpp \ - v8function_handler.cpp v8utils.cpp javascript_callback.cpp \ - $(CPP_FILES) \ - $(LIBS) -lcef -lcef_dll_wrapper -o subprocess -Wl,-rpath,. diff --git a/src/subprocess/setup.py b/src/subprocess/setup.py new file mode 100644 index 00000000..1717a1d8 --- /dev/null +++ b/src/subprocess/setup.py @@ -0,0 +1,181 @@ +import os +import sys +import struct +import platform +import fileinput +import subprocess + +from setuptools import setup +from ext_targets import build_ext, StaticLibrary, Executable + +COMPILE_FLAGS = ['-flto', '-std=gnu++11', '-g', '-Wall', + '-Werror', '-DRENDERER_PROCESS', '-static'] + +LINK_FLAGS = ['-flto', '-Wl,-rpath,.'] + +if len(sys.argv) > 1 and "--fast" in sys.argv: + sys.argv.remove("--fast") + # Fast mode disables optimization flags + FAST = True + print("FAST mode On") +else: + FAST = False + # Fix "ImportError ... undefined symbol ..." caused by CEF's include/base/ + # headers by adding the -flto flag (Issue #230). Unfortunately -flto + # prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/6687630/ + COMPILE_FLAGS += ['-fdata-sections', '-ffunction-sections'] + LINK_FLAGS += ['-Wl,--gc-sections'] + + +# Architecture and OS postfixes +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") +OS_POSTFIX2 = "unknown" +if OS_POSTFIX == "win": + OS_POSTFIX2 = "win32" if ARCH32 else "win64" +elif OS_POSTFIX == "mac": + OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" +elif OS_POSTFIX == "linux": + OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + +# Directories +SUBPROCESS_DIR = os.path.abspath(os.path.dirname(__file__)) +SRC_DIR = os.path.abspath(os.path.join(SUBPROCESS_DIR, "..")) +CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) +BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) +CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, + "cefpython_"+OS_POSTFIX2)) + +CEF_BINARY = os.environ.get('CEF_BINARY') +if not CEF_BINARY or not os.path.exists(CEF_BINARY): + CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) + + +UPSTREAM_BUILD = (os.path.exists(os.path.join(CEF_BINARY, 'bin')) and + os.path.exists(os.path.join(CEF_BINARY, 'lib'))) + +# Python version string: "27" or "32". +PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) + +libcefpython_src = [ + 'cefpython_app.cpp', + 'v8function_handler.cpp', + 'v8utils.cpp', + 'javascript_callback.cpp', + 'main_message_loop/main_message_loop.cpp', + 'main_message_loop/main_message_loop_std.cpp', + 'main_message_loop/main_message_loop_external_pump.cpp' +] + +subprocess_src = [ + 'main.cpp' +] + +libs = [ + 'cefpython', + 'glib-2.0', + 'gtk-x11-2.0', + 'cef_dll_wrapper', + 'cef', +] + +include_dirs = [ + SRC_DIR, + os.path.join(SRC_DIR, 'common'), + os.path.join(CEF_BINARY), + os.path.join(CEF_BINARY, 'include'), + r'/usr/include/python2.7', + r'/usr/include/gtk-2.0', + r'/usr/include/gtk-unix-print-2.0', + r'/usr/include/glib-2.0', + r'/usr/include/cairo', + r'/usr/include/pango-1.0', + r'/usr/include/gdk-pixbuf-2.0', + r'/usr/include/atk-1.0', + r'/usr/lib/x86_64-linux-gnu/gtk-2.0/include', + r'/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/x86_64-linux-gnu/glib-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-2.0/include', + r'/usr/lib/i386-linux-gnu/gtk-unix-print-2.0', + r'/usr/lib/i386-linux-gnu/glib-2.0/include', + r'/usr/lib64/gtk-2.0/include', + r'/usr/lib64/gtk-unix-print-2.0', + r'/usr/lib64/glib-2.0/include', + r'/usr/lib/gtk-2.0/include', + r'/usr/lib/gtk-2.0/gtk-unix-print-2.0', + r'/usr/lib/glib-2.0/include', +] + +if UPSTREAM_BUILD: + libs.append('cef_dll_wrapper') + library_dirs=[ + '.', + os.path.join(CEF_BINARY,'bin'), + os.path.join(CEF_BINARY,'lib'), + ] +else: + library_dirs=[ + '.', + os.path.join(CEF_BINARY,'Release'), + os.path.join(CEF_BINARY,'build','libcef_dll_wrapper'), + ] + + # Build libcef_wrapper + + # Remove dependency on cefclient and cefsimple, we don't need + # them and the spotify minimal builds don't include them + for line in fileinput.input(os.path.join(CEF_BINARY,'CMakeLists.txt'), inplace=True): + comment = '' + if line.strip() in ('add_subdirectory(cefclient)', + 'add_subdirectory(cefsimple)'): + comment = '# ' + print('%s%s' % (comment, line), end='') + + # Run cmake + wrapper_dir = os.path.join(CEF_BINARY,'build') + if not os.path.exists(wrapper_dir): + os.makedirs(wrapper_dir) + subprocess.call(['cmake','-G','Ninja','-DCMAKE_BUILD_TYPE=Release','..'], cwd=wrapper_dir) + + subprocess.call(['ninja','libcef_dll_wrapper'], cwd=wrapper_dir) + + +if OS_POSTFIX.startswith('linux'): + libs.insert(0, 'gobject-2.0') + subprocess_src.append('print_handler_gtk.cpp') + libcefpython_src.extend(['print_handler_gtk.cpp', + 'main_message_loop/main_message_loop_external_pump_linux.cpp']) + +elif OS_POSTFIX.startswith('mac'): + libcefpython_src.append('main_message_loop/main_message_loop_external_pump_mac.mm') + + +libcefpython = StaticLibrary( + name='cefpython', + sources=[os.path.join(SUBPROCESS_DIR, src) for src in libcefpython_src], + include_dirs=include_dirs, + extra_compile_args=COMPILE_FLAGS, + extra_link_args=LINK_FLAGS, +) + +subprocess_exec = Executable( + name="subprocess", + sources=[os.path.join(SUBPROCESS_DIR, src) for src in subprocess_src], + language='c++', + include_dirs=include_dirs, + library_dirs=library_dirs, + libraries=libs, + extra_compile_args=COMPILE_FLAGS, + extra_link_args=LINK_FLAGS, +) + +setup( + name='subprocess_%s' % PYTHON_VERSION, + cmdclass={'build_ext': build_ext}, + ext_modules=[libcefpython, subprocess_exec], + setup_requires = ['setuptools_bin_targets>=1.2'] +)