Skip to content

Commit fae07b3

Browse files
committed
feat(vsvars): Refactor vcvars discovery with reusable function
* Introduced `Vcvars_FindFirstValidMsvcVersion()` to encapsulate logic for selecting the first valid MSVC version from a prioritized list that provides a `vcvars` batch script. * Replaced duplicated logic with a call to the new function, improving clarity and maintainability. * Ensured compatibility with both configuration and script modes. * Added the function to test coverage and documented it with a dedicated `.. command::` section. * Improved formatting and consistency in toolset-to-version mapping documentation, clarifying alias relationships.
1 parent 7475960 commit fae07b3

File tree

2 files changed

+71
-23
lines changed

2 files changed

+71
-23
lines changed

FindVcvars.cmake

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,31 @@ This module also defines the following functions
9797
The name of the variable to be set with the Visual Studio version.
9898
9999
100+
.. command:: Vcvars_FindFirstValidMsvcVersion
101+
102+
The `Vcvars_FindFirstValidMsvcVersion()` function identifies the first MSVC version from a list of candidates that has an associated and discoverable `vcvars` batch script::
103+
104+
```
105+
Vcvars_FindFirstValidMsvcVersion(<msvc_arch> <candidate_msvc_versions> <msvc_version_output_varname> <batch_file_output_varname>)
106+
```
107+
108+
The options are:
109+
110+
``<msvc_arch>``
111+
Specify the Visual Studio architecture. Possible values are `32` or `64`.
112+
113+
``<candidate_msvc_versions>``
114+
A list of MSVC version numbers to check (e.g., `1949;1948;1947`). The list should be ordered from most to least preferred.
115+
116+
``<msvc_version_output_varname>``
117+
The name of the variable to store the first matching MSVC version.
118+
119+
``<batch_file_output_varname>``
120+
The name of the variable to store the path to the corresponding `vcvars` batch script.
121+
122+
This is typically used internally to identify the most recent supported Visual Studio installation that provides the appropriate environment setup scripts, but it can also be reused in custom detection logic when running in configuration or script mode.
123+
124+
100125
The module also defines the following variables mapping MSVC versions
101126
to their associated toolset or Visual Studio major release:
102127
@@ -304,6 +329,37 @@ function(Vcvars_GetVisualStudioPaths msvc_version msvc_arch output_var)
304329
set(${output_var} ${_vs_installer_paths} PARENT_SCOPE)
305330
endfunction()
306331

