cross compile mpd for windows
mpd provides win32 builds on its website, but those builds dont enable sqlite, so we cant use stickers because the server doesnt know this command; to use stickers, we need to do a custom build by ourselves; i am not sure if mpd can be compiled natively on windows; but it is certainly doable to cross compile it on linux; here i mean a real linux os, not cygwin, msys2, etc.; mpd provides, in its user manual, steps for compiling on debian, which should also work on ubuntu; our example is tested on ubuntu 18.04 lts; plus, the user manual was titled with Music Player Daemon 0.22 documentation, however, as of today, the latest mpd version is 0.21.23, thus i dont know where that 0.22 came from; maybe its author is a doc-first believer; our example uses mpd 0.21.21, which is slightly older than the latest one; the entire diff for what described in this article is available here for reference;
install build dependencies
-
install a cross compiler for windows:
apt install mingw-w64
-
install library dependencies, as shown in the manual:
apt install meson g++ \ libpcre3-dev \ libmad0-dev libmpg123-dev libid3tag0-dev \ libflac-dev libvorbis-dev libopus-dev libogg-dev \ libadplug-dev libaudiofile-dev libsndfile1-dev libfaad-dev \ libfluidsynth-dev libgme-dev libmikmod-dev libmodplug-dev \ libmpcdec-dev libwavpack-dev libwildmidi-dev \ libsidplay2-dev libsidutils-dev libresid-builder-dev \ libavcodec-dev libavformat-dev \ libmp3lame-dev libtwolame-dev libshine-dev \ libsamplerate0-dev libsoxr-dev \ libbz2-dev libcdio-paranoia-dev libiso9660-dev libmms-dev \ libzzip-dev \ libcurl4-gnutls-dev libyajl-dev libexpat-dev \ libasound2-dev libao-dev libjack-jackd2-dev libopenal-dev \ libpulse-dev libshout3-dev \ libsndio-dev \ libmpdclient-dev \ libnfs-dev libsmbclient-dev \ libupnp-dev \ libavahi-client-dev \ libsqlite3-dev \ libsystemd-dev \ libgtest-dev \ libboost-dev \ libicu-dev \ libchromaprint-dev \ libgcrypt20-dev
these dependencies are for native compiling on linux, most of which may not be necessary for a cross compile; but they give you an idea what libraries could be needed and make it easier to find their sources by tracing distro build files for those packages; you may skip this step if your disk is low;
-
now you probably find the
meson
version provided by your distro isnt the one listed in mpd manual (0.49.0), and it is no easy downgrade; fortunately, this tool is written in python and is available in pypi; so you can install the exact version with:pip install meson==0.49.0
then use this one instead of that provided by your distro;
add sqlite to mpd dependencies
collecting and compiling all the library dependencies look really cumbersome; so
the mpd author includes a helper script win32/build.py
to help with compiling
on windows; this script automates dependency installs; so we can install sqlite
by adding it to the dependency list;
the list is defined in python/build/libs.py
; apply this diff in its end:
diff --git a/python/build/libs.py b/python/build/libs.py
index 7c317d4..fc7ff9c 100644
--- a/python/build/libs.py
+++ b/python/build/libs.py
@@ -401,3 +401,13 @@ boost = BoostProject(
'59c9b274bc451cf91a9ba1dd2c7fdcaf5d60b1b3aa83f2c9fa143417cc660722',
'include/boost/version.hpp',
)
+
+libsqlite3 = AutotoolsProject(
+ 'https://www.sqlite.org/2020/sqlite-autoconf-3310100.tar.gz',
+ '62284efebc05a76f909c580ffa5c008a7d22a1287285d68b7825a2b6b51949ae',
+ 'lib/libsqlite3.a',
+ [
+ '--disable-shared', '--enable-static',
+ ],
+ autoreconf=True,
+)
this is a nifty change because sqlite3 is an autotools project, for which the build helper already defines how to install;
then add libsqlite3
to win32/build.py
:
diff --git a/win32/build.py b/win32/build.py
index 0e09003..edb5ae2 100755
--- a/win32/build.py
+++ b/win32/build.py
@@ -101,6 +101,7 @@ thirdparty_libs = [
libexpat,
libnfs,
boost,
+ libsqlite3,
]
fix a bug
the build fails when sqlite is added, because there is a bug with sqlite in mpd 0.21.21, which i believe hasnt been fixed in latest; this bug doesnt show up on linux, but on windows;
the bug is about passing a path to a sqlite function; the path may contain wide chars, but the sqlite function expects a utf-8 encoded one; this is easy to fix, because the path class has a member function to convert itself to utf8, which is invoked right after the sqlite function call; move it before the call to fix this bug:
diff --git a/src/sticker/StickerDatabase.cxx b/src/sticker/StickerDatabase.cxx
index 99aa32d..3de24c2 100644
--- a/src/sticker/StickerDatabase.cxx
+++ b/src/sticker/StickerDatabase.cxx
@@ -108,9 +108,9 @@ sticker_global_init(Path path)
/* open/create the sqlite database */
- ret = sqlite3_open(path.c_str(), &sticker_db);
+ const std::string utf8 = path.ToUTF8();
+ ret = sqlite3_open(utf8.c_str(), &sticker_db);
if (ret != SQLITE_OK) {
- const std::string utf8 = path.ToUTF8();
throw SqliteError(sticker_db, ret,
("Failed to open sqlite database '" +
utf8 + "'").c_str()); ## build
finally we can start our build; the manual says:
mkdir -p output/win64
cd output/win64
../../win32/build.py --64
we add an option to enable sqlite in the last line:
../../win32/build.py --64 -Dsqlite=enabled
i havent tested if this additional option is necessary or not, but this option is mentioned somewhere in the manual, and obviously harmless here;
result
the build, when successfully completed, generates a statically linked mpd.exe
,
which is enabled with sqlite; it is a much fatter file (~100 mb) than the
prebuilt one on mpd website (~7 mb), but does its job; you can run it in cmd or
powershell, with any mpd clients working on windows; now it is my time to give
recommendation about my client ncmpy, which i now find much more usable and
convenient than mpc or ncmpc; thanks to python and curses, all i need to do is
to run this command in msys2 (may not be working in cmd or powershell):
pip install ncmpy
this saves me quite some effort cross compiling another linux program;
test
the cross compiled mpd.exe
can be tested on windows with a simple config file
like this:
music_directory "C:/music"
db_file "C:/mpd/database"
log_file "C:/mpd/log"
playlist_directory "C:/mpd/playlists"
pid_file "C:/mpd/pid"
state_file "C:/mpd/state"
sticker_file "C:/mpd/sticker.sql"
you dont even have to define audio_output
: mpd will automatically find one if
none is specified in the config file;