Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

重构 HMCLauncher #3007

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
51b4108
Feature: Support scanning Java from HMCL_JAVA_HOME, JAVA_HOME, PATH a…
burningtnt Apr 26, 2024
7595604
Fix: I forget to remove /* and */. Refactor java.h.
burningtnt Apr 26, 2024
bd04465
Remove useless function.
burningtnt Apr 26, 2024
24b9aae
尝试性的为HMCLauncher添加cmake及gcc支持
YSXX1013 Apr 27, 2024
b63bde4
完善cmake及gcc支持
YSXX1013 Apr 27, 2024
853876c
尝试支持Github Actions
YSXX1013 Apr 27, 2024
185c674
尝试支持Github Actions-2
YSXX1013 Apr 27, 2024
88870c2
尝试支持Github Actions-3
YSXX1013 Apr 27, 2024
e0e30ff
尝试支持Github Actions-4
YSXX1013 Apr 27, 2024
abadd2a
尝试支持Github Actions-5
YSXX1013 Apr 27, 2024
eb95ce4
Merge branch 'HMCL-dev:main' into main
YSXX1013 May 8, 2024
5fdd6f2
Merge branch 'HMCL-dev:main' into main
YSXX1013 May 16, 2024
c8fa232
Merge branch 'HMCL-dev:main' into main
YSXX1013 Jun 3, 2024
89d2bf0
Merge branch 'refs/heads/YSXX1013/main' into feature/refactor-hmclaun…
burningtnt Jun 15, 2024
17d684e
Rrovide a built HMCLauncher.exe
burningtnt Jun 15, 2024
0df1f1d
Feature: Using java from .hmcl/runtime/bin/javaw.exe
burningtnt Jul 5, 2024
46f1984
Feature: Download JRE and detect broken JVM.
burningtnt Jul 22, 2024
8b1c3f5
Fix: msbuild compiling.
burningtnt Jul 22, 2024
9e722ce
Update install.cpp
burningtnt Jul 24, 2024
b7c7ceb
Remove useless functions and Recompile HMCLauncher.
burningtnt Jul 28, 2024
ce87c91
Merge remote-tracking branch 'refs/remotes/official/main' into featur…
burningtnt Nov 1, 2024
cee22d6
Recompile HMCLauncher
burningtnt Nov 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/build-launcher(cmake-gcc).yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Build HMCLauncher (Using CMake and gcc)

on:
push:
paths:
- 'HMCLauncher/**'
- '.github/workflows/build-launcher(cmake-gcc).yml'
pull_request:
paths:
- 'HMCLauncher/**'
- '.github/workflows/build-launcher(cmake-gcc).yml'

