diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 1990c2f5..0d68960b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -20,7 +20,7 @@ jobs: - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install -y libglib2.0 attr automake appstream-compose gettext autopoint bison dbus gtk-doc-tools \ + sudo apt-get install -y libglib2.0 attr automake libappstream-compose-dev gettext autopoint bison dbus gtk-doc-tools \ libfuse-dev ostree libostree-dev libarchive-dev libcap-dev libattr1-dev libdw-dev libelf-dev \ libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \ libseccomp-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \ @@ -53,7 +53,7 @@ jobs: - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install -y libglib2.0 attr automake appstream-compose gettext autopoint bison dbus gtk-doc-tools \ + sudo apt-get install -y libglib2.0 attr automake libappstream-compose-dev gettext autopoint bison dbus gtk-doc-tools \ libfuse-dev ostree libostree-dev libarchive-dev libcap-dev libattr1-dev libdw-dev libelf-dev \ libjson-glib-dev shared-mime-info desktop-file-utils libpolkit-agent-1-dev libpolkit-gobject-1-dev \ libseccomp-dev libsystemd-dev libxml2-utils libgpgme11-dev gobject-introspection \ @@ -95,7 +95,7 @@ jobs: attr \ automake \ autopoint \ - appstream-compose \ + libappstream-compose-dev \ bison \ debugedit \ dbus \ diff --git a/configure.ac b/configure.ac index bfee7888..113b9889 100644 --- a/configure.ac +++ b/configure.ac @@ -41,22 +41,6 @@ else [AC_MSG_ERROR([You need at least version $FLATPAK_REQS of flatpak, your version is $FLATPAK_VERSION])]) fi -AC_CHECK_PROG([APPSTREAMCLI], [appstreamcli], [appstreamcli], [false]) -if test "x$APPSTREAMCLI" = xfalse; then - AC_MSG_ERROR([You need appstreamcli installed]) - APPSTREAMCLI_VERSION=`$APPSTREAMCLI --version | sed 's,.*\ \([0-9]*\.[0-9]*\.[0-9]*\)$,\1,'` - AX_COMPARE_VERSION([$APPSTREAMCLI_REQS],[gt],[$APPSTREAMCLI_VERSION], - [AC_MSG_ERROR([You need at least version $APPSTREAMCLI_REQS of appstreamcli, your version is $APPSTREAMCLI_VERSION])]) -fi - -AC_MSG_CHECKING([whether appstreamcli has compose support]) -AS_IF([appstreamcli compose --help >/dev/null 2>&1], - [AC_MSG_RESULT(yes)], - [ - AC_MSG_RESULT(no) - AC_MSG_ERROR([appstreamcli must have compose support enabled and installed]) - ]) - LT_PREREQ([2.2.6]) LT_INIT([disable-static]) @@ -102,7 +86,7 @@ PKG_PROG_PKG_CONFIG([0.24]) # For libglnx AC_CHECK_HEADER([sys/xattr.h], [], [AC_MSG_ERROR([You must have sys/xattr.h from glibc])]) -PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 ostree-1 >= $OSTREE_REQS json-glib-1.0 libxml-2.0 >= 2.4 libcurl]) +PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 ostree-1 >= $OSTREE_REQS json-glib-1.0 libxml-2.0 >= 2.4 libcurl appstream >= $APPSTREAMCLI_REQS appstream-compose >= $APPSTREAMCLI_REQS]) dnl ************************ dnl *** check for libelf *** diff --git a/doc/flatpak-builder.xml b/doc/flatpak-builder.xml index 8ae33f55..97571d27 100644 --- a/doc/flatpak-builder.xml +++ b/doc/flatpak-builder.xml @@ -587,6 +587,22 @@ + + + + + Allow screencasts in Appstream catalogue. + + + + + + + Use partial URLs in Appstream catalogue. Requires + appstream >= 0.16.3. + + + diff --git a/meson.build b/meson.build index 1085a8f7..8a2d7425 100644 --- a/meson.build +++ b/meson.build @@ -40,10 +40,6 @@ endforeach # The debugedit program is a hard dependency debugedit = find_program('debugedit', version: '>= 5.0') -# Require appstream with compose plugin installed -appstreamcli = find_program('appstreamcli', version: '>= 0.15.0') -appstreamcli_compose = run_command(appstreamcli, ['compose', '--help'], check: true) - subdir('src') subdir('doc') if get_option('tests') diff --git a/src/Makefile.am.inc b/src/Makefile.am.inc index cc426df8..da2d1503 100644 --- a/src/Makefile.am.inc +++ b/src/Makefile.am.inc @@ -53,4 +53,4 @@ flatpak_builder_SOURCES = \ $(NULL) flatpak_builder_LDADD = $(AM_LDADD) $(BASE_LIBS) $(LIBELF_LIBS) $(YAML_LIBS) libglnx.la -flatpak_builder_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(YAML_CFLAGS) +flatpak_builder_CFLAGS = -I$(top_srcdir)/src $(AM_CFLAGS) $(BASE_CFLAGS) $(YAML_CFLAGS) diff --git a/src/asc-font.h b/src/asc-font.h new file mode 100644 index 00000000..158168b4 --- /dev/null +++ b/src/asc-font.h @@ -0,0 +1,20 @@ +/* + * asc-font.h (stub) + * + * This header is intentionally provided as a no-op. + * + * In AppStream < 1.0.6, the public header + * appstream-compose.h -> asc-canvas.h + * includes the private header "asc-font.h". + * + * That private header is not installed by default, and nothing in + * the public API actually depends on its declarations. + * + * To allow building against older AppStream releases, we provide + * this empty stub so the include resolves cleanly. + * + * Safe to remove once the minimum required AppStream is >= 1.0.6. + */ +#ifndef __ASC_FONT_H +#define __ASC_FONT_H +#endif diff --git a/src/builder-context.c b/src/builder-context.c index 508ab91f..27ca98b5 100644 --- a/src/builder-context.c +++ b/src/builder-context.c @@ -86,6 +86,8 @@ struct BuilderContext gboolean no_shallow_clone; gboolean opt_export_only; char *opt_mirror_screenshots_url; + gboolean opt_compose_enable_screencasts; + gboolean opt_compose_enable_partial_urls; BuilderSdkConfig *sdk_config; }; @@ -376,6 +378,32 @@ builder_context_get_opt_mirror_screenshots_url (BuilderContext *self) return self->opt_mirror_screenshots_url; } +void +builder_context_set_opt_compose_enable_screencasts (BuilderContext *self, + gboolean opt_compose_enable_screencasts) +{ + self->opt_compose_enable_screencasts = !!opt_compose_enable_screencasts; +} + +gboolean +builder_context_get_opt_compose_enable_screencasts (BuilderContext *self) +{ + return self->opt_compose_enable_screencasts; +} + +void +builder_context_set_opt_compose_enable_partial_urls (BuilderContext *self, + gboolean opt_compose_enable_partial_urls) +{ + self->opt_compose_enable_partial_urls = !!opt_compose_enable_partial_urls; +} + +gboolean +builder_context_get_opt_compose_enable_partial_urls (BuilderContext *self) +{ + return self->opt_compose_enable_partial_urls; +} + GFile * builder_context_find_in_sources_dirs (BuilderContext *self, ...) diff --git a/src/builder-context.h b/src/builder-context.h index 69671398..1828ad16 100644 --- a/src/builder-context.h +++ b/src/builder-context.h @@ -180,6 +180,16 @@ void builder_context_set_opt_mirror_screenshots_url (BuilderContext * const char * builder_context_get_opt_mirror_screenshots_url (BuilderContext *self); +void builder_context_set_opt_compose_enable_screencasts (BuilderContext *self, + gboolean opt_compose_enable_screencasts); + +gboolean builder_context_get_opt_compose_enable_screencasts (BuilderContext *self); + +void builder_context_set_opt_compose_enable_partial_urls (BuilderContext *self, + gboolean opt_compose_enable_partial_urls); + +gboolean builder_context_get_opt_compose_enable_partial_urls (BuilderContext *self); + BuilderSdkConfig * builder_context_get_sdk_config (BuilderContext *self); gboolean builder_context_create_state_dir (BuilderContext *self, diff --git a/src/builder-main.c b/src/builder-main.c index 606e4d33..abda3b7f 100644 --- a/src/builder-main.c +++ b/src/builder-main.c @@ -89,6 +89,8 @@ static gboolean opt_log_session_bus; static gboolean opt_log_system_bus; static gboolean opt_yes; static gint64 opt_source_date_epoch = -1; +static gboolean opt_compose_enable_screencasts; +static gboolean opt_compose_enable_partial_urls; static GOptionEntry entries[] = { { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL }, @@ -144,6 +146,8 @@ static GOptionEntry entries[] = { { "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL }, { "no-shallow-clone", 0, 0, G_OPTION_ARG_NONE, &opt_no_shallow_clone, "Don't use shallow clones when mirroring git repos", NULL }, { "override-source-date-epoch", 0, 0, G_OPTION_ARG_INT64, &opt_source_date_epoch, "Use this timestamp to perform the build, instead of the last modification time of the manifest.", NULL }, + { "compose-enable-screencasts", 0, 0, G_OPTION_ARG_NONE, &opt_compose_enable_screencasts, "Allow screencasts in Appstream catalogue", NULL }, + { "compose-enable-partial-urls", 0, 0, G_OPTION_ARG_NONE, &opt_compose_enable_partial_urls, "Allow partial URLs in Appstream catalogue", NULL }, { NULL } }; @@ -605,6 +609,8 @@ main (int argc, builder_context_set_bundle_sources (build_context, opt_bundle_sources); builder_context_set_opt_export_only (build_context, opt_export_only); builder_context_set_opt_mirror_screenshots_url (build_context, opt_mirror_screenshots_url); + builder_context_set_opt_compose_enable_screencasts (build_context, opt_compose_enable_screencasts); + builder_context_set_opt_compose_enable_partial_urls (build_context, opt_compose_enable_partial_urls); git_init_email (); diff --git a/src/builder-manifest.c b/src/builder-manifest.c index bcea7b3d..cb272274 100644 --- a/src/builder-manifest.c +++ b/src/builder-manifest.c @@ -30,6 +30,25 @@ #include #include +/* Remove for newer appstream */ +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + +#define I_KNOW_THE_APPSTREAM_COMPOSE_API_IS_SUBJECT_TO_CHANGE +#include +#include + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + #include "builder-manifest.h" #include "builder-utils.h" #include "builder-flatpak-utils.h" @@ -2404,26 +2423,69 @@ cmpstringp (const void *p1, const void *p2) } static gboolean -appstreamcli_compose (GError **error, - ...) +builder_appstreamcli_compose (const gchar *origin, + const gchar *app_id, + const gchar *result_root, + const gchar *data_dir, + const gchar *icon_dir, + const gchar *media_dir, + const gchar *hint_dir, + const gchar *media_baseurl, + gboolean enable_screencasts, + gboolean enable_partial_urls, + GError **error) { - g_autoptr(GPtrArray) args = NULL; - const gchar *arg; - va_list ap; + g_autoptr(AscCompose) compose = NULL; + g_autoptr(AscDirectoryUnit) dirunit = NULL; + g_autofree gchar *desktop_component = NULL; - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("appstreamcli")); - g_ptr_array_add (args, g_strdup ("compose")); + g_return_val_if_fail (origin != NULL, FALSE); + g_return_val_if_fail (app_id != NULL, FALSE); + g_return_val_if_fail (result_root != NULL, FALSE); + g_return_val_if_fail (data_dir != NULL, FALSE); + g_return_val_if_fail (icon_dir != NULL, FALSE); + g_return_val_if_fail (hint_dir != NULL, FALSE); - va_start (ap, error); - while ((arg = va_arg (ap, const gchar *))) - g_ptr_array_add (args, g_strdup (arg)); - g_ptr_array_add (args, NULL); - va_end (ap); + compose = asc_compose_new (); + + asc_compose_set_format (compose, AS_FORMAT_KIND_XML); + asc_compose_set_origin (compose, origin); + asc_compose_set_prefix (compose, "/"); + + asc_compose_add_allowed_cid (compose, app_id); + desktop_component = g_strdup_printf ("%s.desktop", app_id); + asc_compose_add_allowed_cid (compose, desktop_component); + + dirunit = asc_directory_unit_new (result_root); + asc_compose_add_unit (compose, ASC_UNIT (dirunit)); + + asc_compose_set_data_result_dir (compose, data_dir); + asc_compose_set_icons_result_dir (compose, icon_dir); + asc_compose_set_media_baseurl (compose, media_baseurl); + asc_compose_set_media_result_dir (compose, media_dir); + asc_compose_set_hints_result_dir (compose, hint_dir); - if (!flatpak_spawnv (NULL, NULL, 0, error, (const char * const *)args->pdata, NULL)) + asc_compose_add_flags (compose, ASC_COMPOSE_FLAG_PROPAGATE_CUSTOM); + +#if AS_CHECK_VERSION(0, 16, 3) + if (!enable_partial_urls) + asc_compose_add_flags (compose, ASC_COMPOSE_FLAG_NO_PARTIAL_URLS); +#endif + + if (!enable_screencasts) + asc_compose_remove_flags (compose, ASC_COMPOSE_FLAG_ALLOW_SCREENCASTS); + + g_autoptr(GPtrArray) results = asc_compose_run (compose, NULL, error); + if (results == NULL) { - g_prefix_error (error, "ERROR: appstreamcli compose failed: "); + g_prefix_error (error, "AppStream compose failed: "); + return FALSE; + } + + if (asc_compose_has_errors (compose)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "AppStream compose completed with errors"); return FALSE; } @@ -3033,56 +3095,52 @@ builder_manifest_cleanup (BuilderManifest *self, if (self->appstream_compose && appdata_file != NULL) { - g_autofree char *origin = g_strdup_printf ("--origin=%s", - builder_manifest_get_id (self)); - g_autofree char *components_arg = g_strdup_printf ("--components=%s,%s.desktop", - self->id, self->id); const char *app_root_path = flatpak_file_get_path_cached (app_root); - g_autofree char *result_root_arg = g_strdup_printf ("--result-root=%s", app_root_path); - g_autoptr(GFile) xml_dir = flatpak_build_file (app_root, "share/app-info/xmls", NULL); + g_autoptr(GFile) data_out = flatpak_build_file (app_root, "share/app-info/xmls", NULL); g_autoptr(GFile) icon_out = flatpak_build_file (app_root, "share/app-info/icons/flatpak", NULL); - g_autoptr(GFile) media_dir = flatpak_build_file (app_root, "share/app-info/media", NULL); - g_autofree char *data_dir = g_strdup_printf ("--data-dir=%s", - flatpak_file_get_path_cached (xml_dir)); - g_autofree char *icon_dir = g_strdup_printf ("--icons-dir=%s", - flatpak_file_get_path_cached (icon_out)); + g_autoptr(GFile) media_out = flatpak_build_file (app_root, "share/app-info/media", NULL); + g_autoptr(GFile) hint_out = flatpak_build_file (app_root, "appstream", NULL); + const char *data_dir = flatpak_file_get_path_cached(data_out); + const char *icon_dir = flatpak_file_get_path_cached(icon_out); + const char *media_dir = flatpak_file_get_path_cached(media_out); + const char *hint_dir = flatpak_file_get_path_cached(hint_out); const char *opt_mirror_screenshots_url = builder_context_get_opt_mirror_screenshots_url (context); gboolean opt_export_only = builder_context_get_opt_export_only (context); + gboolean opt_enable_screencasts = builder_context_get_opt_compose_enable_screencasts(context); + gboolean opt_enable_partial_urls = builder_context_get_opt_compose_enable_partial_urls(context); + g_print ("Running appstreamcli compose\n"); if (opt_mirror_screenshots_url && !opt_export_only) { g_autofree char *url = g_build_filename (opt_mirror_screenshots_url, NULL); - g_autofree char *arg_base_url = g_strdup_printf ("--media-baseurl=%s", url); - g_autofree char *arg_media_dir = g_strdup_printf ("--media-dir=%s", - flatpak_file_get_path_cached (media_dir)); - - g_print ("Running appstreamcli compose\n"); - g_print ("Saving screenshots in %s\n", flatpak_file_get_path_cached (media_dir)); - if (!appstreamcli_compose (error, - "--prefix=/", - origin, - arg_base_url, - arg_media_dir, - result_root_arg, - data_dir, - icon_dir, - components_arg, - app_root_path, - NULL)) - return FALSE; + + g_print ("Saving screenshots in %s\n", media_dir); + if (!builder_appstreamcli_compose (builder_manifest_get_id (self), + self->id, + app_root_path, + data_dir, + icon_dir, + media_dir, + hint_dir, + url, + opt_enable_screencasts, + opt_enable_partial_urls, + error)) + return FALSE; } else { - g_print ("Running appstreamcli compose\n"); - if (!appstreamcli_compose (error, - "--prefix=/", - origin, - result_root_arg, - data_dir, - icon_dir, - components_arg, - app_root_path, - NULL)) + if (!builder_appstreamcli_compose (builder_manifest_get_id (self), + self->id, + app_root_path, + data_dir, + icon_dir, + NULL, + hint_dir, + NULL, + FALSE, + opt_enable_partial_urls, + error)) return FALSE; } } diff --git a/src/meson.build b/src/meson.build index 91798347..a15073bc 100644 --- a/src/meson.build +++ b/src/meson.build @@ -57,12 +57,15 @@ flatpak_builder_deps = [ dependency('libglnx', default_options: ['tests=false']), dependency('libxml-2.0', version: '>= 2.4'), dependency('ostree-1', version: '>= 2017.14'), + dependency('appstream', version: '>=0.15.0'), + dependency('appstream-compose', version: '>=0.15.0'), yaml_dep, ] flatpak_builder = executable( 'flatpak-builder', flatpak_builder_sources, + include_directories: include_directories('.'), dependencies: flatpak_builder_deps, install: true, )