build, meson, gitlab: Generate native .pdb CodeView symbols on Windows

Reverts dc21fb76

The CodeView format introduces some advantages to our Windows build:
- It is way smaller than DWARF, reducing the .exe installer. With
  the strip of COFF symbols too, the installation is 120MB smaller.
- Can be uploaded as .appxsym to be used on demand by MSIX (in thesis)
- Works better with DIA and DbgHelp debuggers like WinDbg and DrMingW,
  respectively. LLDB also works by using LLDB_USE_NATIVE_PDB_READER=1

Context: that was not working before because DrMingw and LLDB seems to
only search for the build-time .pdb path in '.buildid' section of bins.
See: https://github.com/jrfonseca/drmingw/issues/91 and
https://github.com/llvm/llvm-project/issues/125355. So, we will set
_NT_SYMBOL_PATH at least for $PREFIX/bin for now as workaround.
This commit is contained in:
Bruno Lopes 2025-04-13 14:50:37 -03:00
parent 19bb4a5251
commit 63f5ea9dc5
No known key found for this signature in database
11 changed files with 68 additions and 91 deletions

View file

@ -533,9 +533,6 @@ gimp-win-x86:
GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_STRATEGY: recursive
script: script:
- !reference [gimp-win, script] - !reference [gimp-win, script]
# We split 32-bit DWARF symbols here because LLVM-objcopy do NOT support them
- $env:Path = "$MSYS_ROOT/$MSYSTEM_PREFIX/bin;$MSYS_ROOT/usr/bin;" + $env:Path
- bash build/windows/installer/3_dist-gimp-inno_sym.sh gimp-$MSYSTEM_PREFIX
artifacts: !reference [gimp-win, artifacts] artifacts: !reference [gimp-win, artifacts]

View file

