FluidSynth 是一个用纯 C 语言编写而成的开源 MIDI 软件合成器。本文讲述了它的源代码在 Windows 64 位环境下的编译过程。
编译环境
- Windows 版本不低于 Win 8,必须为 64 位。
- 可能需要挂ti子。
注意
不能使用 MSVC 编译 FluidSynth,必须用 MSYS2 中的编译器,但是编译完成后的二进制仍然可以在 MSVC 中使用。
准备工作
准备 MSYS2
首先要下载并安装 MSYS2。它的安装过程非常简单,在这里笔者就不赘述了。
作者的 MSYS2 安装目录位于 E:\soft\MSYS2(仅供参考),此目录下面有 clang64、mingw64、usr 等文件夹。
修改环境变量
把 MSYS2 安装目录下的 clang64\bin 加入 Path 环境变量。
使用清华大学的软件包镜像源
pacman 工具替换成国内的镜像源可以加快速度,请参考:
在 MSYS2 中安装各种软件包依赖
打开 MSYS2 的 clang64.exe,输入以下指令(直接粘贴到 MSYS2 中即可):
pacman -Syyu --needed --noconfirm mingw-w64-clang-x86_64-toolchain mingw-w64-clang-x86_64-glib2 mingw-w64-clang-x86_64-libsndfile mingw-w64-clang-x86_64-ninja
安装后,MSYS2 有几率会自动关闭,这是由于 MSYS2 自我更新所导致的,不是闪退。
再次打开 MSYS2 的 clang64.exe,再次粘贴并执行刚才的指令,等待所有的软件包安装完毕。
删除动态导入库(lib*.dll.a 文件)
按下 Windows + E 快捷键,然后进入 MSYS2 的 clang64\lib 目录(以 E:\soft\msys2\clang64\lib 为例),搜索“lib*.dll.a”(星号“*”是一个通配符),除了保留 libomp.dll.a 以外,全都删除掉。
修改头文件
依次输入以下5个命令,用于搜索文本 __declspec(dllimport) 并删除,从而解决找不到 glib2 库的问题:
sed -i "s/__declspec(dllimport)//g" /clang64/include/glib-2.0/gmodule.h
sed -i "s/__declspec(dllimport)//g" /clang64/include/glib-2.0/gio/gio-visibility.h
sed -i "s/__declspec(dllimport)//g" /clang64/include/glib-2.0/glib/glib-visibility.h
sed -i "s/__declspec(dllimport)//g" /clang64/include/glib-2.0/gmodule/gmodule-visibility.h
sed -i "s/__declspec(dllimport)//g" /clang64/include/glib-2.0/gobject/gobject-visibility.h
安装 CMake
下载并安装 CMake,安装步骤省略。Download CMakehttps://cmake.org/download/
下载 FluidSynth 和 libinstpatch 的源码
FluidSynth 截至 2023年10月10日已经更新到 2.3.4,libinstpatch 版本为 1.1.6。
Releases - FluidSynth/fluidsynth - GitHubhttps://github.com/FluidSynth/fluidsynth/releases/
建议下载 Source Code(zip)格式。
解压压缩包
将这两个压缩包分别解压,笔者都解压在了 E:\t 目录下(仅供参考)。因此,将会出现两个文件夹:E:\t\fluidsynth-2.2.7 和 E:\t\libinstpatch-1.1.6。
处理 libinstpatch 并编译
FluidSynth 依赖 InstPatch 这个库,所以在编译 FluidSynth 之前要先编译 instpatch。
在 CMake 中配置 instpatch
打开 cmake-gui 程序:
如上图所示,Where is the source code 应该填写刚才解压出来的 instpatch 的文件夹(即 E:\t\libinstpatch-1.1.6);Where to build the binaries 是程序编译生成二进制的目标文件夹,应当与前者不同,以保证不会与源文件混淆。本文以 E:\t\libinstpatch-1.1.6\build 为例子。
勾选 Grouped 和 Advanced,使 CMake 在大列表框中显示的内容更加完整而有序。
点击一下 Configure,会弹出这个,点击 Yes,如下图示:
此时会询问你需要生成什么样的Generator(我们将 Makefiles 或 IDE 的工程文件称为 Generators)。我们需要将它设置为 Ninja,并选中“Specify native compilers”。如下图所示:
填写 C 和 C++ 编译器路径,如下图所示(仅供参考,对应您的 MSYS2 安装目录):
之后点击 Finish。CMake 将会扫描 instpatch 整个项目,速度较慢,请耐心等待。
扫描完毕后,大列表框内将会出现一些选项,有红的,也有白的。其中红的选项是新增的选项,应当浏览并进行修改。如下图所示:
请取消勾选:
- BUILD_SHARED_LIBS
请填写以下变量的值:
变量 | 值 |
---|---|
CMAKE_BUILD_TYPE | Release |
CMAKE_C_FLAGS | -DNDEBUG -O3 -w -fdata-sections -ffunction-sections |
CMAKE_EXE_LINKER_FLAGS | -lm -static -Wl,--gc-sections,--icf=safe,-O3 -s -lws2_32 -lffi -lpcre2-8 -logg -lflac -liconv -lvorbis -lvorbisenc -lopus -lssp -lmp3lame -lmpg123 -lshlwapi |
CMAKE_INSTALL_PREFIX | 【填写你的 MSYS2 下的 clang64 目录,libinstpatch 的所有文件将会安装到此文件夹下。必须填写绝对路径,如:E:/soft/msys2/clang64】 |
LIB_INSTALL_DIR | lib |
LIB_SUFFIX | 【空白不填】 |
填写完毕后,单击 Configure 按钮,若在大列表框中出现红色项目,应当再次点击此按钮。直到没有新增的红色项目后,点击 Generate 生成编译脚本。
使用 Ninja 编译并安装
打开 cmd.exe,然后通过 cd /d 命令切换到 libinstpatch 的构建目录(上文已经提到),命令如下:
cd /d e:\t\libinstpatch-1.1.6\build
ninja install
若没有出现任何错误,将会立即将 instpatch 安装到 MSYS2 中。
处理 FluidSynth 并编译
在 CMake 中配置 FluidSynth
仿照上文编译 instpatch 的方式,填写 Where is the source code 和 Where to build the binaries 目录(下图以 E:/t/fluidsynth-2.2.7 和 E:/t/fluidsynth-2.2.7/build 为例子):
点击 Configure,仍然采用叫做 Ninja 的构建工具,并指定编译器路径,如下两图所示:
CMake 将会扫描整个 FluidSynth 项目。稍等片刻将会扫描完毕。
您需要修改或填写以下项目:
变量 | 值 |
---|---|
DEFAULT_SOUNDFONT | C:\\Windows\\System32\\Drivers\\GM.DLS【注意里面的斜杠都是双反斜杠】 |
CMAKE_C_FLAGS | -DNDEBUG -O3 -w -fdata-sections -ffunction-sections |
CMAKE_CXX_FLAGS | -DNDEBUG -O3 -w -fdata-sections -ffunction-sections |
CMAKE_BUILD_TYPE | Release |
CMAKE_EXE_LINKER_FLAGS | -lm -static -Wl,--gc-sections,--icf=safe,-O3 -s -limm32 -lversion -liconv -lsetupapi -lws2_32 |
CMAKE_SHARED_LINKER_FLAGS | -lm -static -Wl,--gc-sections,--icf=safe,-O3 -s -lsetupapi -logg -lflac -lpsapi -lvorbis -lvorbisenc -lffi -lopus -limm32 -lversion -lpcre2-8 -liconv -lssp -lws2_32 |
CMAKE_INSTALL_PREFIX | 【FluidSynth 程序安装的目标目录,如 E:/t/fluidsynth-2.2.7/build/install 】 |
InstPatch_LIBRARY | 【libinstpatch 的静态库文件名,必须是绝对路径,如 E:/soft/msys2/clang64/libinstpatch-2.a】 |
需要取消勾选:
- enable-pulseaudio
- enable-readline
- enable-waveout
- enable-portaudio
- enable-sdl2
- enable-dbus
- enable-ladspa
- enable-network
- enable-ipv6
- enable-pipewire
确保配置是正确的
点击一下 Configure ,然后查看 CMake 输出的内容,像下面这样:
Checking whether system has ANSI C header files
ANSI C header files - found
Targeting Windows Version 0x0A00
Checking for module 'libpulse-simple>=0.9.8'
Package 'libpulse-simple', required by 'virtual:world', not found
Checking for module 'jack'
Package 'jack', required by 'virtual:world', not found
Checking for module 'libpipewire-0.3'
Package 'libpipewire-0.3', required by 'virtual:world', not found
Looking for ladspa.h
Looking for ladspa.h - not found
Found OpenMP version: 5.0 date: 201811
Looking for sinf
Looking for sinf - found
Looking for cosf
Looking for cosf - found
Looking for fabsf
Looking for fabsf - found
Looking for powf
Looking for powf - found
Looking for sqrtf
Looking for sqrtf - found
Looking for logf
Looking for logf - found
Looking for inet_ntop
Looking for inet_ntop - found
Check size of socklen_t
Check size of socklen_t - done
Could NOT find LibXslt (missing: LIBXSLT_LIBRARIES LIBXSLT_INCLUDE_DIR)
**************************************************************
Build Summary:
Build type: Release
Install Prefix: (是 FluidSynth 的安装目录)
Audio / MIDI driver support:
ALSA: no
CoreAudio: no
CoreMIDI: no
DSound: yes
JACK: no
MidiShare: no
Oboe: no
OpenSLES: no
OS/2 DART: no
OSS: no
PipeWire: no
PortAudio: no
PulseAudio: no
SDL2: no
WASAPI: yes
WaveOut: no
WinMidi: yes
Support for SF3 files: yes
Support for DLS files: yes
Audio to file rendering: yes
libsndfile: yes
Miscellaneous support:
D-Bus: no
LADSPA support: no
LASH support: no
NETWORK Support: no
IPV6 Support: no
Readline: no
systemd: no
getopt: yes
Developer nerds info:
Samples type: double
Multithread rendering: yes
OpenMP 4.0: yes
Profiling: no
Debug Build: no
Trap on FPE (debug): no
Check FPE (debug): no
UBSan (debug): no
Coverage: no
**************************************************************
Configuring done
确保以下项目的值是 yes,表示这些功能都已经启用:
- DSound
- WASAPI
- WinMidi
- Support for SF3 files
- Support for DLS files
- Audio to file rendering
- libsndfile
- getopt
- Multithread rendering
- OpenMP 4.0
其余的项目(功能)都不是 yes,表示禁用这些功能。
一个小的改动
修改 OpenMP_omp_LIBRARY 的值为:
-l:libomp.a
然后再点击 Generate。
开始编译
等到 CMake 程序输出框出现“Generating done”后,仿照上文编译 instpatch 的方法,用 cd /d 命令进入到 FluidSynth 的编译输出目录(以 e:\t\fluidsynth-2.2.7\build 为例),然后还是编译并立即安装:
cd /d e:\t\fluidsynth-2.2.7\build
ninja install
若编译的过程一切正常,将会在最后安装时输出以下信息,表示这些文件已经分别安装完毕:
进入 .\install\bin 目录,测试 fluidsynth.exe 是否安装成功:
cd install\bin
fluidsynth -V
若出现类似于上图中的信息,即为编译成功。
检查 FluidSynth 的 DLL 依赖
我们打开 MSYS2,并使用 MSYS2 自带的 ldd (LD Dependencies)命令查看它所依赖的所有 DLL 文件:
cd /e/t/fluidsynth-2.2.7/build/install/bin
ldd libfluidsynth-3.dll
ldd fluidsynth.exe
在屏幕上显示出来的这些内容就是依赖的 DLL 了。如下图所示:
除了 fluidsynth.exe 要依赖 libfluidsynth-3.dll 以外,请仔细查看其中是否含有非 Windows 系统自带的 DLL,如果有的话,请立即在评论区告诉我,我会设法解决它,并修改本文。
最后的步骤
修改 pkg-config 配置文件
* 此文件是专为 MSYS2 使用的,如果您正在使用 MSVC,则可以跳过此步骤。
用记事本打开 .\install\lib\pkgconfig 下的 fluidsynth.pc 文件,如下图所示:
请将“prefix”字段的值改为 ${pcfiledir}/../.. ,并保存此文件。
将文件复制到合适的位置
进入 MSYS2 的安装目录(以 E:\soft\msys2 为例,仅供参考),根据你使用的工具链,选择一个对应的文件夹并打开(mingw64 或 clang64 或 ucrt64),将 .\install\ 目录下的所有内容(bin、include、lib)复制到刚才打开的文件夹下。
后记
如果您在按照本文操作过程中出现任何错误,或有任何建议或意见,请立即在本文的评论区向我反馈,我会立即修改本文,具体改动请查阅下面的“本文更新记录”。
注:FluidSynth 仍在不断更新中,平均每两个月更新一次。目前已经更新到 2.3.0 版本,但不影响上文讲述的编译步骤。