From 920102ff7988e372d5da19d8b3721bd34b5f0739 Mon Sep 17 00:00:00 2001 From: Meowchestra <42126400+Meowchestra@users.noreply.github.com> Date: Sat, 25 Jan 2025 19:25:49 -0800 Subject: [PATCH] . --- .github/workflows/xmake-release.yaml | 44 ++++---- .github/workflows/xmake.yaml | 61 +++++----- scripts/packaging/debian/ProMidEdit.desktop | 12 ++ scripts/packaging/debian/control | 23 ++++ scripts/packaging/debian/copyright | 12 ++ scripts/packaging/debian/promidedit.png | Bin 0 -> 3923 bytes scripts/packaging/windows/config.xml | 2 +- scripts/xmake/packages.lua | 3 - xmake.lua | 119 ++++++++++++++------ 9 files changed, 178 insertions(+), 98 deletions(-) create mode 100644 scripts/packaging/debian/ProMidEdit.desktop create mode 100644 scripts/packaging/debian/control create mode 100644 scripts/packaging/debian/copyright create mode 100644 scripts/packaging/debian/promidedit.png delete mode 100644 scripts/xmake/packages.lua diff --git a/.github/workflows/xmake-release.yaml b/.github/workflows/xmake-release.yaml index aac55a5c..ea82b2e4 100644 --- a/.github/workflows/xmake-release.yaml +++ b/.github/workflows/xmake-release.yaml @@ -6,7 +6,6 @@ on: jobs: build: runs-on: windows-latest - if: always() steps: - uses: xmake-io/github-action-setup-xmake@v1 @@ -22,9 +21,9 @@ jobs: arch: 'win64_msvc2022_64' modules: 'qtmultimedia' - - name: update repo - run: | - xrepo update-repo + - uses: jmarrec/setup-qtifw@v1 + with: + qtifw-version: '4.x' - uses: actions/checkout@v4 with: @@ -36,35 +35,32 @@ jobs: path: build/website fetch-depth: 1 - - name: cache packages from xrepo - uses: actions/cache@v4 - with: - path: | - ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages - key: ${{ runner.os }}-xrepo-qt-${{ hashFiles('scripts/xmake/packages.lua') }} - - - name: cache xmake - uses: actions/cache@v4 - with: - path: | - ${{ github.workspace }}/.xmake/**/cache - ${{ github.workspace }}/build/.build_cache - ${{ github.workspace }}/build/.deps - ${{ github.workspace }}/build/.gens - ${{ github.workspace }}/build/.objs - key: ${{ runner.os }}-xmake-build-${{ hashFiles('**/xmake.lua') }} - - name: Setup graphviz run: | choco install graphviz doxygen.install - - name: install by xmake + - name: Build run: | xmake config --yes --mode=release --generate-repository=y xmake build --jobs=2 - xmake install installer xmake doxygen --yes + - name: Copy Files + shell: pwsh + run: | + mkdir ./packaging/org.midieditor.midieditor/data/ + cp ./bin/ProMidEdit.exe ./packaging/org.midieditor.midieditor/data/ProMidEdit.exe + windeployqt ./packaging/org.midieditor.midieditor/data/ProMidEdit.exe + mkdir ./packaging/org.midieditor.midieditor/data/metronome + cp ./run_environment/metronome/metronome-01.wav ./packaging/org.midieditor.midieditor/data/metronome + mkdir ./packaging/org.midieditor.manual/data/ + cp -Recurse -Path ./manual/ -Destination ./packaging/org.midieditor.manual/data/ + + - name: Packaging + shell: cmd + run: | + binarycreator.exe --offline-only -c .\scripts\packaging\windows\config.xml -p .\packaging Install.exe + - name: Release installer uses: softprops/action-gh-release@v2 with: diff --git a/.github/workflows/xmake.yaml b/.github/workflows/xmake.yaml index 46a61e74..d2f81ae2 100644 --- a/.github/workflows/xmake.yaml +++ b/.github/workflows/xmake.yaml @@ -3,16 +3,6 @@ on: push: branches: - 'main' - paths: - - '**.c' - - '**.cpp' - - '**.h' - - '**.hpp' - - '**.rc' - - '**.qrc' - - '**.ts' - - '**.lua' - - '.github/workflows/xmake.yaml' jobs: build: @@ -32,41 +22,44 @@ jobs: arch: 'win64_msvc2022_64' modules: 'qtmultimedia' - - name: update repo - run: | - xrepo update-repo + - uses: jmarrec/setup-qtifw@v1 + with: + qtifw-version: '4.x' - uses: actions/checkout@v4 with: fetch-depth: 1 - - name: cache packages from xrepo - uses: actions/cache@v4 - with: - path: | - ${{ env.XMAKE_GLOBALDIR }}/.xmake/packages - key: ${{ runner.os }}-xrepo-qt-${{ hashFiles('scripts/xmake/packages.lua') }} + - name: Build + run: | + xmake config --yes + xmake build --jobs=2 - - name: cache xmake - uses: actions/cache@v4 - with: - path: | - ${{ github.workspace }}/.xmake/**/cache - ${{ github.workspace }}/build/.build_cache - ${{ github.workspace }}/build/.deps - ${{ github.workspace }}/build/.gens - ${{ github.workspace }}/build/.objs - key: ${{ runner.os }}-xmake-build-${{ hashFiles('**/xmake.lua') }} + - name: Copy Files + shell: pwsh + run: | + mkdir ./packaging/org.midieditor.midieditor/data/ + cp ./bin/ProMidEdit.exe ./packaging/org.midieditor.midieditor/data/ProMidEdit.exe + windeployqt ./packaging/org.midieditor.midieditor/data/ProMidEdit.exe + mkdir ./packaging/org.midieditor.midieditor/data/metronome + cp ./run_environment/metronome/metronome-01.wav ./packaging/org.midieditor.midieditor/data/metronome + mkdir ./packaging/org.midieditor.manual/data/ + cp -Recurse -Path ./manual/ -Destination ./packaging/org.midieditor.manual/data/ - - name: config by xmake + - name: Packaging + shell: cmd run: | - xmake config --yes --verbose --diagnosis + binarycreator.exe --offline-only -c .\scripts\packaging\windows\config.xml -p .\packaging Install.exe - - name: build and create installer + - name: List build contents + shell: cmd run: | - xmake build --verbose --diagnosis --jobs=2 - xmake install installer + echo "Listing packaging directory contents:" + dir /s packaging + echo "Listing build directory contents:" + dir /s build + - name: Upload artifact uses: actions/upload-artifact@v4 with: diff --git a/scripts/packaging/debian/ProMidEdit.desktop b/scripts/packaging/debian/ProMidEdit.desktop new file mode 100644 index 00000000..23d24e47 --- /dev/null +++ b/scripts/packaging/debian/ProMidEdit.desktop @@ -0,0 +1,12 @@ + +[Desktop Entry] +Version=1.0.0 +Encoding=UTF-8 +Name=ProMidEdit +Comment=NONE +Exec=promidedit +Icon=midieditor.png +Terminal=false +Type=Application +Categories=AudioVideo;Audio; +Name[ru_RU]=ProMidEdit.desktop diff --git a/scripts/packaging/debian/control b/scripts/packaging/debian/control new file mode 100644 index 00000000..13a7be1d --- /dev/null +++ b/scripts/packaging/debian/control @@ -0,0 +1,23 @@ +Package: promidedit +Version: {VERSION}-{PACKAGE} +Section: sound +Priority: extra +Architecture: {ARCH} +Depends: {DEPENDS} +Installed-Size: {SIZE} +Maintainer: PROPHESSOR, Markus Schwenk +Homepage: https://midieditor.org/ +Description: Graphical interface to edit, play, and record Midi data. + ProMidEdit is a free software providing an interface to edit, + record, and play Midi data. + . + The editor is able to open existing Midi files and modify their + content. New files can be created and the user can enter his own + composition by either recording Midi data from a connected Midi device + (e.g., a digital piano or a keyboard) or by manually creating new + notes and other Midi events. The recorded data can be easily + quantified and edited afterwards using ProMidEdit. + . + ProMidEdit was developed by PROPHESSOR based on Markus Schwenk's MidiEditor. It is entirely written in C++ (Qt 5) + and is available for the platforms Linux and Windows. + Support languages: English and Russian diff --git a/scripts/packaging/debian/copyright b/scripts/packaging/debian/copyright new file mode 100644 index 00000000..2d8aa3c5 --- /dev/null +++ b/scripts/packaging/debian/copyright @@ -0,0 +1,12 @@ +This package was debianized on {DATE}. + +Copyright (c) by PROPHESSOR 2019. + +It was downloaded from https://github.com/PROPHESSOR/ProMidEdit + +Upstream Author: Markus Schwenk + +This code is released under the terms of the GPL license version 3. + +See /usr/share/common-licenses/GPL-3 for the full license. + diff --git a/scripts/packaging/debian/promidedit.png b/scripts/packaging/debian/promidedit.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ed811c6417705403d71a543b0115504af43a53 GIT binary patch literal 3923 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 V@TargetDir@/ProMidEdit.exe - Run ProMidEdit + run midieditor ProMidEdit true diff --git a/scripts/xmake/packages.lua b/scripts/xmake/packages.lua deleted file mode 100644 index e40b76c4..00000000 --- a/scripts/xmake/packages.lua +++ /dev/null @@ -1,3 +0,0 @@ -function add_all_requires() - add_requires("qtifw") -end \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 13de9ed5..f8ff9376 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,7 +1,7 @@ local MIDIEDITOR_RELEASE_VERSION_STRING = "3.9.0" set_version(MIDIEDITOR_RELEASE_VERSION_STRING) -set_allowedplats("windows") +set_allowedplats("windows", "linux", "macosx") option("generate-repository", { description = "generate repositiory to update online repositories", @@ -9,27 +9,25 @@ option("generate-repository", { values = {true, false}, showmenu = true, }) - -includes("scripts/xmake/packages.lua") -add_all_requires() +option("libraries-from-apt", { + description = "use libraries from apt rather than xmake-repo", + default = false, + values = {true, false}, + showmenu = is_host("linux") and (linuxos.name() == "ubuntu"), +}) local installdir = "packaging/org.midieditor.midieditor/data/" target("ProMidEdit") do set_languages("cxx17") - add_rules("qt.widgetapp") - - -- Add Qt6 multimedia include paths explicitly - after_load(function (target) - local qt_dir = os.getenv("QTDIR") - if qt_dir then - target:add("includedirs", path.join(qt_dir, "include/QtMultimedia")) - target:add("includedirs", path.join(qt_dir, "include/QtMultimediaWidgets")) - end - end) + set_targetdir("bin") + add_packages({ + "qt6widgets" + }) + add_rules("qt.widgetapp") add_frameworks({ "QtGui", - "QtWidgets", + "QtWidgets", "QtCore", "QtNetwork", "QtXml", @@ -45,10 +43,21 @@ target("ProMidEdit") do add_defines("MIDIEDITOR_RELEASE_VERSION_ID_DEF=" .. 0) add_defines("MIDIEDITOR_RELEASE_DATE_DEF=" .. os.date("%x")) add_defines("MIDIEDITOR_RELEASE_VERSION_STRING_DEF=" .. MIDIEDITOR_RELEASE_VERSION_STRING) - if is_plat("windows") then + if is_plat("linux", "bsd") then + add_defines({ + "__LINUX_ALSASEQ__", + "__LINUX_ALSA__" + }) + add_syslinks("asound") + elseif is_plat("windows") then add_defines("__WINDOWS_MM__") add_syslinks("winmm") add_files("midieditor.rc") + elseif is_plat("macosx") then + add_defines("__MACOSX_CORE__") + add_frameworks("CoreMidi", "CoreAudio", "CoreFoundation") + -- TODO: icons + add_installfiles("midieditor.icns") end local bindir = path.join(installdir, "bin") @@ -72,12 +81,14 @@ end target("manual") do set_kind("phony") + set_enabled(is_plat("windows")) set_installdir("packaging/org.midieditor.manual/data/manual") add_installfiles("manual/(**)") end -target("installer") +target("installer") do set_kind("phony") + set_enabled(is_plat("windows", "linux")) add_deps("ProMidEdit") set_installdir(installdir) @@ -86,26 +97,62 @@ target("installer") add_packages("qtifw") after_install(function (target, opt) import("core.project.config") - - -- Create required directories - os.mkdir("packaging/org.midieditor.midieditor/data/bin") - - -- Copy all files from release directory - os.cp("build/windows/x64/release/*", "packaging/org.midieditor.midieditor/data/bin/") - - -- Copy additional resources - -- os.cp("run_environment/**", "packaging/org.midieditor.midieditor/data/") - - -- Generate installer local qtifw_dir = target:pkg("qtifw"):installdir() local binarycreator_path = path.join(qtifw_dir, "/bin/binarycreator.exe") - - print("generate off-line installer") - local package_argv = { - "--config", "scripts/packaging/windows/config.xml", - "--packages", "packaging", - "packaging/Install.exe" + local repogen_path = path.join(qtifw_dir, "/bin/repogen.exe") + if config.get("generate-repository") then + print("generate site") + print(" generate repository") + local repo_argv = { + "--update-new-components", + "--packages", "packaging", + path.join(config.buildir(), "website", "repository") + } + os.iorunv(repogen_path, repo_argv) + print(" generate installer") + local package_argv = { + "--config", "scripts/packaging/windows/config.xml", + "--packages", "packaging", + path.join(config.buildir(), "website", "ProMidiEdit.exe") + } + os.iorunv(binarycreator_path, package_argv) + print(" copy online manual") + os.cp("manual/*", path.join(config.buildir(), "website")) + else + print("generate off-line installer") + local package_argv = { + "--config", "scripts/packaging/windows/config.xml", + "--packages", "packaging", + "packaging/Install.exe" + } + os.iorunv(binarycreator_path, package_argv) + end + end) + elseif is_plat("linux") and linuxos.name() == "ubuntu" then + add_installfiles("scripts/packaging/debian/ProMidEdit.desktop", {prefixdir = "usr/share/applications"}) + add_installfiles("scripts/packaging/debian/logo48.png", {prefixdir = "usr/share/pixmaps"}) + add_installfiles("scripts/packaging/debian/copyright", {prefixdir = "usr/share/doc/promidedit/copyright"}) + add_installfiles("$(buildir)/control", {prefixdir = "DEBIAN"}) + add_configfiles("scripts/packaging/debian/control", { + pattern = "{(.-)}", + variables = { + PACKAGE = 1, + DEPENDS = "libc6(>=2.19), libfluidsynth3, qtbase5-dev, qtdeclarative5-dev, libqt5webkit5-dev, libsqlite3-dev, qt5-default, qtmultimedia5-dev, libqt5multimedia5, qttools5-dev-tools, libqt5multimedia5-plugins, libasound2, libgstreamer1.0-0, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, gstreamer1.0-plugins-bad, gstreamer1.0-plugins-ugly, gstreamer1.0-libav, gstreamer1.0-doc, gstreamer1.0-tools", + SIZE = 70, -- in kb, todo } - os.iorunv(binarycreator_path, package_argv) + }) + after_install(function (target, opt) + import("core.project.config") + local installdir_glob = path.join(target:installdir(), "**") + for _, file in ipairs(os.dirs(installdir_glob)) do + os.runv("chmod", {"755", file}) + end + for _, file in ipairs(os.files(installdir_glob)) do + os.runv("chmod", {"644", file}) + end + os.runv("chmod", { + "+x", path.join(target:installdir(), "bin", target:deps()["ProMidEdit"]:filename())}) + os.iorunv("fakeroot", {"dpkg-deb", "--build", target:installdir()}) end) - end \ No newline at end of file + end +end \ No newline at end of file