среда, 2 октября 2019 г.

Run Stm32CubeMX & STM32CubeProgrammer applications with OpenJDK on Windows

Stm32CubeMX требует наличие установленного OracleJRE/JDK и при его отсутствии в системе ругается, что не может найти JRE версии 1.8.0_45 или выше. Кубу всё равно на то, что у меня в системе есть OpenJDK (ставил разные версии, добавлял в PATH, не помогало) и мне на пару секунд даже показалось, что придётся сдаться и поставить ещё и OracleJRE (чего я очень не хотел), но на самом деле сдаваться рано )

Сначала попробовал изменить требуюмую версию Java в инсталлере куба, но понял, что это не помогает. Потом нашёл и "поставил" именно 1.8.0_45 но OpenJRE а не OracleJRE - всё равно не помогло. Потом нашёл некий интересный путь C:\ProgramData\Oracle\Java\javapath ! В нём лежат 3 симлинка на java.exe, javaw.exe, jawaws.exe.

Тут я решил, что "вот оно", мне надо эти симлинки создать на соответствующие exe файлы из моей версии OpenJRE. И создал. И не помогло ) Куб при установке ругался всё тем же сообщением.

Теперь я решил запустить java.exe через мой симлинк и о чудо, java ругнулась, что в реестре не хватает ветки. Я поставил OracleJDK, экспортнул ветку, удалил OracleJDK, импортнул ветку и подправил пути на свои, вычистив лишние ветки/ключи.

И всё заработало !

Моя версия OpenJDK лежит по такому пути: C:\openjdk-12.0.2

А вот текст .reg файла, которым можно указанный выше путь зарегистрировать в реестре:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\12.0.2]

"JavaHome"="C:\\openjdk-12.0.2"
"RuntimeLib"="C:\\openjdk-12.0.2\\bin\\server\\jvm.dll"
"MicroVersion"="0"
"BuildNumber"="10"


Насчёт необходимости ключей "MicroVersion"="0", "BuildNumber"="10" я не разбирался. Может они не нужны (так выглядит), но OracleJRE их создаёт. Хз, решил, что лучше оставить. Кто знает что в будущем может поломаться из за их отсутствия.


ОБНОВЛЕНИЕ:

STM32CubeProgrammer не захотел работать с хаком, описаным выше. Как оказалось, CubeProgrammer использует JavaFX, которого нет в официальной сборке OpenJDK. Почему-то за преемлимое время мне не удалось установить OpenJFX поверх OpenJDK, потому я пошёл другим путём и скачал OpenJDK сразу собранный вместе с OpenJFX.

Скачать можно вот по этой ссылке:  https://bell-sw.com/pages/java-13/

Архив с этим билдом JDK я распаковал в корень диска C

А вот контент .reg файла, регистрирующего установку этой версии JDK:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK]
"CurrentVersion"="13.0.0"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\JDK\10.0.2]
"JavaHome"="C:\\bellsoft-jdk13-windows-amd64\\jdk-13"


Здесь можно заметить, что ветка реестра содержит версию 10.0.2, а не 13.0.0.  Это важно, т.к. по этому имени STM32CubeProgrammer проверяет версию java, которая должна быть 1.8.0 - 10.99.99.  Приходится таким путём обманывать STM32CubeProgrammer, если хочется иметь в системе свежую версию JDK.

понедельник, 2 сентября 2019 г.

Как собирать С++ приложения в Windows C# кодом

Понадобилось тут собрать С++ 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 в текстовом виде, парсим и применяем в своё приложение.

//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");