diff --git a/scripts/meson_configure_qmake_in.py b/scripts/meson_configure_qmake_in.py index 33763465..f74f0de5 100644 --- a/scripts/meson_configure_qmake_in.py +++ b/scripts/meson_configure_qmake_in.py @@ -20,7 +20,7 @@ for name, value in vars.items(): pattern = "\\$\\$({}|\\{{{}\\}})".format(name, name) print(pattern) - content = re.sub(pattern, re.escape(str(value)), content) + content = re.sub(pattern, str(value), content) with open(out_filename, "w") as f: f.write(content) diff --git a/src/bindings/CutterBindings/meson.build b/src/bindings/CutterBindings/meson.build new file mode 100644 index 00000000..ef2327a4 --- /dev/null +++ b/src/bindings/CutterBindings/meson.build @@ -0,0 +1,12 @@ + +# 😠 https://github.com/mesonbuild/meson/issues/2320 + +bindings_src_files = run_command([py3_exe, + join_paths(meson.current_source_dir(), '../src_list.py'), + 'meson']).stdout().split(';') + +bindings_target = custom_target('bindings', + input: bindings_txt, + depend_files: [bindings_h, bindings_xml], + output: bindings_src_files, + command: [shiboken_exe, '--project-file=@INPUT@']) \ No newline at end of file diff --git a/src/bindings/meson.build b/src/bindings/meson.build new file mode 100644 index 00000000..41fdf692 --- /dev/null +++ b/src/bindings/meson.build @@ -0,0 +1,20 @@ + +bindings_xml = configure_file(input: 'bindings.xml', + output: 'bindings.xml', + copy: true) + +conf_json = '''{"BINDINGS_SRC_DIR":"@0@", + "BINDINGS_BUILD_DIR":"@1@", + "BINDINGS_INCLUDE_DIRS":"@2@", + "PYSIDE_TYPESYSTEMS":"@3@"}'''.format( + meson.current_source_dir(), + meson.current_build_dir(), + ':'.join(bindings_generate_inc), + pyside_dep.get_pkgconfig_variable('typesystemdir')) +bindings_txt = configure_file(input: 'bindings.txt.in', + output: 'bindings.txt', + command: configure_qmake_cmd + ['@INPUT@', '@OUTPUT0@', conf_json]) + +bindings_h = files('bindings.h') + +subdir('CutterBindings') \ No newline at end of file diff --git a/src/bindings/src_list.py b/src/bindings/src_list.py old mode 100755 new mode 100644 index a660a838..4f27809f --- a/src/bindings/src_list.py +++ b/src/bindings/src_list.py @@ -8,7 +8,7 @@ import sys script_path = os.path.dirname(os.path.realpath(__file__)) -def get_cpp_files_gen(args): +def get_cpp_files_gen(args, include_package=True): ts_tree = et.parse(os.path.join(script_path, "bindings.xml")) ts_root = ts_tree.getroot() @@ -20,10 +20,13 @@ def get_cpp_files_gen(args): cpp_files_gen = [f"{package.lower()}_module_wrapper.cpp"] cpp_files_gen.extend([f"{typename.lower()}_wrapper.cpp" for typename in types]) + if include_package: + cpp_files_gen = [os.path.join(package, f) for f in cpp_files_gen] + if len(args) > 0: - return [os.path.join(args[0], package, f) for f in cpp_files_gen] - else: - return [os.path.join(package, f) for f in cpp_files_gen] + cpp_files_gen = [os.path.join(args[0], f) for f in cpp_files_gen] + + return cpp_files_gen def cmd_cmake(args): @@ -34,7 +37,11 @@ def cmd_qmake(args): sys.stdout.write("\n".join(get_cpp_files_gen(args)) + "\n") -cmds = {"cmake": cmd_cmake, "qmake": cmd_qmake} +def cmd_meson(args): + sys.stdout.write(";".join(get_cpp_files_gen(args, include_package=False))) + + +cmds = {"cmake": cmd_cmake, "qmake": cmd_qmake, "meson": cmd_meson} if len(sys.argv) < 2 or sys.argv[1] not in cmds: print(f"""usage: {sys.argv[0]} [{"/".join(cmds.keys())}] [base path]""") diff --git a/src/meson.build b/src/meson.build index 824b5209..f43ee2d4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -8,6 +8,12 @@ feature_define_args = [] if get_option('enable_python') message('Python is enabled') feature_define_args += ['-DCUTTER_ENABLE_PYTHON'] + + if get_option('enable_python_bindings') + message('Python Bindings are enabled') + feature_define_args += ['-DCUTTER_ENABLE_PYTHON_BINDINGS'] + endif + if get_option('enable_jupyter') message('Jupyter support enabled') feature_define_args += ['-DCUTTER_ENABLE_JUPYTER'] @@ -22,6 +28,7 @@ endif add_project_arguments(feature_define_args, language: 'cpp') parse_cmd = [py3_exe, join_paths(meson.current_source_dir(), '../scripts/meson_parse_qmake.py')] +configure_qmake_cmd = [py3_exe, join_paths(meson.current_source_dir(), '../scripts/meson_configure_qmake_in.py')] qt_modules += run_command(parse_cmd + ['QT'], check: true).stdout().split(';') sources = run_command(parse_cmd + ['SOURCES'], check: true).stdout().split(';') @@ -38,7 +45,7 @@ conf_json = '''{"CUTTER_VERSION_MAJOR":@0@, version_major, version_minor, version_patch) configure_file(input: 'CutterConfig.h.in', output: 'CutterConfig.h', - command: [py3_exe, join_paths(meson.current_source_dir(), '../scripts/meson_configure_qmake_in.py'), '@INPUT@', '@OUTPUT0@', conf_json]) + command: configure_qmake_cmd + ['@INPUT@', '@OUTPUT0@', conf_json]) conf_inc = include_directories('.') sp_dir = join_paths(meson.source_root(), 'subprojects') @@ -64,7 +71,31 @@ qt5dep = dependency('qt5', modules: qt_modules) deps = [libr2_dep, qt5dep] if get_option('enable_python') - deps += [dependency('python3')] + py3_dep = dependency('python3') + deps += [py3_dep] + if get_option('enable_python_bindings') + shiboken_dep = dependency('shiboken2', method: 'pkg-config') + pyside_dep = dependency('pyside2', method: 'pkg-config') + pyside_inc_dep = declare_dependency(include_directories: include_directories(join_paths(pyside_dep.get_pkgconfig_variable('includedir'), 'QtCore'), + join_paths(pyside_dep.get_pkgconfig_variable('includedir'), 'QtGui'), + join_paths(pyside_dep.get_pkgconfig_variable('includedir'), 'QtWidgets'))) + deps += [shiboken_dep, pyside_dep, pyside_inc_dep] + shiboken_exe = shiboken_dep.get_pkgconfig_variable('generator_location') + qt5core_dep = dependency('Qt5Core', method: 'pkg-config') + bindings_generate_inc = [meson.current_source_dir(), + join_paths(meson.current_source_dir(), 'common'), + join_paths(meson.current_source_dir(), 'widgets'), + join_paths(meson.current_source_dir(), 'plugins'), + join_paths(meson.current_source_dir(), 'subprojects/radare2/libr/include'), + join_paths(meson.current_build_dir(), 'subprojects/radare2'), + qt5core_dep.get_pkgconfig_variable('includedir'), + join_paths(qt5core_dep.get_pkgconfig_variable('includedir'), 'QtCore'), + join_paths(qt5core_dep.get_pkgconfig_variable('includedir'), 'QtGui'), + join_paths(qt5core_dep.get_pkgconfig_variable('includedir'), 'QtWidgets')] + message('bindings_inc: @0@'.format(bindings_generate_inc)) + subdir('bindings') + sources += bindings_target + endif endif moc_files = qt5_mod.preprocess( @@ -96,6 +127,6 @@ cutter_exe = executable( moc_files, gui_app: true, sources: sources, - include_directories: [platform_inc, conf_inc], + include_directories: [include_directories('common', 'widgets', 'plugins'), platform_inc, conf_inc], dependencies: deps, ) diff --git a/src/meson_options.txt b/src/meson_options.txt index 2287ed0f..395f4c67 100644 --- a/src/meson_options.txt +++ b/src/meson_options.txt @@ -1,3 +1,4 @@ option('enable_python', type: 'boolean', value: true) +option('enable_python_bindings', type: 'boolean', value: true) option('enable_jupyter', type: 'boolean', value: false) option('enable_webengine', type: 'boolean', value: false)