mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-13 23:22:56 +00:00
Allow building on Windows with MinGW
Add various fixes to enable us to build a selection of useful USB plugins. Also, skip tests that don't make sense on WIN32 or that will not work. With much help from Mario Limonciello <mario.limonciello@dell.com> -- Thanks!
This commit is contained in:
parent
3e3a0277c9
commit
45a00738d8
@ -28,6 +28,33 @@ jobs:
|
|||||||
paths:
|
paths:
|
||||||
- "dist/docs"
|
- "dist/docs"
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
docker:
|
||||||
|
- image: fedora:31
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: "Install deps"
|
||||||
|
command: dnf install -y diffutils
|
||||||
|
glib2-devel
|
||||||
|
git-core
|
||||||
|
gnutls-utils
|
||||||
|
meson
|
||||||
|
gcc
|
||||||
|
gcab
|
||||||
|
mingw64-gcc
|
||||||
|
mingw64-pkg-config
|
||||||
|
mingw64-glib2
|
||||||
|
mingw64-libgusb
|
||||||
|
mingw64-sqlite
|
||||||
|
mingw64-libarchive
|
||||||
|
mingw64-json-glib
|
||||||
|
mingw64-libsoup
|
||||||
|
wine
|
||||||
|
- run:
|
||||||
|
name: "Build Win32"
|
||||||
|
command: ./contrib/ci/build_windows.sh
|
||||||
|
|
||||||
build-snap:
|
build-snap:
|
||||||
docker:
|
docker:
|
||||||
- image: ubuntu:18.04
|
- image: ubuntu:18.04
|
||||||
@ -102,6 +129,7 @@ workflows:
|
|||||||
version: 2
|
version: 2
|
||||||
main:
|
main:
|
||||||
jobs:
|
jobs:
|
||||||
|
- build-windows
|
||||||
- build-ubuntu-x86_64
|
- build-ubuntu-x86_64
|
||||||
- build-snap
|
- build-snap
|
||||||
- check-abi
|
- check-abi
|
||||||
|
67
contrib/ci/build_windows.sh
Executable file
67
contrib/ci/build_windows.sh
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
#prep
|
||||||
|
export LC_ALL=C.UTF-8
|
||||||
|
export DESTDIR=`pwd`/dist
|
||||||
|
build=`pwd`/build
|
||||||
|
rm -rf $DESTDIR $build
|
||||||
|
|
||||||
|
#build
|
||||||
|
mkdir -p $build $target && cd $build
|
||||||
|
meson .. \
|
||||||
|
--cross-file=../contrib/mingw64.cross \
|
||||||
|
--prefix=/ \
|
||||||
|
--libexecdir=$target \
|
||||||
|
--bindir=$target \
|
||||||
|
-Dbuild=standalone \
|
||||||
|
-Dgpg=false \
|
||||||
|
-Dplugin_coreboot=false \
|
||||||
|
-Dplugin_flashrom=false \
|
||||||
|
-Dplugin_uefi=false \
|
||||||
|
-Dplugin_redfish=false \
|
||||||
|
-Dplugin_altos=false \
|
||||||
|
-Dplugin_dell=false \
|
||||||
|
-Dplugin_nvme=false \
|
||||||
|
-Dsystemd=false \
|
||||||
|
-Dplugin_emmc=false \
|
||||||
|
-Dplugin_amt=false \
|
||||||
|
-Dintrospection=false \
|
||||||
|
-Dplugin_thunderbolt=false \
|
||||||
|
-Dplugin_synaptics=false \
|
||||||
|
-Dman=false \
|
||||||
|
-Dgcab:introspection=false \
|
||||||
|
-Dgcab:docs=false \
|
||||||
|
-Dgcab:nls=false \
|
||||||
|
-Dgcab:vapi=false \
|
||||||
|
-Dgcab:tests=false \
|
||||||
|
-Dlibxmlb:introspection=false \
|
||||||
|
-Dlibxmlb:gtkdoc=false \
|
||||||
|
-Dgudev=false $@
|
||||||
|
ninja -v
|
||||||
|
|
||||||
|
#prepare archive to run on Windows
|
||||||
|
ninja -v install
|
||||||
|
cd $DESTDIR
|
||||||
|
|
||||||
|
#so that it's actually executable
|
||||||
|
cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/*.dll .
|
||||||
|
|
||||||
|
#move these so they work
|
||||||
|
mv fwupd/*.exe .
|
||||||
|
|
||||||
|
#remove static archives
|
||||||
|
find -type f -name "*.dll.a" | xargs rm -f
|
||||||
|
|
||||||
|
#remove stuff that we really don't need
|
||||||
|
rm -fr gcab.exe \
|
||||||
|
xb-tool.exe \
|
||||||
|
share/man \
|
||||||
|
include \
|
||||||
|
fwupd \
|
||||||
|
lib/*.a \
|
||||||
|
lib/pkgconfig/ \
|
||||||
|
var
|
||||||
|
|
||||||
|
export WINEPATH="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/;$build/libfwupd/;$build/subprojects/libxmlb/src/;$build/subprojects/gcab/libgcab/"
|
||||||
|
#TODO: fixup tests
|
||||||
|
ninja -C $build test || true
|
13
contrib/mingw64.cross
Normal file
13
contrib/mingw64.cross
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[binaries]
|
||||||
|
c = '/usr/bin/x86_64-w64-mingw32-gcc'
|
||||||
|
cpp = '/usr/bin/x86_64-w64-mingw32-g++'
|
||||||
|
ar = '/usr/bin/x86_64-w64-mingw32-ar'
|
||||||
|
strip = '/usr/bin/x86_64-w64-mingw32-strip'
|
||||||
|
pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'
|
||||||
|
exe_wrapper = '/usr/bin/wine'
|
||||||
|
|
||||||
|
[host_machine]
|
||||||
|
system = 'windows'
|
||||||
|
cpu_family = 'x86_64'
|
||||||
|
cpu = 'i686'
|
||||||
|
endian = 'little'
|
@ -152,6 +152,15 @@ fwupd_get_os_release (GError **error)
|
|||||||
g_autofree gchar *buf = NULL;
|
g_autofree gchar *buf = NULL;
|
||||||
g_auto(GStrv) lines = NULL;
|
g_auto(GStrv) lines = NULL;
|
||||||
|
|
||||||
|
/* TODO: Read the Windows version */
|
||||||
|
#ifdef _WIN32
|
||||||
|
hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
g_hash_table_insert (hash,
|
||||||
|
g_strdup("OS"),
|
||||||
|
g_strdup("Windows"));
|
||||||
|
return hash;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* find the correct file */
|
/* find the correct file */
|
||||||
for (guint i = 0; paths[i] != NULL; i++) {
|
for (guint i = 0; paths[i] != NULL; i++) {
|
||||||
g_debug ("looking for os-release at %s", paths[i]);
|
g_debug ("looking for os-release at %s", paths[i]);
|
||||||
|
@ -150,6 +150,8 @@ fwupd_remote_download_func (void)
|
|||||||
gboolean ret;
|
gboolean ret;
|
||||||
g_autofree gchar *fn = NULL;
|
g_autofree gchar *fn = NULL;
|
||||||
g_autofree gchar *directory = NULL;
|
g_autofree gchar *directory = NULL;
|
||||||
|
g_autofree gchar *expected_metadata = NULL;
|
||||||
|
g_autofree gchar *expected_signature = NULL;
|
||||||
g_autoptr(FwupdRemote) remote = NULL;
|
g_autoptr(FwupdRemote) remote = NULL;
|
||||||
g_autoptr(GError) error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
@ -159,6 +161,14 @@ fwupd_remote_download_func (void)
|
|||||||
"fwupd",
|
"fwupd",
|
||||||
"remotes.d",
|
"remotes.d",
|
||||||
NULL);
|
NULL);
|
||||||
|
expected_metadata = g_build_filename (FWUPD_LOCALSTATEDIR,
|
||||||
|
"lib",
|
||||||
|
"fwupd",
|
||||||
|
"remotes.d",
|
||||||
|
"lvfs",
|
||||||
|
"metadata.xml.gz",
|
||||||
|
NULL);
|
||||||
|
expected_signature = g_strdup_printf ("%s.asc", expected_metadata);
|
||||||
fwupd_remote_set_remotes_dir (remote, directory);
|
fwupd_remote_set_remotes_dir (remote, directory);
|
||||||
fn = g_build_filename (FU_SELF_TEST_REMOTES_DIR, "remotes.d", "lvfs.conf", NULL);
|
fn = g_build_filename (FU_SELF_TEST_REMOTES_DIR, "remotes.d", "lvfs.conf", NULL);
|
||||||
ret = fwupd_remote_load_from_filename (remote, fn, NULL, &error);
|
ret = fwupd_remote_load_from_filename (remote, fn, NULL, &error);
|
||||||
@ -172,10 +182,8 @@ fwupd_remote_download_func (void)
|
|||||||
g_assert (fwupd_remote_get_metadata_uri_sig (remote) != NULL);
|
g_assert (fwupd_remote_get_metadata_uri_sig (remote) != NULL);
|
||||||
g_assert_cmpstr (fwupd_remote_get_title (remote), ==, "Linux Vendor Firmware Service");
|
g_assert_cmpstr (fwupd_remote_get_title (remote), ==, "Linux Vendor Firmware Service");
|
||||||
g_assert_cmpstr (fwupd_remote_get_report_uri (remote), ==, "https://fwupd.org/lvfs/firmware/report");
|
g_assert_cmpstr (fwupd_remote_get_report_uri (remote), ==, "https://fwupd.org/lvfs/firmware/report");
|
||||||
g_assert_cmpstr (fwupd_remote_get_filename_cache (remote), ==,
|
g_assert_cmpstr (fwupd_remote_get_filename_cache (remote), ==, expected_metadata);
|
||||||
FWUPD_LOCALSTATEDIR "/lib/fwupd/remotes.d/lvfs/metadata.xml.gz");
|
g_assert_cmpstr (fwupd_remote_get_filename_cache_sig (remote), ==, expected_signature);
|
||||||
g_assert_cmpstr (fwupd_remote_get_filename_cache_sig (remote), ==,
|
|
||||||
FWUPD_LOCALSTATEDIR "/lib/fwupd/remotes.d/lvfs/metadata.xml.gz.asc");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* verify we used the FirmwareBaseURI just for firmware */
|
/* verify we used the FirmwareBaseURI just for firmware */
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#ifdef HAVE_FNMATCH_H
|
#ifdef HAVE_FNMATCH_H
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
|
#elif _WIN32
|
||||||
|
#include <shlwapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <archive_entry.h>
|
#include <archive_entry.h>
|
||||||
@ -1655,6 +1657,10 @@ fu_common_fnmatch (const gchar *pattern, const gchar *str)
|
|||||||
g_return_val_if_fail (str != NULL, FALSE);
|
g_return_val_if_fail (str != NULL, FALSE);
|
||||||
#ifdef HAVE_FNMATCH_H
|
#ifdef HAVE_FNMATCH_H
|
||||||
return fnmatch (pattern, str, FNM_NOESCAPE) == 0;
|
return fnmatch (pattern, str, FNM_NOESCAPE) == 0;
|
||||||
|
#elif _WIN32
|
||||||
|
g_return_val_if_fail (strlen (pattern) < MAX_PATH, FALSE);
|
||||||
|
g_return_val_if_fail (strlen (str) < MAX_PATH, FALSE);
|
||||||
|
return PathMatchSpecA (str, pattern);
|
||||||
#else
|
#else
|
||||||
return g_strcmp0 (pattern, str) == 0;
|
return g_strcmp0 (pattern, str) == 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -174,7 +174,7 @@ fu_quirks_add_quirks_for_path (FuQuirks *self, XbBuilder *builder,
|
|||||||
g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
|
g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
|
||||||
|
|
||||||
/* load from keyfile */
|
/* load from keyfile */
|
||||||
xb_builder_source_add_adapter (source, "text/plain",
|
xb_builder_source_add_adapter (source, "text/plain,.quirk",
|
||||||
fu_quirks_convert_quirk_to_xml_cb,
|
fu_quirks_convert_quirk_to_xml_cb,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
if (!xb_builder_source_load_file (source, file,
|
if (!xb_builder_source_load_file (source, file,
|
||||||
|
@ -565,6 +565,11 @@ fu_common_spawn_func (void)
|
|||||||
g_autofree gchar *fn = NULL;
|
g_autofree gchar *fn = NULL;
|
||||||
const gchar *argv[3] = { "replace", "test", NULL };
|
const gchar *argv[3] = { "replace", "test", NULL };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
g_test_skip ("Known failures on Windows right now, skipping spawn func test");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
fn = g_build_filename (TESTDATADIR_SRC, "spawn.sh", NULL);
|
fn = g_build_filename (TESTDATADIR_SRC, "spawn.sh", NULL);
|
||||||
argv[0] = fn;
|
argv[0] = fn;
|
||||||
ret = fu_common_spawn_sync (argv,
|
ret = fu_common_spawn_sync (argv,
|
||||||
@ -583,6 +588,11 @@ fu_common_spawn_timeout_func (void)
|
|||||||
g_autofree gchar *fn = NULL;
|
g_autofree gchar *fn = NULL;
|
||||||
const gchar *argv[3] = { "replace", "test", NULL };
|
const gchar *argv[3] = { "replace", "test", NULL };
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
g_test_skip ("Known failures on Windows right now, skipping spawn timeout test");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
fn = g_build_filename (TESTDATADIR_SRC, "spawn.sh", NULL);
|
fn = g_build_filename (TESTDATADIR_SRC, "spawn.sh", NULL);
|
||||||
argv[0] = fn;
|
argv[0] = fn;
|
||||||
ret = fu_common_spawn_sync (argv, fu_test_stdout_cb, &lines, 50, NULL, &error);
|
ret = fu_common_spawn_sync (argv, fu_test_stdout_cb, &lines, 50, NULL, &error);
|
||||||
|
@ -89,6 +89,7 @@ library_deps = [
|
|||||||
libjsonglib,
|
libjsonglib,
|
||||||
libgcab,
|
libgcab,
|
||||||
valgrind,
|
valgrind,
|
||||||
|
platform_deps,
|
||||||
]
|
]
|
||||||
|
|
||||||
fwupdplugin_mapfile = 'fwupdplugin.map'
|
fwupdplugin_mapfile = 'fwupdplugin.map'
|
||||||
|
26
meson.build
26
meson.build
@ -155,10 +155,17 @@ prefix = get_option('prefix')
|
|||||||
|
|
||||||
bindir = join_paths(prefix, get_option('bindir'))
|
bindir = join_paths(prefix, get_option('bindir'))
|
||||||
libdir = join_paths(prefix, get_option('libdir'))
|
libdir = join_paths(prefix, get_option('libdir'))
|
||||||
datadir = join_paths(prefix, get_option('datadir'))
|
|
||||||
libexecdir = join_paths(prefix, get_option('libexecdir'))
|
libexecdir = join_paths(prefix, get_option('libexecdir'))
|
||||||
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
|
#this ends up in compiled code, ignore prefix
|
||||||
localstatedir = join_paths(prefix, get_option('localstatedir'))
|
if host_machine.system() == 'windows'
|
||||||
|
sysconfdir = get_option('sysconfdir')
|
||||||
|
localstatedir = get_option('localstatedir')
|
||||||
|
datadir = get_option('datadir')
|
||||||
|
else
|
||||||
|
datadir = join_paths(prefix, get_option('datadir'))
|
||||||
|
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
|
||||||
|
localstatedir = join_paths(prefix, get_option('localstatedir'))
|
||||||
|
endif
|
||||||
mandir = join_paths(prefix, get_option('mandir'))
|
mandir = join_paths(prefix, get_option('mandir'))
|
||||||
localedir = join_paths(prefix, get_option('localedir'))
|
localedir = join_paths(prefix, get_option('localedir'))
|
||||||
|
|
||||||
@ -223,6 +230,13 @@ gcab = find_program('gcab', required : true)
|
|||||||
bashcomp = dependency('bash-completion', required: false)
|
bashcomp = dependency('bash-completion', required: false)
|
||||||
python3 = find_program('python3')
|
python3 = find_program('python3')
|
||||||
|
|
||||||
|
platform_deps = []
|
||||||
|
if get_option('default_library') != 'static'
|
||||||
|
if host_machine.system() == 'windows'
|
||||||
|
platform_deps += cc.find_library('shlwapi')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if valgrind.found()
|
if valgrind.found()
|
||||||
conf.set('HAVE_VALGRIND', '1')
|
conf.set('HAVE_VALGRIND', '1')
|
||||||
endif
|
endif
|
||||||
@ -368,7 +382,11 @@ conf.set_quoted('FWUPD_SYSCONFDIR', sysconfdir)
|
|||||||
conf.set_quoted('FWUPD_LOCALEDIR', localedir)
|
conf.set_quoted('FWUPD_LOCALEDIR', localedir)
|
||||||
|
|
||||||
if build_standalone
|
if build_standalone
|
||||||
plugin_dir = join_paths(libdir, 'fwupd-plugins-3')
|
if host_machine.system() == 'windows'
|
||||||
|
plugin_dir = 'fwupd-plugins-3'
|
||||||
|
else
|
||||||
|
plugin_dir = join_paths(libdir, 'fwupd-plugins-3')
|
||||||
|
endif
|
||||||
conf.set_quoted('FWUPD_PLUGINDIR', plugin_dir)
|
conf.set_quoted('FWUPD_PLUGINDIR', plugin_dir)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -4988,11 +4988,13 @@ fu_engine_load (FuEngine *self, FuEngineLoadFlags flags, GError **error)
|
|||||||
if (self->loaded)
|
if (self->loaded)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* TODO: Read registry key [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography] "MachineGuid" */
|
||||||
|
#ifndef _WIN32
|
||||||
/* cache machine ID so we can use it from a sandboxed app */
|
/* cache machine ID so we can use it from a sandboxed app */
|
||||||
self->host_machine_id = fwupd_build_machine_id ("fwupd", error);
|
self->host_machine_id = fwupd_build_machine_id ("fwupd", error);
|
||||||
if (self->host_machine_id == NULL)
|
if (self->host_machine_id == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
#endif
|
||||||
/* read config file */
|
/* read config file */
|
||||||
if (flags & FU_ENGINE_LOAD_FLAG_READONLY_FS)
|
if (flags & FU_ENGINE_LOAD_FLAG_READONLY_FS)
|
||||||
config_flags |= FU_CONFIG_LOAD_FLAG_READONLY_FS;
|
config_flags |= FU_CONFIG_LOAD_FLAG_READONLY_FS;
|
||||||
|
@ -420,7 +420,9 @@ fu_engine_requirements_device_func (gconstpointer user_data)
|
|||||||
" <firmware compare=\"ge\" version=\"1.2.3\"/>"
|
" <firmware compare=\"ge\" version=\"1.2.3\"/>"
|
||||||
" <firmware compare=\"eq\" version=\"4.5.6\">bootloader</firmware>"
|
" <firmware compare=\"eq\" version=\"4.5.6\">bootloader</firmware>"
|
||||||
" <firmware compare=\"eq\" version=\"FFFF\">vendor-id</firmware>"
|
" <firmware compare=\"eq\" version=\"FFFF\">vendor-id</firmware>"
|
||||||
|
#ifndef _WIN32
|
||||||
" <id compare=\"ge\" version=\"4.0.0\">org.kernel</id>"
|
" <id compare=\"ge\" version=\"4.0.0\">org.kernel</id>"
|
||||||
|
#endif
|
||||||
" </requires>"
|
" </requires>"
|
||||||
" <provides>"
|
" <provides>"
|
||||||
" <firmware type=\"flashed\">12345678-1234-1234-1234-123456789012</firmware>"
|
" <firmware type=\"flashed\">12345678-1234-1234-1234-123456789012</firmware>"
|
||||||
@ -2073,6 +2075,10 @@ fu_plugin_module_func (gconstpointer user_data)
|
|||||||
"Integrated Webcam™");
|
"Integrated Webcam™");
|
||||||
g_signal_handlers_disconnect_by_data (self->plugin, &device);
|
g_signal_handlers_disconnect_by_data (self->plugin, &device);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
g_test_skip ("No offline update support on Windows");
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
/* schedule an offline update */
|
/* schedule an offline update */
|
||||||
g_signal_connect (device, "notify::status",
|
g_signal_connect (device, "notify::status",
|
||||||
G_CALLBACK (_plugin_status_changed_cb),
|
G_CALLBACK (_plugin_status_changed_cb),
|
||||||
|
@ -765,6 +765,8 @@ fu_util_download_if_required (FuUtilPrivate *priv, const gchar *perhapsfn, GErro
|
|||||||
|
|
||||||
/* a local file */
|
/* a local file */
|
||||||
uri = soup_uri_new (perhapsfn);
|
uri = soup_uri_new (perhapsfn);
|
||||||
|
if (g_file_test (perhapsfn, G_FILE_TEST_EXISTS))
|
||||||
|
return g_strdup (perhapsfn);
|
||||||
if (uri == NULL)
|
if (uri == NULL)
|
||||||
return g_strdup (perhapsfn);
|
return g_strdup (perhapsfn);
|
||||||
|
|
||||||
|
@ -568,6 +568,8 @@ fu_util_download_if_required (FuUtilPrivate *priv, const gchar *perhapsfn, GErro
|
|||||||
g_autoptr(SoupURI) uri = NULL;
|
g_autoptr(SoupURI) uri = NULL;
|
||||||
|
|
||||||
/* a local file */
|
/* a local file */
|
||||||
|
if (g_file_test (perhapsfn, G_FILE_TEST_EXISTS))
|
||||||
|
return g_strdup (perhapsfn);
|
||||||
uri = soup_uri_new (perhapsfn);
|
uri = soup_uri_new (perhapsfn);
|
||||||
if (uri == NULL)
|
if (uri == NULL)
|
||||||
return g_strdup (perhapsfn);
|
return g_strdup (perhapsfn);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[wrap-git]
|
[wrap-git]
|
||||||
directory = libxmlb
|
directory = libxmlb
|
||||||
url = https://github.com/hughsie/libxmlb.git
|
url = https://github.com/hughsie/libxmlb.git
|
||||||
revision = 0.1.13
|
revision = 0.1.14
|
||||||
|
Loading…
Reference in New Issue
Block a user