- 硬件仿真
- 游戏开发
【免费下载链接】Mesen
Mesen is a cross-platform (Windows & Linux) NES/Famicom emulator built in C++ and C#
本文以 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 版) | Windows | Visual Studio 2019 | Mesen.exe+ 依赖 |
| Standalone(GUI 版) | Linux | clang/g++ + Mono (xbuild) | bin/<平台>/Release/Mesen.exe(Mono 运行) |
| Libretro 核心 | Windows | VS2019 或 MINGW | mesen_libretro.dll |
| Libretro 核心 | Linux | make(C++14 编译器) | mesen_libretro.so |
二、Windows 平台编译
2.1 Standalone 独立版(Visual Studio 2019)
按照 COMPILING.md 的官方步骤:
- 用 Visual Studio 2019 打开 Mesen.sln;
- 将
GUI.NET设为启动项目(Startup Project); - 以
Release/x64或Release/x86配置编译; - 运行
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 等前端)的步骤:
- 在 Visual Studio 2019 中打开解决方案;
- 以
Libretro/x64或Libretro/x86配置编译; - 使用产物
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 行):
- 编译链接 C++ 共享库
libMesenCore.<平台>.dll:将InteropDLL/*.cpp与 Core、Utilities、SevenZip、Lua、Linux 平台层、libevdev 全部对象一起以-shared -Wl,-z,defs链接,其中-Wl,-z,defs强制所有符号必须有定义,避免运行时缺符号; - 用 Mono 的
xbuild工具构建 C# 侧UpdateHelper(自动更新器); - 将
GUI.NET/Dependencies/下的运行时依赖(字体、Lua 脚本等)连同libMesenCore一并复制到bin/<平台>/Release/Dependencies/,并打包为Dependencies.zip; - 再次用
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
- 将若干
*.nes文件放入 PGOHelper/PGOGames 目录。该目录下的说明文件指出:其中所有.nes文件都会以 console 模式运行数秒,作为 PGO 的采样负载;官方建议使用覆盖不同 mapper 的多种 ROM 以获得更好的采样代表性; - 运行采样程序时会在其旁边创建
PGOMesenHome临时目录,作为 Mesen 运行期间写入文件的 home 位置。
5.2 两阶段构建流程
make pgo(clang,或USE_GCC=true make pgo)会执行以下动作(对应 buildPGO.sh 逻辑):
- 阶段一(插桩):以
LTO=true STATICLINK=true PGO=profile重新构建核心,并构建pgohelper可执行文件。pgohelper的入口在 PGOHelper/PGOHelper.cpp:扫描 ROM 目录后调用核心导出的PgoRunTest(testRoms, enableDebugger)(声明见 Core/PgoUtilities.h),逐个加载并运行 ROM 采集分支/内联剖面数据(clang 下写入pgo.profraw); - 运行插桩二进制:执行
./pgohelper完成采样; - 合并剖面:clang 下执行
llvm-profdata merge -output=pgo.profdata pgo.profraw将原始剖面合并; - 阶段二(优化重建):以
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#
相关推荐
RenderDoc 全平台编译指南:Windows / Linux / macOS / Android 从源码构建实战
RenderDoc 全平台编译指南:Windows / Linux / macOS / Android 从源码构建实战 RenderDoc 是一款独立的图形调试
开发工具调试器图形学GPUdouyin-downloader 实战指南:抖音无水印批量下载完整教程
douyin downloader 实战指南:抖音无水印批量下载完整教程 douyin downloader 是一套面向抖音无水印下载的开源免费命令行工具:粘一
网页爬虫CLIPrusaSlicer 源码构建完全指南:从零编译 Windows / macOS / Linux 版本
PrusaSlicer 源码构建完全指南:从零编译 Windows / macOS / Linux 版本 导读 本文是 PrusaSlicer 官方源码构建指南
桌面应用3D渲染
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考