jobs:
build:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
steps:
- name: 'Setup MSYS2'
uses: msys2/setup-msys2@v2
with:
msystem: mingw32
update: true
install: >-
mingw-w64-i686-toolchain
mingw-w64-i686-ninja
mingw-w64-i686-cmake
git
- name: 'Checkout'
uses: actions/checkout@v4
- name: Build HMCLauncher
run: |
cmake -S ./HMCLauncher/HMCL -B ./HMCLauncher/HMCL/build -DCMAKE_BUILD_TYPE=Release
cmake --build ./HMCLauncher/HMCL/build
- name: Copy HMCLauncher to assets
run: cp ./HMCLauncher/HMCL/build/HMCLauncher.exe ./HMCL/src/main/resources/assets/HMCLauncher.exe
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '11'
java-package: 'jdk+fx'
- name: Build with Gradle
run: ./gradlew makeExecutables --no-daemon
env:
MICROSOFT_AUTH_ID: ${{ secrets.MICROSOFT_AUTH_ID }}
MICROSOFT_AUTH_SECRET: ${{ secrets.MICROSOFT_AUTH_SECRET }}
CURSEFORGE_API_KEY: ${{ secrets.CURSEFORGE_API_KEY }}
- name: Get short SHA
uses: benjlevesque/[email protected]
with:
length: 7
- name: Copy HMCLauncher to libs
run: cp ./HMCLauncher/HMCL/build/HMCLauncher.exe ./HMCL/build/libs/HMCLauncher.exe
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: HMCLauncher-${{ env.SHA }}
path: HMCL/build/libs/*.exe
Binary file modified HMCL/src/main/resources/assets/HMCLauncher.exe
Binary file not shown.
20 changes: 20 additions & 0 deletions HMCLauncher/HMCL/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.25)
project(HMCLauncher)
if(MSVC)
add_compile_options(/utf-8 /D_UNICODE /W4)
else()
add_compile_options(-municode -Wall -Wextra -Wpedantic)
endif()
if(MSVC)
add_link_options(/ENTRY:wWinMainCRTStartup)
else()
add_link_options(-municode)
endif()
OPTION(ENABLE_MINGW_STATIC_LINK_LIBSTDCXX "Link the C++ standard library statically to the executable file(mingw only)." ON)
if(ENABLE_MINGW_STATIC_LINK_LIBSTDCXX AND MINGW)
add_link_options(-static)
endif()
set(CMAKE_WIN32_EXECUTABLE ON)
add_executable(HMCLauncher WIN32 HMCL.rc java.cpp main.cpp os.cpp stdafx.cpp Version.cpp)
target_link_libraries(HMCLauncher Version)
install(TARGETS HMCLauncher)
6 changes: 6 additions & 0 deletions HMCLauncher/HMCL/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ class Version {
if (ver[i] != other.ver[i]) return ver[i] < other.ver[i];
return true;
}

bool operator>=(const Version &other) const {
for (int i = 0; i < 4; ++i)
if (ver[i] != other.ver[i]) return ver[i] > other.ver[i];
return true;
}
};
170 changes: 140 additions & 30 deletions HMCLauncher/HMCL/java.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,94 @@

const Version JAVA_8(L"1.8"), JAVA_11(L"11");

const LPCWSTR JDK_NEW = L"SOFTWARE\\JavaSoft\\JDK";
const LPCWSTR JRE_NEW = L"SOFTWARE\\JavaSoft\\JRE";
const LPCWSTR JDK_OLD = L"SOFTWARE\\JavaSoft\\Java Development Kit";
const LPCWSTR JRE_OLD = L"SOFTWARE\\JavaSoft\\Java Runtime Environment";
const LPCWSTR JDK_HKEYS[] = {L"SOFTWARE\\JavaSoft\\JDK",
L"SOFTWARE\\JavaSoft\\JRE",
L"SOFTWARE\\JavaSoft\\Java Development Kit",
L"SOFTWARE\\JavaSoft\\Java Runtime Environment"};

bool oldJavaFound = false;
const LPCWSTR VENDOR_DIRS[] = {L"Java", L"Microsoft", L"BellSoft",
L"Zulu", L"Eclipse Foundation", L"AdoptOpenJDK",
L"Semeru"};

bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring& path) {
const LPCWSTR PROGRAM_DIRS[] = {L"ProgramFiles", L"ProgramFiles(x86)",
L"ProgramW6432"};

/* Here we find the java from Environment Variable and Registry, which is fast,
* and store the result to 'path'. */
void ScanJava(std::wstring& result, int& status) {
status = JAVA_STATUS_NOT_FOUND;

// If 'HMCL_JAVA_HOME' is settled, this value MUST be used without any check.
if (ERROR_SUCCESS == MyGetEnvironmentVariable(L"HMCL_JAVA_HOME", result)) {
MyPathNormalize(result);
status = JAVA_STATUS_BEST;
return;
}

std::wstring currentResult;
if (ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", currentResult)) {
MyPathNormalize(result);
if (DeterminJavaHome(currentResult, result, status) &&
status == JAVA_STATUS_BEST) {
return;
}
}

for (LPCWSTR hkey : JDK_HKEYS) {
ScanJavaRegistry(HKEY_LOCAL_MACHINE, hkey, result, status);
if (status == JAVA_STATUS_BEST) {
return;
}
}

std::wstring envPath;
if (ERROR_SUCCESS == MyGetEnvironmentVariable(L"PATH", envPath)) {
int length = envPath.size();
int lastI = 0;
for (int i = 0; i < length; i++) {
if (envPath[i] == L';') {
int partL = i - lastI;
if (partL > 0) {
std::wstring part = envPath.substr(lastI, partL);
MyPathNormalize(part);
MyPathAddBackslash(part);
int partL2 = part.size();
if (part[partL2 - 5] == L'\\' && part[partL2 - 4] == L'b' &&
part[partL2 - 3] == L'i' && part[partL2 - 2] == L'n' &&
part[partL2 - 1] == L'\\') {
part.resize(partL2 - 5);
if (DeterminJavaHome(part, result, status) && status == JAVA_STATUS_BEST) {
return;
}
}
}

lastI = i + 1;
}
}
}

std::wstring root;
for (LPCWSTR program : PROGRAM_DIRS) {
if (ERROR_SUCCESS != MyGetEnvironmentVariable(program, root)) {
continue;
}

MyPathNormalize(root);
for (LPCWSTR vender : VENDOR_DIRS) {
std::wstring currentRoot = root + L"";
MyPathAppend(currentRoot, vender);
MyPathAddBackslash(currentRoot);
ScanJavaFolder(currentRoot, result, status);
if (status == JAVA_STATUS_BEST) {
return;
}
}
}
}

