From 63f5ea9dc56c72915ae7144f8146fa1dbd00d920 Mon Sep 17 00:00:00 2001 From: Bruno Lopes Date: Sun, 13 Apr 2025 14:50:37 -0300 Subject: [PATCH] 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. --- .gitlab-ci.yml | 3 -- app/signals.c | 7 ++++ build/windows/2_bundle-gimp-uni_base.sh | 16 +++++++--- .../windows/2_bundle-gimp-uni_sym.sh | 12 +++++-- build/windows/installer/3_dist-gimp-inno.ps1 | 18 ----------- .../windows/installer/3_dist-gimp-inno_sym.sh | 32 ------------------- build/windows/installer/base_executables.isi | 8 ++--- build/windows/installer/base_gimp3264.iss | 12 +++++-- build/windows/store/3_dist-gimp-winsdk.ps1 | 24 ++++++-------- libgimp/gimp.c | 7 ++++ meson.build | 20 ++++++------ 11 files changed, 68 insertions(+), 91 deletions(-) rename meson_install_win_debug.sh => build/windows/2_bundle-gimp-uni_sym.sh (62%) delete mode 100644 build/windows/installer/3_dist-gimp-inno_sym.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ef2ddf5053..e36ac79d49 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -533,9 +533,6 @@ gimp-win-x86: GIT_SUBMODULE_STRATEGY: recursive 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] diff --git a/app/signals.c b/app/signals.c index e727293857..43247a6924 100644 --- a/app/signals.c +++ b/app/signals.c @@ -53,6 +53,7 @@ void gimp_init_signal_handlers (gchar **backtrace_file) { time_t t; + gchar *codeview_path; gchar *filename; gchar *dir; #if defined (G_OS_WIN32) && defined (HAVE_EXCHNDL) @@ -60,6 +61,12 @@ gimp_init_signal_handlers (gchar **backtrace_file) #endif #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 directory) as backtraces correspond to the binaries on this system. */ diff --git a/build/windows/2_bundle-gimp-uni_base.sh b/build/windows/2_bundle-gimp-uni_base.sh index 364aaec701..f7994cc35a 100644 --- a/build/windows/2_bundle-gimp-uni_base.sh +++ b/build/windows/2_bundle-gimp-uni_base.sh @@ -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; done -### .pdb (CodeView) debug symbols -### crossroad don't have LLVM/Clang backend yet -#if [ "$CI_JOB_NAME" != "gimp-win-x64-cross" ]; then -# cp -fr ${GIMP_PREFIX}/bin/*.pdb ${GIMP_DISTRIB}/bin/ -#fi +### .pdb (CodeView) debug symbols from babl, gegl and GIMP binaries +bundle "$GIMP_PREFIX" bin/*.pdb +### Remove ancient COFF symbol table (not used for debugging) from MSYS2 binaries +binArray=($(find $GIMP_DISTRIB \( -iname '*.dll' -or -iname '*.exe' -or -iname '*.pyd' \) -type f)) +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). clean "$GIMP_DISTRIB" lib/*.a diff --git a/meson_install_win_debug.sh b/build/windows/2_bundle-gimp-uni_sym.sh similarity index 62% rename from meson_install_win_debug.sh rename to build/windows/2_bundle-gimp-uni_sym.sh index 5d09524bc6..f33ed121de 100644 --- a/meson_install_win_debug.sh +++ b/build/windows/2_bundle-gimp-uni_sym.sh @@ -8,13 +8,19 @@ do if [ x"$installed_bin" != "x" ]; then install_dir=$(dirname ${installed_bin}) 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 - # 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 cp -f $pdb_debug $install_dir 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 done; diff --git a/build/windows/installer/3_dist-gimp-inno.ps1 b/build/windows/installer/3_dist-gimp-inno.ps1 index 761e3ad701..6652fcb53b 100644 --- a/build/windows/installer/3_dist-gimp-inno.ps1 +++ b/build/windows/installer/3_dist-gimp-inno.ps1 @@ -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 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 $INSTALLER="gimp-${CUSTOM_GIMP_VERSION}-setup.exe" diff --git a/build/windows/installer/3_dist-gimp-inno_sym.sh b/build/windows/installer/3_dist-gimp-inno_sym.sh deleted file mode 100644 index 2ca7cabd9c..0000000000 --- a/build/windows/installer/3_dist-gimp-inno_sym.sh +++ /dev/null @@ -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 diff --git a/build/windows/installer/base_executables.isi b/build/windows/installer/base_executables.isi index 65378543b4..22e40d80dc 100644 --- a/build/windows/installer/base_executables.isi +++ b/build/windows/installer/base_executables.isi @@ -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\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}\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}\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,*.pdb,*.a,*.pc,lua,gluas.dll,python3.12"; Components: deps{#COMPONENT}; Flags: {#COMMON_FLAGS} ;Optional arch-specific components (full installation) #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 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 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}\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 diff --git a/build/windows/installer/base_gimp3264.iss b/build/windows/installer/base_gimp3264.iss index b373d9b88f..03f1850ab0 100644 --- a/build/windows/installer/base_gimp3264.iss +++ b/build/windows/installer/base_gimp3264.iss @@ -312,7 +312,7 @@ Source: "{#ASSETS_DIR}\installsplash_small.bmp"; Flags: dontcopy ;Required arch-neutral files (compact install) #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}\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} @@ -1331,7 +1331,7 @@ begin 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 procedure RemoveDebugFilesFromDir(pDir: String; var pDirectories: TArrayOfString); var FindRec: TFindRec; @@ -1344,11 +1344,19 @@ begin repeat if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then 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 begin DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name); DeleteFile(AddBackSlash(pDir) + FindRec.Name); 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 begin if (FindRec.Name <> '.') and (FindRec.Name <> '..') then diff --git a/build/windows/store/3_dist-gimp-winsdk.ps1 b/build/windows/store/3_dist-gimp-winsdk.ps1 index 00b33def34..52c32361b5 100644 --- a/build/windows/store/3_dist-gimp-winsdk.ps1 +++ b/build/windows/store/3_dist-gimp-winsdk.ps1 @@ -287,22 +287,18 @@ foreach ($bundle in $supported_archs) ## Remove uneeded files (to match the Inno Windows Installer artifact) 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 ## Make .appxsym for each msix_arch (ONLY FOR RELEASES) $APPXSYM = "${IDENTITY_NAME}_${CUSTOM_GIMP_VERSION}_$msix_arch.appxsym" - #if ($GIMP_RELEASE -and -not $GIMP_IS_RC_GIT) - # { - # Write-Output "(INFO): putting .pdb symbols into $APPXSYM" - # Get-ChildItem $msix_arch -Filter *.pdb -Recurse | - # Compress-Archive -DestinationPath "${IDENTITY_NAME}_${CUSTOM_GIMP_VERSION}_$msix_arch.zip" - # Get-ChildItem *.zip | Rename-Item -NewName $APPXSYM - # Get-ChildItem $msix_arch -Include *.pdb -Recurse -Force | Remove-Item -Recurse -Force - # } + if ($CI_COMMIT_TAG -match 'GIMP_[0-9]*_[0-9]*_[0-9]*' -or $GIMP_CI_MS_STORE -like 'MSIXUPLOAD*') + { + Write-Output "(INFO): making $APPXSYM" + Get-ChildItem $msix_arch -Filter *.pdb -Recurse | Compress-Archive -DestinationPath "$APPXSYM.zip" + Get-ChildItem *.zip | Rename-Item -NewName $APPXSYM + Get-ChildItem $msix_arch -Include *.pdb -Recurse -Force | Remove-Item -Recurse -Force + } ## Make .msix from each msix_arch $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) { 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 *.appxsym | Remove-Item -Recurse -Force - Get-ChildItem *.msixbundle | Remove-Item -Recurse -Force + Remove-Item *.appxsym -Force + Remove-Item *.msixbundle -Force } Write-Output "$([char]27)[0Ksection_end:$(Get-Date -UFormat %s -Millisecond 0):msix_making$([char]13)$([char]27)[0K" } diff --git a/libgimp/gimp.c b/libgimp/gimp.c index 1ced5f5a01..3eb7d74cf4 100644 --- a/libgimp/gimp.c +++ b/libgimp/gimp.c @@ -226,10 +226,17 @@ gimp_main (GType plug_in_type, /* Use Dr. Mingw (dumps backtrace on crash) if it is available. */ { time_t t; + gchar *codeview_path; gchar *filename; gchar *dir; 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 * directory) as backtraces correspond to the binaries on this * system. diff --git a/meson.build b/meson.build index 5a4cf56149..662614948e 100644 --- a/meson.build +++ b/meson.build @@ -333,12 +333,12 @@ if platform_windows and cc.get_id() == 'clang' compiler_args += '-fansi-escape-codes' endif -# Generate .pdb (CodeView) debug symbols (makes possible to debug with DIA SDK) -#pdb_support = cc.has_argument('-gcodeview') and cc.has_link_argument('-Wl,--pdb=') -#if platform_windows and pdb_support -# compiler_args += '-gcodeview' -# linker_args += '-Wl,--pdb=' -#endif +# 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=') +if platform_windows and pdb_support + compiler_args += '-gcodeview' + linker_args += '-Wl,--pdb=' +endif conf.set('HAVE__NL_MEASUREMENT_MEASUREMENT', @@ -2140,10 +2140,10 @@ pkgconfig.generate(libgimpui, # Install native debug data (.pdb) on Windows # Ideally meson should take care of it automatically. # See: https://github.com/mesonbuild/meson/issues/12977 -#if platform_windows and pdb_support -# install_win_debug_script = find_program('./meson_install_win_debug.sh') -# meson.add_install_script(install_win_debug_script) -#endif +if platform_windows and pdb_support + install_win_debug_script = find_program('build/windows/2_bundle-gimp-uni_sym.sh') + meson.add_install_script(install_win_debug_script) +endif # On Windows, install deps in a bundle before distributing if get_option('windows-installer') or get_option('ms-store')