diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0efd1a45f4..dca6a17ab4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,13 +54,13 @@ jobs: name: macOS Debug, os: macos-latest, buildtype: debugoptimized, - args: -Ddefault_library=static -Dbuild_osx_bundle=true -Dlocal_boost=true + args: -Ddefault_library=static -Dbuild_osx_bundle=true -Dlocal_boost=true --force-fallback-for=ffms2 } - { name: macOS Release, os: macos-latest, buildtype: release, - args: -Ddefault_library=static -Dbuild_osx_bundle=true -Dlocal_boost=true + args: -Ddefault_library=static -Dbuild_osx_bundle=true -Dlocal_boost=true --force-fallback-for=ffms2 } steps: @@ -123,7 +123,10 @@ jobs: # Windows artifacts - name: Generate Windows installer if: matrix.config.os == 'windows-latest' - run: meson compile win-installer -C build + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: + meson compile win-installer -C build - name: Generate Windows portable installer if: matrix.config.os == 'windows-latest' @@ -135,6 +138,7 @@ jobs: with: name: ${{ matrix.config.name }} - installer path: build/Aegisub-*.exe + if-no-files-found: error - name: Upload artifacts - portable.zip uses: actions/upload-artifact@v3 @@ -156,3 +160,4 @@ jobs: with: name: ${{ matrix.config.name }} - installer path: build/Aegisub-*.dmg + if-no-files-found: error diff --git a/meson.build b/meson.build index c93670e569..1a3d53507b 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('Aegisub', ['c', 'cpp'], license: 'BSD-3-Clause', - meson_version: '>=0.56.1', + meson_version: '>=0.57.0', default_options: ['cpp_std=c++20', 'buildtype=debugoptimized'], version: '3.2.2') @@ -52,6 +52,10 @@ if get_option('debug') and host_machine.system() != 'windows' add_project_arguments('-D_DEBUG', language: 'cpp') endif +if get_option('buildtype') == 'release' + add_project_arguments('-DNDEBUG', language: 'cpp') +endif + conf = configuration_data() conf.set_quoted('P_DATA', dataroot) conf.set_quoted('P_LOCALE', localedir) @@ -338,7 +342,7 @@ subdir('tests') aegisub_cpp_pch = ['src/include/agi_pre.h'] aegisub_c_pch = ['src/include/agi_pre_c.h'] -aegisub = executable('aegisub', aegisub_src, version_h, acconf, +aegisub = executable('aegisub', aegisub_src, version_h, acconf, resrc, link_with: [libresrc, libaegisub], include_directories: [libaegisub_inc, libresrc_inc, version_inc, deps_inc, include_directories('src')], cpp_pch: aegisub_cpp_pch, diff --git a/packages/win_installer/fragment_codecs.iss b/packages/win_installer/fragment_codecs.iss index 06e73b0372..4313ec6109 100644 --- a/packages/win_installer/fragment_codecs.iss +++ b/packages/win_installer/fragment_codecs.iss @@ -1,7 +1,7 @@ [Files] ; Avisynth -DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\system\DevIL.dll; Flags: ignoreversion; Components: main -DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\AviSynth.dll; Flags: ignoreversion; Components: main -DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\plugins\DirectShowSource.dll; Flags: ignoreversion; Components: main +DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\Output\system\DevIL.dll; Flags: ignoreversion; Components: main +DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\Output\AviSynth.dll; Flags: ignoreversion; Components: main +DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\Output\plugins\DirectShowSource.dll; Flags: ignoreversion; Components: main ; VSFilter DestDir: {app}\csri; Source: {#DEPS_DIR}\VSFilter\x64\VSFilter.dll; Flags: ignoreversion; Components: main diff --git a/packages/win_installer/fragment_spelling.iss b/packages/win_installer/fragment_spelling.iss index 331f3eb296..8a5bca5e15 100644 --- a/packages/win_installer/fragment_spelling.iss +++ b/packages/win_installer/fragment_spelling.iss @@ -1,5 +1,5 @@ ; This file declares all installables related to spell checking and thesaurii in Aegisub [Files] -Source: {#DEPS_DIR}\dictionaries\en_US.aff; DestDir: {app}\dictionaries; Flags: skipifsourcedoesntexist ignoreversion -Source: {#DEPS_DIR}\dictionaries\en_US.dic; DestDir: {app}\dictionaries; Flags: skipifsourcedoesntexist ignoreversion +Source: {#DEPS_DIR}\dictionaries\en_US.aff; DestDir: {app}\dictionaries; Flags: skipifsourcedoesntexist ignoreversion; Components: dictionaries/en_US +Source: {#DEPS_DIR}\dictionaries\en_US.dic; DestDir: {app}\dictionaries; Flags: skipifsourcedoesntexist ignoreversion; Components: dictionaries/en_US diff --git a/packages/win_installer/portable/create-portable.ps1 b/packages/win_installer/portable/create-portable.ps1 index 0b121254f8..0a23ceb223 100644 --- a/packages/win_installer/portable/create-portable.ps1 +++ b/packages/win_installer/portable/create-portable.ps1 @@ -51,11 +51,14 @@ Copy-New-Item $InstallerDir\bin\aegisub.exe $PortableOutputDir Write-Output 'Copying - translations' Copy-New-Items "$InstallerDir\share\locale\*" "$PortableOutputDir\locale" -Recurse +Write-Output 'Copying - dictionaries' +Copy-New-Item $InstallerDepsDir\dictionaries\en_US.aff $PortableOutputDir\dictionaries +Copy-New-Item $InstallerDepsDir\dictionaries\en_US.dic $PortableOutputDir\dictionaries Write-Output 'Copying - codecs' Write-Output 'Copying - codecs\Avisynth' -Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\DevIL.dll $PortableOutputDir -Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\AviSynth.dll $PortableOutputDir -Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x86-64\plugins\DirectShowSource.dll $PortableOutputDir +Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\Output\system\DevIL.dll $PortableOutputDir +Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\Output\AviSynth.dll $PortableOutputDir +Copy-New-Item $InstallerDepsDir\AvisynthPlus64\x64\Output\plugins\DirectShowSource.dll $PortableOutputDir Write-Output 'Copying - codecs\VSFilter' Copy-New-Item $InstallerDepsDir\VSFilter\x64\VSFilter.dll $PortableOutputDir\csri Write-Output 'Copying - runtimes\MS-CRT' diff --git a/src/crash_writer_minidump.cpp b/src/crash_writer_minidump.cpp index b5b02deb47..b6a5c133ac 100644 --- a/src/crash_writer_minidump.cpp +++ b/src/crash_writer_minidump.cpp @@ -24,11 +24,12 @@ #include #include +#include #include #include -#include #include +#include extern EXCEPTION_POINTERS *wxGlobalSEInformation; diff --git a/src/libresrc/meson.build b/src/libresrc/meson.build index d4be467d74..3d172673af 100644 --- a/src/libresrc/meson.build +++ b/src/libresrc/meson.build @@ -1,9 +1,21 @@ +fs = import('fs') + respack = find_program(meson.project_source_root() / 'tools/respack.py') +bitmap_manifest = '../bitmaps/manifest.respack' +bitmap_files = [] +foreach bfile : fs.read(bitmap_manifest).strip().split('\n') + bfile_s = bfile.strip() + if bfile_s != '' + bitmap_files += files('../bitmaps' / bfile_s) + endif +endforeach + resrc = [ custom_target('bitmap.{cpp,h}', command: [respack, '@INPUT@', '@OUTPUT@'], - input: files('../bitmaps/manifest.respack'), + input: files(bitmap_manifest), + depend_files: bitmap_files, output: ['bitmap.cpp', 'bitmap.h']) ] @@ -12,17 +24,26 @@ conf_platform_json = configure_file(input: 'default_config_platform.json.in', configuration: conf_platform) if host_machine.system() == 'darwin' - resrc += custom_target('default_config.{cpp,h}', - command: [respack, '@INPUT0@', '@OUTPUT@'], - input: [files('manifest_osx.respack'), conf_platform_json], - output: ['default_config.cpp', 'default_config.h']) + resmanifest = 'manifest_osx.respack' else - resrc += custom_target('default_config.{cpp,h}', - command: [respack, '@INPUT0@', '@OUTPUT@'], - input: [files('manifest.respack'), conf_platform_json], - output: ['default_config.cpp', 'default_config.h']) + resmanifest = 'manifest.respack' endif +resmanifest_files = [conf_platform_json] +# Filter out the files we've generated ourselves +foreach rfile : fs.read(resmanifest).strip().split('\n') + rfile_s = rfile.strip() + if fs.is_file(rfile_s) + resmanifest_files += files(rfile_s) + endif +endforeach + +resrc += custom_target('default_config.{cpp,h}', + command: [respack, '@INPUT0@', '@OUTPUT@'], + input: [files(resmanifest)], + depend_files: resmanifest_files, + output: ['default_config.cpp', 'default_config.h']) + libresrc_inc = include_directories('.') libresrc = static_library('resrc', 'libresrc.cpp', resrc, include_directories: deps_inc, dependencies: deps) diff --git a/src/meson.build b/src/meson.build index 93c805802b..a6fe4c3b00 100644 --- a/src/meson.build +++ b/src/meson.build @@ -54,7 +54,6 @@ aegisub_src = files( 'command/vis_tool.cpp', 'compat.cpp', 'context.cpp', - 'crash_writer.cpp', 'dialog_about.cpp', 'dialog_attachments.cpp', 'dialog_automation.cpp', @@ -171,6 +170,7 @@ if host_machine.system() == 'darwin' elif host_machine.system() == 'windows' aegisub_src += files( 'avisynth_wrap.cpp', + 'crash_writer_minidump.cpp', 'font_file_lister_gdi.cpp', # 'libass_gdi_fontselect.cpp', 'video_provider_avs.cpp', @@ -213,6 +213,13 @@ elif host_machine.system() == 'windows' depends: version_h, include_directories: [res_inc, version_inc, wx_inc]) endif + aegisub_src += windows.compile_resources('res/strings.rc') +endif + +if host_machine.system() != 'windows' + aegisub_src += files( + 'crash_writer.cpp' + ) endif if conf.has('WITH_FONTCONFIG') diff --git a/subprojects/nasm.wrap b/subprojects/nasm.wrap index 6f1ad8dab3..dfb3c66e00 100644 --- a/subprojects/nasm.wrap +++ b/subprojects/nasm.wrap @@ -1,6 +1,7 @@ [wrap-file] directory = nasm-2.15.05 source_url = https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/win64/nasm-2.15.05-win64.zip +source_fallback_url = https://web.archive.org/web/20210420023625if_/https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/win64/nasm-2.15.05-win64.zip source_filename = nasm-2.15.05-win64.zip source_hash = f5c93c146f52b4f1664fa3ce6579f961a910e869ab0dae431bd871bdd2584ef2 patch_directory = nasm diff --git a/subprojects/packagefiles/luajit/meson.build b/subprojects/packagefiles/luajit/meson.build index 174199f891..e27a933feb 100644 --- a/subprojects/packagefiles/luajit/meson.build +++ b/subprojects/packagefiles/luajit/meson.build @@ -7,6 +7,10 @@ system_deps = [ cc.find_library('m', required: false) ] +# get architecture id for the host machine so it can be set when compiling buildvm natively +lj_target_id = cc.get_define('LUAJIT_TARGET', prefix: '#include "@0@/src/lj_arch.h"'.format(meson.current_source_dir())) +add_project_arguments('-DLUAJIT_TARGET=@0@'.format(lj_target_id), language: 'c', native: true) + # compat flag is needed for both the buildvm code generator (compiled natively) and luajit itself add_project_arguments('-DLUAJIT_ENABLE_LUA52COMPAT', '-DENDIAN_LE', language: 'c', native: true) add_project_arguments('-DLUAJIT_ENABLE_LUA52COMPAT', '-DENDIAN_LE', language: 'c', native: false) diff --git a/subprojects/packagefiles/luajit/src/host/meson.build b/subprojects/packagefiles/luajit/src/host/meson.build index 0fdc262a3f..bf1e2450ef 100644 --- a/subprojects/packagefiles/luajit/src/host/meson.build +++ b/subprojects/packagefiles/luajit/src/host/meson.build @@ -25,10 +25,6 @@ checkdefs = [ ['LJ_ABI_PAUTH', '1', ['-D', 'PAUTH']], ] -if host_machine.cpu_family() == 'x86' - checkdefs += ['__SSE2__', '1', ['-D', 'SSE']] -endif - foreach def: checkdefs if cc.get_define(def[0], prefix: hpre) == def[1] dasm += def[2] diff --git a/tools/osx-bundle.sh b/tools/osx-bundle.sh index f8d4a682ed..ac0f580806 100755 --- a/tools/osx-bundle.sh +++ b/tools/osx-bundle.sh @@ -61,7 +61,14 @@ echo "---- Copying dictionaries ----" if test -f "${DICT_DIR}"; then cp -v "${DICT_DIR}/*" "${PKG_DIR}/Contents/SharedSupport/dictionaries" else - echo "Specified dictionary directory ${DICT_DIR} not found!" + mkdir -p "${BUILD_DIR}/dictionaries" + if ! test -f "${BUILD_DIR}/dictionaries/en_US.aff"; then + echo "Specified dictionary directory ${DICT_DIR} not found. Downloading dictionaries:" + curl -L "https://raw.githubusercontent.com/TypesettingTools/Aegisub-dictionaries/master/dicts/en_US.aff" -o "${BUILD_DIR}/dictionaries/en_US.aff" + curl -L "https://raw.githubusercontent.com/TypesettingTools/Aegisub-dictionaries/master/dicts/en_US.dic" -o "${BUILD_DIR}/dictionaries/en_US.dic" + fi + cp -v "${BUILD_DIR}/dictionaries/en_US.aff" "${PKG_DIR}/Contents/SharedSupport/dictionaries" + cp -v "${BUILD_DIR}/dictionaries/en_US.dic" "${PKG_DIR}/Contents/SharedSupport/dictionaries" fi echo diff --git a/tools/osx-fix-libs.py b/tools/osx-fix-libs.py old mode 100755 new mode 100644 index d853e20ee7..7a7930d88f --- a/tools/osx-fix-libs.py +++ b/tools/osx-fix-libs.py @@ -9,10 +9,10 @@ is_bad_lib = re.compile(r'(/usr/local|/opt)').match is_sys_lib = re.compile(r'(/usr|/System)').match -otool_libname_extract = re.compile(r'\s+(/.*?)[(\s:]').search -otool_loader_path_extract = re.compile(r'\s+@loader_path/(.*?)[(\s:]').search +otool_libname_extract = re.compile(r'\s+([/@].*?)[(\s:]').search goodlist = [] badlist = [] +badlist_orig = [] link_map = {} @@ -22,23 +22,58 @@ def otool(cmdline): return p.stdout.readlines() +def get_rpath(lib): + info = otool(['-l', lib]) + commands = [] + command = [] + for line in info: + line = line.strip() + if line.startswith("Load command "): + commands.append(command) + command = [] + else: + command.append(line) + commands.append(command) + + # yuck + return [line.split()[1] for command in commands if "cmd LC_RPATH" in command for line in command if line.startswith("path")] + + def collectlibs(lib, masterlist, targetdir): global goodlist, link_map liblist = otool(['-L', lib]) locallist = [] for l in liblist: - lr = otool_libname_extract(l) - if lr: - l = lr.group(1) - else: - lr = otool_loader_path_extract(l) - if lr: - l = os.path.join(os.path.dirname(lib), lr.group(1)) - else: - continue - if is_bad_lib(l) and l not in badlist: - badlist.append(l) + l = otool_libname_extract(l) + if not l: + continue + + l = l.group(1) + l_orig = l + + if l.startswith("@rpath/"): + rpath = get_rpath(lib) + + if not rpath: + print(f"{lib} uses @rpath but has no rpath set!") + exit(-1) + + # all cases of libs using rpath so far just had a single directory in rpath... + # so let's just hope it stays that way and worry about the other cases when we get to them + if len(rpath) >= 2: + print(f"Warning: {lib} uses @rpath with more than one entry in rpath. Guessing one entry...") + + l = os.path.join(rpath[0], l[len("@rpath/"):]) + + if l.startswith("@loader_path/"): + l = os.path.join(os.path.dirname(lib), l[len("@loader_path/"):]) + + if is_bad_lib(l): + if l not in badlist: + badlist.append(l) + if l_orig not in badlist_orig: + badlist_orig.append(l_orig) if ((not is_sys_lib(l)) or is_bad_lib(l)) and l not in masterlist: locallist.append(l) print("found %s:" % l) @@ -76,7 +111,6 @@ def collectlibs(lib, masterlist, targetdir): print(" LINK %s ... copied to target" % check) link_list.append(basename) check = os.path.join(os.path.dirname(check), link_dst) - elif l not in goodlist and l not in masterlist: goodlist.append(l) masterlist.extend(locallist) @@ -101,10 +135,13 @@ def collectlibs(lib, masterlist, targetdir): print() print("Fixing library install names...") in_tool_cmdline = ['install_name_tool'] - for lib in libs: + for lib in badlist_orig: libbase = os.path.basename(lib) if libbase in link_map: + print("%s -> @executable_path/%s (REMAPPED)" % (lib, libbase)) libbase = link_map[libbase] + else: + print("%s -> @executable_path/%s" % (lib, libbase)) in_tool_cmdline = in_tool_cmdline + ['-change', lib, '@executable_path/' + libbase] for lib in libs: @@ -112,9 +149,6 @@ def collectlibs(lib, masterlist, targetdir): if libbase in link_map: libbase = link_map[libbase] - print("%s -> @executable_path/%s (REMAPPED)" % (lib, libbase)) - else: - print("%s -> @executable_path/%s" % (lib, libbase)) targetlib = targetdir + '/' + libbase orig_permission = os.stat(targetlib).st_mode diff --git a/tools/win-installer-setup.ps1 b/tools/win-installer-setup.ps1 index 312bf292ca..714739ab99 100644 --- a/tools/win-installer-setup.ps1 +++ b/tools/win-installer-setup.ps1 @@ -18,6 +18,11 @@ $Env:SOURCE_ROOT = $SourceRoot Set-Location $DepsDir +$GitHeaders = @{} +if (Test-Path 'Env:GITHUB_TOKEN') { + $GitHeaders = @{ 'Authorization' = 'Bearer ' + $Env:GITHUB_TOKEN } +} + # DepCtrl if (!(Test-Path DependencyControl)) { git clone https://github.com/TypesettingTools/DependencyControl.git @@ -38,7 +43,7 @@ if (!(Test-Path luajson)) { # Avisynth if (!(Test-Path AviSynthPlus64)) { - $avsReleases = Invoke-WebRequest "https://api.github.com/repos/AviSynth/AviSynthPlus/releases/latest" -UseBasicParsing | ConvertFrom-Json + $avsReleases = Invoke-WebRequest "https://api.github.com/repos/AviSynth/AviSynthPlus/releases/latest" -Headers $GitHeaders -UseBasicParsing | ConvertFrom-Json $avsUrl = $avsReleases.assets[0].browser_download_url Invoke-WebRequest $avsUrl -OutFile AviSynthPlus.7z -UseBasicParsing 7z x AviSynthPlus.7z @@ -50,7 +55,7 @@ if (!(Test-Path AviSynthPlus64)) { if (!(Test-Path VSFilter)) { $vsFilterDir = New-Item -ItemType Directory VSFilter Set-Location $vsFilterDir - $vsFilterReleases = Invoke-WebRequest "https://api.github.com/repos/pinterf/xy-VSFilter/releases/latest" -UseBasicParsing | ConvertFrom-Json + $vsFilterReleases = Invoke-WebRequest "https://api.github.com/repos/pinterf/xy-VSFilter/releases/latest" -Headers $GitHeaders -UseBasicParsing | ConvertFrom-Json $vsFilterUrl = $vsFilterReleases.assets[0].browser_download_url Invoke-WebRequest $vsFilterUrl -OutFile VSFilter.7z -UseBasicParsing 7z x VSFilter.7z @@ -64,22 +69,31 @@ if (!(Test-Path ffi-experiments)) { git clone https://github.com/TypesettingTools/ffi-experiments.git Set-Location ffi-experiments meson build -Ddefault_library=static + if(!$?) { Exit $LASTEXITCODE } meson compile -C build + if(!$?) { Exit $LASTEXITCODE } Set-Location $DepsDir } # VC++ redistributable if (!(Test-Path VC_redist)) { $redistDir = New-Item -ItemType Directory VC_redist - Invoke-WebRequest https://aka.ms/vs/16/release/VC_redist.x64.exe -OutFile "$redistDir\VC_redist.x64.exe" -UseBasicParsing + Invoke-WebRequest https://aka.ms/vs/17/release/VC_redist.x64.exe -OutFile "$redistDir\VC_redist.x64.exe" -UseBasicParsing } -# TODO dictionaries +# dictionaries +if (!(Test-Path dictionaries)) { + New-Item -ItemType Directory dictionaries + Invoke-WebRequest https://raw.githubusercontent.com/TypesettingTools/Aegisub-dictionaries/master/dicts/en_US.aff -OutFile dictionaries/en_US.aff -UseBasicParsing + Invoke-WebRequest https://raw.githubusercontent.com/TypesettingTools/Aegisub-dictionaries/master/dicts/en_US.dic -OutFile dictionaries/en_US.dic -UseBasicParsing +} # localization Set-Location $BuildRoot meson compile aegisub-gmo +if(!$?) { Exit $LASTEXITCODE } # Invoke InnoSetup $IssUrl = Join-Path $InstallerDir "aegisub_depctrl.iss" iscc $IssUrl +if(!$?) { Exit $LASTEXITCODE }