319 lines
14 KiB
Batchfile
319 lines
14 KiB
Batchfile
@echo off
|
|
REM Enters the compiler environment a Windows preset needs, in THIS cmd.exe
|
|
REM session: what opening "x64 Native Tools Command Prompt for VS" or an MSYS2
|
|
REM MINGW64 shell by hand does, without opening a window or leaving the
|
|
REM console you are in.
|
|
REM
|
|
REM Not run directly -- breeze\scripts\build.bat calls it once the preset is known:
|
|
REM call "breeze\scripts\_winenv.bat" ^<preset^>
|
|
REM It uses no SETLOCAL on purpose: the variables vcvarsall.bat sets (PATH,
|
|
REM INCLUDE, LIB, ...) have to land in the CALLER's session. build.bat's own
|
|
REM SETLOCAL discards them again when it ends, so nothing leaks into the
|
|
REM prompt you started it from.
|
|
REM
|
|
REM preset environment entered
|
|
REM windows-x64-msvc, windows-arm64-msvc the Visual Studio developer
|
|
REM prompt for that target
|
|
REM (vcvarsall.bat from the newest
|
|
REM Visual Studio or Build Tools
|
|
REM that has the C++ tools)
|
|
REM windows-x64-clang-cl, the same, plus clang-cl on PATH
|
|
REM windows-arm64-clang-cl if it is not already (LLVM's own
|
|
REM folder, else the copy Visual
|
|
REM Studio ships)
|
|
REM windows-x64-mingw64, MSYS2's mingw64\bin or
|
|
REM windows-x86-mingw32 mingw32\bin first on PATH, unless
|
|
REM that compiler is already there
|
|
REM windows-x64-clang, MSYS2's clang64\bin or
|
|
REM windows-arm64-clang clangarm64\bin first on PATH --
|
|
REM always: a clang++ from anywhere
|
|
REM else targets a different ABI
|
|
REM
|
|
REM After entering a Visual Studio environment it checks that the target's runtime
|
|
REM libraries exist (lib\TARGET\msvcrt.lib), and for arm64 picks the newest Visual
|
|
REM Studio that has the ARM64 component: from an x64 machine that is the only way
|
|
REM to build arm64, as a cross build, and without it the failure would only appear
|
|
REM at CMake's compiler test. MSYS2 has no CLANGARM64 environment on an x64
|
|
REM machine; windows-arm64-clang says so and points at the cross-building presets.
|
|
REM
|
|
REM Left alone: a shell that is already a developer prompt for the right
|
|
REM architecture; any preset not listed (cmake reports an unknown one itself);
|
|
REM and everything, when PMN_NO_ENV is set to anything -- for a toolchain this script does
|
|
REM not know about, or a prompt you have set up yourself.
|
|
REM MSYS2 is looked for in MSYS2_ROOT, else the msys64 folder on the system
|
|
REM drive -- the same place breeze\scripts\setup.bat installs it.
|
|
REM
|
|
REM Exit status: 0 = ready, or nothing to do. 1 = the environment the preset
|
|
REM needs is not available, after saying what to install.
|
|
REM
|
|
REM Flat on purpose: single-line IF and GOTO, no parenthesized blocks. The paths
|
|
REM expanded here can contain "(x86)", and an unquoted close-paren ends a block
|
|
REM early.
|
|
|
|
if "%~1"=="" exit /b 0
|
|
if defined PMN_NO_ENV exit /b 0
|
|
|
|
set "_pmn_e_tgt="
|
|
set "_pmn_e_llvm="
|
|
set "_pmn_e_sub="
|
|
set "_pmn_e_exe="
|
|
set "_pmn_e_probe="
|
|
set "_pmn_e_pkg="
|
|
set "_pmn_e_vs="
|
|
set "_pmn_e_arg="
|
|
set "_pmn_e_need="
|
|
|
|
if /i "%~1"=="windows-x64-msvc" goto pick_msvc_x64
|
|
if /i "%~1"=="windows-arm64-msvc" goto pick_msvc_arm64
|
|
if /i "%~1"=="windows-x64-clang-cl" goto pick_clangcl_x64
|
|
if /i "%~1"=="windows-arm64-clang-cl" goto pick_clangcl_arm64
|
|
if /i "%~1"=="windows-x64-mingw64" goto pick_mingw64
|
|
if /i "%~1"=="windows-x86-mingw32" goto pick_mingw32
|
|
if /i "%~1"=="windows-x64-clang" goto pick_clang64
|
|
if /i "%~1"=="windows-arm64-clang" goto pick_clangarm64
|
|
goto env_ok
|
|
|
|
:pick_msvc_x64
|
|
set "_pmn_e_tgt=x64"
|
|
goto run_vs
|
|
:pick_msvc_arm64
|
|
set "_pmn_e_tgt=arm64"
|
|
goto run_vs
|
|
:pick_clangcl_x64
|
|
set "_pmn_e_tgt=x64"
|
|
set "_pmn_e_llvm=1"
|
|
goto run_vs
|
|
:pick_clangcl_arm64
|
|
set "_pmn_e_tgt=arm64"
|
|
set "_pmn_e_llvm=1"
|
|
goto run_vs
|
|
:pick_mingw64
|
|
set "_pmn_e_sub=mingw64"
|
|
set "_pmn_e_exe=g++.exe"
|
|
set "_pmn_e_probe=x86_64-w64-mingw32-g++"
|
|
set "_pmn_e_pkg=mingw-w64-x86_64-gcc"
|
|
goto run_msys
|
|
:pick_mingw32
|
|
set "_pmn_e_sub=mingw32"
|
|
set "_pmn_e_exe=g++.exe"
|
|
set "_pmn_e_probe=i686-w64-mingw32-g++"
|
|
set "_pmn_e_pkg=mingw-w64-i686-gcc"
|
|
goto run_msys
|
|
:pick_clang64
|
|
set "_pmn_e_sub=clang64"
|
|
set "_pmn_e_exe=clang++.exe"
|
|
set "_pmn_e_pkg=mingw-w64-clang-x86_64-clang"
|
|
goto run_msys
|
|
:pick_clangarm64
|
|
set "_pmn_e_sub=clangarm64"
|
|
set "_pmn_e_exe=clang++.exe"
|
|
set "_pmn_e_pkg=mingw-w64-clang-aarch64-clang"
|
|
goto run_msys
|
|
|
|
REM ---------------------------------------------------------------------
|
|
REM Visual Studio: msvc and clang-cl presets
|
|
REM ---------------------------------------------------------------------
|
|
:run_vs
|
|
if not defined VSCMD_VER goto vs_find
|
|
if /i "%VSCMD_ARG_TGT_ARCH%"=="%_pmn_e_tgt%" goto vs_have
|
|
goto vs_find
|
|
|
|
:vs_have
|
|
where cl >nul 2>nul
|
|
if errorlevel 1 goto vs_find
|
|
if defined VSINSTALLDIR set "_pmn_e_vs=%VSINSTALLDIR%"
|
|
goto vs_verify
|
|
|
|
:vs_find
|
|
set "_pmn_e_vs="
|
|
set "_pmn_e_vswhere=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
|
if not exist "%_pmn_e_vswhere%" goto vs_missing
|
|
|
|
REM Which component provides the target's compilers and libraries: the x86/x64
|
|
REM tools for x64, and for arm64 the ARM64 tools too -- an x64 machine reaches
|
|
REM arm64 through them (a cross build), and an ARM64 machine builds natively.
|
|
REM The newest install that has what the target needs wins, so an older Visual
|
|
REM Studio that has it beats a newer one that does not.
|
|
set "_pmn_e_need=Microsoft.VisualStudio.Component.VC.Tools.x86.x64"
|
|
if /i "%_pmn_e_tgt%"=="arm64" set "_pmn_e_need=Microsoft.VisualStudio.Component.VC.Tools.x86.x64 Microsoft.VisualStudio.Component.VC.Tools.ARM64"
|
|
for /f "usebackq delims=" %%I in (`"%_pmn_e_vswhere%" -latest -products * -requires %_pmn_e_need% -property installationPath`) do set "_pmn_e_vs=%%I"
|
|
if defined _pmn_e_vs goto vs_have_install
|
|
|
|
REM None has it. Is there a Visual Studio with C++ at all? Then it is only the
|
|
REM target's component that is missing, which has its own message.
|
|
for /f "usebackq delims=" %%I in (`"%_pmn_e_vswhere%" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do set "_pmn_e_vs=%%I"
|
|
if not defined _pmn_e_vs goto vs_missing
|
|
goto vs_target_missing
|
|
|
|
:vs_have_install
|
|
set "_pmn_e_vcvars=%_pmn_e_vs%\VC\Auxiliary\Build\vcvarsall.bat"
|
|
if not exist "%_pmn_e_vcvars%" goto vs_missing
|
|
|
|
REM vcvarsall's argument is HOST_TARGET, or just TARGET when the two match.
|
|
set "_pmn_e_host=%PROCESSOR_ARCHITECTURE%"
|
|
if defined PROCESSOR_ARCHITEW6432 set "_pmn_e_host=%PROCESSOR_ARCHITEW6432%"
|
|
if /i "%_pmn_e_host%"=="AMD64" goto vs_arg_amd64
|
|
if /i "%_pmn_e_host%"=="ARM64" goto vs_arg_arm64
|
|
set "_pmn_e_arg=x86_%_pmn_e_tgt%"
|
|
goto vs_enter
|
|
:vs_arg_amd64
|
|
if /i "%_pmn_e_tgt%"=="x64" set "_pmn_e_arg=x64"
|
|
if /i "%_pmn_e_tgt%"=="arm64" set "_pmn_e_arg=x64_arm64"
|
|
goto vs_enter
|
|
:vs_arg_arm64
|
|
if /i "%_pmn_e_tgt%"=="x64" set "_pmn_e_arg=arm64_x64"
|
|
if /i "%_pmn_e_tgt%"=="arm64" set "_pmn_e_arg=arm64"
|
|
goto vs_enter
|
|
|
|
REM Success is judged by what vcvarsall left behind -- the target it reports
|
|
REM and a cl on PATH, which is what the build needs -- not by its exit status.
|
|
:vs_enter
|
|
set "VSCMD_SKIP_SENDTELEMETRY=1"
|
|
echo ==^> Environment: Visual Studio developer prompt for %_pmn_e_tgt% ^(vcvarsall %_pmn_e_arg%^)
|
|
call "%_pmn_e_vcvars%" %_pmn_e_arg% >"%TEMP%\pmn-vcvarsall.log" 2>&1
|
|
if /i "%VSCMD_ARG_TGT_ARCH%"=="%_pmn_e_tgt%" goto vs_check_cl
|
|
goto vs_failed
|
|
:vs_check_cl
|
|
where cl >nul 2>nul
|
|
if errorlevel 1 goto vs_failed
|
|
if not defined VCToolsInstallDir goto vs_failed
|
|
goto vs_verify
|
|
|
|
REM The target's runtime libraries must exist: with the target's component
|
|
REM missing, vcvarsall can still report the target and leave a cl on PATH (the
|
|
REM host's x64 one), and the failure only shows up at CMake's compiler test as
|
|
REM "cannot open msvcrt.lib". This catches it first, with the fix.
|
|
:vs_verify
|
|
if not defined VCToolsInstallDir goto vs_after
|
|
if exist "%VCToolsInstallDir%lib\%_pmn_e_tgt%\msvcrt.lib" goto vs_after
|
|
goto vs_target_missing
|
|
|
|
:vs_after
|
|
del "%TEMP%\pmn-vcvarsall.log" >nul 2>nul
|
|
if not "%_pmn_e_llvm%"=="1" goto env_ok
|
|
where clang-cl >nul 2>nul
|
|
if not errorlevel 1 goto env_ok
|
|
set "_pmn_e_pf=%ProgramW6432%"
|
|
if not defined _pmn_e_pf set "_pmn_e_pf=%ProgramFiles%"
|
|
if exist "%_pmn_e_pf%\LLVM\bin\clang-cl.exe" goto llvm_standalone
|
|
if not defined _pmn_e_vs goto llvm_missing
|
|
if exist "%_pmn_e_vs%\VC\Tools\Llvm\x64\bin\clang-cl.exe" goto llvm_vs_x64
|
|
if exist "%_pmn_e_vs%\VC\Tools\Llvm\ARM64\bin\clang-cl.exe" goto llvm_vs_arm64
|
|
if exist "%_pmn_e_vs%\VC\Tools\Llvm\bin\clang-cl.exe" goto llvm_vs_x86
|
|
goto llvm_missing
|
|
|
|
:llvm_standalone
|
|
set "PATH=%_pmn_e_pf%\LLVM\bin;%PATH%"
|
|
echo ==^> Environment: clang-cl from %_pmn_e_pf%\LLVM\bin
|
|
goto env_ok
|
|
:llvm_vs_x64
|
|
set "PATH=%_pmn_e_vs%\VC\Tools\Llvm\x64\bin;%PATH%"
|
|
echo ==^> Environment: clang-cl from Visual Studio ^(VC\Tools\Llvm\x64\bin^)
|
|
goto env_ok
|
|
:llvm_vs_arm64
|
|
set "PATH=%_pmn_e_vs%\VC\Tools\Llvm\ARM64\bin;%PATH%"
|
|
echo ==^> Environment: clang-cl from Visual Studio ^(VC\Tools\Llvm\ARM64\bin^)
|
|
goto env_ok
|
|
:llvm_vs_x86
|
|
set "PATH=%_pmn_e_vs%\VC\Tools\Llvm\bin;%PATH%"
|
|
echo ==^> Environment: clang-cl from Visual Studio ^(VC\Tools\Llvm\bin^)
|
|
goto env_ok
|
|
|
|
:llvm_missing
|
|
echo error: preset %~1 needs clang-cl, and none was found on PATH, in %_pmn_e_pf%\LLVM\bin or in Visual Studio. 1>&2
|
|
echo Run breeze\scripts\setup.bat to install LLVM, or: winget install LLVM.LLVM 1>&2
|
|
goto env_fail
|
|
|
|
:vs_missing
|
|
echo error: preset %~1 needs Visual Studio or Build Tools with the C++ tools ^(workload "Desktop development with C++"^), and none was found. 1>&2
|
|
echo Run breeze\scripts\setup.bat to install it. If you use a Visual Studio this script cannot find, open its 1>&2
|
|
echo developer prompt for %_pmn_e_tgt% yourself and set PMN_NO_ENV=1. 1>&2
|
|
if /i "%_pmn_e_tgt%"=="arm64" echo For ARM64 targets add the "MSVC ARM64 build tools" component in the Visual Studio Installer. 1>&2
|
|
goto env_fail
|
|
|
|
:vs_target_missing
|
|
echo error: preset %~1 needs the MSVC tools and libraries for %_pmn_e_tgt%, and the Visual Studio install here does not have them. 1>&2
|
|
if defined VCToolsInstallDir echo %VCToolsInstallDir%lib\%_pmn_e_tgt%\msvcrt.lib is missing. 1>&2
|
|
if exist "%TEMP%\pmn-vcvarsall.log" type "%TEMP%\pmn-vcvarsall.log" 1>&2
|
|
if /i "%_pmn_e_tgt%"=="arm64" goto vs_target_missing_arm64
|
|
echo Add the component "MSVC ... C++ x64/x86 build tools (Latest)" in the Visual Studio Installer ^(Modify, Individual components^). 1>&2
|
|
goto env_fail
|
|
:vs_target_missing_arm64
|
|
echo Building for ARM64 -- from an x64 machine that is a cross build -- needs the component 1>&2
|
|
echo "MSVC ... C++ ARM64/ARM64EC build tools (Latest)". Run breeze\scripts\setup.bat, which offers to add it, or add it in the 1>&2
|
|
echo Visual Studio Installer: Modify, Individual components, search for ARM64. 1>&2
|
|
goto env_fail
|
|
|
|
:vs_failed
|
|
echo error: could not enter the Visual Studio environment for %_pmn_e_tgt% ^(vcvarsall %_pmn_e_arg%^). Its output: 1>&2
|
|
if exist "%TEMP%\pmn-vcvarsall.log" type "%TEMP%\pmn-vcvarsall.log" 1>&2
|
|
echo If this shell is already a developer prompt for another architecture, open a fresh one. 1>&2
|
|
if /i "%_pmn_e_tgt%"=="arm64" echo ARM64 targets need the "MSVC ARM64 build tools" component of Visual Studio. 1>&2
|
|
goto env_fail
|
|
|
|
REM ---------------------------------------------------------------------
|
|
REM MSYS2: mingw and clang presets
|
|
REM ---------------------------------------------------------------------
|
|
:run_msys
|
|
set "_pmn_e_root=%MSYS2_ROOT%"
|
|
if not defined _pmn_e_root set "_pmn_e_root=%SystemDrive%\msys64"
|
|
if not defined _pmn_e_probe goto msys_enter
|
|
where %_pmn_e_probe% >nul 2>nul
|
|
if not errorlevel 1 goto env_ok
|
|
|
|
:msys_enter
|
|
if not exist "%_pmn_e_root%\%_pmn_e_sub%\bin\%_pmn_e_exe%" goto msys_missing
|
|
set "PATH=%_pmn_e_root%\%_pmn_e_sub%\bin;%PATH%"
|
|
echo ==^> Environment: MSYS2 %_pmn_e_sub% ^(%_pmn_e_root%\%_pmn_e_sub%\bin first on PATH^)
|
|
goto env_ok
|
|
|
|
:msys_missing
|
|
if /i "%_pmn_e_sub%"=="clangarm64" goto msys_missing_arm
|
|
goto msys_missing_pkg
|
|
|
|
REM MSYS2 has a CLANGARM64 environment only on ARM64 Windows; on an x64 machine
|
|
REM there is nothing to install, so say what to use instead.
|
|
:msys_missing_arm
|
|
set "_pmn_e_host=%PROCESSOR_ARCHITECTURE%"
|
|
if defined PROCESSOR_ARCHITEW6432 set "_pmn_e_host=%PROCESSOR_ARCHITEW6432%"
|
|
if /i "%_pmn_e_host%"=="ARM64" goto msys_missing_pkg
|
|
echo error: preset %~1 needs MSYS2's CLANGARM64 environment, which MSYS2 provides only on ARM64 Windows ^(this machine is %_pmn_e_host%^). 1>&2
|
|
echo To build for Windows ARM64 from here use windows-arm64-clang-cl or windows-arm64-msvc: they cross-compile 1>&2
|
|
echo with Visual Studio's ARM64 build tools ^(breeze\scripts\setup.bat offers to add them^). 1>&2
|
|
goto env_fail
|
|
|
|
:msys_missing_pkg
|
|
echo error: preset %~1 needs MSYS2's %_pmn_e_sub% toolchain, and %_pmn_e_root%\%_pmn_e_sub%\bin\%_pmn_e_exe% was not found. 1>&2
|
|
echo Run breeze\scripts\setup.bat to install it, or in an MSYS2 shell: pacman -S %_pmn_e_pkg% 1>&2
|
|
echo MSYS2 itself: winget install MSYS2.MSYS2 ^(set MSYS2_ROOT if it lives somewhere other than the msys64 folder on the system drive^) 1>&2
|
|
goto env_fail
|
|
|
|
REM ---------------------------------------------------------------------
|
|
REM Exits. Every path out goes through one of these two, which clear the
|
|
REM scratch variables this script made (all start with _pmn_e_).
|
|
REM ---------------------------------------------------------------------
|
|
:env_ok
|
|
call :clear
|
|
exit /b 0
|
|
|
|
:env_fail
|
|
call :clear
|
|
exit /b 1
|
|
|
|
:clear
|
|
set "_pmn_e_tgt="
|
|
set "_pmn_e_llvm="
|
|
set "_pmn_e_sub="
|
|
set "_pmn_e_exe="
|
|
set "_pmn_e_probe="
|
|
set "_pmn_e_pkg="
|
|
set "_pmn_e_vs="
|
|
set "_pmn_e_arg="
|
|
set "_pmn_e_vswhere="
|
|
set "_pmn_e_vcvars="
|
|
set "_pmn_e_need="
|
|
set "_pmn_e_host="
|
|
set "_pmn_e_pf="
|
|
set "_pmn_e_root="
|
|
goto :eof
|