cmake_minimum_required(VERSION 3.20) project(wine_access LANGUAGES C CXX) include(GNUInstallDirs) set(WINE_ACCESS_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/cthulhu/wine" CACHE PATH "Installation directory for the Wine helper and its Winelib sidecar") find_package(PkgConfig REQUIRED) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb) find_program(WIDL_EXECUTABLE widl REQUIRED) find_program(MINGW_C_COMPILER x86_64-w64-mingw32-gcc REQUIRED) find_program(MINGW32_C_COMPILER i686-w64-mingw32-gcc REQUIRED) # A PE hook DLL can be loaded into ordinary Wine applications without any # GLib dependencies. Keep it alongside the Winelib helper. set(menu_hook "${CMAKE_CURRENT_BINARY_DIR}/wine-access-menu.dll") add_custom_command(OUTPUT "${menu_hook}" COMMAND "${MINGW_C_COMPILER}" -std=c11 -O2 -Wall -Wextra -shared -static-libgcc -o "${menu_hook}" "${CMAKE_CURRENT_SOURCE_DIR}/menu_hook.c" "${CMAKE_CURRENT_SOURCE_DIR}/edit_hook.c" "${CMAKE_CURRENT_SOURCE_DIR}/scintilla_hook.c" -luser32 -lcomctl32 -lgdi32 DEPENDS menu_hook.c menu_bridge.h edit_hook.c edit_hook.h control_class.h scintilla_hook.c scintilla_messages.h VERBATIM) add_custom_target(wine-access-menu ALL DEPENDS "${menu_hook}") set(menu_hook32 "${CMAKE_CURRENT_BINARY_DIR}/wine-access-menu32.dll") set(menu_host32 "${CMAKE_CURRENT_BINARY_DIR}/wine-access-menu-host32.exe") add_custom_command(OUTPUT "${menu_hook32}" "${menu_host32}" COMMAND "${MINGW32_C_COMPILER}" -std=c11 -O2 -Wall -Wextra -shared -static-libgcc -Wl,--kill-at -o "${menu_hook32}" "${CMAKE_CURRENT_SOURCE_DIR}/menu_hook.c" "${CMAKE_CURRENT_SOURCE_DIR}/edit_hook.c" -luser32 -lcomctl32 COMMAND "${MINGW32_C_COMPILER}" -std=c11 -O2 -Wall -Wextra -mwindows -static-libgcc -o "${menu_host32}" "${CMAKE_CURRENT_SOURCE_DIR}/menu_host32.c" -luser32 DEPENDS menu_hook.c menu_bridge.h menu_host32.c edit_hook.c edit_hook.h control_class.h VERBATIM) add_custom_target(wine-access-menu32 ALL DEPENDS "${menu_hook32}" "${menu_host32}") set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated") set(generated_header "${generated_dir}/nvdaController.h") set(generated_server "${generated_dir}/nvdaController_s.c") file(MAKE_DIRECTORY "${generated_dir}") add_custom_command( OUTPUT "${generated_header}" "${generated_server}" COMMAND "${WIDL_EXECUTABLE}" --win64 -h -H "${generated_header}" -s -S "${generated_server}" "${CMAKE_CURRENT_SOURCE_DIR}/nvdaController.idl" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/nvdaController.idl" VERBATIM) add_executable(cthulhu-wine-access reader_events.cpp msaa_events.cpp main.cpp foreground_focus.cpp list_view.cpp native_items.cpp review_capture.cpp review_x11.cpp review_service.cpp "${generated_server}") add_dependencies(cthulhu-wine-access wine-access-menu wine-access-menu32) target_compile_features(cthulhu-wine-access PRIVATE cxx_std_20) target_include_directories(cthulhu-wine-access PRIVATE "${generated_dir}") target_link_libraries(cthulhu-wine-access PRIVATE PkgConfig::GIO PkgConfig::XCB oleacc ole32 oleaut32 rpcrt4 user32 gdi32 shell32) target_link_options(cthulhu-wine-access PRIVATE -mwindows) target_compile_options(cthulhu-wine-access PRIVATE $<$:-Wall -Wextra>) include(CTest) if(BUILD_TESTING) set(foreground_fixture "${CMAKE_CURRENT_BINARY_DIR}/foreground-fixture.exe") add_custom_command(OUTPUT "${foreground_fixture}" COMMAND "${MINGW_C_COMPILER}" -std=c11 -Wall -Wextra -mwindows -o "${foreground_fixture}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/foreground_fixture.c" -luser32 DEPENDS tests/foreground_fixture.c VERBATIM) add_custom_target(foreground-fixture ALL DEPENDS "${foreground_fixture}") add_executable(foreground-focus-test tests/foreground_focus_test.cpp foreground_focus.cpp review_x11.cpp) add_dependencies(foreground-focus-test foreground-fixture) target_compile_features(foreground-focus-test PRIVATE cxx_std_20) target_compile_options(foreground-focus-test PRIVATE -Wall -Wextra) target_link_libraries(foreground-focus-test PRIVATE user32 PkgConfig::XCB) add_test(NAME foreground-focus COMMAND python3 "${CMAKE_CURRENT_SOURCE_DIR}/tests/foreground_focus_test.py" "${CMAKE_CURRENT_BINARY_DIR}") set_tests_properties(foreground-focus PROPERTIES TIMEOUT 90 ENVIRONMENT "WINEPREFIX=${CMAKE_CURRENT_BINARY_DIR}/focus-prefix;CTHULHU_WINE_ACCESS_MANAGED=1;WINEDEBUG=-all;WINEDLLOVERRIDES=mscoree,mshtml=") add_executable(msaa-states-test tests/msaa_states_test.cpp) target_compile_features(msaa-states-test PRIVATE cxx_std_20) target_compile_options(msaa-states-test PRIVATE -Wall -Wextra) add_test(NAME msaa-states COMMAND "${CMAKE_CURRENT_BINARY_DIR}/msaa-states-test.exe") set_tests_properties(msaa-states PROPERTIES ENVIRONMENT "WINEPREFIX=${CMAKE_CURRENT_BINARY_DIR}/test-prefix;CTHULHU_WINE_ACCESS_MANAGED=1;WINEDEBUG=-all;WINEDLLOVERRIDES=mscoree,mshtml=") add_executable(review-capture-test tests/review_capture_test.cpp) target_compile_features(review-capture-test PRIVATE cxx_std_20) target_compile_options(review-capture-test PRIVATE -Wall -Wextra) target_link_libraries(review-capture-test PRIVATE ole32 oleacc oleaut32 user32 gdi32 PkgConfig::GIO PkgConfig::XCB) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/review_capture.cpp") target_sources(review-capture-test PRIVATE review_capture.cpp review_x11.cpp list_view.cpp native_items.cpp) endif() foreach(arch IN ITEMS 64 32) if(arch EQUAL 32) set(fixture_compiler "${MINGW32_C_COMPILER}") else() set(fixture_compiler "${MINGW_C_COMPILER}") endif() set(review_fixture "${CMAKE_CURRENT_BINARY_DIR}/review-fixture${arch}.exe") add_custom_command(OUTPUT "${review_fixture}" COMMAND "${fixture_compiler}" -std=c11 -Wall -Wextra -mwindows -o "${review_fixture}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/review_fixture.c" -luser32 -lcomctl32 DEPENDS tests/review_fixture.c VERBATIM) add_custom_target(review-fixture${arch} ALL DEPENDS "${review_fixture}") add_dependencies(review-capture-test review-fixture${arch}) add_test(NAME review-capture${arch} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/review-capture-test.exe" --fixture "${review_fixture}") set_tests_properties(review-capture${arch} PROPERTIES TIMEOUT 35 ENVIRONMENT "WINEPREFIX=${CMAKE_CURRENT_BINARY_DIR}/review-prefix${arch};CTHULHU_WINE_ACCESS_MANAGED=1;WINEDEBUG=-all;WINEDLLOVERRIDES=mscoree,mshtml=") endforeach() endif() # Winegcc emits a launcher and a Winelib sidecar. CMake's normal target # installation looks for the Linux target name, so install both emitted # artifacts explicitly and keep them together for Wine to resolve. install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/cthulhu-wine-access.exe" DESTINATION "${WINE_ACCESS_INSTALL_DIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cthulhu-wine-access.exe.so" "${menu_hook}" "${menu_hook32}" "${menu_host32}" DESTINATION "${WINE_ACCESS_INSTALL_DIR}")