diff --git a/apps/desktop/tests/build_define_scope_test.lua b/apps/desktop/tests/build_define_scope_test.lua new file mode 100644 index 00000000..df8f70be --- /dev/null +++ b/apps/desktop/tests/build_define_scope_test.lua @@ -0,0 +1,78 @@ +-- Run from the repository root: xmake lua apps/desktop/tests/build_define_scope_test.lua windows true +-- Inspect the real Xmake target graph without configuring/downloading packages. +function main(plat, portable) + import("core.project.config") + import("core.project.project") + config.load() + config.set("plat", plat or "windows", {force = true}) + config.set("arch", plat == "macosx" and "arm64" or "x64", {force = true}) + config.set("CROSSDESK_PORTABLE", portable == "true", {force = true}) + config.set("CROSSDESK_VERSION", "v1.5.3-2-20260913", {force = true}) + local targets = project.targets() + local function flatten(values) + local result = {} + local function append(value) + if type(value) == "table" then + for _, entry in ipairs(value) do append(entry) end + elseif value ~= nil then + table.insert(result, value) + end + end + append(values) + return result + end + local function contains(values, expected) + return table.contains(flatten(values), expected) + end + local function effective_defines(target) + return table.join(table.wrap(target:get("defines")), + flatten(target:get_from("defines", "dep::*"))) + end + + for _, name in ipairs({"minirtc", "media", "common", "crossdesk_wire", "rd_log"}) do + for _, define in ipairs(effective_defines(targets[name])) do + assert(not define:startswith("CROSSDESK_VERSION"), name .. " inherits version macros") + assert(not define:startswith("CROSSDESK_PORTABLE"), name .. " inherits portable macros") + end + end + for _, name in ipairs({"gui", "crossdesk", "path_manager"}) do + assert(contains(effective_defines(targets[name]), "CROSSDESK_PORTABLE=1") == + (portable == "true"), name .. " has inconsistent portable layout/configuration") + end + + local gui = targets.gui + local version_files = { + ["apps/desktop/src/gui/application/gui_application.cpp"] = true, + ["apps/desktop/src/gui/runtime/peer_event_handler.cpp"] = true + } + local seen = {} + for _, file in ipairs(gui:sourcefiles()) do + assert(not seen[file], "duplicate GUI source: " .. file) + seen[file] = true + local defines = (gui:fileconfig(file) or {}).defines + assert(contains(defines, 'CROSSDESK_VERSION="v1.5.3-2-20260913"') == + (version_files[file] == true), "unexpected version scope: " .. file) + end + for file in pairs(version_files) do + assert(seen[file], "missing version consumer: " .. file) + end + + if plat == "windows" then + local resources = { + crossdesk = portable == "true" and "crossdesk_portable" or "crossdesk", + crossdesk_service = "crossdesk_service", + crossdesk_session_helper = "crossdesk_session_helper", + crossdesk_privacy_window = "crossdesk_privacy_window", + wgc_plugin = "wgc_plugin" + } + for name, resource in pairs(resources) do + local defines = targets[name]:fileconfig( + "apps/desktop/resources/windows/" .. resource .. ".rc").defines + assert(contains(defines, 'CROSSDESK_VERSION_STRING="v1.5.3-2-20260913"')) + assert(contains(defines, "CROSSDESK_VERSION_NUMERIC=1,5,3,0")) + assert(contains(defines, "CROSSDESK_PORTABLE=1") == + (name == "crossdesk_session_helper" and portable == "true")) + end + end + print("Build define scopes passed: %s portable=%s", plat, portable) +end diff --git a/apps/desktop/xmake/options.lua b/apps/desktop/xmake/options.lua index 9428b5dd..1a0faf82 100644 --- a/apps/desktop/xmake/options.lua +++ b/apps/desktop/xmake/options.lua @@ -29,30 +29,6 @@ function setup_options_and_dependencies() set_description("Build CrossDesk as a portable package that stores data beside the executable") option_end() - -- Preserve the existing codebase/toolchain contract. Slint targets opt in to - -- C++20 locally because its generated C++ API requires it. - local crossdesk_version = get_config("CROSSDESK_VERSION") or "0.0.0" - local version_base = crossdesk_version:gsub("^v", ""):match("^(%d[%d%.]*)") or "0.0.0" - local version_parts = {} - for part in version_base:gmatch("%d+") do - local value = tonumber(part) or 0 - if value > 65535 then - value = 0 - end - table.insert(version_parts, value) - if #version_parts == 4 then - break - end - end - while #version_parts < 4 do - table.insert(version_parts, 0) - end - - add_defines("CROSSDESK_VERSION_STRING=\"" .. crossdesk_version .. "\"") - if is_os("windows") then - add_defines("CROSSDESK_VERSION_NUMERIC=" .. table.concat(version_parts, ",")) - end - -- set_policy("build.warning", true) -- set_warnings("all", "extra") -- add_cxxflags("/W4", "/WX") @@ -61,10 +37,6 @@ function setup_options_and_dependencies() add_defines("USE_CUDA=" .. (is_config("USE_CUDA", true) and "1" or "0")) add_defines("USE_WAYLAND=" .. (is_config("USE_WAYLAND", true) and "1" or "0")) add_defines("USE_DRM=" .. (is_config("USE_DRM", true) and "1" or "0")) - if is_config("CROSSDESK_PORTABLE", true) then - add_defines("CROSSDESK_PORTABLE=1") - end - if is_mode("debug") then add_defines("CROSSDESK_DEBUG") end diff --git a/apps/desktop/xmake/targets.lua b/apps/desktop/xmake/targets.lua index a2cc62d5..0c5d1f91 100644 --- a/apps/desktop/xmake/targets.lua +++ b/apps/desktop/xmake/targets.lua @@ -3,6 +3,30 @@ function setup_targets() includes("deps/submodules", "deps/thirdparty") + local crossdesk_version = get_config("CROSSDESK_VERSION") or "0.0.0" + local version_define = "CROSSDESK_VERSION=\"" .. crossdesk_version .. "\"" + local windows_resource_defines = { + "CROSSDESK_VERSION_STRING=\"" .. crossdesk_version .. "\"" + } + local version_base = crossdesk_version:gsub("^v", ""):match("^(%d[%d%.]*)") or "0.0.0" + local version_parts = {} + for part in version_base:gmatch("%d+") do + local value = tonumber(part) or 0 + table.insert(version_parts, value <= 65535 and value or 0) + if #version_parts == 4 then + break + end + end + while #version_parts < 4 do + table.insert(version_parts, 0) + end + table.insert(windows_resource_defines, + "CROSSDESK_VERSION_NUMERIC=" .. table.concat(version_parts, ",")) + local windows_helper_resource_defines = table.join(windows_resource_defines) + if is_config("CROSSDESK_PORTABLE", true) then + table.insert(windows_helper_resource_defines, "CROSSDESK_PORTABLE=1") + end + local function copy_slint_runtime(target) if not target:is_plat("windows") then return @@ -50,6 +74,9 @@ function setup_targets() target("path_manager") set_kind("object") + if is_config("CROSSDESK_PORTABLE", true) then + add_defines("CROSSDESK_PORTABLE=1") + end add_deps("rd_log") add_files("apps/desktop/src/path_manager/*.cpp") if is_os("windows") then @@ -182,7 +209,8 @@ function setup_targets() set_runtimes("MT") add_files("apps/desktop/src/platform/windows/privacy/band_module/main.cpp") add_files("apps/desktop/src/platform/windows/privacy/band_module/privacy_cover_renderer.cpp") - add_files("apps/desktop/resources/windows/crossdesk_privacy_window.rc") + add_files("apps/desktop/resources/windows/crossdesk_privacy_window.rc", + {defines = windows_resource_defines}) add_syslinks("user32", "gdi32", "dwmapi") target("crossdesk_privacy_cursor_helper") @@ -321,7 +349,6 @@ function setup_targets() target("version_checker") set_kind("object") add_packages("cpp-httplib") - add_defines("CROSSDESK_VERSION=\"" .. (get_config("CROSSDESK_VERSION") or "Unknown") .. "\"") add_deps("rd_log") add_files("apps/desktop/src/version_checker/*.cpp") add_includedirs("apps/desktop/src/version_checker", {public = true}) @@ -353,7 +380,11 @@ function setup_targets() add_packages("slint", {public = true}) add_packages("libyuv", "tinyfiledialogs") add_rules("slint") - add_defines("CROSSDESK_VERSION=\"" .. (get_config("CROSSDESK_VERSION") or "Unknown") .. "\"") + if is_config("CROSSDESK_PORTABLE", true) then + -- RuntimeState changes layout in portable builds. Consumers of GUI + -- headers must see the same definition, without affecting its deps. + add_defines("CROSSDESK_PORTABLE=1", {public = true}) + end add_deps("rd_log", "common", "assets", "config_center", "minirtc", "path_manager", "screen_capturer", "speaker_capturer", "device_controller", "thumbnail", "version_checker", "tools", @@ -365,6 +396,11 @@ function setup_targets() "apps/desktop/src/gui/features/devices/*.cpp", "apps/desktop/src/gui/features/input/*.cpp", "apps/desktop/src/gui/features/clipboard/*.cpp", "apps/desktop/src/gui/features/file_transfer/*.cpp", "apps/desktop/src/gui/features/settings/*.cpp", "apps/desktop/src/gui/ui/crossdesk_ui.slint") + -- Only these translation units consume the application version. Keep + -- version changes out of the flags for media and the rest of the GUI. + add_files("apps/desktop/src/gui/application/gui_application.cpp", + "apps/desktop/src/gui/runtime/peer_event_handler.cpp", + {defines = version_define}) add_includedirs("apps/desktop/src", "apps/desktop/src/gui", {public = true}) add_includedirs("apps/desktop/src/platform/common/input") if is_os("windows") then @@ -416,7 +452,8 @@ function setup_targets() add_files("apps/desktop/src/platform/windows/screen_capturer/screen_capturer_wgc.cpp", "apps/desktop/src/platform/windows/screen_capturer/wgc_session_impl.cpp", "apps/desktop/src/platform/windows/screen_capturer/wgc_plugin_entry.cpp") - add_files("apps/desktop/resources/windows/wgc_plugin.rc") + add_files("apps/desktop/resources/windows/wgc_plugin.rc", + {defines = windows_resource_defines}) add_includedirs("apps/desktop/src/common", "apps/desktop/src/screen_capturer", "apps/desktop/src/platform/windows/screen_capturer", "deps/submodules/minirtc/src/api") @@ -427,7 +464,8 @@ function setup_targets() add_links("Advapi32", "Wtsapi32", "Ole32", "Userenv") add_files("apps/desktop/src/platform/windows/service/main.cpp", "apps/desktop/src/platform/windows/service/service_host.cpp") - add_files("apps/desktop/resources/windows/crossdesk_service.rc") + add_files("apps/desktop/resources/windows/crossdesk_service.rc", + {defines = windows_resource_defines}) add_includedirs("apps/desktop/src/platform/windows/service") target("crossdesk_session_helper") @@ -436,7 +474,8 @@ function setup_targets() add_deps("rd_log", "path_manager") add_links("Advapi32", "User32", "Wtsapi32", "Gdi32") add_files("apps/desktop/src/platform/windows/service/session_helper_main.cpp") - add_files("apps/desktop/resources/windows/crossdesk_session_helper.rc") + add_files("apps/desktop/resources/windows/crossdesk_session_helper.rc", + {defines = windows_helper_resource_defines}) add_includedirs("apps/desktop/src/common", "apps/desktop/src/platform/windows/service") add_includedirs("apps/desktop/src/platform/windows/input") @@ -453,7 +492,7 @@ function setup_targets() add_includedirs("apps/desktop/src/platform/windows/service") add_links("Advapi32", "Wtsapi32", "Ole32", "Userenv") add_deps("wgc_plugin", "crossdesk_service", "crossdesk_session_helper") - add_files(crossdesk_windows_resource) + add_files(crossdesk_windows_resource, {defines = windows_resource_defines}) elseif is_os("macosx") then add_files("apps/desktop/src/platform/common/posix_daemon_backend.cpp", "apps/desktop/src/platform/macos/daemon_backend.cpp")