diff --git a/ChangeLog b/ChangeLog index 2c2ea7beb..4b3c48b6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ Enhancements: - #7464 Restore `--only-python` arg to only install Python deps - #7465 Also cut `+` char for `SHORT_VERSION` var used on upload - #7467 Load server or client args from `synergy-config.toml` +- #7469 Option to link against local `libportal` and other subprojects # 1.15.1 diff --git a/cmake/Libraries.cmake b/cmake/Libraries.cmake index 4c0a0b5a3..8cd9359c4 100644 --- a/cmake/Libraries.cmake +++ b/cmake/Libraries.cmake @@ -38,6 +38,7 @@ macro(configure_unix_libs) include(CheckIncludeFileCXX) include(CheckSymbolExists) include(CheckCSourceCompiles) + include(FindPkgConfig) check_include_file_cxx(istream HAVE_ISTREAM) check_include_file_cxx(ostream HAVE_OSTREAM) @@ -167,32 +168,8 @@ endmacro() macro(configure_wayland_libs) - include(FindPkgConfig) - - pkg_check_modules(LIBEI QUIET "libei-1.0 >= ${LIBEI_MIN_VERSION}") - if(LIBEI_FOUND) - message(STATUS "libei version: ${LIBEI_VERSION}") - add_definitions(-DWINAPI_LIBEI=1) - include_directories(${LIBEI_INCLUDE_DIRS}) - else() - message( - WARNING - "libei >= ${LIBEI_MIN_VERSION} not found, Wayland support will be disabled." - ) - endif() - - pkg_check_modules(LIBPORTAL QUIET "libportal >= ${LIBPORTAL_MIN_VERSION}") - if(LIBPORTAL_FOUND) - message(STATUS "libportal version: ${LIBPORTAL_VERSION}") - add_definitions(-DWINAPI_LIBPORTAL=1) - include_directories(${LIBPORTAL_INCLUDE_DIRS}) - check_libportal() - else() - message( - WARNING - "libportal >= ${LIBPORTAL_MIN_VERSION} not found, some Wayland features will be disabled." - ) - endif() + configure_libei() + configure_libportal() pkg_check_modules(LIBXKBCOMMON REQUIRED xkbcommon) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) @@ -202,23 +179,103 @@ macro(configure_wayland_libs) endmacro() +macro(configure_libei) + option(SYSTEM_LIBEI "Use system libei" ON) + if(SYSTEM_LIBEI) + pkg_check_modules(LIBEI QUIET "libei-1.0 >= ${LIBEI_MIN_VERSION}") + if(LIBEI_FOUND) + message(STATUS "libei version: ${LIBEI_VERSION}") + add_definitions(-DWINAPI_LIBEI=1) + include_directories(${LIBEI_INCLUDE_DIRS}) + else() + message(WARNING "libei >= ${LIBEI_MIN_VERSION} not found") + endif() + else() + set(libei_bin_dir ${CMAKE_BINARY_DIR}/meson/subprojects/libei/src) + set(libei_src_dir ${CMAKE_SOURCE_DIR}/subprojects/libei) + find_library( + LIBEI_LINK_LIBRARIES + NAMES ei + PATHS ${libei_bin_dir} + NO_DEFAULT_PATH) + if(LIBEI_LINK_LIBRARIES) + message(STATUS "Using local subproject libei") + set(LIBEI_FOUND true) + add_definitions(-DWINAPI_LIBEI=1) + set(LIBEI_INCLUDE_DIRS ${libei_src_dir}/src) + include_directories(${LIBEI_INCLUDE_DIRS}) + else() + message(WARNING "Local libei not found") + endif() + endif() +endmacro() + +macro(configure_libportal) + option(SYSTEM_LIBPORTAL "Use system libportal" ON) + if(SYSTEM_LIBPORTAL) + pkg_check_modules(LIBPORTAL QUIET "libportal >= ${LIBPORTAL_MIN_VERSION}") + if(LIBPORTAL_FOUND) + message(STATUS "libportal version: ${LIBPORTAL_VERSION}") + check_libportal() + else() + message(WARNING "libportal >= ${LIBPORTAL_MIN_VERSION} not found") + endif() + else() + set(libportal_bin_dir + ${CMAKE_BINARY_DIR}/meson/subprojects/libportal/libportal) + set(libportal_src_dir ${CMAKE_SOURCE_DIR}/subprojects/libportal) + find_library( + LIBPORTAL_LINK_LIBRARIES + NAMES portal + PATHS ${libportal_bin_dir} + NO_DEFAULT_PATH) + + if(LIBPORTAL_LINK_LIBRARIES) + message(STATUS "Using local subproject libportal") + set(LIBPORTAL_FOUND true) + set(LIBPORTAL_INCLUDE_DIRS ${libportal_src_dir}) + + # HACK: Somehow `check_symbol_exists` doesn't pick up on the symbols even though + # they are actually there. Since we use master branch of libportal, for now we'll + # assume that the symbols are there. + set(HAVE_LIBPORTAL_SESSION_CONNECT_TO_EIS true) + set(HAVE_LIBPORTAL_CREATE_REMOTE_DESKTOP_SESSION_FULL true) + set(HAVE_LIBPORTAL_INPUTCAPTURE true) + set(HAVE_LIBPORTAL_OUTPUT_NONE true) + else() + message(WARNING "Local libportal not found") + endif() + endif() + + if(LIBPORTAL_FOUND) + add_definitions(-DWINAPI_LIBPORTAL=1) + include_directories(${LIBPORTAL_INCLUDE_DIRS}) + endif() + +endmacro() + +# libportal 0.7 has xdp_session_connect_to_eis but it doesn't have remote desktop session restore or +# the inputcapture code, so let's check for explicit functions that bits depending on what we have macro(check_libportal) - # libportal 0.7 has xdp_session_connect_to_eis but it doesn't have remote desktop session restore or - # the inputcapture code, so let's check for explicit functions that bits depending on what we have include(CMakePushCheckState) include(CheckCXXSourceCompiles) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES};${LIBPORTAL_INCLUDE_DIRS};${GLIB2_INCLUDE_DIRS}" ) set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};${LIBPORTAL_LINK_LIBRARIES};${GLIB2_LINK_LIBRARIES}" ) + check_symbol_exists(xdp_session_connect_to_eis "libportal/portal.h" HAVE_LIBPORTAL_SESSION_CONNECT_TO_EIS) + check_symbol_exists( xdp_portal_create_remote_desktop_session_full "libportal/portal.h" HAVE_LIBPORTAL_CREATE_REMOTE_DESKTOP_SESSION_FULL) + check_symbol_exists(xdp_input_capture_session_connect_to_eis "libportal/inputcapture.h" HAVE_LIBPORTAL_INPUTCAPTURE) @@ -227,8 +284,25 @@ macro(check_libportal) "#include int main() { XdpOutputType out = XDP_OUTPUT_NONE; } " HAVE_LIBPORTAL_OUTPUT_NONE) + cmake_pop_check_state() + if(NOT HAVE_LIBPORTAL_SESSION_CONNECT_TO_EIS) + message(WARNING "xdp_session_connect_to_eis not found") + endif() + + if(NOT HAVE_LIBPORTAL_CREATE_REMOTE_DESKTOP_SESSION_FULL) + message(WARNING "xdp_portal_create_remote_desktop_session_full not found") + endif() + + if(NOT HAVE_LIBPORTAL_INPUTCAPTURE) + message(WARNING "xdp_input_capture_session_connect_to_eis not found") + endif() + + if(NOT HAVE_LIBPORTAL_OUTPUT_NONE) + message(WARNING "XDP_OUTPUT_NONE not found") + endif() + endmacro() # diff --git a/meson.build b/meson.build index 32baeeb5b..10e0f295f 100644 --- a/meson.build +++ b/meson.build @@ -36,6 +36,6 @@ if host_machine.system() == 'linux' dependency('libportal', required: false) else # Using the subproject is only useful for development; it's not intended for normal use. - subproject('libportal', default_options: ['docs=false', 'backend-gtk3=enabled']) + subproject('libportal', default_options: ['docs=false', 'backend-gtk3=enabled', 'backend-qt6=disabled']) endif endif diff --git a/res/config.h.in b/res/config.h.in index 8a040406a..463d644f2 100644 --- a/res/config.h.in +++ b/res/config.h.in @@ -177,6 +177,3 @@ /* Define if libportal has input capture support */ #cmakedefine HAVE_LIBPORTAL_INPUTCAPTURE ${HAVE_LIBPORTAL_INPUTCAPTURE} - -/* Define if libei ei_device_start_emulating takes a sequence number */ -#cmakedefine HAVE_LIBEI_SEQUENCE_NUMBER ${HAVE_LIBEI_SEQUENCE_NUMBER} diff --git a/scripts/install_deps.py b/scripts/install_deps.py index 64673b2b5..1b5b52676 100755 --- a/scripts/install_deps.py +++ b/scripts/install_deps.py @@ -16,31 +16,7 @@ def main(): if is_ci: print("CI environment detected") - parser = argparse.ArgumentParser() - parser.add_argument( - "--pause-on-exit", action="store_true", help="Useful on Windows" - ) - parser.add_argument( - "--ci-env", - action="store_true", - help="Useful for faking CI env (defaults to true in CI env)", - default=is_ci, - ) - parser.add_argument( - "--only-python", action="store_true", help="Only install Python dependencies" - ) - parser.add_argument( - "--skip-system", - action="store_true", - help="Do not install system dependencies (apt, dnf, etc)", - ) - parser.add_argument( - "--skip-meson", action="store_true", help="Do not setup and install with Meson" - ) - parser.add_argument( - "--subproject", type=str, help="Sub-project to install dependencies for" - ) - args = parser.parse_args() + args = parse_args(is_ci) env.ensure_dependencies() env.ensure_in_venv(__file__, auto_create=True) @@ -86,6 +62,44 @@ def main(): sys.exit(1) +def parse_args(is_ci): + parser = argparse.ArgumentParser() + parser.add_argument( + "--pause-on-exit", action="store_true", help="Useful on Windows" + ) + parser.add_argument( + "--ci-env", + action="store_true", + help="Useful for faking CI env (defaults to true in CI env)", + default=is_ci, + ) + parser.add_argument( + "--only-python", action="store_true", help="Only install Python dependencies" + ) + parser.add_argument( + "--skip-system", + action="store_true", + help="Do not install system dependencies (apt, dnf, etc)", + ) + parser.add_argument( + "--skip-meson", action="store_true", help="Do not setup and compile with Meson" + ) + parser.add_argument( + "--subproject", type=str, help="Sub-project to install dependencies for" + ) + parser.add_argument( + "--meson-install", + action="store_true", + help="Install built Meson subprojects to system", + ) + parser.add_argument( + "--meson-no-system", + nargs="+", + help="Specify which Meson subprojects to use instead of system dependencies", + ) + return parser.parse_args() + + def run(args): if args.subproject: deps = SubprojectDependencies(args.subproject) @@ -97,20 +111,22 @@ def run(args): deps.install() if not args.skip_meson: - run_meson() + run_meson(args.meson_install, args.meson_no_system) # It's a bit weird to use Meson just for installing deps, but it's a stopgap until # we fully switch from CMake to Meson. For the meantime, Meson will install the deps # so that CMake can find them easily. Once we switch to Meson, it might be possible for # Meson handle the deps resolution, so that we won't need to install them on the system. -def run_meson(): - meson.setup() +def run_meson(install, no_system_list): + meson.setup(no_system_list) # Only compile and install on Linux for now, since we're only using Meson to fetch # the deps on Windows and macOS. if env.is_linux(): meson.compile() + + if install: meson.install() diff --git a/scripts/lib/meson.py b/scripts/lib/meson.py index bd1fe6e54..39efd8b9c 100644 --- a/scripts/lib/meson.py +++ b/scripts/lib/meson.py @@ -6,14 +6,21 @@ build_dir = "build/meson" meson_bin = env.get_python_executable("meson") -def setup(): +def setup(no_system_list): cmd = [meson_bin, "setup", build_dir] if env.is_windows(): cmd.append("-Dsystem_gtest=false") + for subproject in no_system_list or []: + cmd.append(f"-Dsystem_{subproject}=false") + + # This might be a bit rude, but Meson seems to cache a lot (like CMake), + # so wiping every time is the easiest way to ensure that the build is clean. + # Plus, the way we're using Meson (at the moment) is just for satisfying + # dependencies, so this script is run infrequently enough to not matter. if os.path.exists(build_dir): - cmd.append("--reconfigure") + cmd.append("--wipe") cmd_utils.run(cmd, print_cmd=True) diff --git a/subprojects/libei.wrap b/subprojects/libei.wrap index 83a5db463..ccd0acb76 100644 --- a/subprojects/libei.wrap +++ b/subprojects/libei.wrap @@ -1,3 +1,3 @@ [wrap-git] url = https://gitlab.freedesktop.org/libinput/libei.git -revision = tags/1.3.0 +revision = main diff --git a/subprojects/libportal.wrap b/subprojects/libportal.wrap index d0fb1f7e6..da1ed2c4e 100644 --- a/subprojects/libportal.wrap +++ b/subprojects/libportal.wrap @@ -1,3 +1,3 @@ [wrap-git] url = https://github.com/flatpak/libportal.git -revision = a1530a9 +revision = main