☰
Mesen 从源码编译实战:Windows/Linux 独立版、Libretro 核心与 PGO 优化构建全流程
2026/10/14 17:03:42 网站建设 项目流程
  • 硬件仿真
  • 游戏开发

【免费下载链接】Mesen

Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++ and C#

项目地址:https://gitcode.com/gh_mirrors/me/Mesen
点击查看免费下载

本文以 Mesen 仓库的 COMPILING.md 为主体,完整讲解在 Windows(Visual Studio)和 Linux(makefile)上编译 Mesen 独立版与 Libretro 核心的每一步操作,并结合根目录 makefile、Libretro/Makefile、buildPGO.sh 等构建脚本源码,深入解析平台参数、LTO、PGO 等编译选项背后的实际机制,帮助读者从零完成一次可运行、可发布、可性能优化的完整构建。

一、编译路线总览:同一套核心代码,四种产物

Mesen 是一个跨平台(Windows & Linux)的 NES/Famicom 模拟器,核心用 C++ 编写,UI 用 C# 编写(见 README.md)。从 Mesen.sln 解决方案文件可以看到,整个项目由 10 个子工程组成:

  • C++ 侧:Core(模拟核心)、Utilities(通用工具)、Windows(Windows 平台层)、InteropDLL(C++/C# 互操作层)、SevenZip(归档解压)、Lua(脚本引擎)、Libretro(RetroArch 核心)、TestHelper(ROM 测试)、PGOHelper(PGO 采样运行器);
  • C# 侧:GUI.NET(主界面)、UpdateHelper(更新器)、DependencyPacker(依赖打包)。

解决方案中定义了 5 套配置:Debug、Release、Libretro、PGO Profile、PGO Optimize,平台覆盖x86、x64、Any CPU。这正好对应四条编译路线:

目标平台工具链产物
Standalone(GUI 版)WindowsVisual Studio 2019Mesen.exe+ 依赖
Standalone(GUI 版)Linuxclang/g++ + Mono (xbuild)bin/<平台>/Release/Mesen.exe(Mono 运行)
Libretro 核心WindowsVS2019 或 MINGWmesen_libretro.dll
Libretro 核心Linuxmake(C++14 编译器)mesen_libretro.so

二、Windows 平台编译

2.1 Standalone 独立版(Visual Studio 2019)

按照 COMPILING.md 的官方步骤:

  1. 用 Visual Studio 2019 打开 Mesen.sln;
  2. 将GUI.NET设为启动项目(Startup Project);
  3. 以Release/x64或Release/x86配置编译;
  4. 运行Mesen.exe。

官方文档还给出两条重要的环境提示,均可在仓库中得到印证:

  • 确保解决方案中所有工程都成功加载。Mesen.sln 中工程之间存在明确的依赖链,例如InteropDLL依赖Utilities、Windows、Lua、Core,GUI.NET依赖InteropDLL等,任何一个工程加载失败都会导致链接缺失。
  • 若报错提示项目针对 .NET Framework 4.5:选择下载缺失的组件,再通过 Visual Studio Installer 安装 ".NET Framework 4.5 targeting pack"。这一点有源码佐证——GUI.NET/GUI.NET.csproj 中明确写着<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>,UpdateHelper与DependencyPacker同为 .NET Framework 4.5,因此缺少该 targeting pack 时无法编译任何 C# 工程。

从解决方案结构看,Standalone 版的运行形态是:C# 的GUI.NET主程序通过InteropDLL暴露的接口调用 C++ 的Core,互操作入口位于 InteropDLL/ConsoleWrapper.cpp(其中声明了Console、CheatManager、MovieManager等核心对象的托管封装),C++ 平台层则在Windows/目录下。

2.2 Libretro 核心(Visual Studio 或 MINGW)

编译 Libretro 核心(用于 RetroArch 等前端)的步骤:

  1. 在 Visual Studio 2019 中打开解决方案;
  2. 以Libretro/x64或Libretro/x86配置编译;
  3. 使用产物bin/(x64 或 x86)/Libretro/mesen_libretro.dll。

文档同时指出:也可以不依赖 Visual Studio,直接用 MINGW 配合Libretro子目录中的 makefile 构建。Libretro/Makefile 正是标准的 RetroArch 核心构建脚本,它自动检测宿主平台(unix / MINGW / osx / ios / libnx 等),在 Windows(MINGW)下产出mesen_libretro.dll,并默认静态链接 libgcc/libstdc++(-static-libgcc -static-libstdc++ -s)以减小分发体积。

三、Linux 平台编译(Standalone)

3.1 编译器与依赖要求

Linux 下编译 Mesen 的要求(引自 COMPILING.md):

  • clang 7.0+ 或 gcc 9.0+——因为 Mesen 需要支持 filesystem API(std::filesystem)的 C++17 编译器;
  • Mono 5.18+(包:mono-devel)——用于构建和运行 C# UI;
  • SDL2(包:libsdl2-dev)——Linux 平台的窗口/输入/音频后端。

文档特别强调 Mono 版本下限的原因:Mono 5.18 以下(如 4.2.2)存在稳定性与性能问题,可能导致崩溃和 UI 变慢;Ubuntu 18.04 默认的 Mono 4.6.2 还会引发 Mesen 界面布局问题,因此建议按官方指引安装更新版本。README.md 中"运行 Mesen 所需包"一节也重申了这一点,并给出最小运行依赖:mono-complete、libsdl2-2.0、gnome-themes-standard。

从源码结构看,C++17 filesystem 依赖是真实存在的:例如 PGOHelper/PGOHelper.cpp 优先#include <filesystem>,回退到<experimental/filesystem>。另外,根 makefile 中定义了FSLIB=-lstdc++fs,链接时始终带上——这是 gcc 9 时代链接std::filesystem所需的库。SDL2 则通过sdl2-config --libs/--cflags探测(makefile 第 86-87 行),所以必须安装libsdl2-dev才能通过sdl2-config。

3.2 makefile 参数详解

makefile 顶部自带了参数说明,完整梳理如下:

变量/写法作用
make默认构建 x64 Standalone(all指向ui目标)
MESENPLATFORM=x86 make切换为 32 位构建(追加-m32),缺省为 x64(-m64)
LTO=true make开启链接期优化,追加-flto;官方文档称可获得 25-30%+ 的性能提升
USE_GCC=true make使用 gcc/g++;缺省使用 clang/clang++
PGO=profile/PGO=optimize分别启用 clang 的-fprofile-instr-generate/-fprofile-instr-use(GCC 下对应-fprofile-generate/-fprofile-use),用于 PGO 两阶段构建
STATICLINK=true make追加-static-libgcc -static-libstdc++,静态链接运行时库
SYSTEM_LIBEVDEV=true用系统libevdev(通过pkg-config)替代仓库内置的 Linux/libevdev

其他可参考的目标:

  • make run:构建后执行mono bin/<平台>/Release/Mesen.exe启动模拟器;
  • make debug:带MONO_LOG_LEVEL=debug启动,用于排查 Mono 层问题;
  • make testhelper/make runtests/make rungametests:构建并运行 TestHelper/TestHelper.cpp 的 ROM 回归测试;
  • make libretro:等价于MESENFLAGS=-D LIBRETRO构建核心,产出mesen_libretro.<平台>.so并复制到bin/;
  • make pgo:调用 buildPGO.sh 执行 PGO 优化构建(见第五节);
  • make official:调用 build.sh,这是官方发布用的构建脚本(不构建 UI);
  • make clean:清理各目录下的obj.<平台>与bin/<平台>/Release。

关于 LTO,makefile 中的注释写道:"LTO gives a 25-30% performance boost, so use it whenever you can",这与 COMPILING.md 中"clang 下 LTO 带来 25-30%+ 提升,强烈建议开启"的说法一致,官方还补充了实测观察:LTO 的收益主要在 clang 上体现(gcc 下"似乎没有帮助")。

3.3 Standalone 构建流程拆解(ui 目标)

make的默认目标ui实际上串联了 C++ 与 C# 两侧,流程值得拆开看(makefile 第 92-100 行):

  1. 编译链接 C++ 共享库libMesenCore.<平台>.dll:将InteropDLL/*.cpp与 Core、Utilities、SevenZip、Lua、Linux 平台层、libevdev 全部对象一起以-shared -Wl,-z,defs链接,其中-Wl,-z,defs强制所有符号必须有定义,避免运行时缺符号;
  2. 用 Mono 的xbuild工具构建 C# 侧UpdateHelper(自动更新器);
  3. 将GUI.NET/Dependencies/下的运行时依赖(字体、Lua 脚本等)连同libMesenCore一并复制到bin/<平台>/Release/Dependencies/,并打包为Dependencies.zip;
  4. 再次用xbuild构建GUI.NET主程序,并注入HIDETESTMENU,DISABLEAUTOUPDATE两个预处理器常量——即源码构建的本地版会隐藏测试菜单并禁用自动更新。

最终产物位于bin/<平台>/Release/,用mono Mesen.exe运行即可,与 README 中对 Linux 运行方式的说明一致。

四、Linux Libretro 核心编译

COMPILING.md 对 Linux Libretro 的说明较简短:

需要一个支持 C++14 的 clang/gcc 版本;在Libretro子目录中运行make即可构建 Libretro 核心。

这里"C++14 即可"(比 Standalone 的 C++17 要求低)在 Libretro/Makefile 中得到印证:第 327-328 行为 C/C++ 分别追加-D LIBRETRO与-std=c++14。也就是说,编译时通过LIBRETRO宏切换平台实现(渲染/音频/输入由 Libretro/LibretroRenderer.h、LibretroSoundManager.h、LibretroKeyManager.h等提供,替代 Linux 下的 SDL 后端),且核心代码本身不依赖 C++17 的 filesystem API。

其他值得了解的细节:

  • 源码清单在 Libretro/Makefile.common 中显式列出:SevenZip 的 20 个 C 文件 +libretro.cpp+ 约 100 个Core/*.cpp+ 约 40 个Utilities/*.cpp(含 HQX、xBRZ、Scale2x 等滤镜实现),与 Standalone 构建共用同一套Core与Utilities源码;
  • 符号导出控制:unix 平台链接时使用-Wl,--version-script=link.T -Wl,--no-undefined,Libretro/link.T 的内容是global: retro_*; local: *;——即只导出retro_*系列 Libretro ABI 接口,其余符号全部私有,--no-undefined则保证核心自包含;
  • 优化选项:LTO=true make可追加-flto(此时链接器切换为 g++),DEBUG=1 make可产出带调试信息的-O0 -g构建;
  • 产物为mesen_libretro.so,可放入 RetroArch 的cores/目录使用。

五、进阶:PGO 优化构建(官方发布的性能来源)

buildPGO.sh 与 build.sh 揭示了 Mesen 官方构建的完整 PGO(Profile-Guided Optimization)流水线,值得单独说明,因为它解释了"开发构建比官方构建慢 20-30%"的原因(README.md 提到开发构建未经 PGO 优化)。

5.1 准备工作:录制采样 ROM

  1. 将若干*.nes文件放入 PGOHelper/PGOGames 目录。该目录下的说明文件指出:其中所有.nes文件都会以 console 模式运行数秒,作为 PGO 的采样负载;官方建议使用覆盖不同 mapper 的多种 ROM 以获得更好的采样代表性;
  2. 运行采样程序时会在其旁边创建PGOMesenHome临时目录,作为 Mesen 运行期间写入文件的 home 位置。

5.2 两阶段构建流程

make pgo(clang,或USE_GCC=true make pgo)会执行以下动作(对应 buildPGO.sh 逻辑):

  1. 阶段一(插桩):以LTO=true STATICLINK=true PGO=profile重新构建核心,并构建pgohelper可执行文件。pgohelper的入口在 PGOHelper/PGOHelper.cpp:扫描 ROM 目录后调用核心导出的PgoRunTest(testRoms, enableDebugger)(声明见 Core/PgoUtilities.h),逐个加载并运行 ROM 采集分支/内联剖面数据(clang 下写入pgo.profraw);
  2. 运行插桩二进制:执行./pgohelper完成采样;
  3. 合并剖面:clang 下执行llvm-profdata merge -output=pgo.profdata pgo.profraw将原始剖面合并;
  4. 阶段二(优化重建):以PGO=optimize(-fprofile-instr-use)重新构建,编译器据此对热路径做内联与调度优化,最终产物为bin/x64/Release/Mesen.exe。

buildPGO.sh 的注释给出了效果数据:在 clang 下,"PGO + LTO" 相比普通make可带来60% 左右的提速;同时脚本也提醒,GCC 虽然能走通整个流程,但产物运行时性能"相当糟糕"(构建方式可能有问题)。

5.3 官方发布构建

make official调用的 build.sh 用于官方发布:

  • Libretro 分支:分别在 x64/x86 下以LTO=true执行make clean && make libretro -j 16;
  • 默认分支:分别在 x64/x86 下执行BUILDTARGET=core ./buildPGO.sh,然后把两份libMesenCore.<平台>.dll复制到bin/Any CPU/PGO Profile/Dependencies/,供 Visual Studio 的PGO Profile配置使用——这也解释了 Mesen.sln 中PGO Profile/PGO Optimize两套配置在 Windows 侧的存在意义。

六、常见构建问题速查

现象原因与处理
VS 中编译 C# 工程报 .NET Framework 4.5 相关错误通过 Visual Studio Installer 安装 ".NET Framework 4.5 targeting pack"(C# 工程均针对 .NET Framework 4.5,见 GUI.NET/GUI.NET.csproj)
Linux 下 C++17 filesystem 相关编译错误确认 clang ≥ 7.0 或 gcc ≥ 9.0;gcc 下链接期需要-lstdc++fs(makefile 已自动处理)
Linux 下sdl2-config找不到安装libsdl2-dev
Linux 下运行后界面卡顿/布局异常/崩溃Mono 版本过低,升级到 Mono 5.18+(安装mono-devel)
想用系统手柄库而非内置实现SYSTEM_LIBEVDEV=true make(需要libevdev的 pkg-config 支持)
构建产物性能偏低加LTO=true(25-30%+ 提升);追求极致可执行make pgo(clang 下约 +60%)
想要可分发的静态核心STATICLINK=true make,静态链接 libgcc/libstdc++

七、参考文件索引

  • 编译指南原文:COMPILING.md
  • Linux 主构建脚本:makefile、build.sh、buildPGO.sh
  • Libretro 构建:Libretro/Makefile、Libretro/Makefile.common、Libretro/link.T、Libretro/libretro.cpp
  • PGO 采样工具:PGOHelper/PGOHelper.cpp、Core/PgoUtilities.h
  • 解决方案与工程配置:Mesen.sln、GUI.NET/GUI.NET.csproj、InteropDLL/ConsoleWrapper.cpp
  • 运行依赖说明:README.md
  • 硬件仿真
  • 游戏开发

【免费下载链接】Mesen

Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++ and C#

项目地址:https://gitcode.com/gh_mirrors/me/Mesen
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询