void ScanJavaRegistry(HKEY rootKey, LPCWSTR subKey, std::wstring& path,
int& status) {
WCHAR javaVer[MAX_KEY_LENGTH]; // buffer for subkey name, special for
// JavaVersion
DWORD cbName; // size of name string
Expand All @@ -25,9 +105,10 @@ bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring& path) {

HKEY hKey;
if (ERROR_SUCCESS !=
(result =
RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ, &hKey)))
return false;
(result = RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ,
&hKey))) {
return;
}

RegQueryInfoKey(hKey, // key handle
NULL, // buffer for class name
Expand All @@ -42,9 +123,10 @@ bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring& path) {
NULL, // security descriptor
NULL); // last write time

if (!cSubKeys) return false;
if (!cSubKeys) {
return;
}

bool flag = false;
for (DWORD i = 0; i < cSubKeys; ++i) {
cbName = MAX_KEY_LENGTH;
if (ERROR_SUCCESS != (result = RegEnumKeyEx(hKey, i, javaVer, &cbName, NULL,
Expand All @@ -55,30 +137,58 @@ bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring& path) {
if (ERROR_SUCCESS != RegOpenKeyEx(hKey, javaVer, 0, KEY_READ, &javaKey))
continue;

if (ERROR_SUCCESS == MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, path)) {
if (Version(javaVer) < JAVA_8)
oldJavaFound = true;
else
flag = true;
}
std::wstring currentPath;
if (ERROR_SUCCESS ==
MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, currentPath)) {
MyPathNormalize(currentPath);
Version v = Version(javaVer);

if (flag) break;
if (status < JAVA_STATUS_BEST && v >= JAVA_11) {
path = currentPath;
status = JAVA_STATUS_BEST;
break;
} else if (status < JAVA_STATUS_USABLE && v >= JAVA_8) {
path = currentPath;
status = JAVA_STATUS_USABLE;
}
}
}

RegCloseKey(hKey);

return flag;
}

bool FindJavaInRegistry(std::wstring& path) {
return FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_NEW, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_NEW, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_OLD, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_OLD, path);
}
void ScanJavaFolder(std::wstring root, std::wstring& result, int& status) {
WIN32_FIND_DATA data;
HANDLE hFind =
FindFirstFile((root + L"*").c_str(), &data); // Search all subdirectory

bool FindJava(std::wstring& path) {
return ERROR_SUCCESS == MyGetEnvironmentVariable(L"HMCL_JAVA_HOME", path) ||
ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", path) ||
FindJavaInRegistry(path);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (DeterminJavaHome(root + data.cFileName, result, status) && status == JAVA_STATUS_BEST) {
goto done;
}
} while (FindNextFile(hFind, &data));

done:
FindClose(hFind);
}
}

boolean DeterminJavaHome(std::wstring target, std::wstring& result, int& status) {
Version version(L"");
std::wstring currentRoot = target + L"";
MyPathAppend(currentRoot, std::wstring(L"bin\\javaw.exe"));

if (!MyGetFileVersionInfo(currentRoot, version)) return false;

if (status < JAVA_STATUS_BEST && version >= JAVA_11) {
result = target;
status = JAVA_STATUS_BEST;
return true;
} else if (status < JAVA_STATUS_USABLE && version >= JAVA_8) {
result = target;
status = JAVA_STATUS_USABLE;
return true;
}
return false;
}
17 changes: 13 additions & 4 deletions HMCLauncher/HMCL/java.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@
#include <windows.h>
#include <string>

// Find Java installation in system registry
bool FindJavaInRegistry(std::wstring &path);
// These increasing values represent the priority of the Java.
// Be careful while changing their values!
const int JAVA_STATUS_NOT_FOUND = 0;
const int JAVA_STATUS_USABLE = 1; // Java 8 - 11 (Exclude)
const int JAVA_STATUS_BEST = 2; // Java 11 (Include) - ++

// Find Java Installation in registry and environment variable
bool FindJava(std::wstring &path);
void ScanJava(std::wstring& result, int& status);

void ScanJavaRegistry(HKEY rootKey, LPCWSTR subKey, std::wstring& path,
int& status);

void ScanJavaFolder(std::wstring root, std::wstring& result, int& status);

boolean DeterminJavaHome(std::wstring target, std::wstring& result, int& status);
Loading