Понадобилось тут собрать С++ Qmake приложение под Windows используя cl компилятор из под C# приложения. При этом хотелось не запускать это C# приложение из под VisualStudio comand prompt, а разрулить всё прямо в коде.
Обычно, для сборки приложения в консоли студийным компилятором, необходимо открыть VisualStudio command prompt и делать сборку там, либо вручную вызвать vcvars64.bat или vcvarsall.bat для настройки окружения, но тут есть 2 проблемы: 1. Как найти этот bat файл, 2. Как его запустить внутри C# приложения так, что бы он правильно настроил environment variables.
Решение:
1. Найти все VisualStudio >= 2017 можно при помощи приложения vswhere, которое ставится с VisualStudio installer
2. Находим VisualStudio при помощи vswhere, находим vcvars64.bat, выполняем bat файл, забирая себе его environment в текстовом виде, парсим и применяем в своё приложение.
Обычно, для сборки приложения в консоли студийным компилятором, необходимо открыть VisualStudio command prompt и делать сборку там, либо вручную вызвать vcvars64.bat или vcvarsall.bat для настройки окружения, но тут есть 2 проблемы: 1. Как найти этот bat файл, 2. Как его запустить внутри C# приложения так, что бы он правильно настроил environment variables.
Решение:
1. Найти все VisualStudio >= 2017 можно при помощи приложения vswhere, которое ставится с VisualStudio installer
2. Находим VisualStudio при помощи vswhere, находим vcvars64.bat, выполняем bat файл, забирая себе его environment в текстовом виде, парсим и применяем в своё приложение.
//Find vswhere path var programFilesDir = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); var vsInstallationDir = Path.Combine(programFilesDir, @"Microsoft Visual Studio", "Installer"); var vsWherePath = Path.Combine(vsInstallationDir, "vswhere.exe"); //Find latest VisualStudio installation directory var vsWhereResult = SystemProcess.Execute(vsWherePath, "-latest -property installationPath"); var vsInstallPath = vsWhereResult.outBuffer[0]; //Import VisualStudio environment var vsEnvBatchFile = Path.Combine(vsInstallPath, @"VC\Auxiliary\Build\vcvars64.bat"); var vsEnvResult = SystemProcess.Execute("cmd", $"/C \"{vsEnvBatchFile}\" > nul 2>&1 && set"); Regex envVariableRegex = new Regex("^([^=]+)=(.*)"); foreach(var str in vsEnvResult.outBuffer) { var match = envVariableRegex.Match(str); if (match.Success) { System.Environment.SetEnvironmentVariable(match.Groups[1].Value, match.Groups[2].Value); } }В коде вообще нет ни каких проверок, потестил просто как proof of concept. SystemProcess - мой мини враппер над System.Diagnostics.Process, запускает процесс и возвращает массив строк stdout, stderr и exit code. По хорошему надо делать не совсем так, необходимо применить лишь diff переменных окружения, но в моей задаче это было не нужно. А дальше просто собираем своё Qmake приложение:
//run qmake SystemProcess.Execute(@"C:\Qt\5.13.0\msvc2019_64_custom\bin\qmake.exe", proFileDir + " -spec win32-msvc \"CONFIG += release\""); //run nmake SystemProcess.Execute("nmake");
Комментариев нет:
Отправить комментарий