Friday, July 26, 2024

Automating MSVC builds

While rewritting a few of my personal tools from Rust back to C++, I found myself willing to automate the build process. At first, I tried to invoke MSVC’s cl compiler directly, but it has proven to be absolute hell to do.

Eventually I stumbled upon the marvellous MSBuild tool, which is capable of understanding the .sln file and take all compiler and linker options from it:

msbuild foo.sln /p:Configuration=Release /p:Platform=x64

With that, I could leverage vswhere to locate vcvars64.bat for any Visual Studio version, then write the script to automate one build:

@echo off
setlocal

for /f "usebackq delims=" %%i in (`
	"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ^
	-latest ^
	-property installationPath
`) do set VSBUILDROOT=%%i

if not defined VSBUILDROOT (
	echo Visual Studio not found.
	exit /b 1
)

call "%VSBUILDROOT%\VC\Auxiliary\Build\vcvars64.bat"

set APP="id3-fit"
msbuild %APP%.sln /p:Configuration=Release /p:Platform=x64
move /Y x64_Release\%APP%.exe "D:\Stuff\apps\_audio tools\"
rmdir /S /Q x64_Release
pause

Finally, it was time to automate the release build of all my listed projects:

@echo off
setlocal

for /f "usebackq delims=" %%i in (`
	"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ^
	-latest ^
	-property installationPath
`) do set VSBUILDROOT=%%i

if not defined VSBUILDROOT (
	echo Visual Studio not found.
	exit /b 1
)

call "%VSBUILDROOT%\VC\Auxiliary\Build\vcvars64.bat"
if errorlevel 1 exit /b 1

call :Deploy "id3-fit"      || exit /b 1
call :Deploy "sync-folders" || exit /b 1
call :Deploy "yt-dl"        || exit /b 1

pause
exit /b 0

:Deploy
	cd .\%~1
	msbuild %~1.slnx /p:Configuration=Release /p:Platform=x64
	if errorlevel 1 (
		echo Build failed: %~1
		cd ..
		pause
		exit /b 1
	)
	move /Y x64_Release\%~1.exe .\
	rmdir /S /Q x64_Release
	cd ..
	exit /b 0

The main point is that :Deploy is a subroutine – or a function –, with %~1 being the first argument, and exit /b being the return statement. Also, if one of the build fails, the script stops.

Friday, July 12, 2024

C++20 variadics with abbreviated function template

Today, when working with my stripped C++ Win32 library – after the frustration with Rust’s long compile times in WinSafe –, I was trying to implement an overloaded variadic method, in order to get rid of initializer_list. Then I stumbled upon a great article which introduced me to the abbreviated function template feature of C++20, which I’m using.

This is an example:

int foo(std::wstring n)
{
	OutputDebugStringW(n.data());
	OutputDebugStringW(L"\n");
	return 43;
}

int foo(std::wstring n, std::convertible_to<std::wstring> auto... nn)
{
	foo(n);
	return foo(nn...);
}

The convertible_to concept is particularly interesting in narrowing the template type.