diff --git a/.gitignore b/.gitignore index fe9da4f..b56fd08 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ +/build +/src/resources.rs +/target Cargo.lock -test.sqlite -/res/resources.gresource -/target \ No newline at end of file +test.sqlite \ No newline at end of file diff --git a/README.md b/README.md index 3f6975b..80bb0e1 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,16 @@ https://musicus.org ## Hacking -For now you have to generate the static resources manually before the first -compilation and after changes to them. Use the following command line: +Musicus uses the [Meson build system](https://mesonbuild.com/). You can build +it using the following commands: ``` -$ cd res && glib-compile-resources resources.xml && cd .. +$ meson build +$ ninja -C build ``` -Afterwards you can compile and run the program using: - -``` -$ cargo run -``` +Afterwards the resulting binary executable is under +`build/target/debug/musicus`. This program uses [Diesel](https://diesel.rs) as its ORM. After installing the Diesel command line utility, you will be able to create a new schema diff --git a/build-aux/cargo.sh b/build-aux/cargo.sh new file mode 100644 index 0000000..b37435f --- /dev/null +++ b/build-aux/cargo.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +export MESON_BUILD_ROOT="$1" +export MESON_SOURCE_ROOT="$2" +export CARGO_TARGET_DIR="$MESON_BUILD_ROOT"/target +export CARGO_HOME="$CARGO_TARGET_DIR"/cargo-home +export OUTPUT="$3" +export BUILDTYPE="$4" +export APP_BIN="$5" + + +if [ $BUILDTYPE = "release" ] +then + echo "RELEASE MODE" + cargo build --manifest-path \ + "$MESON_SOURCE_ROOT"/Cargo.toml --release && \ + cp "$CARGO_TARGET_DIR"/release/"$APP_BIN" "$OUTPUT" +else + echo "DEBUG MODE" + cargo build --manifest-path \ + "$MESON_SOURCE_ROOT"/Cargo.toml --verbose && \ + cp "$CARGO_TARGET_DIR"/debug/"$APP_BIN" "$OUTPUT" +fi + diff --git a/build-aux/postinstall.py b/build-aux/postinstall.py new file mode 100755 index 0000000..6a3ea97 --- /dev/null +++ b/build-aux/postinstall.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +from os import environ, path +from subprocess import call + +prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local') +datadir = path.join(prefix, 'share') +destdir = environ.get('DESTDIR', '') + +# Package managers set this so we don't need to run +if not destdir: + print('Updating icon cache...') + call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')]) + + print('Updating desktop database...') + call(['update-desktop-database', '-q', path.join(datadir, 'applications')]) + + print('Compiling GSettings schemas...') + call(['glib-compile-schemas', path.join(datadir, 'glib-2.0', 'schemas')]) + + diff --git a/data/de.johrpan.musicus.desktop.in b/data/de.johrpan.musicus.desktop.in new file mode 100644 index 0000000..59c2d9c --- /dev/null +++ b/data/de.johrpan.musicus.desktop.in @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=Musicus +Exec=musicus +Terminal=false +Type=Application +Categories=GTK; +StartupNotify=true diff --git a/data/de.johrpan.musicus.gschema.xml b/data/de.johrpan.musicus.gschema.xml new file mode 100644 index 0000000..2609270 --- /dev/null +++ b/data/de.johrpan.musicus.gschema.xml @@ -0,0 +1,9 @@ + + + + + "" + Path to the music library folder + + + diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 0000000..3834bbe --- /dev/null +++ b/data/meson.build @@ -0,0 +1,26 @@ +desktop_file = i18n.merge_file( + input: 'de.johrpan.musicus.desktop.in', + output: 'de.johrpan.musicus.desktop', + type: 'desktop', + po_dir: '../po', + install: true, + install_dir: join_paths(get_option('datadir'), 'applications') +) + +desktop_utils = find_program('desktop-file-validate', required: false) +if desktop_utils.found() + test('Validate desktop file', desktop_utils, + args: [desktop_file] + ) +endif + +install_data('de.johrpan.musicus.gschema.xml', + install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas') +) + +compile_schemas = find_program('glib-compile-schemas', required: false) +if compile_schemas.found() + test('Validate schema file', compile_schemas, + args: ['--strict', '--dry-run', meson.current_source_dir()] + ) +endif diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..c9281cd --- /dev/null +++ b/meson.build @@ -0,0 +1,21 @@ +project('musicus', 'rust', + version: '0.1.0', + meson_version: '>= 0.50.0', + license: 'AGPLv3+', +) + +dependency('glib-2.0', version: '>= 2.56') +dependency('gio-2.0', version: '>= 2.56') +dependency('gtk+-3.0', version: '>= 3.24.7') +dependency('libhandy-1', version: '>= 1.0.0') +dependency('pango', version: '>= 1.0') +dependency('sqlite3', version: '>= 3.20') + +i18n = import('i18n') + +subdir('data') +subdir('po') +subdir('res') +subdir('src') + +meson.add_install_script('build-aux/postinstall.py') \ No newline at end of file diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..e69de29 diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000..e69de29 diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..38f16f1 --- /dev/null +++ b/po/meson.build @@ -0,0 +1 @@ +i18n.gettext('musicus', preset: 'glib') diff --git a/res/meson.build b/res/meson.build new file mode 100644 index 0000000..13d8d92 --- /dev/null +++ b/res/meson.build @@ -0,0 +1,9 @@ +pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name()) +gnome = import('gnome') + +resources = gnome.compile_resources('musicus', + 'musicus.gresource.xml', + gresource_bundle: true, + install: true, + install_dir: pkgdatadir, +) diff --git a/res/resources.xml b/res/musicus.gresource.xml similarity index 100% rename from res/resources.xml rename to res/musicus.gresource.xml diff --git a/src/main.rs b/src/main.rs index b7d15f3..a7b359e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,13 +20,12 @@ mod widgets; mod window; use window::Window; +mod resources; + fn main() { gtk::init().expect("Failed to initialize GTK!"); libhandy::init(); - - let bytes = glib::Bytes::from(include_bytes!("../res/resources.gresource").as_ref()); - let resource = gio::Resource::from_data(&bytes).expect("Failed to load resources!"); - gio::resources_register(&resource); + resources::init().expect("Failed to initialize resources!"); let app = gtk::Application::new( Some("de.johrpan.musicus"), diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..7355386 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,75 @@ +resource_conf = configuration_data() +resource_conf.set_quoted('RESOURCEFILE', resources.full_path()) +resource_rs = configure_file( + input: 'resources.rs.in', + output: 'resources.rs', + configuration: resource_conf +) + +run_command( + 'cp', + resource_rs, + meson.current_source_dir(), + check: true +) + +sources = files( + 'database/database.rs', + 'database/mod.rs', + 'database/models.rs', + 'database/schema.rs', + 'database/tables.rs', + 'dialogs/ensemble_editor.rs', + 'dialogs/ensemble_selector.rs', + 'dialogs/instrument_editor.rs', + 'dialogs/instrument_selector.rs', + 'dialogs/mod.rs', + 'dialogs/part_editor.rs', + 'dialogs/performance_editor.rs', + 'dialogs/person_editor.rs', + 'dialogs/person_selector.rs', + 'dialogs/preferences.rs', + 'dialogs/recording_editor.rs', + 'dialogs/recording_selector.rs', + 'dialogs/section_editor.rs', + 'dialogs/track_editor.rs', + 'dialogs/tracks_editor.rs', + 'dialogs/work_editor.rs', + 'dialogs/work_selector.rs', + 'screens/ensemble_screen.rs', + 'screens/mod.rs', + 'screens/person_screen.rs', + 'screens/recording_screen.rs', + 'screens/work_screen.rs', + 'widgets/list.rs', + 'widgets/mod.rs', + 'widgets/navigator.rs', + 'widgets/person_list.rs', + 'widgets/poe_list.rs', + 'widgets/selector_row.rs', + 'backend.rs', + 'main.rs', + 'resources.rs', + 'resources.rs.in', + 'window.rs', +) + +cargo_script = find_program(join_paths(meson.source_root(), 'build-aux/cargo.sh')) +cargo_release = custom_target( + 'cargo-build', + build_by_default: true, + input: sources, + depends: resources, + output: meson.project_name(), + console: true, + install: true, + install_dir: get_option('bindir'), + command: [ + cargo_script, + meson.build_root(), + meson.source_root(), + '@OUTPUT@', + get_option('buildtype'), + meson.project_name(), + ] +) diff --git a/src/resources.rs.in b/src/resources.rs.in new file mode 100644 index 0000000..6ece05e --- /dev/null +++ b/src/resources.rs.in @@ -0,0 +1,9 @@ +use anyhow::Result; + +pub fn init() -> Result<()> { + let bytes = glib::Bytes::from(include_bytes!(@RESOURCEFILE@).as_ref()); + let resource = gio::Resource::from_data(&bytes)?; + gio::resources_register(&resource); + + Ok(()) +}