mirror of
https://github.com/jellyfin/jellyfin-desktop.git
synced 2026-10-26 16:45:24 +00:00
Bundle VC runtime DLLs for Windows installer
- Support user-level install (no admin required) - Bundle MSVC runtime DLLs from deps/vcruntime - Offer system-wide VCRedist install when running as admin - Add portable ZIP artifact (windows_zip target) - Add combined windows_all target for installer + ZIP
This commit is contained in:
1 parent
01a50a8bab
commit
747275054e
4 files changed
+118
-65
No files matched your search
@@ -6,6 +6,7 @@ CMakeLists.txt.user
|
||||
CMakeLists.txt.user.*
|
||||
build/*
|
||||
build_deps/*
|
||||
deps/*
|
||||
build_vs_debug/*
|
||||
.idea
|
||||
.install_pkg
|
||||
|
||||
@@ -48,6 +48,27 @@ else()
|
||||
message(STATUS "Not using separate ANGLE deps")
|
||||
endif()
|
||||
|
||||
# Bundle MSVC runtime DLLs (pre-extracted by setup-windows.bat)
|
||||
set(VCRUNTIME_DIR "@PROJECT_SOURCE_DIR@/deps/vcruntime")
|
||||
set(VCREDIST_EXE "@PROJECT_SOURCE_DIR@/deps/vc_redist.x64.exe")
|
||||
|
||||
if(EXISTS "${VCRUNTIME_DIR}" AND EXISTS "${VCREDIST_EXE}")
|
||||
# Copy runtime DLLs to redist subfolder
|
||||
file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/redist")
|
||||
file(GLOB RUNTIME_DLLS "${VCRUNTIME_DIR}/*.dll")
|
||||
foreach(dll_path ${RUNTIME_DLLS})
|
||||
get_filename_component(dll_name "${dll_path}" NAME)
|
||||
file(INSTALL "${dll_path}" DESTINATION "${CMAKE_INSTALL_PREFIX}/redist")
|
||||
message(STATUS "Bundled runtime: ${dll_name}")
|
||||
endforeach()
|
||||
|
||||
# Copy VCRedist installer for bundling
|
||||
file(INSTALL "${VCREDIST_EXE}" DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
message(STATUS "Bundled VCRedist installer: vc_redist.x64.exe")
|
||||
else()
|
||||
message(WARNING "VCRuntime DLLs not found. Run setup-windows.bat first.")
|
||||
endif()
|
||||
|
||||
if(@DO_SIGN@)
|
||||
file(GLOB_RECURSE EXES ${CMAKE_INSTALL_PREFIX}/*.exe ${CMAKE_INSTALL_PREFIX}/*.dll)
|
||||
set(ENV{errorlevel} 1)
|
||||
|
||||
@@ -59,4 +59,36 @@ add_custom_target(JellyfinDesktopInstaller
|
||||
# Alias target for convenience
|
||||
add_custom_target(windows_package DEPENDS JellyfinDesktopInstaller)
|
||||
|
||||
# Create portable ZIP archive (includes bundled runtime DLLs in root)
|
||||
set(ZIP_OUTPUT_NAME "${INSTALLER_BASE_NAME}.zip")
|
||||
set(ZIP_STAGING_DIR "${CMAKE_CURRENT_BINARY_DIR}/portable")
|
||||
|
||||
# Configure the prepare script
|
||||
configure_file(
|
||||
${PROJECT_SOURCE_DIR}/CMakeModules/PreparePortableZip.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/PreparePortableZip.cmake
|
||||
@ONLY
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ZIP_OUTPUT_NAME}
|
||||
DEPENDS innosetup_install ${CMAKE_CURRENT_BINARY_DIR}/PreparePortableZip.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/PreparePortableZip.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E tar cf ${CMAKE_CURRENT_BINARY_DIR}/${ZIP_OUTPUT_NAME} --format=zip .
|
||||
WORKING_DIRECTORY ${ZIP_STAGING_DIR}
|
||||
COMMENT "Building portable ZIP: ${ZIP_OUTPUT_NAME}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(JellyfinDesktopZip
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ZIP_OUTPUT_NAME}
|
||||
)
|
||||
|
||||
add_custom_target(windows_zip DEPENDS JellyfinDesktopZip)
|
||||
|
||||
# Combined target for both installer and ZIP
|
||||
add_custom_target(windows_all DEPENDS JellyfinDesktopInstaller JellyfinDesktopZip)
|
||||
|
||||
message(STATUS "Windows installer target configured: windows_package")
|
||||
message(STATUS "Windows portable ZIP target configured: windows_zip")
|
||||
message(STATUS "Windows combined target configured: windows_all")
|
||||
@@ -12,7 +12,6 @@
|
||||
#define MyAppExeName "Jellyfin Desktop.exe"
|
||||
#define MyAppGUID "{{a78bea4a-5bd0-4aa3-bdf3-579b4f58a921}"
|
||||
#define DeployPath "@CMAKE_INSTALL_PREFIX@"
|
||||
#define VCRedistURL "https://aka.ms/vs/17/release/vc_redist.x64.exe"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application.
|
||||
@@ -32,7 +31,8 @@ DisableProgramGroupPage=yes
|
||||
MinVersion=10.0
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
ArchitecturesAllowed=x64compatible
|
||||
PrivilegesRequired=admin
|
||||
PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputDir=.
|
||||
OutputBaseFilename=JellyfinDesktop-{#MyAppVersion}-windows-x64
|
||||
SetupIconFile=@PROJECT_SOURCE_DIR@/bundle/win/jellyfin.ico
|
||||
@@ -56,15 +56,20 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
||||
|
||||
[Files]
|
||||
Source: "{#DeployPath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; Main application files (exclude redist folder - handled separately)
|
||||
Source: "{#DeployPath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; Excludes: "redist,redist\*,vc_redist.x64.exe"
|
||||
; Bundled VC runtime DLLs - only copied if needed (see Code section)
|
||||
Source: "{#DeployPath}\redist\*.dll"; DestDir: "{app}"; Flags: ignoreversion; Check: NeedsBundledRuntime
|
||||
; Bundled VCRedist installer - extracted to temp for potential system-wide install
|
||||
Source: "{#DeployPath}\vc_redist.x64.exe"; DestDir: "{tmp}"; Flags: ignoreversion deleteafterinstall; Check: ShouldExtractVCRedist
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\Jellyfin Desktop"; Filename: "{app}\{#MyAppExeName}"; Comment: "Jellyfin desktop client"; WorkingDir: "{app}"
|
||||
Name: "{autodesktop}\Jellyfin Desktop"; Filename: "{app}\{#MyAppExeName}"; Comment: "Jellyfin desktop client"; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
; Install VCRedist - will be downloaded if needed
|
||||
Filename: "{tmp}\vcredist_x64.exe"; Parameters: "/install /passive /norestart"; StatusMsg: "Installing Visual C++ Redistributable..."; Flags: waituntilterminated; Check: VCRedistNeedsInstall
|
||||
; Install VCRedist if downloaded
|
||||
Filename: "{tmp}\vc_redist.x64.exe"; Parameters: "/install /passive /norestart"; StatusMsg: "Installing Visual C++ Redistributable..."; Flags: waituntilterminated; Check: ShouldInstallVCRedist
|
||||
; Launch app after install
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "Launch Jellyfin Desktop"; Flags: nowait postinstall skipifsilent
|
||||
|
||||
@@ -72,91 +77,85 @@ Filename: "{app}\{#MyAppExeName}"; Description: "Launch Jellyfin Desktop"; Flags
|
||||
const
|
||||
PF_AVX2_INSTRUCTIONS_AVAILABLE = 40;
|
||||
|
||||
var
|
||||
VCRedistNeedsInstallFlag: Boolean;
|
||||
|
||||
function IsProcessorFeaturePresent(ProcessorFeature: DWORD): BOOL;
|
||||
external 'IsProcessorFeaturePresent@kernel32.dll stdcall';
|
||||
|
||||
function VCRedistNeedsInstall: Boolean;
|
||||
begin
|
||||
Result := VCRedistNeedsInstallFlag;
|
||||
end;
|
||||
|
||||
function CheckVCRedist(): Boolean;
|
||||
var
|
||||
UCRTBasePath: String;
|
||||
MSVCPPath: String;
|
||||
begin
|
||||
UCRTBasePath := ExpandConstant('{sys}\ucrtbase.dll');
|
||||
MSVCPPath := ExpandConstant('{sys}\msvcp140.dll');
|
||||
RemoveUserData: Boolean;
|
||||
VCRedistNeeded: Boolean;
|
||||
InstallVCRedist: Boolean;
|
||||
UseBundledRuntime: Boolean;
|
||||
|
||||
// Good if ucrtbase.dll exists
|
||||
if FileExists(UCRTBasePath) then
|
||||
begin
|
||||
Result := True;
|
||||
Log('VCRedist OK: ucrtbase.dll found');
|
||||
end
|
||||
// Bad if msvcp140.dll exists but ucrtbase.dll doesn't (corrupted install)
|
||||
else if FileExists(MSVCPPath) then
|
||||
begin
|
||||
Result := False;
|
||||
Log('Bad VCRedist: msvcp140.dll exists but ucrtbase.dll missing');
|
||||
end
|
||||
else
|
||||
begin
|
||||
Result := False;
|
||||
Log('VCRedist not installed');
|
||||
end;
|
||||
function HasSystemVCRuntime: Boolean;
|
||||
begin
|
||||
Result := FileExists(ExpandConstant('{sys}\vcruntime140.dll'));
|
||||
end;
|
||||
|
||||
function NeedsBundledRuntime: Boolean;
|
||||
begin
|
||||
// Use bundled DLLs if: system doesn't have VCRedist AND (user install OR user declined VCRedist install)
|
||||
Result := UseBundledRuntime;
|
||||
end;
|
||||
|
||||
function ShouldExtractVCRedist: Boolean;
|
||||
begin
|
||||
// Extract bundled VCRedist to temp if: admin install AND system missing VCRedist AND user wants to install it
|
||||
Result := InstallVCRedist;
|
||||
end;
|
||||
|
||||
function ShouldInstallVCRedist: Boolean;
|
||||
begin
|
||||
// Run VCRedist installer if user chose to install it
|
||||
Result := InstallVCRedist;
|
||||
end;
|
||||
|
||||
function InitializeSetup(): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
|
||||
// Check VCRedist and set flag for download
|
||||
VCRedistNeedsInstallFlag := not CheckVCRedist();
|
||||
|
||||
if VCRedistNeedsInstallFlag then
|
||||
Log('VCRedist will be installed during setup');
|
||||
VCRedistNeeded := not HasSystemVCRuntime;
|
||||
InstallVCRedist := False;
|
||||
UseBundledRuntime := False;
|
||||
end;
|
||||
|
||||
function PrepareToInstall(var NeedsRestart: Boolean): String;
|
||||
var
|
||||
DownloadPage: TDownloadWizardPage;
|
||||
VCRedistPath: String;
|
||||
begin
|
||||
Result := '';
|
||||
NeedsRestart := False;
|
||||
|
||||
// Download VCRedist if needed
|
||||
if VCRedistNeedsInstallFlag then
|
||||
if not VCRedistNeeded then
|
||||
begin
|
||||
VCRedistPath := ExpandConstant('{tmp}\vcredist_x64.exe');
|
||||
Log('VCRedist already installed on system');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not FileExists(VCRedistPath) then
|
||||
// Check if running as admin
|
||||
if IsAdmin then
|
||||
begin
|
||||
// Offer to install VCRedist system-wide
|
||||
if MsgBox('Visual C++ Redistributable is not installed.' + #13#10 + #13#10 +
|
||||
'Would you like to install it system-wide?' + #13#10 +
|
||||
'(Recommended - receives security updates via Windows Update)' + #13#10 + #13#10 +
|
||||
'If you choose No, bundled runtime libraries will be used instead.',
|
||||
mbConfirmation, MB_YESNO) = IDYES then
|
||||
begin
|
||||
DownloadPage := CreateDownloadPage('Downloading Dependencies', 'Downloading required dependencies...', nil);
|
||||
DownloadPage.Clear;
|
||||
DownloadPage.Add('{#VCRedistURL}', 'vcredist_x64.exe', '');
|
||||
DownloadPage.Show;
|
||||
try
|
||||
DownloadPage.Download;
|
||||
except
|
||||
Result := 'Failed to download Visual C++ Redistributable.' + #13#10 +
|
||||
'Please check your internet connection and try again.';
|
||||
Exit;
|
||||
finally
|
||||
DownloadPage.Hide;
|
||||
end;
|
||||
InstallVCRedist := True;
|
||||
Log('Will install VCRedist system-wide');
|
||||
end
|
||||
else
|
||||
begin
|
||||
// User declined, use bundled
|
||||
Log('User declined VCRedist install, using bundled runtime');
|
||||
UseBundledRuntime := True;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Non-admin install, use bundled
|
||||
Log('Non-admin install, using bundled runtime');
|
||||
UseBundledRuntime := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
RemoveUserData: Boolean;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
FallbackPath: String;
|
||||
|
||||
Reference in new issue
Block a user