@ -53,6 +53,7 @@ void
gimp_init_signal_handlers (gchar **backtrace_file) gimp_init_signal_handlers (gchar **backtrace_file)
{ {
time_t t; time_t t;
gchar *codeview_path;
gchar *filename; gchar *filename;
gchar *dir; gchar *dir;
#if defined (G_OS_WIN32) && defined (HAVE_EXCHNDL) #if defined (G_OS_WIN32) && defined (HAVE_EXCHNDL)
@ -60,6 +61,12 @@ gimp_init_signal_handlers (gchar **backtrace_file)
#endif #endif
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
/* FIXME: https://github.com/jrfonseca/drmingw/issues/91 */
codeview_path = g_build_filename (gimp_installation_directory (),
"bin", NULL);
g_setenv ("_NT_SYMBOL_PATH", codeview_path, TRUE);
g_free (codeview_path);
/* This has to be the non-roaming directory (i.e., the local /* This has to be the non-roaming directory (i.e., the local
directory) as backtraces correspond to the binaries on this directory) as backtraces correspond to the binaries on this
system. */ system. */

View file

@ -218,11 +218,17 @@ for dep in "${libArray[@]}"; do
python3 $GIMP_SOURCE/build/windows/2_bundle-gimp-uni_dep.py $dep $MSYSTEM_PREFIX/ $GIMP_PREFIX/ $GIMP_DISTRIB --output-dll-list done-dll.list; python3 $GIMP_SOURCE/build/windows/2_bundle-gimp-uni_dep.py $dep $MSYSTEM_PREFIX/ $GIMP_PREFIX/ $GIMP_DISTRIB --output-dll-list done-dll.list;
done done
### .pdb (CodeView) debug symbols ### .pdb (CodeView) debug symbols from babl, gegl and GIMP binaries
### crossroad don't have LLVM/Clang backend yet bundle "$GIMP_PREFIX" bin/*.pdb
#if [ "$CI_JOB_NAME" != "gimp-win-x64-cross" ]; then ### Remove ancient COFF symbol table (not used for debugging) from MSYS2 binaries
# cp -fr ${GIMP_PREFIX}/bin/*.pdb ${GIMP_DISTRIB}/bin/ binArray=($(find $GIMP_DISTRIB \( -iname '*.dll' -or -iname '*.exe' -or -iname '*.pyd' \) -type f))
#fi for bin in "${binArray[@]}"; do
if [[ ! "$(grep -a RSDS $bin)" ]]; then
echo "(INFO): stripping COFF symbols from ${bin##*/}"
strip $bin
fi
done
## Development files (to build GEGL filters and GIMP plug-ins). ## Development files (to build GEGL filters and GIMP plug-ins).
clean "$GIMP_DISTRIB" lib/*.a clean "$GIMP_DISTRIB" lib/*.a

View file

@ -8,13 +8,19 @@ do
if [ x"$installed_bin" != "x" ]; then if [ x"$installed_bin" != "x" ]; then
install_dir=$(dirname ${installed_bin}) install_dir=$(dirname ${installed_bin})
pdb_debug=$(echo $build_bin|sed 's/\.\(dll\|exe\)$/.pdb/') pdb_debug=$(echo $build_bin|sed 's/\.\(dll\|exe\)$/.pdb/')
echo Installing $pdb_debug to $install_dir
# Clang correctly puts the .pdb along the $installed_bin
if [ -f "$pdb_debug" ]; then if [ -f "$pdb_debug" ]; then
# Note: meson hides script outputs anyway on success. But this can be
# useful when debugging.
echo Installing $pdb_debug to $install_dir
if [ -z "$MESON_INSTALL_DRY_RUN" ]; then if [ -z "$MESON_INSTALL_DRY_RUN" ]; then
cp -f $pdb_debug $install_dir cp -f $pdb_debug $install_dir
fi fi
# GCC dumbly puts the .pdb in $MESON_BUILD_ROOT
else
if [ -z "$MESON_INSTALL_DRY_RUN" ]; then
find . -name ${pdb_debug##*/} -exec cp -f "{}" $install_dir \;
fi
fi fi
fi fi
done; done;

View file

@ -208,24 +208,6 @@ $twain_list = (python3 build/windows/2_bundle-gimp-uni_dep.py --debug debug-only
(Get-Content $twain_list_file) | Select-string 'Installed' -notmatch | Set-Content $twain_list_file (Get-Content $twain_list_file) | Select-string 'Installed' -notmatch | Set-Content $twain_list_file
Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):installer_files$([char]13)$([char]27)[0K" Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):installer_files$([char]13)$([char]27)[0K"
## Do arch-specific things
foreach ($bundle in $supported_archs)
{
Write-Output "$([char]27)[0Ksection_start:$(Get-Date -UFormat %s -Millisecond 0):${bundle}_files[collapsed=true]$([char]13)$([char]27)[0KPreparing GIMP files in $bundle bundle"
## Split .debug symbols
if ("$bundle" -eq "$GIMP32")
{
#We do not split 32-bit DWARF symbols here (they were in gimp-win-x86 job)
Write-Output "(INFO): skipping (already done) $GIMP32 .debug extracting"
}
else
{
bash build/windows/installer/3_dist-gimp-inno_sym.sh $bundle
}
Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):${bundle}_files$([char]13)$([char]27)[0K"
}
# 5. COMPILE .EXE INSTALLER # 5. COMPILE .EXE INSTALLER
$INSTALLER="gimp-${CUSTOM_GIMP_VERSION}-setup.exe" $INSTALLER="gimp-${CUSTOM_GIMP_VERSION}-setup.exe"

View file

@ -1,32 +0,0 @@
#!/bin/bash
if [ ! "$1" ]; then
echo -e "\033[31m(ERROR)\033[0m: Script called without specifying a bundle. Please, call it this way: '$0 bundle_dir'."
exit 1
fi
# (we extract and link DWARF .debug symbols to
# make possible save space with Inno custom install)
echo "(INFO): extracting DWARF symbols from binaries in $1 bundle"
binArray=($(find $1 \( -iname '*.dll' -or -iname '*.exe' -or -iname '*.pyd' \) -type f))
for bin in "${binArray[@]}"; do
debug=$(echo "${bin}.debug")
NAME="${bin##*/}"
DIR="${debug%/*}/.debug/"
if [ ! -f "$DIR/$NAME.debug" ]; then
## Split/extract DWARF symbols from binary to .debug
#echo "(INFO): extracting DWARF symbols from $NAME to $DIR"
objcopy --only-keep-debug $bin $debug
## Link .debug to binary
objcopy --add-gnu-debuglink=$debug $bin --strip-unneeded
## Move .debug files to .debug folder
if [ ! -d "$DIR" ]; then
mkdir "$DIR"
fi
mv "$debug" "$DIR"
fi
done

View file

@ -29,12 +29,12 @@ Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\*.dll"; DestDir: "{app}\lib\gimp"; Componen
Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\*.exe"; DestDir: "{app}\lib\gimp"; Excludes: "{#OPTIONAL_EXE}"; Components: gimp{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\*.exe"; DestDir: "{app}\lib\gimp"; Excludes: "{#OPTIONAL_EXE}"; Components: gimp{#COMPONENT}; Flags: {#COMMON_FLAGS}
Source: "{#GIMP_DIR}\{#DIR}\lib\girepository-1.0\Gimp*.typelib"; DestDir: "{app}\lib\girepository-1.0"; Components: gimp{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR}\{#DIR}\lib\girepository-1.0\Gimp*.typelib"; DestDir: "{app}\lib\girepository-1.0"; Components: gimp{#COMPONENT}; Flags: {#COMMON_FLAGS}
Source: "{#DEPS_DIR}\{#DDIR}\bin\*"; DestDir: "{app}\bin"; Excludes: "libgimp*.dll,gimp*.exe,*.debug,{#OPTIONAL_DLL},{#OPTIONAL_EXE}"; Components: deps{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#DEPS_DIR}\{#DDIR}\bin\*"; DestDir: "{app}\bin"; Excludes: "libgimp*.dll,gimp*.exe,*.pdb,{#OPTIONAL_DLL},{#OPTIONAL_EXE}"; Components: deps{#COMPONENT}; Flags: {#COMMON_FLAGS}
Source: "{#DEPS_DIR}\{#DDIR}\lib\*"; DestDir: "{app}\lib"; Excludes: "gimp,Gimp*.typelib,*.debug,*.a,*.pc,lua,gluas.dll,python3.12"; Components: deps{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#DEPS_DIR}\{#DDIR}\lib\*"; DestDir: "{app}\lib"; Excludes: "gimp,Gimp*.typelib,*.pdb,*.a,*.pc,lua,gluas.dll,python3.12"; Components: deps{#COMPONENT}; Flags: {#COMMON_FLAGS}
;Optional arch-specific components (full installation) ;Optional arch-specific components (full installation)
#ifdef DEBUG_SYMBOLS #ifdef DEBUG_SYMBOLS
Source: "{#GIMP_DIR}\{#DIR}\*.debug"; DestDir: "{app}"; Components: debug{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR}\{#DIR}\*.pdb"; DestDir: "{app}"; Components: debug{#COMPONENT}; Flags: {#COMMON_FLAGS}
#endif #endif
Source: "{#GIMP_DIR}\{#DIR}\*.h"; DestDir: "{app}"; Components: dev{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR}\{#DIR}\*.h"; DestDir: "{app}"; Components: dev{#COMPONENT}; Flags: {#COMMON_FLAGS}
@ -54,5 +54,5 @@ Source: "{#DEPS_DIR}\{#DDIR}\lib\gluas.dll"; DestDir: "{app}\lib"; Components: l
#ifdef PYTHON #ifdef PYTHON
Source: "{#DEPS_DIR}\{#DDIR}\bin\libpython*.dll"; DestDir: "{app}\bin"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#DEPS_DIR}\{#DDIR}\bin\libpython*.dll"; DestDir: "{app}\bin"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS}
Source: "{#DEPS_DIR}\{#DDIR}\bin\python*.exe"; DestDir: "{app}\bin"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS} Source: "{#DEPS_DIR}\{#DDIR}\bin\python*.exe"; DestDir: "{app}\bin"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS}
Source: "{#DEPS_DIR}\{#DDIR}\lib\python3.12\*"; DestDir: "{app}\lib\python3.12"; Excludes: "*.debug,*.py"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS} createallsubdirs Source: "{#DEPS_DIR}\{#DDIR}\lib\python3.12\*"; DestDir: "{app}\lib\python3.12"; Excludes: "*.pdb,*.py"; Components: py{#COMPONENT}; Flags: {#COMMON_FLAGS} createallsubdirs
#endif #endif

View file

@ -312,7 +312,7 @@ Source: "{#ASSETS_DIR}\installsplash_small.bmp"; Flags: dontcopy
;Required arch-neutral files (compact install) ;Required arch-neutral files (compact install)
#define GIMP_ARCHS="gimp32 or gimp64 or gimpARM64" #define GIMP_ARCHS="gimp32 or gimp64 or gimpARM64"
#define OPTIONAL_EXT="*.debug,*.lua,*.py" #define OPTIONAL_EXT="*.pdb,*.lua,*.py"
Source: "{#GIMP_DIR32}\etc\gimp\*"; DestDir: "{app}\etc\gimp"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR32}\etc\gimp\*"; DestDir: "{app}\etc\gimp"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS}
Source: "{#GIMP_DIR32}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\environ\default.env"; DestDir: "{app}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\environ"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR32}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\environ\default.env"; DestDir: "{app}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\environ"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS}
Source: "{#GIMP_DIR32}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\interpreters\gimp-script-fu-interpreter.interp"; DestDir: "{app}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\interpreters"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS} Source: "{#GIMP_DIR32}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\interpreters\gimp-script-fu-interpreter.interp"; DestDir: "{app}\lib\gimp\{#GIMP_PKGCONFIG_VERSION}\interpreters"; Components: {#GIMP_ARCHS}; Flags: {#COMMON_FLAGS}
@ -1331,7 +1331,7 @@ begin
end; end;
end; end;
//remove .debug files from previous installs //remove .pdb files from previous installs
//there's no built-in way in Inno to recursively delete files with wildcard+extension //there's no built-in way in Inno to recursively delete files with wildcard+extension
procedure RemoveDebugFilesFromDir(pDir: String; var pDirectories: TArrayOfString); procedure RemoveDebugFilesFromDir(pDir: String; var pDirectories: TArrayOfString);
var FindRec: TFindRec; var FindRec: TFindRec;
@ -1344,11 +1344,19 @@ begin
repeat repeat
if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
begin begin
//Up to GIMP 3.0.2 we shipped only DWARF .debug symbols
if (Length(FindRec.Name) > 6) and (LowerCase(Copy(FindRec.Name, Length(FindRec.Name) - 5, 6)) = '.debug') then if (Length(FindRec.Name) > 6) and (LowerCase(Copy(FindRec.Name, Length(FindRec.Name) - 5, 6)) = '.debug') then
begin begin
DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name); DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name);
DeleteFile(AddBackSlash(pDir) + FindRec.Name); DeleteFile(AddBackSlash(pDir) + FindRec.Name);
end; end;
//Starting with GIMP 3.0.4 we ship native CodeView .pdb symbols
if (Length(FindRec.Name) > 4) and (LowerCase(Copy(FindRec.Name, Length(FindRec.Name) - 3, 4)) = '.pdb') then
begin
DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name);
DeleteFile(AddBackSlash(pDir) + FindRec.Name);
end;
end else end else
begin begin
if (FindRec.Name <> '.') and (FindRec.Name <> '..') then if (FindRec.Name <> '.') and (FindRec.Name <> '..') then

View file

@ -287,22 +287,18 @@ foreach ($bundle in $supported_archs)
## Remove uneeded files (to match the Inno Windows Installer artifact) ## Remove uneeded files (to match the Inno Windows Installer artifact)
Get-ChildItem "$vfs" -Recurse -Include (".gitignore", "gimp.cmd") | Remove-Item -Recurse Get-ChildItem "$vfs" -Recurse -Include (".gitignore", "gimp.cmd") | Remove-Item -Recurse
## Remove uncompliant files (to avoid WACK/'signtool' issues)
Get-ChildItem "$vfs" -Recurse -Include ("*.debug", "*.tar") | Remove-Item -Recurse
# 5.A. MAKE .MSIX AND CORRESPONDING .APPXSYM # 5.A. MAKE .MSIX AND CORRESPONDING .APPXSYM
## Make .appxsym for each msix_arch (ONLY FOR RELEASES) ## Make .appxsym for each msix_arch (ONLY FOR RELEASES)
$APPXSYM = "${IDENTITY_NAME}_${CUSTOM_GIMP_VERSION}_$msix_arch.appxsym" $APPXSYM = "${IDENTITY_NAME}_${CUSTOM_GIMP_VERSION}_$msix_arch.appxsym"
#if ($GIMP_RELEASE -and -not $GIMP_IS_RC_GIT) if ($CI_COMMIT_TAG -match 'GIMP_[0-9]*_[0-9]*_[0-9]*' -or $GIMP_CI_MS_STORE -like 'MSIXUPLOAD*')
# { {
# Write-Output "(INFO): putting .pdb symbols into $APPXSYM" Write-Output "(INFO): making $APPXSYM"
# Get-ChildItem $msix_arch -Filter *.pdb -Recurse | Get-ChildItem $msix_arch -Filter *.pdb -Recurse | Compress-Archive -DestinationPath "$APPXSYM.zip"
# Compress-Archive -DestinationPath "${IDENTITY_NAME}_${CUSTOM_GIMP_VERSION}_$msix_arch.zip" Get-ChildItem *.zip | Rename-Item -NewName $APPXSYM
# Get-ChildItem *.zip | Rename-Item -NewName $APPXSYM Get-ChildItem $msix_arch -Include *.pdb -Recurse -Force | Remove-Item -Recurse -Force
# Get-ChildItem $msix_arch -Include *.pdb -Recurse -Force | Remove-Item -Recurse -Force }
# }
## Make .msix from each msix_arch ## Make .msix from each msix_arch
$MSIX_ARTIFACT = $APPXSYM -replace '.appxsym','.msix' $MSIX_ARTIFACT = $APPXSYM -replace '.appxsym','.msix'
@ -338,10 +334,10 @@ if (((Test-Path $a64_bundle) -and (Test-Path $x64_bundle)) -and (Get-ChildItem *
if ($GIMP_RELEASE -and -not $GIMP_IS_RC_GIT) if ($GIMP_RELEASE -and -not $GIMP_IS_RC_GIT)
{ {
Write-Output "(INFO): creating $MSIXUPLOAD for submission" Write-Output "(INFO): creating $MSIXUPLOAD for submission"
Get-ChildItem *.msixbundle | ForEach-Object { Compress-Archive -Path "$($_.Basename).msixbundle" -DestinationPath "$($_.Basename).zip" } Compress-Archive -Path "*.appxsym","*.msixbundle" -DestinationPath "$MSIXUPLOAD.zip"
Get-ChildItem ${IDENTITY_NAME}*.zip | Rename-Item -NewName $MSIXUPLOAD Get-ChildItem ${IDENTITY_NAME}*.zip | Rename-Item -NewName $MSIXUPLOAD
#Get-ChildItem *.appxsym | Remove-Item -Recurse -Force Remove-Item *.appxsym -Force
Get-ChildItem *.msixbundle | Remove-Item -Recurse -Force Remove-Item *.msixbundle -Force
} }
Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):msix_making$([char]13)$([char]27)[0K" Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):msix_making$([char]13)$([char]27)[0K"
} }

View file

@ -226,10 +226,17 @@ gimp_main (GType plug_in_type,
/* Use Dr. Mingw (dumps backtrace on crash) if it is available. */ /* Use Dr. Mingw (dumps backtrace on crash) if it is available. */
{ {
time_t t; time_t t;
gchar *codeview_path;
gchar *filename; gchar *filename;
gchar *dir; gchar *dir;
wchar_t *plug_in_backtrace_path_utf16; wchar_t *plug_in_backtrace_path_utf16;
/* FIXME: https://github.com/jrfonseca/drmingw/issues/91 */
codeview_path = g_build_filename (gimp_installation_directory (),
"bin", NULL);
g_setenv ("_NT_SYMBOL_PATH", codeview_path, TRUE);
g_free (codeview_path);
/* This has to be the non-roaming directory (i.e., the local /* This has to be the non-roaming directory (i.e., the local
* directory) as backtraces correspond to the binaries on this * directory) as backtraces correspond to the binaries on this
* system. * system.

View file

@ -333,12 +333,12 @@ if platform_windows and cc.get_id() == 'clang'
compiler_args += '-fansi-escape-codes' compiler_args += '-fansi-escape-codes'
endif endif
# Generate .pdb (CodeView) debug symbols (makes possible to debug with DIA SDK) # Generate native .pdb (CodeView) debug symbols (for DIA or DbgHelp debuggers and LLDB)
#pdb_support = cc.has_argument('-gcodeview') and cc.has_link_argument('-Wl,--pdb=') pdb_support = cc.has_argument('-gcodeview') and cc.has_link_argument('-Wl,--pdb=')
#if platform_windows and pdb_support if platform_windows and pdb_support
# compiler_args += '-gcodeview' compiler_args += '-gcodeview'
# linker_args += '-Wl,--pdb=' linker_args += '-Wl,--pdb='
#endif endif
conf.set('HAVE__NL_MEASUREMENT_MEASUREMENT', conf.set('HAVE__NL_MEASUREMENT_MEASUREMENT',
@ -2140,10 +2140,10 @@ pkgconfig.generate(libgimpui,
# Install native debug data (.pdb) on Windows # Install native debug data (.pdb) on Windows
# Ideally meson should take care of it automatically. # Ideally meson should take care of it automatically.
# See: https://github.com/mesonbuild/meson/issues/12977 # See: https://github.com/mesonbuild/meson/issues/12977
#if platform_windows and pdb_support if platform_windows and pdb_support
# install_win_debug_script = find_program('./meson_install_win_debug.sh') install_win_debug_script = find_program('build/windows/2_bundle-gimp-uni_sym.sh')
# meson.add_install_script(install_win_debug_script) meson.add_install_script(install_win_debug_script)
#endif endif
# On Windows, install deps in a bundle before distributing # On Windows, install deps in a bundle before distributing
if get_option('windows-installer') or get_option('ms-store') if get_option('windows-installer') or get_option('ms-store')