From 031ae2ebf622bc1a87a3dfaf3a95e5b123805a0c Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Fri, 1 Aug 2025 03:03:58 +0000 Subject: [PATCH] build: fix CMake slowness Optimize the `find_wx_util` function to try the major and minor version parsed from the lib file first, avoiding a very slow exhaustive search of possible version numbers. Signed-off-by: Rafael Kitover --- CMakeLists.txt | 4 ++ cmake/VbamFunctions.cmake | 104 ++++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6103892f..212b6045 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,10 @@ cmake_minimum_required(VERSION 3.19) cmake_policy(VERSION 3.19...3.28.3) +# Use new link library de-duplication behavior. +cmake_policy(SET CMP0156 NEW) +cmake_policy(SET CMP0179 NEW) + set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) if(WIN32) diff --git a/cmake/VbamFunctions.cmake b/cmake/VbamFunctions.cmake index 6e1344c6..a8f9d001 100644 --- a/cmake/VbamFunctions.cmake +++ b/cmake/VbamFunctions.cmake @@ -37,8 +37,48 @@ function(check_clean_exit var) set(${var} ${exit_status} PARENT_SCOPE) endfunction() +function(try_wx_util var util conf_suffix major_version minor_version) + unset(suffix) + if(conf_suffix) + set(suffix "-${conf_suffix}") + endif() + if(major_version) + set(suffix "${suffix}-${major_version}") + + if(NOT minor_version EQUAL -1) + set(suffix "${suffix}.${minor_version}") + endif() + endif() + + # find_program caches the result + set(exe NOTFOUND CACHE INTERNAL "" FORCE) + find_program(exe NAMES "${util}${suffix}") + + # try infix variant, as on FreeBSD + if(NOT EXISTS "${exe}") + string(REGEX REPLACE "^-" "" suffix "${suffix}") + + string(REGEX REPLACE "-" "${suffix}-" try "${util}") + + set(exe NOTFOUND CACHE INTERNAL "" FORCE) + find_program(exe NAMES "${try}") + endif() + + if(EXISTS "${exe}") + # check that the utility can be executed cleanly + # in case we find e.g. the wrong architecture binary + # when cross-compiling + check_clean_exit(exit_status "${exe}" --help) + + if(exit_status EQUAL 0) + set("${var}" "${exe}" PARENT_SCOPE) + return() + endif() + endif() +endfunction() + function(find_wx_util var util) - if(WIN32 OR EXISTS /etc/gentoo-release) + if((WIN32 AND (NOT CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")) OR EXISTS /etc/gentoo-release) # On win32, including cross builds we prefer the plain utility # name first from PATH, with the exception of -static for static # builds. @@ -57,48 +97,34 @@ function(find_wx_util var util) set(major_versions ";") endif() - list(APPEND conf_suffixes gtk4u gtk4 gtk3u gtk3 gtk2u gtk2 "") - list(APPEND major_versions 4 3 2 "") + list(APPEND conf_suffixes "" gtk3u gtk3 gtk2u gtk2) + list(APPEND major_versions "" 3) + + get_target_property(wx_base_lib_prop wx::base LOCATION) + string(STRIP "${wx_base_lib_prop}" wx_base_lib) + + if(wx_base_lib MATCHES "wx_baseu?-([0-9]+)\\.([0-9]+)\\.") + set(lib_major "${CMAKE_MATCH_1}") + set(lib_minor "${CMAKE_MATCH_2}") + endif() foreach(conf_suffix IN LISTS conf_suffixes) + if(lib_major AND lib_minor) + try_wx_util(exe "${util}" "${conf_suffix}" "${lib_major}" "${lib_minor}") + + if(exe) + set("${var}" "${exe}" PARENT_SCOPE) + return() + endif() + endif() + foreach(major_version IN LISTS major_versions) - foreach(minor_version RANGE 100 -1 -1) - unset(suffix) - if(conf_suffix) - set(suffix "-${conf_suffix}") - endif() - if(major_version) - set(suffix "${suffix}-${major_version}") + foreach(minor_version RANGE 30 -1 -1) + try_wx_util(exe "${util}" "${conf_suffix}" "${major_version}" "${minor_version}") - if(NOT minor_version EQUAL -1) - set(suffix "${suffix}.${minor_version}") - endif() - endif() - - # find_program caches the result - set(exe NOTFOUND CACHE INTERNAL "" FORCE) - find_program(exe NAMES "${util}${suffix}") - - # try infix variant, as on FreeBSD - if(NOT EXISTS ${exe}) - string(REGEX REPLACE "^-" "" suffix "${suffix}") - - string(REGEX REPLACE "-" "${suffix}-" try ${util}) - - set(exe NOTFOUND CACHE INTERNAL "" FORCE) - find_program(exe NAMES ${try}) - endif() - - if(EXISTS ${exe}) - # check that the utility can be executed cleanly - # in case we find e.g. the wrong architecture binary - # when cross-compiling - check_clean_exit(exit_status ${exe} --help) - - if(exit_status EQUAL 0) - set(${var} ${exe} PARENT_SCOPE) - return() - endif() + if(exe) + set("${var}" "${exe}" PARENT_SCOPE) + return() endif() # don't iterate over minor versions for empty major version