From 0cc85e2c86f37bc3ceed01d1480b18af0666bfae Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 02:51:06 +0530 Subject: [PATCH 01/28] third-party: add ARM64 support for FTDI library download Signed-off-by: Amit Kucheria --- third-party/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 8d948ba..69e75da 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -40,8 +40,13 @@ if(WIN32) set(DEBUG_LIB "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib/ftd2xx.lib") set(RELEASE_LIB "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib/ftd2xx.lib") else() - set(FTDI_URL "https://ftdichip.com/wp-content/uploads/2025/03/libftd2xx-linux-x86_64-1.4.33.tgz") - set(FTDI_ARCHIVE "libftd2xx-linux-x86_64-1.4.33.tgz") + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") + set(FTDI_URL "https://ftdichip.com/wp-content/uploads/2025/03/libftd2xx-linux-arm-v8-1.4.33.tgz") + set(FTDI_ARCHIVE "libftd2xx-linux-arm-v8-1.4.33.tgz") + else() + set(FTDI_URL "https://ftdichip.com/wp-content/uploads/2025/03/libftd2xx-linux-x86_64-1.4.33.tgz") + set(FTDI_ARCHIVE "libftd2xx-linux-x86_64-1.4.33.tgz") + endif() set(DEBUG_LIB "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib/libftd2xx.a") set(RELEASE_LIB "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib/libftd2xx.a") endif() From a45762cda83320f00e92885c3510e495c7e5b9a7 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 03:19:41 +0530 Subject: [PATCH 02/28] third-party: fix FTDI static lib glob to search recursively The single-level glob missed libftd2xx-static.a when the archive uses a different subdirectory depth. GLOB_RECURSE finds it regardless. Also adds a fatal error if the library is absent so the failure is clear. Signed-off-by: Amit Kucheria --- third-party/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 69e75da..0b861ea 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -109,7 +109,10 @@ if(NEED_DOWNLOAD) else() file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") - file(GLOB SOURCE_LIB "${TEMP_DIR}/*/libftd2xx-static.a") + file(GLOB_RECURSE SOURCE_LIB "${TEMP_DIR}/libftd2xx-static.a") + if(NOT SOURCE_LIB) + message(FATAL_ERROR "libftd2xx-static.a not found in downloaded FTDI archive") + endif() file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib/libftd2xx-static.a" "${DEBUG_LIB}") From 050c4494b5b62006ddc02907c03c1ab9dfb57b64 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 03:35:55 +0530 Subject: [PATCH 03/28] cmake: fix qt_generate_deploy_app_script compat with Qt < 6.5 OUTPUT_SCRIPT was added in Qt 6.5; older system Qt (e.g. Ubuntu 24.04 ships 6.4.2) only knows FILENAME_VARIABLE. Add a qtac_deploy_app() macro in src/applications/CMakeLists.txt that selects the right argument name based on Qt6Core_VERSION, and replace all eight call sites with it. Signed-off-by: Amit Kucheria --- src/applications/CMakeLists.txt | 18 ++++++++++++++++++ src/applications/device-catalog/CMakeLists.txt | 7 +------ src/applications/devlist/CMakeLists.txt | 7 +------ src/applications/ftdi-check/CMakeLists.txt | 7 +------ .../programmers/lite-programmer/CMakeLists.txt | 7 +------ .../tac-configuration-editor/CMakeLists.txt | 6 +----- src/applications/tacdump/CMakeLists.txt | 7 +------ .../test-automation-controller/CMakeLists.txt | 7 +------ .../updatedevicelist/CMakeLists.txt | 7 +------ 9 files changed, 26 insertions(+), 47 deletions(-) diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt index 03f5074..ebcd4ed 100644 --- a/src/applications/CMakeLists.txt +++ b/src/applications/CMakeLists.txt @@ -41,6 +41,24 @@ find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() +# Qt 6.3/6.4 use FILENAME_VARIABLE; Qt 6.5+ renamed it to OUTPUT_SCRIPT. +macro(qtac_deploy_app target) + if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") + qt_generate_deploy_app_script( + TARGET ${target} + OUTPUT_SCRIPT deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR + ) + else() + qt_generate_deploy_app_script( + TARGET ${target} + FILENAME_VARIABLE deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR + ) + endif() + install(SCRIPT ${deploy_script}) +endmacro() + add_subdirectory(devlist) add_subdirectory(tacdump) add_subdirectory(ftdi-check) diff --git a/src/applications/device-catalog/CMakeLists.txt b/src/applications/device-catalog/CMakeLists.txt index cded440..3a002a6 100644 --- a/src/applications/device-catalog/CMakeLists.txt +++ b/src/applications/device-catalog/CMakeLists.txt @@ -118,9 +118,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET DeviceCatalog - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(DeviceCatalog) diff --git a/src/applications/devlist/CMakeLists.txt b/src/applications/devlist/CMakeLists.txt index 8b118f1..fb79db6 100644 --- a/src/applications/devlist/CMakeLists.txt +++ b/src/applications/devlist/CMakeLists.txt @@ -82,9 +82,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET ${APP_NAME} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(${APP_NAME}) diff --git a/src/applications/ftdi-check/CMakeLists.txt b/src/applications/ftdi-check/CMakeLists.txt index 02697be..0e9c269 100644 --- a/src/applications/ftdi-check/CMakeLists.txt +++ b/src/applications/ftdi-check/CMakeLists.txt @@ -112,9 +112,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET FTDICheck - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(FTDICheck) diff --git a/src/applications/programmers/lite-programmer/CMakeLists.txt b/src/applications/programmers/lite-programmer/CMakeLists.txt index 0e21133..239b26e 100644 --- a/src/applications/programmers/lite-programmer/CMakeLists.txt +++ b/src/applications/programmers/lite-programmer/CMakeLists.txt @@ -85,9 +85,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET ${APP_NAME} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(${APP_NAME}) diff --git a/src/applications/tac-configuration-editor/CMakeLists.txt b/src/applications/tac-configuration-editor/CMakeLists.txt index 662b3ee..d6e1a90 100644 --- a/src/applications/tac-configuration-editor/CMakeLists.txt +++ b/src/applications/tac-configuration-editor/CMakeLists.txt @@ -133,8 +133,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script(TARGET ${APP_NAME} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(${APP_NAME}) diff --git a/src/applications/tacdump/CMakeLists.txt b/src/applications/tacdump/CMakeLists.txt index 5e9610d..c7ab853 100644 --- a/src/applications/tacdump/CMakeLists.txt +++ b/src/applications/tacdump/CMakeLists.txt @@ -92,9 +92,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET ${APP_NAME} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(${APP_NAME}) diff --git a/src/applications/test-automation-controller/CMakeLists.txt b/src/applications/test-automation-controller/CMakeLists.txt index 0252a7b..f158d08 100644 --- a/src/applications/test-automation-controller/CMakeLists.txt +++ b/src/applications/test-automation-controller/CMakeLists.txt @@ -134,12 +134,7 @@ install(TARGETS TAC RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET TAC - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(TAC) if(WIN32 AND WINDEPLOYQT_EXECUTABLE) add_custom_command(TARGET ${APP_NAME} POST_BUILD diff --git a/src/applications/updatedevicelist/CMakeLists.txt b/src/applications/updatedevicelist/CMakeLists.txt index d88c315..450b354 100644 --- a/src/applications/updatedevicelist/CMakeLists.txt +++ b/src/applications/updatedevicelist/CMakeLists.txt @@ -78,9 +78,4 @@ install(TARGETS ${APP_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) -qt_generate_deploy_app_script( - TARGET ${APP_NAME} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR -) -install(SCRIPT ${deploy_script}) +qtac_deploy_app(${APP_NAME}) From 30e5c656de3b8d855fee4cc6d26066d1cd55a19a Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 03:42:09 +0530 Subject: [PATCH 04/28] qcommon: select QCheckBox signal compatible with Qt < 6.7 and >= 6.7 stateChanged(int) is deprecated-as-error in Qt 6.7+ (Debian 12); checkStateChanged(Qt::CheckState) was not added until Qt 6.7 and does not exist on Ubuntu 24.04's system Qt (6.4). Use QT_VERSION_CHECK to select the right signal at compile time. Signed-off-by: Amit Kucheria --- src/libraries/qcommon/TableCheckBox.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libraries/qcommon/TableCheckBox.cpp b/src/libraries/qcommon/TableCheckBox.cpp index 6d31857..4d4c348 100644 --- a/src/libraries/qcommon/TableCheckBox.cpp +++ b/src/libraries/qcommon/TableCheckBox.cpp @@ -51,7 +51,11 @@ TableCheckBox::TableCheckBox // Initialize the check-box _checkBox = new QCheckBox(this); - connect(_checkBox, &QCheckBox::checkStateChanged, this, [=, this](bool newState){ emit checkStateChanged(newState); }); +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) + connect(_checkBox, &QCheckBox::checkStateChanged, this, [=, this](Qt::CheckState state){ emit checkStateChanged(state == Qt::Checked); }); +#else + connect(_checkBox, &QCheckBox::stateChanged, this, [=, this](int state){ emit checkStateChanged(state == Qt::Checked); }); +#endif // Prepare check box layout QHBoxLayout* layoutCheckBox = new QHBoxLayout(this); From e4dc8ea948e2576767f20e97117ce6817e14a407 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 5 May 2026 00:58:49 +0530 Subject: [PATCH 05/28] cmake: replace hardcoded x64 link path with STATIC_LIBPATH target_link_directories was using a hardcoded Windows-specific __Builds/x64/$/lib path in every application and library CMakeLists.txt. On Linux this produced a spurious "search path not found" linker warning. Replace with ${STATIC_LIBPATH}, which is already set correctly per platform by the included Common.cmake. Signed-off-by: Amit Kucheria --- src/applications/device-catalog/CMakeLists.txt | 2 +- src/applications/devlist/CMakeLists.txt | 2 +- src/applications/ftdi-check/CMakeLists.txt | 2 +- src/applications/programmers/lite-programmer/CMakeLists.txt | 2 +- src/applications/tac-configuration-editor/CMakeLists.txt | 2 +- src/applications/tacdump/CMakeLists.txt | 2 +- src/applications/test-automation-controller/CMakeLists.txt | 2 +- src/applications/updatedevicelist/CMakeLists.txt | 2 +- src/libraries/qcommon/CMakeLists.txt | 2 +- src/libraries/ui-common/CMakeLists.txt | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/applications/device-catalog/CMakeLists.txt b/src/applications/device-catalog/CMakeLists.txt index 3a002a6..f44c089 100644 --- a/src/applications/device-catalog/CMakeLists.txt +++ b/src/applications/device-catalog/CMakeLists.txt @@ -72,7 +72,7 @@ target_compile_definitions(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_link_libraries(${APP_NAME} PRIVATE diff --git a/src/applications/devlist/CMakeLists.txt b/src/applications/devlist/CMakeLists.txt index fb79db6..4873e6d 100644 --- a/src/applications/devlist/CMakeLists.txt +++ b/src/applications/devlist/CMakeLists.txt @@ -52,7 +52,7 @@ target_compile_definitions(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_link_libraries(${APP_NAME} PRIVATE diff --git a/src/applications/ftdi-check/CMakeLists.txt b/src/applications/ftdi-check/CMakeLists.txt index 0e9c269..9b9ab8c 100644 --- a/src/applications/ftdi-check/CMakeLists.txt +++ b/src/applications/ftdi-check/CMakeLists.txt @@ -60,7 +60,7 @@ target_compile_definitions(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_link_libraries(${APP_NAME} PRIVATE diff --git a/src/applications/programmers/lite-programmer/CMakeLists.txt b/src/applications/programmers/lite-programmer/CMakeLists.txt index 239b26e..4efe77c 100644 --- a/src/applications/programmers/lite-programmer/CMakeLists.txt +++ b/src/applications/programmers/lite-programmer/CMakeLists.txt @@ -53,7 +53,7 @@ target_compile_definitions(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_link_libraries(${APP_NAME} PRIVATE diff --git a/src/applications/tac-configuration-editor/CMakeLists.txt b/src/applications/tac-configuration-editor/CMakeLists.txt index d6e1a90..00787e7 100644 --- a/src/applications/tac-configuration-editor/CMakeLists.txt +++ b/src/applications/tac-configuration-editor/CMakeLists.txt @@ -74,7 +74,7 @@ target_include_directories(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_compile_definitions(${APP_NAME} PRIVATE diff --git a/src/applications/tacdump/CMakeLists.txt b/src/applications/tacdump/CMakeLists.txt index c7ab853..a01af35 100644 --- a/src/applications/tacdump/CMakeLists.txt +++ b/src/applications/tacdump/CMakeLists.txt @@ -45,7 +45,7 @@ target_include_directories(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_compile_definitions(${APP_NAME} PRIVATE diff --git a/src/applications/test-automation-controller/CMakeLists.txt b/src/applications/test-automation-controller/CMakeLists.txt index f158d08..60a3d41 100644 --- a/src/applications/test-automation-controller/CMakeLists.txt +++ b/src/applications/test-automation-controller/CMakeLists.txt @@ -65,7 +65,7 @@ target_include_directories(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_compile_definitions(${APP_NAME} PRIVATE diff --git a/src/applications/updatedevicelist/CMakeLists.txt b/src/applications/updatedevicelist/CMakeLists.txt index 450b354..23797fe 100644 --- a/src/applications/updatedevicelist/CMakeLists.txt +++ b/src/applications/updatedevicelist/CMakeLists.txt @@ -49,7 +49,7 @@ target_include_directories(${APP_NAME} PRIVATE ) target_link_directories(${APP_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_link_libraries(${APP_NAME} PRIVATE diff --git a/src/libraries/qcommon/CMakeLists.txt b/src/libraries/qcommon/CMakeLists.txt index dc6522f..5707239 100644 --- a/src/libraries/qcommon/CMakeLists.txt +++ b/src/libraries/qcommon/CMakeLists.txt @@ -78,7 +78,7 @@ target_include_directories(${LIBRARY_NAME} PUBLIC ) target_link_directories(${LIBRARY_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_compile_definitions(${LIBRARY_NAME} PUBLIC diff --git a/src/libraries/ui-common/CMakeLists.txt b/src/libraries/ui-common/CMakeLists.txt index 8e07e99..30c29a0 100644 --- a/src/libraries/ui-common/CMakeLists.txt +++ b/src/libraries/ui-common/CMakeLists.txt @@ -41,7 +41,7 @@ target_include_directories(${LIBRARY_NAME} PUBLIC ) target_link_directories(${LIBRARY_NAME} PRIVATE - ${CMAKE_SOURCE_DIR}/__Builds/x64/$/lib + ${STATIC_LIBPATH} ) target_compile_definitions(${LIBRARY_NAME} PUBLIC From c292eedca10fcb9d17f8d9b774e54647c7b7d52b Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 7 May 2026 00:57:46 +0530 Subject: [PATCH 06/28] cmake: qualify build/output dirs by distro ID for container testing Avoids output directory conflicts when building for multiple distros side-by-side (e.g. in CI containers) and allows keeping macOS and Linux builds on the same checkout. Unsupported platforms now get an explicit error instead of silently inheriting a wrong DISTRO value. Signed-off-by: Amit Kucheria --- build.sh | 43 +++++++++++++++++++--- src/libraries/qcommon-console/Common.cmake | 4 ++ src/libraries/qcommon/Common.cmake | 4 ++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 1009d7c..5d80d2f 100644 --- a/build.sh +++ b/build.sh @@ -36,6 +36,20 @@ set -e +PRISTINE=1 + +for arg in "$@"; do + case "$arg" in + --pristine) PRISTINE=1 ;; + --incremental) PRISTINE=0 ;; + *) + echo "Usage: $0 [--pristine|--incremental]" + echo " --pristine Delete build/, __Builds/, and cached downloads (default)" + echo " --incremental Reuse existing build tree and downloaded libraries" + exit 1 ;; + esac +done + if [ -z "$QTBIN" ]; then echo "Set QTBIN first" exit 1 @@ -43,15 +57,32 @@ fi export PATH="$QTBIN:$PATH" -# Clean start -rm -rf build __Builds +case "$(uname)" in + Linux) + DISTRO=$(. /etc/os-release && echo "$ID") + CMAKE_DISTRO_FLAG="-DLINUX_DISTRO=${DISTRO}" + ;; + Darwin) + DISTRO="macOS" + CMAKE_DISTRO_FLAG="" + ;; + *) + echo "Unsupported platform: $(uname)" + exit 1 + ;; +esac + +if [ "$PRISTINE" -eq 1 ]; then + rm -rf build __Builds + rm -f third-party/*.tgz third-party/*.zip +fi # Debug -cmake -S . -B build/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug -cmake --build build/Debug +cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} +cmake --build build/${DISTRO}/Debug # Release -cmake -S . -B build/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release -cmake --build build/Release +cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} +cmake --build build/${DISTRO}/Release echo "Check __Builds directory" diff --git a/src/libraries/qcommon-console/Common.cmake b/src/libraries/qcommon-console/Common.cmake index 57c4f86..86253b2 100644 --- a/src/libraries/qcommon-console/Common.cmake +++ b/src/libraries/qcommon-console/Common.cmake @@ -112,6 +112,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(WIN32) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zi") set(CONFIGURATION "${WINTARGET}/Debug") + elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") + set(CONFIGURATION "Linux-${LINUX_DISTRO}/Debug") else() set(CONFIGURATION "Linux/Debug") endif() @@ -119,6 +121,8 @@ else() list(APPEND QCOMMONCONSOLE_DEFINITIONS _NDEBUG NDEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Release") + elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") + set(CONFIGURATION "Linux-${LINUX_DISTRO}/Release") else() set(CONFIGURATION "Linux/Release") endif() diff --git a/src/libraries/qcommon/Common.cmake b/src/libraries/qcommon/Common.cmake index e1afddb..b79292e 100644 --- a/src/libraries/qcommon/Common.cmake +++ b/src/libraries/qcommon/Common.cmake @@ -102,6 +102,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") list(APPEND QCOMMON_DEFINITIONS _DEBUG DEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Debug") + elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") + set(CONFIGURATION "Linux-${LINUX_DISTRO}/Debug") else() set(CONFIGURATION "Linux/Debug") endif() @@ -109,6 +111,8 @@ else() list(APPEND QCOMMON_DEFINITIONS _NDEBUG NDEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Release") + elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") + set(CONFIGURATION "Linux-${LINUX_DISTRO}/Release") else() set(CONFIGURATION "Linux/Release") endif() From ffa39650d472df5dbb1e25cfb48bbd2f9dd312f0 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 7 May 2026 01:10:31 +0530 Subject: [PATCH 07/28] build: parallelize cmake build across all available CPUs Use nproc on Linux and sysctl -n hw.logicalcpu on Darwin to pass --parallel to cmake --build. Unparallelized builds on an 8-core machine took ~4x longer with no benefit. Signed-off-by: Amit Kucheria --- build.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 5d80d2f..7123667 100644 --- a/build.sh +++ b/build.sh @@ -61,10 +61,12 @@ case "$(uname)" in Linux) DISTRO=$(. /etc/os-release && echo "$ID") CMAKE_DISTRO_FLAG="-DLINUX_DISTRO=${DISTRO}" + NPROC=$(nproc) ;; Darwin) DISTRO="macOS" CMAKE_DISTRO_FLAG="" + NPROC=$(sysctl -n hw.logicalcpu) ;; *) echo "Unsupported platform: $(uname)" @@ -79,10 +81,10 @@ fi # Debug cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -cmake --build build/${DISTRO}/Debug +cmake --build build/${DISTRO}/Debug --parallel ${NPROC} # Release cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -cmake --build build/${DISTRO}/Release +cmake --build build/${DISTRO}/Release --parallel ${NPROC} echo "Check __Builds directory" From 4dde09caf89fb1849be2db1644b85116ed6a5ea3 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 03:47:08 +0530 Subject: [PATCH 08/28] build: add --pristine/--incremental options to build.sh and build.bat --pristine deletes build/, __Builds/, and cached third-party download archives (.tgz/.zip) before configuring. --incremental skips all deletion so cmake reuses the existing tree and already-downloaded libraries. Pristine remains the default to preserve prior behaviour. Signed-off-by: Amit Kucheria --- build.bat | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/build.bat b/build.bat index a713d84..8ca4549 100644 --- a/build.bat +++ b/build.bat @@ -39,14 +39,30 @@ if "%QTBIN%"=="" ( exit /b 1 ) +set PRISTINE=1 + +:parse_args +if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) +if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) +if not "%~1"=="" ( + echo Usage: build.bat [--pristine^|--incremental] + echo --pristine Delete build\, __Builds\, and cached downloads ^(default^) + echo --incremental Reuse existing build tree and downloaded libraries + exit /b 1 +) + call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat" call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" set "PATH=%QTBIN%;%PATH%" -if exist build rmdir /s /q build -if exist __Builds rmdir /s /q __Builds +if "%PRISTINE%"=="1" ( + if exist build rmdir /s /q build + if exist __Builds rmdir /s /q __Builds + del /q third-party\*.tgz 2>nul + del /q third-party\*.zip 2>nul +) cmake -S . -B build\Debug -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ -DCMAKE_COLOR_DIAGNOSTICS=ON ^ From 1afa8487be7221777fa7e9f55af8932f0a22ea54 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 5 May 2026 00:58:57 +0530 Subject: [PATCH 09/28] cmake: add macOS CONFIGURATION branch in Common.cmake Without an APPLE branch, macOS (which is UNIX but not WIN32) fell into the Linux else() and set CONFIGURATION to "Linux/Debug|Release". Add elseif(APPLE) to produce "macOS/Debug|Release" so build outputs land in __Builds/macOS/ rather than __Builds/Linux/. Signed-off-by: Amit Kucheria --- src/libraries/qcommon-console/Common.cmake | 4 ++++ src/libraries/qcommon/Common.cmake | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/libraries/qcommon-console/Common.cmake b/src/libraries/qcommon-console/Common.cmake index 86253b2..913b03d 100644 --- a/src/libraries/qcommon-console/Common.cmake +++ b/src/libraries/qcommon-console/Common.cmake @@ -112,6 +112,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(WIN32) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zi") set(CONFIGURATION "${WINTARGET}/Debug") + elseif(APPLE) + set(CONFIGURATION "macOS/Debug") elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") set(CONFIGURATION "Linux-${LINUX_DISTRO}/Debug") else() @@ -121,6 +123,8 @@ else() list(APPEND QCOMMONCONSOLE_DEFINITIONS _NDEBUG NDEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Release") + elseif(APPLE) + set(CONFIGURATION "macOS/Release") elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") set(CONFIGURATION "Linux-${LINUX_DISTRO}/Release") else() diff --git a/src/libraries/qcommon/Common.cmake b/src/libraries/qcommon/Common.cmake index b79292e..2fcb993 100644 --- a/src/libraries/qcommon/Common.cmake +++ b/src/libraries/qcommon/Common.cmake @@ -102,6 +102,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") list(APPEND QCOMMON_DEFINITIONS _DEBUG DEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Debug") + elseif(APPLE) + set(CONFIGURATION "macOS/Debug") elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") set(CONFIGURATION "Linux-${LINUX_DISTRO}/Debug") else() @@ -111,6 +113,8 @@ else() list(APPEND QCOMMON_DEFINITIONS _NDEBUG NDEBUG) if(WIN32) set(CONFIGURATION "${WINTARGET}/Release") + elseif(APPLE) + set(CONFIGURATION "macOS/Release") elseif(DEFINED LINUX_DISTRO AND NOT LINUX_DISTRO STREQUAL "") set(CONFIGURATION "Linux-${LINUX_DISTRO}/Release") else() From edf970bed887bca4a2cbfb9c3ce4c2a48c2c6b1a Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 5 May 2026 00:59:08 +0530 Subject: [PATCH 10/28] third-party: add macOS FTDI D2XX support Without an APPLE branch, macOS downloaded and linked the Linux ELF libftd2xx.a, causing a "not a mach-o file" linker error. Add APPLE handling throughout third-party/CMakeLists.txt: - Platform selection: use D2XX1.4.30.dmg (present locally in third-party/; downloaded from ftdichip.com if absent) - Download: preserve existing DMG; skip cmake -E tar validation which fails on disk images - Extraction: mount with hdiutil, copy the Mach-O universal libftd2xx.a, then detach - link_ftd2xx(): link only ftd2xx on APPLE; pthread and dl are in macOS libSystem and need not be listed explicitly Signed-off-by: Amit Kucheria --- third-party/CMakeLists.txt | 139 +++++++++++++++++++++++-------------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 0b861ea..63495b7 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -39,6 +39,12 @@ if(WIN32) set(FTDI_ARCHIVE "CDM-v2.12.36.20-WHQL-Certified.zip") set(DEBUG_LIB "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib/ftd2xx.lib") set(RELEASE_LIB "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib/ftd2xx.lib") +elseif(APPLE) + set(FTDI_DMG "D2XX1.4.30.dmg") + set(FTDI_URL "https://ftdichip.com/wp-content/uploads/2024/04/${FTDI_DMG}") + set(FTDI_ARCHIVE "${FTDI_DMG}") + set(DEBUG_LIB "${CMAKE_SOURCE_DIR}/__Builds/macOS/Debug/lib/libftd2xx.a") + set(RELEASE_LIB "${CMAKE_SOURCE_DIR}/__Builds/macOS/Release/lib/libftd2xx.a") else() if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64") set(FTDI_URL "https://ftdichip.com/wp-content/uploads/2025/03/libftd2xx-linux-arm-v8-1.4.33.tgz") @@ -60,66 +66,95 @@ if(NOT EXISTS "${DEBUG_LIB}" OR NOT EXISTS "${RELEASE_LIB}") endif() if(NEED_DOWNLOAD) - set(RETRY_COUNT 0) - while(RETRY_COUNT LESS 3) - math(EXPR RETRY_COUNT "${RETRY_COUNT} + 1") - if(EXISTS "${ARCHIVE_PATH}") - file(REMOVE "${ARCHIVE_PATH}") - endif() - file(DOWNLOAD "${FTDI_URL}" "${ARCHIVE_PATH}" SHOW_PROGRESS STATUS DOWNLOAD_STATUS TIMEOUT 300) - list(GET DOWNLOAD_STATUS 0 DOWNLOAD_ERROR_CODE) - if(DOWNLOAD_ERROR_CODE EQUAL 0 AND EXISTS "${ARCHIVE_PATH}") - execute_process(COMMAND ${CMAKE_COMMAND} -E tar tf "${ARCHIVE_PATH}" RESULT_VARIABLE TAR_RESULT OUTPUT_QUIET ERROR_QUIET) - if(TAR_RESULT EQUAL 0) - break() + if(APPLE) + if(NOT EXISTS "${ARCHIVE_PATH}") + file(DOWNLOAD "${FTDI_URL}" "${ARCHIVE_PATH}" SHOW_PROGRESS STATUS DOWNLOAD_STATUS TIMEOUT 300) + list(GET DOWNLOAD_STATUS 0 DOWNLOAD_ERROR_CODE) + if(NOT DOWNLOAD_ERROR_CODE EQUAL 0 OR NOT EXISTS "${ARCHIVE_PATH}") + message(FATAL_ERROR "Failed to download FTDI D2XX for macOS from ${FTDI_URL}") endif() endif() - if(RETRY_COUNT LESS 3) - execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 5) + else() + set(RETRY_COUNT 0) + while(RETRY_COUNT LESS 3) + math(EXPR RETRY_COUNT "${RETRY_COUNT} + 1") + if(EXISTS "${ARCHIVE_PATH}") + file(REMOVE "${ARCHIVE_PATH}") + endif() + file(DOWNLOAD "${FTDI_URL}" "${ARCHIVE_PATH}" SHOW_PROGRESS STATUS DOWNLOAD_STATUS TIMEOUT 300) + list(GET DOWNLOAD_STATUS 0 DOWNLOAD_ERROR_CODE) + if(DOWNLOAD_ERROR_CODE EQUAL 0 AND EXISTS "${ARCHIVE_PATH}") + execute_process(COMMAND ${CMAKE_COMMAND} -E tar tf "${ARCHIVE_PATH}" RESULT_VARIABLE TAR_RESULT OUTPUT_QUIET ERROR_QUIET) + if(TAR_RESULT EQUAL 0) + break() + endif() + endif() + if(RETRY_COUNT LESS 3) + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 5) + endif() + endwhile() + if(RETRY_COUNT EQUAL 3) + message(FATAL_ERROR "Failed to download FTDI library after 3 attempts") endif() - endwhile() - if(RETRY_COUNT EQUAL 3) - message(FATAL_ERROR "Failed to download FTDI library after 3 attempts") endif() - file(REMOVE_RECURSE "${TEMP_DIR}") - file(MAKE_DIRECTORY "${TEMP_DIR}") - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf "${ARCHIVE_PATH}" WORKING_DIRECTORY "${TEMP_DIR}") - - if(WIN32) - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib") - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib") - file(GLOB SOURCE_LIB "${TEMP_DIR}/amd64/ftd2xx.lib") - - file(GLOB SOURCE_DLL "${TEMP_DIR}/amd64/FTD2XX64.dll") - if(SOURCE_DLL) - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin") - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin") - file(COPY "${SOURCE_DLL}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin") - file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin/FTD2XX64.dll" "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin/ftd2xx.dll") - file(COPY "${SOURCE_DLL}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin") - file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin/FTD2XX64.dll" "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin/ftd2xx.dll") - endif() - - if(NOT SOURCE_LIB) - file(GLOB SOURCE_LIB "${TEMP_DIR}/Static/amd64/ftd2xx.lib") + if(APPLE) + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/macOS/Debug/lib") + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/macOS/Release/lib") + execute_process( + COMMAND hdiutil attach -readonly -nobrowse "${ARCHIVE_PATH}" + OUTPUT_VARIABLE HDIUTIL_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX MATCH "/Volumes/[^\n\t ]*" MOUNT_POINT "${HDIUTIL_OUTPUT}") + string(STRIP "${MOUNT_POINT}" MOUNT_POINT) + execute_process( + COMMAND find "${MOUNT_POINT}" -name "libftd2xx.a" + OUTPUT_VARIABLE MACOS_LIB OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT MACOS_LIB) + message(FATAL_ERROR "libftd2xx.a not found in FTDI DMG at ${MOUNT_POINT}") endif() - file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib") - file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib") + execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${MACOS_LIB}" "${DEBUG_LIB}") + execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${MACOS_LIB}" "${RELEASE_LIB}") + execute_process(COMMAND hdiutil detach "${MOUNT_POINT}") else() - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") - file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") - file(GLOB_RECURSE SOURCE_LIB "${TEMP_DIR}/libftd2xx-static.a") - if(NOT SOURCE_LIB) - message(FATAL_ERROR "libftd2xx-static.a not found in downloaded FTDI archive") + file(REMOVE_RECURSE "${TEMP_DIR}") + file(MAKE_DIRECTORY "${TEMP_DIR}") + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf "${ARCHIVE_PATH}" WORKING_DIRECTORY "${TEMP_DIR}") + + if(WIN32) + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib") + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib") + file(GLOB SOURCE_LIB "${TEMP_DIR}/amd64/ftd2xx.lib") + + file(GLOB SOURCE_DLL "${TEMP_DIR}/amd64/FTD2XX64.dll") + if(SOURCE_DLL) + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin") + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin") + file(COPY "${SOURCE_DLL}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin") + file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin/FTD2XX64.dll" "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/bin/ftd2xx.dll") + file(COPY "${SOURCE_DLL}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin") + file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin/FTD2XX64.dll" "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/bin/ftd2xx.dll") + endif() + + if(NOT SOURCE_LIB) + file(GLOB SOURCE_LIB "${TEMP_DIR}/Static/amd64/ftd2xx.lib") + endif() + file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Debug/lib") + file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/x64/Release/lib") + else() + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") + file(GLOB_RECURSE SOURCE_LIB "${TEMP_DIR}/libftd2xx-static.a") + if(NOT SOURCE_LIB) + message(FATAL_ERROR "libftd2xx-static.a not found in downloaded FTDI archive") + endif() + file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") + file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") + file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib/libftd2xx-static.a" "${DEBUG_LIB}") + file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib/libftd2xx-static.a" "${RELEASE_LIB}") endif() - file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib") - file(COPY "${SOURCE_LIB}" DESTINATION "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib") - file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/Linux/Debug/lib/libftd2xx-static.a" "${DEBUG_LIB}") - file(RENAME "${CMAKE_SOURCE_DIR}/__Builds/Linux/Release/lib/libftd2xx-static.a" "${RELEASE_LIB}") + + file(REMOVE_RECURSE "${TEMP_DIR}") endif() - - file(REMOVE_RECURSE "${TEMP_DIR}") endif() if(WIN32) @@ -169,6 +204,8 @@ endif() function(link_ftd2xx target_name) if(WIN32) target_link_libraries(${target_name} PRIVATE $<$:ftd2xx_debug> $<$:ftd2xx_release>) + elseif(APPLE) + target_link_libraries(${target_name} PRIVATE ftd2xx) else() target_link_libraries(${target_name} PRIVATE ftd2xx pthread dl) endif() From 723a25f9cddddf5d2b41531e4630eec47f5c52d0 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 5 May 2026 01:31:19 +0530 Subject: [PATCH 11/28] third-party: link CoreFoundation and IOKit via ftd2xx INTERFACE on macOS libftd2xx.a bundles darwin_usb.o which calls into CoreFoundation and IOKit. Eight targets in src/ link ftd2xx directly rather than through link_ftd2xx(), so adding the frameworks only to that helper was insufficient. Attach the frameworks as INTERFACE_LINK_LIBRARIES on the ftd2xx IMPORTED target instead. CMake propagates them automatically to every consumer regardless of how ftd2xx is referenced. Signed-off-by: Amit Kucheria --- third-party/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 63495b7..78f8a89 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -169,6 +169,10 @@ else() IMPORTED_LOCATION_RELEASE "${RELEASE_LIB}" IMPORTED_LOCATION "${RELEASE_LIB}" ) + if(APPLE) + set_target_properties(ftd2xx PROPERTIES + INTERFACE_LINK_LIBRARIES "-framework CoreFoundation;-framework IOKit") + endif() endif() if(WIN32 AND DEFINED ENV{QTDIR}) From bc545a1a60c60ee2599b0482e91a5feb8d2df20f Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 5 May 2026 01:41:02 +0530 Subject: [PATCH 12/28] updatedevicelist: fix platform-specific path constants on macOS Both FTDITemplateCompiler.cpp and UpdateDeviceList.cpp defined per-platform constants under #ifdef Q_OS_WIN / #ifdef Q_OS_LINUX with no macOS branch, causing "undeclared identifier" compile errors. FTDITemplateCompiler: remove the compile-time xmlTemplatePath global entirely and compute it at runtime in load() using QCoreApplication::applicationDirPath(). The template is deployed alongside the executable on all platforms, so this works correctly everywhere without hardcoded paths. UpdateDeviceList: kServerConfigDir is a developer-workspace fallback path that cannot be generalised to macOS. Consolidate the two separate in write() with the same condition so macOS falls through directly to tacConfigRoot(). Signed-off-by: Amit Kucheria --- .../updatedevicelist/FTDITemplateCompiler.cpp | 19 +++---------------- .../updatedevicelist/UpdateDeviceList.cpp | 5 +++-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/applications/updatedevicelist/FTDITemplateCompiler.cpp b/src/applications/updatedevicelist/FTDITemplateCompiler.cpp index f1c0b5c..cf11495 100644 --- a/src/applications/updatedevicelist/FTDITemplateCompiler.cpp +++ b/src/applications/updatedevicelist/FTDITemplateCompiler.cpp @@ -41,6 +41,7 @@ #include "PlatformID.h" // Qt +#include #include #include #include @@ -49,22 +50,6 @@ #include #include -#ifdef Q_OS_WIN - #ifdef DEBUG - const QString xmlTemplatePath(QStringLiteral("C:\\github\\open-source\\qcom-test-automation-controller\\__Builds\\x64\\Debug\\bin\\ftdi-template.xml")); - #else - const QString xmlTemplatePath(QStringLiteral("C:\\Program Files (x86)\\Qualcomm\\QTAC\\ftdi-template.xml")); - #endif -#endif - -#ifdef Q_OS_LINUX - #ifdef DEBUG - const QString xmlTemplatePath(QStringLiteral("/local/mnt/workspace/github/open-source/qcom-test-automation-controller/__Builds/Linux/Debug/bin/ftdi-template.xml")); - #else - const QString xmlTemplatePath(QStringLiteral("/opt/qcom/QTAC/bin/ftdi-template.xml")); - #endif -#endif - const QString kUSBDescriptorPattern(QStringLiteral("%%USB_DESCRIPTOR%%")); @@ -116,6 +101,8 @@ void FTDITemplateCompiler::write() bool FTDITemplateCompiler::load() { bool result{false}; + const QString xmlTemplatePath = + QCoreApplication::applicationDirPath() + QStringLiteral("/ftdi-template.xml"); QFile xmlFile(xmlTemplatePath); if (_template.isNull() && xmlFile.open(QIODevice::ReadOnly)) diff --git a/src/applications/updatedevicelist/UpdateDeviceList.cpp b/src/applications/updatedevicelist/UpdateDeviceList.cpp index 671cb4c..201c745 100644 --- a/src/applications/updatedevicelist/UpdateDeviceList.cpp +++ b/src/applications/updatedevicelist/UpdateDeviceList.cpp @@ -53,8 +53,7 @@ #ifdef Q_OS_WIN const QString kServerConfigDir(QStringLiteral("C:\\github\\open-source\\qcom-test-automation-controller\\configurations")); -#endif -#ifdef Q_OS_LINUX +#elif defined(Q_OS_LINUX) const QString kServerConfigDir = expandPath("/local/mnt/workspace/github/open-source/qcom-test-automation-controller/configurations"); #endif @@ -191,6 +190,7 @@ void UpdateDeviceList::write() } else { +#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) configFilePath = QDir::cleanPath(kServerConfigDir); if (QDir(configFilePath).exists()) @@ -205,6 +205,7 @@ void UpdateDeviceList::write() // don't print this one // std::cout << configFilePath.toLatin1().data() << " does not exist " << std::endl; } +#endif configFilePath = QDir::cleanPath(tacConfigRoot()); if (QDir(configFilePath).exists()) From a9c9a2bfc70f5011a6eb4e4a010434cec9cc06bc Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 7 May 2026 01:21:03 +0530 Subject: [PATCH 13/28] TACDev: fix TACDEV_EXPORT macro for macOS The macro used #ifdef __linux__ to guard the __attribute__ path, so macOS fell through to __declspec which clang rejects without -fdeclspec. Replace the _WIN32/else fallthrough with explicit _WIN32 / __linux__ || __APPLE__ branches and a #error guard for unsupported platforms, matching the explicit platform dispatch convention used in CMake throughout the project. Signed-off-by: Amit Kucheria --- interfaces/C++/TACDev/TACDev.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/interfaces/C++/TACDev/TACDev.h b/interfaces/C++/TACDev/TACDev.h index 11a537a..d9827be 100644 --- a/interfaces/C++/TACDev/TACDev.h +++ b/interfaces/C++/TACDev/TACDev.h @@ -39,16 +39,20 @@ */ #if defined(TACDEV_LIBRARY) - #ifdef __linux__ + #if defined(_WIN32) + #define TACDEV_EXPORT __declspec(dllexport) + #elif defined(__linux__) || defined(__APPLE__) #define TACDEV_EXPORT __attribute__((visibility("default"))) #else - #define TACDEV_EXPORT __declspec(dllexport) + #error "Unsupported platform" #endif #else - #ifdef __linux__ - # define TACDEV_EXPORT __attribute__((visibility("default"))) + #if defined(_WIN32) + #define TACDEV_EXPORT __declspec(dllimport) + #elif defined(__linux__) || defined(__APPLE__) + #define TACDEV_EXPORT __attribute__((visibility("default"))) #else - # define TACDEV_EXPORT __declspec(dllimport) + #error "Unsupported platform" #endif #endif From 36b90652125ed95c2f7a9c3dd4b3dc8adff243dd Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 1 May 2026 02:48:31 +0530 Subject: [PATCH 14/28] cmake: lower Qt minimum version to 6.8 Allows building against system Qt on Debian 12 and Ubuntu 24.04 (both ship Qt 6.8); previously required 6.9 which forced the Qt Online Installer even on current LTS distros that ship 6.8. Signed-off-by: Amit Kucheria --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4921c68..2d959d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Multimedia) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent Gui Multimedia MultimediaWidgets Network SerialPort Widgets Xml) -qt_standard_project_setup(REQUIRES 6.9) +qt_standard_project_setup(REQUIRES 6.8) add_subdirectory(third-party) add_subdirectory(src/libraries) From e64d6575cc3a848a49d7972a72e323da8d8dc1ee Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Tue, 28 Apr 2026 19:42:15 +0530 Subject: [PATCH 15/28] build: add --no-gui flag to build.sh and build.bat Headless environments (servers, CI) and SDK-only consumers do not need the Qt GUI stack. --no-gui sets BUILD_UI=OFF, skipping Qt Multimedia, Widgets, qcommon, ui-common, and all GUI applications; only QCommonConsole and TACDev are compiled, with a correspondingly smaller Qt dependency footprint. Signed-off-by: Amit Kucheria --- CMakeLists.txt | 20 +++++++++++++++++--- build.bat | 13 +++++++++---- build.sh | 9 ++++++--- src/libraries/CMakeLists.txt | 6 ++++-- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d959d0..7886088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,12 +42,26 @@ set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON) -find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Multimedia) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent Gui Multimedia MultimediaWidgets Network SerialPort Widgets Xml) +option(BUILD_UI "Build GUI applications and UI libraries" ON) + +if(BUILD_UI) + find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core Multimedia) + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent Gui Multimedia MultimediaWidgets Network SerialPort Widgets Xml) +else() + find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) + find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Concurrent Core Network SerialPort Xml) +endif() qt_standard_project_setup(REQUIRES 6.8) +include(GNUInstallDirs) add_subdirectory(third-party) add_subdirectory(src/libraries) -add_subdirectory(src/applications) +if(BUILD_UI) + add_subdirectory(src/applications) +endif() add_subdirectory(interfaces) + +install(DIRECTORY configurations/ + DESTINATION ${CMAKE_INSTALL_DATADIR}/qtac/configurations +) diff --git a/build.bat b/build.bat index 8ca4549..d0fe90e 100644 --- a/build.bat +++ b/build.bat @@ -40,14 +40,17 @@ if "%QTBIN%"=="" ( ) set PRISTINE=1 +set BUILD_UI=ON :parse_args -if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) -if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) +if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) +if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) +if "%~1"=="--no-gui" ( set BUILD_UI=OFF & shift & goto :parse_args ) if not "%~1"=="" ( - echo Usage: build.bat [--pristine^|--incremental] + echo Usage: build.bat [--pristine^|--incremental] [--no-gui] echo --pristine Delete build\, __Builds\, and cached downloads ^(default^) echo --incremental Reuse existing build tree and downloaded libraries + echo --no-gui Build just low-level libraries without the UI application exit /b 1 ) @@ -68,6 +71,7 @@ cmake -S . -B build\Debug -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ -DCMAKE_COLOR_DIAGNOSTICS=ON ^ -DCMAKE_GENERATOR=Ninja ^ -DCMAKE_BUILD_TYPE=Debug ^ + -DBUILD_UI=%BUILD_UI% ^ -DCMAKE_CXX_FLAGS_INIT=-DQT_QML_DEBUG cmake --build build\Debug @@ -75,7 +79,8 @@ cmake --build build\Debug cmake -S . -B build\Release -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ -DCMAKE_COLOR_DIAGNOSTICS=ON ^ -DCMAKE_GENERATOR=Ninja ^ - -DCMAKE_BUILD_TYPE=Release + -DCMAKE_BUILD_TYPE=Release ^ + -DBUILD_UI=%BUILD_UI% cmake --build build\Release diff --git a/build.sh b/build.sh index 7123667..ab0aa37 100644 --- a/build.sh +++ b/build.sh @@ -37,15 +37,18 @@ set -e PRISTINE=1 +BUILD_UI=ON for arg in "$@"; do case "$arg" in --pristine) PRISTINE=1 ;; --incremental) PRISTINE=0 ;; + --no-gui) BUILD_UI=OFF ;; *) - echo "Usage: $0 [--pristine|--incremental]" + echo "Usage: $0 [--pristine|--incremental] [--no-gui]" echo " --pristine Delete build/, __Builds/, and cached downloads (default)" echo " --incremental Reuse existing build tree and downloaded libraries" + echo " --no-gui Build just low-level libraries without the UI application" exit 1 ;; esac done @@ -80,11 +83,11 @@ if [ "$PRISTINE" -eq 1 ]; then fi # Debug -cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} +cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} cmake --build build/${DISTRO}/Debug --parallel ${NPROC} # Release -cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} +cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} cmake --build build/${DISTRO}/Release --parallel ${NPROC} echo "Check __Builds directory" diff --git a/src/libraries/CMakeLists.txt b/src/libraries/CMakeLists.txt index 1ad2a12..35ba2fd 100644 --- a/src/libraries/CMakeLists.txt +++ b/src/libraries/CMakeLists.txt @@ -8,5 +8,7 @@ find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() add_subdirectory(qcommon-console) -add_subdirectory(qcommon) -add_subdirectory(ui-common) +if(BUILD_UI) + add_subdirectory(qcommon) + add_subdirectory(ui-common) +endif() From 0db046409e9bb3677d251f98b51c3db756c89db5 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 7 May 2026 02:39:42 +0530 Subject: [PATCH 16/28] build: skip Debug build by default, add --debug flag to opt in Release is always built. Debug is only built when --debug is passed, avoiding unnecessary build time during routine builds. Signed-off-by: Amit Kucheria --- build.bat | 21 +++++++++++++-------- build.sh | 15 ++++++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/build.bat b/build.bat index d0fe90e..bf1c225 100644 --- a/build.bat +++ b/build.bat @@ -41,16 +41,19 @@ if "%QTBIN%"=="" ( set PRISTINE=1 set BUILD_UI=ON +set BUILD_DEBUG=0 :parse_args if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) if "%~1"=="--no-gui" ( set BUILD_UI=OFF & shift & goto :parse_args ) +if "%~1"=="--debug" ( set BUILD_DEBUG=1 & shift & goto :parse_args ) if not "%~1"=="" ( - echo Usage: build.bat [--pristine^|--incremental] [--no-gui] + echo Usage: build.bat [--pristine^|--incremental] [--no-gui] [--debug] echo --pristine Delete build\, __Builds\, and cached downloads ^(default^) echo --incremental Reuse existing build tree and downloaded libraries echo --no-gui Build just low-level libraries without the UI application + echo --debug Also build Debug configuration ^(Release is always built^) exit /b 1 ) @@ -67,14 +70,16 @@ if "%PRISTINE%"=="1" ( del /q third-party\*.zip 2>nul ) -cmake -S . -B build\Debug -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ - -DCMAKE_COLOR_DIAGNOSTICS=ON ^ - -DCMAKE_GENERATOR=Ninja ^ - -DCMAKE_BUILD_TYPE=Debug ^ - -DBUILD_UI=%BUILD_UI% ^ - -DCMAKE_CXX_FLAGS_INIT=-DQT_QML_DEBUG +if "%BUILD_DEBUG%"=="1" ( + cmake -S . -B build\Debug -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ + -DCMAKE_COLOR_DIAGNOSTICS=ON ^ + -DCMAKE_GENERATOR=Ninja ^ + -DCMAKE_BUILD_TYPE=Debug ^ + -DBUILD_UI=%BUILD_UI% ^ + -DCMAKE_CXX_FLAGS_INIT=-DQT_QML_DEBUG -cmake --build build\Debug + cmake --build build\Debug +) cmake -S . -B build\Release -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ -DCMAKE_COLOR_DIAGNOSTICS=ON ^ diff --git a/build.sh b/build.sh index ab0aa37..fc8fbab 100644 --- a/build.sh +++ b/build.sh @@ -38,17 +38,20 @@ set -e PRISTINE=1 BUILD_UI=ON +BUILD_DEBUG=0 for arg in "$@"; do case "$arg" in --pristine) PRISTINE=1 ;; --incremental) PRISTINE=0 ;; - --no-gui) BUILD_UI=OFF ;; + --no-gui) BUILD_UI=OFF ;; + --debug) BUILD_DEBUG=1 ;; *) - echo "Usage: $0 [--pristine|--incremental] [--no-gui]" + echo "Usage: $0 [--pristine|--incremental] [--no-gui] [--debug]" echo " --pristine Delete build/, __Builds/, and cached downloads (default)" echo " --incremental Reuse existing build tree and downloaded libraries" - echo " --no-gui Build just low-level libraries without the UI application" + echo " --no-gui Build just low-level libraries without the UI application" + echo " --debug Also build Debug configuration (Release is always built)" exit 1 ;; esac done @@ -83,8 +86,10 @@ if [ "$PRISTINE" -eq 1 ]; then fi # Debug -cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} -cmake --build build/${DISTRO}/Debug --parallel ${NPROC} +if [ "$BUILD_DEBUG" -eq 1 ]; then + cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} + cmake --build build/${DISTRO}/Debug --parallel ${NPROC} +fi # Release cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} From 671aa319d4be54e9b331c4a51b44eb50115b1ed4 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 00:19:59 +0530 Subject: [PATCH 17/28] TACDev: declare library as STATIC qt_add_library() without a type keyword defaults to BUILD_SHARED_LIBS (dynamic if that variable is set); STATIC makes the intent explicit and is required for the cmake install target to export a usable archive. Without STATIC, cmake --install fails trying to install the non-existent CMakeRelink copy of the .so. Signed-off-by: Amit Kucheria --- interfaces/C++/TACDev/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/C++/TACDev/CMakeLists.txt b/interfaces/C++/TACDev/CMakeLists.txt index 01f1fbb..e1706ed 100644 --- a/interfaces/C++/TACDev/CMakeLists.txt +++ b/interfaces/C++/TACDev/CMakeLists.txt @@ -40,7 +40,7 @@ else() set(LIBRARY_NAME TACDev) endif() -qt_add_library(${LIBRARY_NAME} +qt_add_library(${LIBRARY_NAME} STATIC TACDev.cpp TACDev.h TACDevCore.cpp TACDevCore.h ) From cfeb8e7f59d1047611126603a2ac2eefed1558bf Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Mon, 20 Apr 2026 11:46:36 +0530 Subject: [PATCH 18/28] cmake: add install rules for TACDev and QCommonConsole Allows SDK consumers to use cmake --install to deploy the C++ interface library and headers without building from source. Installs TACDev library, TACDev.h, QCommonConsole library, and device configurations to their standard CMAKE_INSTALL_* destinations. Signed-off-by: Amit Kucheria --- interfaces/C++/TACDev/CMakeLists.txt | 2 ++ src/libraries/qcommon-console/CMakeLists.txt | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/interfaces/C++/TACDev/CMakeLists.txt b/interfaces/C++/TACDev/CMakeLists.txt index e1706ed..257ee5c 100644 --- a/interfaces/C++/TACDev/CMakeLists.txt +++ b/interfaces/C++/TACDev/CMakeLists.txt @@ -97,7 +97,9 @@ if(UNIX) endif() install(TARGETS ${LIBRARY_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) +install(FILES TACDev.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qtac) diff --git a/src/libraries/qcommon-console/CMakeLists.txt b/src/libraries/qcommon-console/CMakeLists.txt index 52ae499..bcdde74 100644 --- a/src/libraries/qcommon-console/CMakeLists.txt +++ b/src/libraries/qcommon-console/CMakeLists.txt @@ -152,3 +152,9 @@ target_link_libraries(${LIBRARY_NAME} PUBLIC Qt6::Xml ftd2xx ) + +install(TARGETS ${LIBRARY_NAME} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} +) From bef67780e80def0dee6847fc0c85f5e43abc48b9 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Fri, 8 May 2026 23:50:18 +0530 Subject: [PATCH 19/28] build: add --install option to build.sh and build.bat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will install the TACDev libraries and various binaries so they don't need to be run from the build directory. Runs cmake --install on the Release build tree when --install is passed. Installs to CMAKE_INSTALL_PREFIX (default /usr/local on Linux/macOS, C:/Program Files/ on Windows); override by setting -DCMAKE_INSTALL_PREFIX at configure time. What gets installed: - Static libraries (QCommonConsole, QCommon, ui-common, TACDev) → lib/ - Public header (TACDev.h) → include/qtac/ - Applications (TAC, devlist, tacdump, etc.) → bin/ - Board configurations (.tcnf) → share/qtac/configurations/ - FTDI D2XX static library → lib/ (via new install rule in third-party/CMakeLists.txt) - Desktop entries and icons (Linux) → share/applications/, share/icons/ Signed-off-by: Amit Kucheria --- build.bat | 14 +++++++++++++- build.sh | 10 +++++++++- third-party/CMakeLists.txt | 2 ++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/build.bat b/build.bat index bf1c225..0cc0fdb 100644 --- a/build.bat +++ b/build.bat @@ -42,18 +42,21 @@ if "%QTBIN%"=="" ( set PRISTINE=1 set BUILD_UI=ON set BUILD_DEBUG=0 +set INSTALL=0 :parse_args if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) if "%~1"=="--no-gui" ( set BUILD_UI=OFF & shift & goto :parse_args ) if "%~1"=="--debug" ( set BUILD_DEBUG=1 & shift & goto :parse_args ) +if "%~1"=="--install" ( set INSTALL=1 & shift & goto :parse_args ) if not "%~1"=="" ( - echo Usage: build.bat [--pristine^|--incremental] [--no-gui] [--debug] + echo Usage: build.bat [--pristine^|--incremental] [--no-gui] [--debug] [--install] echo --pristine Delete build\, __Builds\, and cached downloads ^(default^) echo --incremental Reuse existing build tree and downloaded libraries echo --no-gui Build just low-level libraries without the UI application echo --debug Also build Debug configuration ^(Release is always built^) + echo --install Install libraries, headers, applications, and configs exit /b 1 ) @@ -89,4 +92,13 @@ cmake -S . -B build\Release -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ cmake --build build\Release +if "%INSTALL%"=="1" ( + net session >nul 2>&1 + if errorlevel 1 ( + echo Error: --install requires Administrator privileges. Re-run build.bat as Administrator. + exit /b 1 + ) + cmake --install build\Release +) + echo Check __Builds directory diff --git a/build.sh b/build.sh index fc8fbab..fa83ef4 100644 --- a/build.sh +++ b/build.sh @@ -39,6 +39,7 @@ set -e PRISTINE=1 BUILD_UI=ON BUILD_DEBUG=0 +INSTALL=0 for arg in "$@"; do case "$arg" in @@ -46,12 +47,15 @@ for arg in "$@"; do --incremental) PRISTINE=0 ;; --no-gui) BUILD_UI=OFF ;; --debug) BUILD_DEBUG=1 ;; + --install) INSTALL=1 ;; *) - echo "Usage: $0 [--pristine|--incremental] [--no-gui] [--debug]" + echo "Usage: $0 [--pristine|--incremental] [--no-gui] [--debug] [--install]" echo " --pristine Delete build/, __Builds/, and cached downloads (default)" echo " --incremental Reuse existing build tree and downloaded libraries" echo " --no-gui Build just low-level libraries without the UI application" echo " --debug Also build Debug configuration (Release is always built)" + echo " --install Install libraries, headers, applications, and configs" + echo " (installs to CMAKE_INSTALL_PREFIX, default: /usr/local)" exit 1 ;; esac done @@ -95,4 +99,8 @@ fi cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} cmake --build build/${DISTRO}/Release --parallel ${NPROC} +if [ "$INSTALL" -eq 1 ]; then + sudo cmake --install build/${DISTRO}/Release +fi + echo "Check __Builds directory" diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 78f8a89..e766f57 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -205,6 +205,8 @@ if(WIN32 AND DEFINED ENV{QTDIR}) endif() endif() +install(FILES "${RELEASE_LIB}" DESTINATION ${CMAKE_INSTALL_LIBDIR}) + function(link_ftd2xx target_name) if(WIN32) target_link_libraries(${target_name} PRIVATE $<$:ftd2xx_debug> $<$:ftd2xx_release>) From 78cdcf3dec71501e8b25cf8bd949a22f9dcc4929 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 00:02:12 +0530 Subject: [PATCH 20/28] cmake: add MACOSX_BUNDLE to GUI apps only on macOS Qt requires .app bundles for GUI applications; plain executables are not supported by macdeployqt or qt_generate_deploy_app_script. Add MACOSX_BUNDLE to the three GUI targets (TAC, TACConfigEditor, DeviceCatalog) via qt_add_executable(). CLI tools (DevList, TACDump, FTDICheck, UpdateDeviceList, LITEProgrammer) must remain plain executables; wrapping them in bundles causes macdeployqt to chase transitive QtPdf/QtSvg framework dependencies that are absent from split Homebrew Qt installations. Signed-off-by: Amit Kucheria --- src/applications/CMakeLists.txt | 7 +++++++ src/applications/device-catalog/CMakeLists.txt | 2 +- src/applications/tac-configuration-editor/CMakeLists.txt | 2 +- src/applications/test-automation-controller/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt index ebcd4ed..06663d5 100644 --- a/src/applications/CMakeLists.txt +++ b/src/applications/CMakeLists.txt @@ -41,6 +41,13 @@ find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() +if(APPLE) + # Add the Qt frameworks directory to the install rpath so apps can find Qt + # frameworks at runtime without a full macdeployqt deployment. + get_filename_component(_qt_lib_dir "${Qt6Core_DIR}/../../" ABSOLUTE) + list(APPEND CMAKE_INSTALL_RPATH "${_qt_lib_dir}") +endif() + # Qt 6.3/6.4 use FILENAME_VARIABLE; Qt 6.5+ renamed it to OUTPUT_SCRIPT. macro(qtac_deploy_app target) if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") diff --git a/src/applications/device-catalog/CMakeLists.txt b/src/applications/device-catalog/CMakeLists.txt index f44c089..a1b5b8f 100644 --- a/src/applications/device-catalog/CMakeLists.txt +++ b/src/applications/device-catalog/CMakeLists.txt @@ -40,7 +40,7 @@ qt_add_resources(DC_RESOURCES resources/DeviceCatalog.qrc ) -qt_add_executable(${APP_NAME} WIN32 +qt_add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE DeviceCatalog.cpp DeviceCatalog.h DeviceCatalog.ui DeviceCatalogApplication.cpp DeviceCatalogApplication.h DeviceSelectionDialog.cpp DeviceSelectionDialog.h DeviceSelectionDialog.ui diff --git a/src/applications/tac-configuration-editor/CMakeLists.txt b/src/applications/tac-configuration-editor/CMakeLists.txt index 00787e7..d88bbcb 100644 --- a/src/applications/tac-configuration-editor/CMakeLists.txt +++ b/src/applications/tac-configuration-editor/CMakeLists.txt @@ -40,7 +40,7 @@ qt_add_resources(TAC_EDITOR_RESOURCES resources/TACConfigEditor.qrc ) -qt_add_executable(${APP_NAME} WIN32 +qt_add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE ButtonEditor.cpp ButtonEditor.h ButtonEditor.ui CodeEditor.cpp CodeEditor.h CodeEditor.ui ConfigEditorApplication.cpp ConfigEditorApplication.h diff --git a/src/applications/test-automation-controller/CMakeLists.txt b/src/applications/test-automation-controller/CMakeLists.txt index 60a3d41..eefbbef 100644 --- a/src/applications/test-automation-controller/CMakeLists.txt +++ b/src/applications/test-automation-controller/CMakeLists.txt @@ -40,7 +40,7 @@ qt_add_resources(TAC_RESOURCES resources/TAC.qrc ) -qt_add_executable(${APP_NAME} WIN32 +qt_add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE PreferencesDialog.cpp PreferencesDialog.h PreferencesDialog.ui TACApplication.cpp TACApplication.h TACDeviceSelection.cpp TACDeviceSelection.h TACDeviceSelection.ui From 76b5ba1473460c184a7fc7bb78e4b274c7508cc8 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 00:24:46 +0530 Subject: [PATCH 21/28] cmake: skip Qt deploy script on Linux system installs The Qt deploy tool on Linux copies all runtime dependencies (Qt shared libs, libEGL, libFLAC, even ld-linux-aarch64.so.1) into the install prefix. This is appropriate for portable bundles like AppImage but wrong for system installs to /usr/local where Qt and system libraries are already provided by the distro package manager. Restrict the deploy script to WIN32 and APPLE only. Windows needs Qt DLLs next to the executable; macOS needs frameworks bundled inside the .app. Linux system installs need neither. On Linux we instead install qt.conf on Linux to fix missing platform plugin Without the Qt deploy script, installed binaries have no qt.conf and Qt reports an empty plugin path at runtime, causing the 'could not find platform plugin xcb' error. Query qmake for QT_INSTALL_PLUGINS at configure time and install a qt.conf next to the binaries. This works for both apt Qt (/usr/lib//qt6/plugins) and aqtinstall without copying any runtime libraries into the install prefix. Signed-off-by: Amit Kucheria --- src/applications/CMakeLists.txt | 48 ++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt index 06663d5..f12265e 100644 --- a/src/applications/CMakeLists.txt +++ b/src/applications/CMakeLists.txt @@ -49,23 +49,45 @@ if(APPLE) endif() # Qt 6.3/6.4 use FILENAME_VARIABLE; Qt 6.5+ renamed it to OUTPUT_SCRIPT. +# On Linux, system installs use system-provided Qt shared libraries; +# running the deploy tool would copy system libs into /usr/local which is wrong. macro(qtac_deploy_app target) - if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") - qt_generate_deploy_app_script( - TARGET ${target} - OUTPUT_SCRIPT deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR - ) - else() - qt_generate_deploy_app_script( - TARGET ${target} - FILENAME_VARIABLE deploy_script - NO_UNSUPPORTED_PLATFORM_ERROR - ) + if(WIN32 OR APPLE) + if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") + qt_generate_deploy_app_script( + TARGET ${target} + OUTPUT_SCRIPT deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR + ) + else() + qt_generate_deploy_app_script( + TARGET ${target} + FILENAME_VARIABLE deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR + ) + endif() + install(SCRIPT ${deploy_script}) endif() - install(SCRIPT ${deploy_script}) endmacro() +if(UNIX AND NOT APPLE) + # Install a qt.conf pointing to the Qt plugins directory used at build time. + # Without this, installed binaries report an empty plugin path and fail to + # start. Works for both apt Qt (/usr/lib/.../qt6/plugins) and aqtinstall. + get_target_property(_qmake Qt6::qmake IMPORTED_LOCATION) + execute_process( + COMMAND "${_qmake}" -query QT_INSTALL_PLUGINS + OUTPUT_VARIABLE _qt_plugins_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + "[Paths]\nPlugins=${_qt_plugins_dir}\n" + ) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" + DESTINATION ${CMAKE_INSTALL_BINDIR} + ) +endif() + add_subdirectory(devlist) add_subdirectory(tacdump) add_subdirectory(ftdi-check) From 11978c404eba836278ccef4f7e1f83c8d6b86f9a Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 00:55:20 +0530 Subject: [PATCH 22/28] build: add --deploy flag to opt in to Qt runtime bundling macdeployqt/windeployqt run for every app on every install and copy hundreds of MB of Qt frameworks, making --install very slow. For release testing this is unnecessary -- apps can run against the system Qt using the rpath already added on macOS. Add DEPLOY_APPS cmake option (default OFF) that gates the deploy scripts. Add --deploy flag to build.sh and build.bat that passes -DDEPLOY_APPS=ON at configure time. Normal workflow: ./build.sh --install # fast: installs binaries only ./build.sh --install --deploy # slow: full Qt bundling for distribution Signed-off-by: Amit Kucheria --- build.bat | 12 ++++++++++-- build.sh | 14 +++++++++++--- src/applications/CMakeLists.txt | 7 ++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/build.bat b/build.bat index 0cc0fdb..85f6f8a 100644 --- a/build.bat +++ b/build.bat @@ -43,6 +43,7 @@ set PRISTINE=1 set BUILD_UI=ON set BUILD_DEBUG=0 set INSTALL=0 +set DEPLOY=0 :parse_args if "%~1"=="--pristine" ( set PRISTINE=1 & shift & goto :parse_args ) @@ -50,13 +51,15 @@ if "%~1"=="--incremental" ( set PRISTINE=0 & shift & goto :parse_args ) if "%~1"=="--no-gui" ( set BUILD_UI=OFF & shift & goto :parse_args ) if "%~1"=="--debug" ( set BUILD_DEBUG=1 & shift & goto :parse_args ) if "%~1"=="--install" ( set INSTALL=1 & shift & goto :parse_args ) +if "%~1"=="--deploy" ( set DEPLOY=1 & shift & goto :parse_args ) if not "%~1"=="" ( - echo Usage: build.bat [--pristine^|--incremental] [--no-gui] [--debug] [--install] + echo Usage: build.bat [--pristine^|--incremental] [--no-gui] [--debug] [--install] [--deploy] echo --pristine Delete build\, __Builds\, and cached downloads ^(default^) echo --incremental Reuse existing build tree and downloaded libraries echo --no-gui Build just low-level libraries without the UI application echo --debug Also build Debug configuration ^(Release is always built^) echo --install Install libraries, headers, applications, and configs + echo --deploy Bundle Qt dependencies into each app ^(slow; for distribution^) exit /b 1 ) @@ -79,16 +82,21 @@ if "%BUILD_DEBUG%"=="1" ( -DCMAKE_GENERATOR=Ninja ^ -DCMAKE_BUILD_TYPE=Debug ^ -DBUILD_UI=%BUILD_UI% ^ + -DDEPLOY_APPS=OFF ^ -DCMAKE_CXX_FLAGS_INIT=-DQT_QML_DEBUG cmake --build build\Debug ) +set DEPLOY_APPS_FLAG=OFF +if "%DEPLOY%"=="1" set DEPLOY_APPS_FLAG=ON + cmake -S . -B build\Release -DCMAKE_PREFIX_PATH="%QTBIN%\.." ^ -DCMAKE_COLOR_DIAGNOSTICS=ON ^ -DCMAKE_GENERATOR=Ninja ^ -DCMAKE_BUILD_TYPE=Release ^ - -DBUILD_UI=%BUILD_UI% + -DBUILD_UI=%BUILD_UI% ^ + -DDEPLOY_APPS=%DEPLOY_APPS_FLAG% cmake --build build\Release diff --git a/build.sh b/build.sh index fa83ef4..be54951 100644 --- a/build.sh +++ b/build.sh @@ -40,6 +40,7 @@ PRISTINE=1 BUILD_UI=ON BUILD_DEBUG=0 INSTALL=0 +DEPLOY=0 for arg in "$@"; do case "$arg" in @@ -48,14 +49,16 @@ for arg in "$@"; do --no-gui) BUILD_UI=OFF ;; --debug) BUILD_DEBUG=1 ;; --install) INSTALL=1 ;; + --deploy) DEPLOY=1 ;; *) - echo "Usage: $0 [--pristine|--incremental] [--no-gui] [--debug] [--install]" + echo "Usage: $0 [--pristine|--incremental] [--no-gui] [--debug] [--install] [--deploy]" echo " --pristine Delete build/, __Builds/, and cached downloads (default)" echo " --incremental Reuse existing build tree and downloaded libraries" echo " --no-gui Build just low-level libraries without the UI application" echo " --debug Also build Debug configuration (Release is always built)" echo " --install Install libraries, headers, applications, and configs" echo " (installs to CMAKE_INSTALL_PREFIX, default: /usr/local)" + echo " --deploy Bundle Qt dependencies into each app (slow; for distribution)" exit 1 ;; esac done @@ -91,12 +94,17 @@ fi # Debug if [ "$BUILD_DEBUG" -eq 1 ]; then - cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} + cmake -S . -B build/${DISTRO}/Debug -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Debug ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} -DDEPLOY_APPS=OFF cmake --build build/${DISTRO}/Debug --parallel ${NPROC} fi # Release -cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} +if [ "$DEPLOY" -eq 1 ]; then + DEPLOY_APPS_FLAG=ON +else + DEPLOY_APPS_FLAG=OFF +fi +cmake -S . -B build/${DISTRO}/Release -DCMAKE_PREFIX_PATH="$(dirname "$QTBIN")" -DCMAKE_BUILD_TYPE=Release ${CMAKE_DISTRO_FLAG} -DBUILD_UI=${BUILD_UI} -DDEPLOY_APPS=${DEPLOY_APPS_FLAG} cmake --build build/${DISTRO}/Release --parallel ${NPROC} if [ "$INSTALL" -eq 1 ]; then diff --git a/src/applications/CMakeLists.txt b/src/applications/CMakeLists.txt index f12265e..1aaf4a0 100644 --- a/src/applications/CMakeLists.txt +++ b/src/applications/CMakeLists.txt @@ -41,6 +41,8 @@ find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) qt_standard_project_setup() +option(DEPLOY_APPS "Run macdeployqt/windeployqt to create self-contained app bundles (slow)" OFF) + if(APPLE) # Add the Qt frameworks directory to the install rpath so apps can find Qt # frameworks at runtime without a full macdeployqt deployment. @@ -51,8 +53,11 @@ endif() # Qt 6.3/6.4 use FILENAME_VARIABLE; Qt 6.5+ renamed it to OUTPUT_SCRIPT. # On Linux, system installs use system-provided Qt shared libraries; # running the deploy tool would copy system libs into /usr/local which is wrong. +# On Windows/macOS the deploy step is opt-in via -DDEPLOY_APPS=ON (or --deploy +# in build.sh/build.bat) to avoid slow macdeployqt/windeployqt runs during +# routine testing. macro(qtac_deploy_app target) - if(WIN32 OR APPLE) + if(DEPLOY_APPS AND (WIN32 OR APPLE)) if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") qt_generate_deploy_app_script( TARGET ${target} From e4632b4d3f9c2fde44c1931856822b64ef357d2b Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 01:14:40 +0530 Subject: [PATCH 23/28] build: pristine clean only the current platform's build directories Previously --pristine deleted the entire build/ and __Builds/ trees, wiping out any other platform's build (e.g. a macOS build while cleaning for a Debian rebuild). On Linux/macOS, delete only build// and __Builds//: Linux debian: build/debian/ __Builds/Linux-debian/ macOS: build/macOS/ __Builds/macOS/ Introduce BUILDS_SUBDIR alongside DISTRO in the uname case block to hold the __Builds prefix (Linux- vs macOS). On Windows, scope the clean to build\Debug, build\Release, and __Builds\x64 rather than the entire tree. Signed-off-by: Amit Kucheria --- build.bat | 5 +++-- build.sh | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/build.bat b/build.bat index 85f6f8a..a362d91 100644 --- a/build.bat +++ b/build.bat @@ -70,8 +70,9 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliar set "PATH=%QTBIN%;%PATH%" if "%PRISTINE%"=="1" ( - if exist build rmdir /s /q build - if exist __Builds rmdir /s /q __Builds + if exist build\Debug rmdir /s /q build\Debug + if exist build\Release rmdir /s /q build\Release + if exist __Builds\x64 rmdir /s /q __Builds\x64 del /q third-party\*.tgz 2>nul del /q third-party\*.zip 2>nul ) diff --git a/build.sh b/build.sh index be54951..ab80bc1 100644 --- a/build.sh +++ b/build.sh @@ -75,11 +75,13 @@ case "$(uname)" in DISTRO=$(. /etc/os-release && echo "$ID") CMAKE_DISTRO_FLAG="-DLINUX_DISTRO=${DISTRO}" NPROC=$(nproc) + BUILDS_SUBDIR="Linux-${DISTRO}" ;; Darwin) DISTRO="macOS" CMAKE_DISTRO_FLAG="" NPROC=$(sysctl -n hw.logicalcpu) + BUILDS_SUBDIR="macOS" ;; *) echo "Unsupported platform: $(uname)" @@ -88,7 +90,7 @@ case "$(uname)" in esac if [ "$PRISTINE" -eq 1 ]; then - rm -rf build __Builds + rm -rf build/${DISTRO} __Builds/${BUILDS_SUBDIR} rm -f third-party/*.tgz third-party/*.zip fi From 1ae35e2cc7321de07f99f415ccb9cd16a712f406 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Thu, 7 May 2026 02:58:40 +0530 Subject: [PATCH 24/28] docs: document new build options --pristine/--incremental and --debug are useful during development --install and --deploy are useful for end users to deploy QTAC --no-gui to only build the core libraries w/o the UI applications build.bat has no --no-gui flag; Windows no-GUI builds use BUILD_UI=OFF directly on the cmake command line. Signed-off-by: Amit Kucheria --- README.md | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c3478e5..0ed7db7 100644 --- a/README.md +++ b/README.md @@ -99,8 +99,18 @@ Execute `build.bat` to generate executables: build.bat ``` +**Build options**: +| Flag | Description | +| :-- | :-- | +| `--pristine` | Delete `build\`, `__Builds\`, and cached downloads before building (default) | +| `--incremental` | Reuse existing build tree and downloaded libraries | +| `--no-gui` | Build only headless libraries (`QCommonConsole`, `TACDev`) without Qt GUI modules or applications | +| `--debug` | Also build a Debug configuration (Release is always built) | +| `--install` | Install binaries, libraries, headers, and configs to `CMAKE_INSTALL_PREFIX` (default: `C:\Program Files\QTAC`); requires Administrator | +| `--deploy` | Run `windeployqt` to bundle Qt DLLs into each app directory (slow; use for distribution packages) | + **Build output**: -- Debug: `__Builds\x64\Debug` +- Debug (with `--debug`): `__Builds\x64\Debug` - Release: `__Builds\x64\Release` **Usage**: @@ -133,7 +143,7 @@ __Builds\x64\Release\QTAC.exe ``` 4. **Environment Variable**: ```bash - export QTBIN=/path/to/Qt/directory//gcc_64/bin + export QTBIN=/usr/lib/qt6/bin ``` ### Build & Usage @@ -144,9 +154,26 @@ Execute `build.sh` to generate executables: ./build.sh ``` +**Build options**: +| Flag | Description | +| :-- | :-- | +| `--pristine` | Delete `build/`, `__Builds/`, and cached downloads before building (default) | +| `--incremental` | Reuse the existing build tree; skip the clean step. | +| `--no-gui` | Build only headless libraries (`QCommonConsole`, `TACDev`) without Qt GUI modules or applications; omits Qt Multimedia, Widgets, `qcommon`, `ui-common`, and all GUI apps | +| `--debug` | Also build a Debug configuration (Release is always built). | +| `--install` | Install binaries, libraries, headers, and configs to `CMAKE_INSTALL_PREFIX` (default: `/usr/local`); invokes `sudo cmake --install` | +| `--deploy` | Run `macdeployqt` to bundle Qt frameworks into each app bundle (slow; use for distribution packages; macOS only) | + +**No-GUI build** — omits Qt Multimedia, Qt Widgets, `qcommon`, `ui-common`, and all GUI +applications. Only `QCommonConsole` and `TACDev` are compiled: + +```bash +./build.sh --no-gui +``` + **Build output**: -- Debug: `__Builds/Linux/Debug` -- Release: `__Builds/Linux/Release` +- Release: `__Builds/Linux-/Release` +- Debug (with `--debug`): `__Builds/Linux-/Debug` > [!NOTE] > Ensure that [make](https://www.gnu.org/software/make/) is available in your environment before building. From 1a5bb4ad530be071c163522db4a40e183b57e5c6 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 01:49:17 +0530 Subject: [PATCH 25/28] docs: document Linux build prerequisites List all packages needed before running build.sh: cmake 3.16+, build-essential (GCC 11+), ninja-build; document all three Qt install paths (apt for Ubuntu 24.04+, Qt Online Installer, aqtinstall) with a note that Ubuntu 22.04 system Qt is too old; add the reduced package set for --no-gui builds; add the missing udevadm trigger step; document QTBIN for both apt and installer layouts. Signed-off-by: Amit Kucheria --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0ed7db7..4ff6c89 100644 --- a/README.md +++ b/README.md @@ -125,26 +125,58 @@ __Builds\x64\Release\QTAC.exe > [!IMPORTANT] > - Installation using Qt Online Installer will require users to create a Qt account. > - If you're frequently working with Qt on Linux, consider adding the environment variables to `.bashrc`. -> - Using `sudo apt install ` will update setup packages. Review command usage to prevent issues with other applications. -1. **Qt Installation** (choose one): - - **Option A**: Qt Online Installer - - Install Qt 6.9+ for **GCC 64-bit** and **Qt Serial Port** component using [Qt Online Installer](https://www.qt.io/download-qt-installer-oss) - - **Option B**: Quick Installation via apt +1. **Build Tools**: + ```bash + sudo apt install cmake build-essential ninja-build git + ``` + - `cmake` 3.16 or later + - `build-essential` — GCC/G++ 11 or later and make + - `ninja-build` — faster parallel builds (recommended) + +2. **Qt 6.8+** (choose one): + + **Option A**: System Qt via apt (Ubuntu 24.04+ / Debian 13+) + ```bash + sudo apt install qt6-base-dev qt6-multimedia-dev qt6-serialport-dev qt6-tools-dev + ``` + > [!NOTE] + > Ubuntu 22.04 ships Qt 6.2 which is too old. Use Option B or C on 22.04. + + For `--no-gui` builds only `QCommonConsole` and `TACDev` are compiled, so fewer Qt + packages are needed: ```bash - sudo apt install qt6-base-dev qt6-serialport-dev + sudo apt install qt6-base-dev qt6-serialport-dev qt6-tools-dev ``` -2. **Runtime Dependencies**: + + **Option B**: Qt Online Installer (any distro / Ubuntu version) + - Install Qt 6.8+ for **GCC 64-bit**, selecting the **Qt Serial Port** and + **Qt Multimedia** components using the + [Qt Online Installer](https://www.qt.io/download-qt-installer-oss) + + **Option C**: aqtinstall (scriptable, no Qt account required) + ```bash + pip install aqtinstall + aqt install-qt linux desktop 6.8.0 gcc_64 -m qtserialport qtmultimedia + ``` + +3. **USB Access** — install the udev rule so the debug board is accessible without root: ```bash sudo cp udev-rules/99-QTAC-USB.rules /etc/udev/rules.d/ sudo udevadm control --reload + sudo udevadm trigger ``` -4. **Environment Variable**: + +4. **Environment Variable** — set `QTBIN` to the Qt `bin/` directory: + + System Qt (apt): ```bash export QTBIN=/usr/lib/qt6/bin ``` + Qt Online Installer or aqtinstall: + ```bash + export QTBIN=~/Qt/6.8.0/gcc_64/bin + ``` ### Build & Usage From 2ca50ad66407c1c5c27fa7d7dd007dbdf1c60841 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 01:49:38 +0530 Subject: [PATCH 26/28] docs: document Windows build prerequisites Signed-off-by: Amit Kucheria --- README.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4ff6c89..eb5147f 100644 --- a/README.md +++ b/README.md @@ -80,16 +80,33 @@ git clone https://github.com/qualcomm/qcom-test-automation-controller.git ### Configuration -1. **Visual Studio**: Install **Desktop development with C++** and **.NET desktop development**. +1. **Git**: Install [Git for Windows](https://git-scm.com/download/win). + +2. **Visual Studio 2022**: Install the + [Community](https://aka.ms/vs/17/release/vs_community.exe), + Professional, or Enterprise edition and select the following workloads: + - **Desktop development with C++** (required — provides MSVC compiler, CMake, and Ninja) + - **.NET desktop development** (required for C# interop builds) + ![Desktop development with C++](./docs/resources/qtac-msvc-2022-requirements.png) -2. **Qt**: Install Qt 6.9+ for **MSVC 2022 64-bit**, **Qt Serial Port** and **Qt Multimedia** components. - -> [!NOTE] -> Installation using Qt Online Installer will require users to create a Qt account. -3. **Environment Variable**: + + > [!NOTE] + > CMake 3.16+ and Ninja are bundled with Visual Studio; no separate installation needed. + +3. **Qt 6.8+**: Use the [Qt Online Installer](https://www.qt.io/download-qt-installer-oss) + and select the following for the **MSVC 2022 64-bit** target: + - Qt 6.8.x → **MSVC 2022 64-bit** (compiler binaries) + - Qt 6.8.x → **Qt Serial Port** + - Qt 6.8.x → **Qt Multimedia** + + > [!NOTE] + > Installation using Qt Online Installer requires a Qt account. + +4. **Environment Variable** — set `QTBIN` permanently in your user environment: ```cmd setx QTBIN C:\Qt\\msvc2022_64\bin ``` + Open a new command prompt after running `setx` for the change to take effect. ### Build & Usage From fb47bdff8c8edec827ec2e234667b18fdcfa1be5 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 01:50:38 +0530 Subject: [PATCH 27/28] docs: add macOS guide and build prerequisites Document Xcode Command Line Tools, cmake, and Qt 6.8+ installation for macOS; note that FTDI D2XX is auto-downloaded via hdiutil at configure time; remove obsolete make note (ninja-build is now listed in prerequisites). Signed-off-by: Amit Kucheria --- README.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eb5147f..415bf33 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ - [Common Prerequisites](#common-prerequisites) - [Windows Guide](#windows-guide) - [Linux Guide](#linux-guide) +- [macOS Guide](#macos-guide) - [Repository Structure](#repository-structure) - [Application Dependency Architecture](#application-dependency-architecture) - [Advanced Topics](#advanced-topics) @@ -224,12 +225,69 @@ applications. Only `QCommonConsole` and `TACDev` are compiled: - Release: `__Builds/Linux-/Release` - Debug (with `--debug`): `__Builds/Linux-/Debug` -> [!NOTE] -> Ensure that [make](https://www.gnu.org/software/make/) is available in your environment before building. +**Usage**: +```bash +./__Builds/Linux-$(. /etc/os-release && echo "$ID")/Release/bin/TAC +``` + +## macOS Guide + +### Configuration + +1. **Xcode Command Line Tools**: + ```bash + xcode-select --install + ``` + +2. **CMake 3.16+** (choose one): + - Download from [cmake.org](https://cmake.org/download/) + - Or install via Homebrew: `brew install cmake` + +3. **Qt 6.8+** (choose one): + + **Option A**: Homebrew (simplest — includes all required modules) + ```bash + brew install qt + ``` + + **Option B**: Qt Online Installer + - Use the [Qt Online Installer](https://www.qt.io/download-qt-installer-oss) and select + the following for the **macOS** target: + - Qt 6.8.x → **macOS** (compiler binaries) + - Qt 6.8.x → **Qt Serial Port** + - Qt 6.8.x → **Qt Multimedia** + + > [!NOTE] + > Installation using Qt Online Installer requires a Qt account. + +4. **Environment Variable** — set `QTBIN` to the Qt `bin/` directory: + + Homebrew: + ```bash + export QTBIN=$(brew --prefix qt)/bin + ``` + Qt Online Installer: + ```bash + export QTBIN=~/Qt/6.8.0/macos/bin + ``` + +### Build & Usage + +`build.sh` is used on macOS with the same flags as Linux. FTDI D2XX is downloaded +automatically from an FTDI-provided DMG at cmake configure time (requires `hdiutil`, +which is built into macOS). + +```bash +./build.sh +``` + +**Build output**: +- Release: `__Builds/macOS/Release` +- Debug (with `--debug`): `__Builds/macOS/Debug` **Usage**: ```bash -./__Builds/Linux/Release/QTAC +open __Builds/macOS/Release/bin/TAC.app ``` ## Repository Structure From 3d5274db4624525dc5a1e96c3fbb01bfa25e836c Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Sat, 9 May 2026 01:51:19 +0530 Subject: [PATCH 28/28] docs: document cmake install target per platform For each platform (Linux, Windows, macOS), list every path installed by 'cmake --install': binaries, static libraries (libTACDev.a, libftd2xx.a), public header (TACDev.h), device configurations, desktop files, icons, and qt.conf. Note the RPATH strategy on Linux/macOS, the Administrator requirement on Windows, and the Qt DLL caveat when --deploy is not used. Signed-off-by: Amit Kucheria --- README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/README.md b/README.md index 415bf33..ee7ce6a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - [Windows Guide](#windows-guide) - [Linux Guide](#linux-guide) - [macOS Guide](#macos-guide) +- [Installing QTAC](#installing-qtac) - [Repository Structure](#repository-structure) - [Application Dependency Architecture](#application-dependency-architecture) - [Advanced Topics](#advanced-topics) @@ -290,6 +291,92 @@ which is built into macOS). open __Builds/macOS/Release/bin/TAC.app ``` +## Installing QTAC + +Pass `--install` to `build.sh` or `build.bat` to run `cmake --install` after a successful +build. The default install prefix is `/usr/local` on Linux/macOS and +`C:\Program Files\QTAC` on Windows. Override it by setting `CMAKE_INSTALL_PREFIX` in your +cmake invocation. + +### Linux + +```bash +./build.sh --install +# or, to install to a custom prefix: +cmake --install build/debian/Release --prefix /opt/qtac +``` + +| Installed path | Content | +| :-- | :-- | +| `$PREFIX/bin/TAC` | Test Automation Controller GUI | +| `$PREFIX/bin/TACConfigEditor` | TAC Configuration Editor GUI | +| `$PREFIX/bin/DeviceCatalog` | Device Catalog GUI | +| `$PREFIX/bin/DevList` | List connected debug boards | +| `$PREFIX/bin/TACDump` | Dump TAC configuration | +| `$PREFIX/bin/FTDICheck` | FTDI device diagnostics | +| `$PREFIX/bin/UpdateDeviceList` | Update the device list | +| `$PREFIX/bin/LITEProgrammer` | Program LITE debug boards | +| `$PREFIX/bin/qt.conf` | Qt plugin path for installed binaries | +| `$PREFIX/lib/libTACDev.a` | TACDev C++ static library | +| `$PREFIX/lib/libftd2xx.a` | FTDI D2XX static library | +| `$PREFIX/include/qtac/TACDev.h` | TACDev public header | +| `$PREFIX/share/qtac/configurations/` | Device configuration files (`.tcnf`, `devicelist.json`) | +| `$PREFIX/share/applications/` | `.desktop` files for TAC, TACConfigEditor, DeviceCatalog | +| `$PREFIX/share/icons/` | Application icons | + +Installed binaries have RPATH `$ORIGIN:$ORIGIN/../lib` so they find `libftd2xx.a` at +runtime without needing `LD_LIBRARY_PATH`. + +### Windows + +Run `build.bat --install` from an **Administrator** command prompt. The install step +checks for Administrator privileges and exits if not elevated. + +| Installed path | Content | +| :-- | :-- | +| `$PREFIX\bin\TAC.exe` | Test Automation Controller GUI | +| `$PREFIX\bin\TACConfigEditor.exe` | TAC Configuration Editor GUI | +| `$PREFIX\bin\DeviceCatalog.exe` | Device Catalog GUI | +| `$PREFIX\bin\DevList.exe` | List connected debug boards | +| `$PREFIX\bin\TACDump.exe` | Dump TAC configuration | +| `$PREFIX\bin\FTDICheck.exe` | FTDI device diagnostics | +| `$PREFIX\bin\UpdateDeviceList.exe` | Update the device list | +| `$PREFIX\bin\LITEProgrammer.exe` | Program LITE debug boards | +| `$PREFIX\lib\TACDev.lib` | TACDev C++ static library (Release) | +| `$PREFIX\lib\ftd2xx.lib` | FTDI D2XX static library | +| `$PREFIX\include\qtac\TACDev.h` | TACDev public header | +| `$PREFIX\share\qtac\configurations\` | Device configuration files | + +> [!NOTE] +> Qt DLLs are **not** bundled unless `--deploy` was also passed. Without `--deploy`, +> ensure Qt's `bin\` directory is on `PATH` when running installed binaries. + +### macOS + +```bash +./build.sh --install +# or, to install to a custom prefix: +sudo cmake --install build/macOS/Release --prefix /opt/qtac +``` + +| Installed path | Content | +| :-- | :-- | +| `$PREFIX/bin/TAC.app` | Test Automation Controller GUI (app bundle) | +| `$PREFIX/bin/TACConfigEditor.app` | TAC Configuration Editor GUI (app bundle) | +| `$PREFIX/bin/DeviceCatalog.app` | Device Catalog GUI (app bundle) | +| `$PREFIX/bin/DevList` | List connected debug boards | +| `$PREFIX/bin/TACDump` | Dump TAC configuration | +| `$PREFIX/bin/FTDICheck` | FTDI device diagnostics | +| `$PREFIX/bin/UpdateDeviceList` | Update the device list | +| `$PREFIX/bin/LITEProgrammer` | Program LITE debug boards | +| `$PREFIX/lib/libTACDev.a` | TACDev C++ static library | +| `$PREFIX/lib/libftd2xx.a` | FTDI D2XX static library | +| `$PREFIX/include/qtac/TACDev.h` | TACDev public header | +| `$PREFIX/share/qtac/configurations/` | Device configuration files | + +App bundles embed an RPATH pointing to the Qt frameworks directory used at build time. +Pass `--deploy` to run `macdeployqt` and make bundles fully self-contained for distribution. + ## Repository Structure | Directory | Content |