Skip to content

Commit

Permalink
Merge pull request #32 from aminya/vcvarsall
Browse files Browse the repository at this point in the history
  • Loading branch information
aminya authored Nov 28, 2021
2 parents b4a886b + 4e98afa commit c858050
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 9 deletions.
14 changes: 5 additions & 9 deletions src/Sanitizers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,12 @@ function(
target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
else()
if("$ENV{VCINSTALLDIR}" STREQUAL "")
string(FIND "$ENV{VSINSTALLDIR}" "$ENV{PATH}" index_of_vs_install_dir)
if("index_of_vs_install_dir" STREQUAL "-1")
message(
FATAL_ERROR
"Using MSVC sanitizers requires that you have set the MSVC environment before building the project. Please use the MSVC command prompt and rebuild the project. You can set up the MSVC environment using vcvarsall in cmd:
# find vcvarsall.bat
vswhere -products * -latest -prerelease -find \"**/VC/Auxiliary/Build/vcvarsall.bat\"
# set up the environment for x64
\"path/to/vcvarsall\" x64
")
SEND_ERROR
"Using MSVC sanitizers requires setting the MSVC environment before building the project. Please manually open the MSVC command prompt and rebuild the project."
)
endif()
target_compile_options(${project_name} INTERFACE /fsanitize=${LIST_OF_SANITIZERS} /Zi /INCREMENTAL:NO)
target_link_options(${project_name} INTERFACE /INCREMENTAL:NO)
Expand Down
4 changes: 4 additions & 0 deletions src/StandardProjectSettings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ if(NOT "${CMAKE_CXX_STANDARD}")
)
set(CMAKE_CXX_STANDARD ${CXX_LATEST_STANDARD})
endif()

# run vcvarsall when msvc is used
include("${ProjectOptions_SRC_DIR}/VCEnvironment.cmake")
run_vcvarsall()
84 changes: 84 additions & 0 deletions src/Utilities.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# find a subtring from a string by a given prefix such as VCVARSALL_ENV_START
function(
find_substring_by_prefix
output
prefix
input)
# find the prefix
string(FIND "${input}" "${prefix}" prefix_index)
if("${prefix_index}" STREQUAL "-1")
message(SEND_ERROR "Could not find ${prefix} in ${input}")
endif()
# find the start index
string(LENGTH "${prefix}" prefix_length)
math(EXPR start_index "${prefix_index} + ${prefix_length}")

string(
SUBSTRING "${input}"
"${start_index}"
"-1"
_output)
set("${output}"
"${_output}"
PARENT_SCOPE)
endfunction()

# A function to set environment variables of CMake from the output of `cmd /c set`
function(set_env_from_string env_string)
# replace ; in paths with __sep__ so we can split on ;
string(
REGEX
REPLACE ";"
"__sep__"
env_string_sep_added
"${env_string}")

# the variables are separated by \r?\n
string(
REGEX
REPLACE "\r?\n"
";"
env_list
"${env_string_sep_added}")

foreach(env_var ${env_list})
# split by =
string(
REGEX
REPLACE "="
";"
env_parts
"${env_var}")

list(LENGTH env_parts env_parts_length)
if("${env_parts_length}" EQUAL "2")
# get the variable name and value
list(
GET
env_parts
0
env_name)
list(
GET
env_parts
1
env_value)

# recover ; in paths
string(
REGEX
REPLACE "__sep__"
";"
env_value
"${env_value}")

# set env_name to env_value
set(ENV{${env_name}} "${env_value}")

# update cmake program path
if("${env_name}" EQUAL "PATH")
list(APPEND CMAKE_PROGRAM_PATH ${env_value})
endif()
endif()
endforeach()
endfunction()
59 changes: 59 additions & 0 deletions src/VCEnvironment.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
include("${ProjectOptions_SRC_DIR}/Utilities.cmake")

# Run vcvarsall.bat and set CMake environment variables
function(run_vcvarsall)
# if MSVC but VSCMD_VER is not set, which means vcvarsall has not run
if(MSVC AND "$ENV{VSCMD_VER}" STREQUAL "")

# find vcvarsall.bat
get_filename_component(MSVC_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
find_file(
VCVARSALL_FILE
NAMES vcvarsall.bat
PATHS "${MSVC_DIR}"
"${MSVC_DIR}/.."
"${MSVC_DIR}/../.."
"${MSVC_DIR}/../../../../../../../.."
"${MSVC_DIR}/../../../../../../.."
PATH_SUFFIXES "VC/Auxiliary/Build" "Common7/Tools" "Tools")

if(VCVARSALL_FILE_FOUND)

# detect the architecture
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" CMAKE_SYSTEM_PROCESSOR_LOWER)
if(CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL x86 OR CMAKE_SYSTEM_PROCESSOR_LOWER MATCHES "^i[3456]86$")
set(VCVARSALL_ARCH x86)
elseif(CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL amd64)
set(VCVARSALL_ARCH x64)
elseif(CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL arm)
set(VCVARSALL_ARCH arm)
elseif(CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL arm64 OR CMAKE_SYSTEM_PROCESSOR_LOWER STREQUAL aarch64)
set(VCVARSALL_ARCH arm64)
else()
message(WARNING "Unkown architecture: ${lowercase_CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()

# run vcvarsall and print the environment variables
message(STATUS "Running `${VCVARSALL_FILE} ${VCVARSALL_ARCH}` to set up the MSVC environment")
execute_process(
COMMAND
"cmd" "/c" ${VCVARSALL_FILE} ${VCVARSALL_ARCH} #
"&&" "call" "echo" "VCVARSALL_ENV_START" #
"&" "set" #
OUTPUT_VARIABLE VCVARSALL_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE)

# parse the output and get the environment variables string
find_substring_by_prefix(VCVARSALL_ENV "VCVARSALL_ENV_START" "${VCVARSALL_OUTPUT}")

# set the environment variables
set_env_from_string("${VCVARSALL_ENV}")

else()
message(
WARNING
"Could not find `vcvarsall.bat` for automatic MSVC environment preparation. Please manually open the MSVC command prompt and rebuild the project.
")
endif()
endif()
endfunction()

0 comments on commit c858050

Please sign in to comment.