332+
function(Vcvars_FindFirstValidMsvcVersion msvc_arch candidate_msvc_versions msvc_version_output_varname batch_file_output_varname)
333+
_vcvars_message(STATUS "Setting ${msvc_version_output_varname}")
334+
# which vcvars script ?
335+
if(msvc_arch STREQUAL "64")
336+
set(_candidate_scripts vcvarsamd64.bat vcvars64.bat)
337+
else()
338+
set(_candidate_scripts vcvars32.bat)
339+
endif()
340+
foreach(_candidate_msvc_version IN LISTS candidate_msvc_versions)
341+
Vcvars_GetVisualStudioPaths(${_candidate_msvc_version} "${msvc_arch}" _paths)
342+
Vcvars_ConvertMsvcVersionToVsVersion(${_candidate_msvc_version} _candidate_vs_version)
343+
set(_msg " Visual Studio ${_candidate_vs_version} (${_candidate_msvc_version})")
344+
_vcvars_message(STATUS "${_msg}")
345+
find_program(_batch_file NAMES ${_candidate_scripts}
346+
PATHS ${_paths}
347+
NO_CACHE
348+
)
349+
if(_batch_file)
350+
_vcvars_message(STATUS "${_msg} - found")
351+
set(_msvc_version ${_candidate_msvc_version})
352+
_vcvars_message(STATUS "Setting ${msvc_version_output_varname} to '${_msvc_version}' as it was the newest Visual Studio installed providing vcvars scripts")
353+
# Output variables
354+
set(${msvc_version_output_varname} ${_msvc_version} PARENT_SCOPE)
355+
set(${batch_file_output_varname} ${_batch_file} PARENT_SCOPE)
356+
break()
357+
else()
358+
_vcvars_message(STATUS "${_msg} - not found")
359+
endif()
360+
endforeach()
361+
endfunction()
362+
307363
if(_Vcvars_FUNCTIONS_ONLY)
308364
set(Vcvars_FOUND TRUE)
309365
return()
@@ -360,28 +416,19 @@ endif()
360416
# set Vcvars_BATCH_FILE
361417
if(NOT DEFINED Vcvars_MSVC_VERSION)
362418
# auto-discover Vcvars_MSVC_VERSION value
363-
_vcvars_message(STATUS "Setting Vcvars_MSVC_VERSION")
364-
foreach(_candidate_msvc_version IN LISTS _Vcvars_SUPPORTED_MSVC_VERSIONS)
365-
Vcvars_GetVisualStudioPaths(${_candidate_msvc_version} "${Vcvars_MSVC_ARCH}" _paths)
366-
Vcvars_ConvertMsvcVersionToVsVersion(${_candidate_msvc_version} _candidate_vs_version)
367-
set(_msg " Visual Studio ${_candidate_vs_version} (${_candidate_msvc_version})")
368-
_vcvars_message(STATUS "${_msg}")
369-
find_program(Vcvars_BATCH_FILE NAMES ${_Vcvars_SCRIPTS}
370-
DOC "Visual Studio ${_candidate_vs_version} ${_Vcvars_SCRIPTS}"
371-
PATHS ${_paths}
372-
)
373-
if(Vcvars_BATCH_FILE)
374-
_vcvars_message(STATUS "${_msg} - found")
375-
set(Vcvars_MSVC_VERSION ${_candidate_msvc_version})
376-
_vcvars_message(STATUS "Setting Vcvars_MSVC_VERSION to '${Vcvars_MSVC_VERSION}' as it was the newest Visual Studio installed providing vcvars scripts")
377-
break()
378-
else()
379-
_vcvars_message(STATUS "${_msg} - not found")
380-
endif()
381-
endforeach()
382-
unset(_candidate_msvc_version)
383-
unset(_candidate_vs_version)
384-
unset(_paths)
419+
Vcvars_FindFirstValidMsvcVersion(
420+
"${Vcvars_MSVC_ARCH}"
421+
"${_Vcvars_SUPPORTED_MSVC_VERSIONS}"
422+
Vcvars_MSVC_VERSION
423+
_batch_file
424+
)
425+
Vcvars_ConvertMsvcVersionToVsVersion(${Vcvars_MSVC_VERSION} _vs_version)
426+
unset(Vcvars_BATCH_FILE)
427+
set(Vcvars_BATCH_FILE ${_batch_file}
428+
CACHE FILEPATH "Visual Studio ${_vs_version} vcvars script"
429+
)
430+
unset(_batch_file)
431+
unset(_vs_version)
385432
else()
386433
# use provided Vcvars_MSVC_VERSION value
387434
if(NOT Vcvars_MSVC_VERSION MATCHES ${_Vcvars_MSVC_VERSION_REGEX})
@@ -390,7 +437,7 @@ else()
390437
Vcvars_GetVisualStudioPaths(${Vcvars_MSVC_VERSION} "${Vcvars_MSVC_ARCH}" _paths)
391438
Vcvars_ConvertMsvcVersionToVsVersion(${Vcvars_MSVC_VERSION} _vs_version)
392439
find_program(Vcvars_BATCH_FILE NAMES ${_Vcvars_SCRIPTS}
393-
DOC "Visual Studio ${_vs_version} ${_Vcvars_SCRIPTS}"
440+
DOC "Visual Studio ${_vs_version} vcvars script"
394441
PATHS ${_paths}
395442
)
396443
unset(_paths)

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ check_var_equals("Vcvars_FOUND" "TRUE")
157157

158158
check_function_defined("Vcvars_ConvertMsvcVersionToVsVersion")
159159
check_function_defined("Vcvars_GetVisualStudioPaths")
160+
check_function_defined("Vcvars_FindFirstValidMsvcVersion")
160161

161162
# VS 2022
162163
check_var_equals(Vcvars_TOOLSET_143_MSVC_VERSIONS "1949;1948;1947;1946;1945;1944;1943;1942;1941;1940;1939;1938;1937;1936;1935;1934;1933;1932;1931;1930")

0 commit comments

Comments
 (0)