先决条件

  特定历史版本依赖的详细环境和平台库版本参见开发文档 doc/Dependencies.txt 。以下仅为当前最新主分支版本中用于构建 YSLib 自身及基于 YSLib 开发应用的环境配置说明。

  关于本项目对平台的定义和项目保持的环境约束,包括开发需要的以下基础环境外的其它第三方依赖,在了解下文内容后,参见开发说明

注意 获取到源代码并不保证能够直接构建 YSLib (特别是对于直接从版本库获取的途径)。如需自行构建,应注意开发说明中有关外部依赖项的部分获取必要的其它文件。

  关于运行环境,另见运行时平台环境的说明

  详细提交测试的环境参见开发文档 doc/Test.txt

  若不使用特定的特性或构建平台,构建环境的部分要求是可选的。

  以下各节的环境配置以“宿主平台/目标平台(目标平台名)”为标题指定,其中目标平台名是正式的配置名称(也在其它项目文档中作为配置名称使用),若和平台一致则被省略;其它平台的标识当前仅为明确开发流程,在用户文档中使用。对宿主平台和目标平台两者一致的情形,只标识一个平台。关于“平台”的一般含义,参见术语

公共构建环境

  构建环境提供工具链(语言实现)和构建需要的工具。某些工具被不同的构建环境共享(但可能仍需针对不同构建平台使用不同二进制程序)。

  Windows 平台上的 MSYS2 基础环境符合以下公共构建环境的所有要求。当前发布和一般提交(包括本机平台和交叉构建)时仅测试 MSYS2 。

命令行环境

  除非另行指定,构建环境的命令兼容 POSIX shell 。当前非 POSIX shell 的命令行构建环境仅在 Sysroot stage 2 环境 被支持。

工具链

  使用 make 的平台需要 POSIX shell 支持。

  除非另行指定, make 使用 GNU make ,版本 3.78 以上(建议使用 4.0 以上版本,虽然 YSLib makefile 不使用不兼容的特性);不使用 mingw32-make

  注意 make 可能被构建工具使用,详见以下链接时优化的说明。

  POSIX shell 实现可使用和工具脚本兼容的脚本解释环境 ,一般即 bash (建议版本 4.0 或以上)。

  除非另行指定,直接支持的 C++ 实现为 GNU C++ 4.9 或以上版本。

自动环境检测

  在命令行环境中使用脚本构建时,脚本可能自动检测构建环境而需要附加的工具。这些工具可能在具体的构建环境(如以下各节)中可能已被提供或可选安装,参阅各个构建环境附带的文档。

  • grep :用于判断线程支持的命令行选项。
  • uname :用于查询平台配置。

  使用特定的选项跳过自动检测构建时,可不依赖某些工具。详见具体脚本的说明。

控制台和终端

  除了自动检测环境( Win32 或非 Win32 下使用 ANSI 转义序列)开启的彩色(前景色)文本,构建环境没有使用依赖特定终端的字符界面。因此可以使用不同的控制台或终端模拟器。

注意 在 Windows 平台上若使用 ConEmu 出现 0xC0000005 错误,尝试升级到最新版本后勾选 Inject ConEmuHk 选项 ,或直接使用 cmd 代替。

线程执行环境

  除非另行指定,线程执行环境使用 ISO C++ 的定义,参见 ISO C++ [intro.multithread]

  库或接口的集合对多线程环境的依赖性满足以下要求:

  • 明确不依赖多线程执行环境时,保证在指定平台上可用的的公开 API 可构建并满足接口约定的语义,可在单线程执行环境中运行。
  • 明确严格不依赖多线程执行环境时,在不依赖多线程执行环境的要求上,还应保证语义一致。
  • 否则,不保证接口提供的功能可用。

  YSLib 整体不依赖多线程执行环境。特定的依赖多线程执行的情形包括以下话题:

  • 使用 ISO C++ 线程环境(首先要求实现满足整体要求):
    • 运行时环境需要部署的线程支持库,参见以下章节对各个平台的说明。
    • 特定的依赖线程环境语义的接口,参见具体组件的开发文档(如 doc/YSLib.txt )及源代码中的 API 注释或以此构建 API 文档
  • 特定的平台实现使用非 ISO C++ 线程模型或实现(不保证平台中立):
    • 不会作为对所有平台必要的公开接口。
    • YCLib 提供 POSIX API 封装。
    • 其它实现细节参见开发文档 doc/YCLib.txt 等。

链接时优化(LTO)

  YSLib 默认在 release 构建配置下通过向编译器和链接器传递命令行参数 -flto 等启用 LTO 。若工具链不支持 LTO ,可能需要自行修改脚本去除相关选项——这不被正式支持。

  MSYS2 的 MinGW 目标的 binutils-git 包的 gnu-ar 较早启用了 LTO 插件,可以直接使用。现在 MSYS2 的 MinGW 目标的 binutils 包也应支持。其它工具链需自行验证。

注意 GCC 4.9 起使用 LTO 默认不启用 -ffat-lto-objects 选项,因此需要链接器具有 LTO 插件支持,否则在启用 -flto 选项时会出现无法解析符号的链接错误。

注意 GCC 的 LTO wrapper 默认使用 make ,若没有 make 也没有通过指定 MAKE 环境变量替代,构建时使用 -flto 会失败。

PC/DS(DS)

  支持的构建环境:

  • DS 交叉编译环境,包括
    • 使用 make 的公共构建环境
    • ARM 目标平台 C/C++ 交叉编译环境
    • 生成 .nds 文件的 ndstool 工具
    • 环境变量 DEVKITARM 指定工具路径(见以下说明)

  支持的运行环境:

  • Nintendo/iQue DS[Lite/i/LL]
    • 仅测试了 iQue DS Lite
  • DeSmuME 0.9.9 (注意新版本因为自动 DLDI 存在缺陷,暂时不支持运行自制程序。)

  环境变量 DEVKITARM 指定一个 POSIX 路径,其中的 bin 子目录下包括工具。示例( POSIX shell 使用 Windows 路径):

export DEVKITARM=/C/devkitPro/devkitARM

  建议使用发布时最新版本的 devkitPro

  devkitPro 在 Windows 下提供 MSYS ,在 devkitPro 安装目录下 msys/bin 包含 bash 等程序。可把此路径添加到环境变量 PATH 。也可使用 MSYS2 替代。

  发布和一般提交时仅测试 devkitPro 最新版本,目标平台三元组 arm-none-eabi。

PC(Win32)

  Windows 平台使用 Microsoft VC++ 构建。因为一些已知的问题,暂不正式支持。参见以下 MinGW32 平台的构建条件以获取 Windows 可执行文件。

  但以下的部分信息和 MinGW 通用。

Windows 子系统(subsystem)

  Windows NT 内核以上支持不同的称为子系统 的用户模式运行时环境 ,主要包括 Win32 子系统、 OS/2 子系统和 POSIX 子系统。

  因为标准库实现以及 YFramework 的部分组件依赖 Win32 API , YSLib 在 Windows 上的实现依赖 Win32 子系统。

  Microsoft Visual C++ 提供 /SUBSYSTEM 链接器选项来指定不同的子系统。在此 CONSOLE 指定控制台程序,而 WINDOWS 指定非控制台的通常使用 GUI 的程序,它们都使用 Win32 子系统实现。

  控制台程序和 GUI 程序的入口不同,也有一些行为上的不同。例如,启动控制台程序默认会显示命令行窗口; GUI 程序忽略命令行的交互式输入。

操作系统版本

  Windows 操作系统版本一般对(非交叉编译的)构建没有直接影响,但有以下例外:

  GCC 的预编译头文件不保证对系统兼容:升级系统后可能出现错误,例如升级 Windows 10 1803 以后的系统,使用旧的预编译头文件(而不更改编译器二进制文件),可能出现以下内部错误:

internal error in mingw32_gt_pch_use_address, at config/i386/host-mingw32.c:184: MapViewOfFileEx: 试图访问无效的地址。

  此时删除所有预编译头文件,或不使用预编译头文件重新构建即可。类似的问题在其它的项目中也是已知的问题,使用类似的方式解决。

  另外,部分 Windows 版本可能存在不明原因的内核缺陷导致类似的问题。不仅限于构建,这些问题可能对运行也有影响。

预编译头文件

  部分构建使用可选的预编译头文件。

PC(MinGW32)

  MinGW32 包含 32 位和 64 位宿主和目标平台。关于 MinGW 或 MinGW32 的称谓,参见这里的说明。

  支持的构建环境:

  • 目标 32 位(i686) MinGW GCC 工具链。
    • 支持不同的 MinGW 运行时
      • MinGW-W64 (目标三元组 i686-w64-mingw32 )。
      • MinGW.org (目标平台三元组 i686-pc-mingw32 )
    • 要求标准库多线程支持,否则只支持构建 YBase ,不支持构建 YFramework 。
      • 当前 GCC 官方的 libstdc++ 只提供 POSIX 线程模型的支持,不支持 Win32 线程模型。
      • 可考虑使用 mcfgthread
    • 仅测试 Windows 上的本机构建(构建平台三元组同目标平台三元组)。
      • 一般提交时仅测试 MinGW-W64 的发行版。

  非正式支持的构建环境:

  • 目标 64 位(x86_64) MinGW GCC 工具链(目标平台三元组 x86_64-w64-mingw32 或 x86_64-pc-mingw32 )。
  • 以上工具链中使用 LLVM 和 Clang++ 代替 GCC 。
    • 只测试 MSYS2 。
    • 当前暂不支持 LLD( MSYS2 包 mingw32/mingw-w64-i686-lld )。

  对 i686 平台, YSLib 版本库中 /YFramework/MinGW32/lib-i686 目录用于保存外部依赖项 FreeType2 和修改版 FreeImage 的二进制文件。

  对 x86_64 平台,需要自行编译依赖项。若构建环境存在可二进制兼容的 FreeType2 ,只需要编译修改版本的 FreeImage 。

  支持的运行环境:

  • Microsoft Windows XP 或以上版本操作系统
    • 对于 64 位目标工具链构建的程序,需要 64 位操作系统
  • 构建环境匹配的附加运行库,默认支持的工具链包括:
    • libwinpthread-1.dll
    • libgcc_s_dw2-1.dll
    • libstdc++-6.dll

  注意以上运行库未在发布版本中打包。此处依赖的详细说明参见开发文档 doc/Dependencies.txt @1.5.2 。

  若缺少 DLL ,也可在 MinGW32 GCC 发行版中的 bin 目录下找到。

特别注意 应使用对应的正确的线程模型(使用 POSIX 或 MCF 而不是 Win32 ,后者没有实现标准库的线程支持)以及异常模型( i686 为 Dwarf2 和 SjLj 之一,特定构建版本相关)。运行时 DLL 不匹配会导致错误。

MSYS2

  建议使用 MSYS2 ,相关问题可参考官方 Wiki

  MSYS2 以从 Arch Linux 移植的 pacman 作为包管理器,可以直接通过命令行安装和移除不同的包,包括开发工具。以下环境也可用于开发其它 MSYS2 或 MinGW32 应用(忽略标注为 YSLib 的步骤即可)。

体系结构和命令行调用

  一个 MSYS2 环境同时支持 MSYS2 和 i686(x86) 和 x86_64(x64) 的 MinGW32 三个目标平台。其中 MSYS2 目标类似 Cygwin ,运行时依赖特定的 POSIX 兼容层 DLL (这里一般是 msys-2.0.dll ),性能往往较依赖 MSVCRT (默认版本现在 Windows 系统中应都已存在部署)的 MinGW32 目标低。所以不需要严格的 POSIX 兼容的应用尽量使用 MinGW 而不是 MSYS2 目标。

  MSYS2 自身也存在不同的体系结构而成为目标平台。和 MinGW32 不同,每个基础环境是 i686 和 x86_64 之一。在 x64 Windows 上,可以通过部署多个基础环境,合理设置环境变量 PATH 来切换使用 i686 或 x86_64 (而 32 位 Windows 只支持 i686 )路径;但一般情形下只需要使用其中之一。这个决定一般会作用到所有 MSYS2 程序,如 bash

  不论是 i686 还是 x86_64 的 MSYS2 基础环境,都可以选择安装 i686 或 x86_64 的 MinGW32 目标的包,但因为使用不同的 MSYS2 程序,两者并非可完全替换。

注意 因为基础环境中 uname 是位于 /usr/bin 的 MSYS2 程序,基础环境的体系结构会影响 uname 的结果而导致目标体系结构的自动判断结果不同,当前可能会影响后续需要的命令,详见 MinGW Sysroot 开发指令

注意 MSYS2 程序和不同体系结构的(本机或其它 MSYS2 )程序混用可能出现问题。参见下文关于 MSYS2 程序运行问题的说明。

  一个 MSYS2 环境中可能同时存在不同目标的程序,通过合理控制环境变量 PATH 的顺序或在调用时加前缀(prefix) 控制。例如 /usr/bin/gcc.exe/mingw32/bin/gcc.exe 可能同时存在,分别是 MSYS2 和 i686 MinGW32 的 GCC ,可通过以下方式确定调用 MinGW32 GCC :

  • PATH 中使 /mingw32/bin 尽量靠前来指定 gcc 调用 MinGW32 而不是 MSYS2 GCC
  • 若存在 i686-w64-mingw32-gcc 等明确目标平台的版本,一般可以直接在命令行中代替 gcc
  • 明确路径前缀,即使用 /mingw32/bin/gcc 代替 gcc

  某些工具可能在附加路径前缀 /mingw32 指定此类程序的安装位置。但当前 YSLib 不提供工具控制这些部署方式,默认只使用第一种方式:手动配置 PATH

  MSYS2 MinGW 工具链使用 POSIX 线程模型。

  MSYS2 MinGW i686 工具链使用 Dwarf2 异常模型。

  当前 YSLib 不支持 MSYS 目标。

主要配置步骤

  (某些步骤和原理也可参考官方 Wiki 。)

  • 进入官方发布站点/北京理工大学镜像/清华大学 TUNA 镜像/中国科学技术大学开源软件镜像的其中一个子目录下载 MSYS2 基础环境

    • 目录 i686x86_64 针对 MSYS2 而非 MinGW32 目标
    • 一般尽量选择较新的 x86_64 版本
    • 如果有能解压缩 .xz 的软件,可以直接下载压缩包,否则选择 .exe 文件;对应版本内容一致
  • 安装 MSYS2 基础环境到自定义的目录如 C:\msys2 (以下称为MSYS2 根目录

    • 注意 Win32 下 PATH_MAX260 ,此处最好避免过长的路径以使一些软件具有更好的兼容性
    • 对压缩包直接利用现有工具解压;对可执行文件直接执行安装
    • 之后,必须执行 MSYS2 根目录下的 msys2_shell.bat 确保完成安装
  • 设置环境变量

    • 可总是使用 MSYS2 根目录下自带的批处理文件打开 终端(默认是 mintty ),会自动在终端环境的 PATH 变量前加入对应所需的路径,不需要另行设置
      • 对较新的版本(安装了 filesystem-2016.05-2 或更新版本的包)的 MSYS2 基础环境安装,分别运行 msys2_shell.cmd -msysmsys2_shell.cmd -mingw32mingw64_shell.bat -mingw64 进入对应的 MSYS2 、 MinGW32 和 MinGW64 的 shell
      • 对未更新 filesystem-2016.05-2 或更新版本的包的 MSYS2 旧版本基础环境安装,分别运行 msys2_shell.cmdmingw32_shell.batmingw64_shell.bat 进入对应的 MSYS2 、 MinGW32 和 MinGW64 的 shell
    • 也可直接一次性设置 Windows 系统环境变量(注意需要符合 Windows 的路径格式,每个路径之间以分号分隔),这样可以对其它命令行环境(如 cmd )生效
      • 需要设置 bash 所在的 MSYS 工具的目录(即 MSYS2 根目录下的 /usr/bin )以及 MinGW 目标编译器和其它工具所在的目录(对 32 位的目标为 MSYS2 根目录下的 /mingw32/bin
      • 注意 因为 MSYS 和 MinGW 是不同的目标,使用不同的 GCC (可能被同时安装),需要保证 MinGW 编译器被优先搜索,所以 MinGW 目录一般应在 MSYS 目录之前
    • 一些构建环境可能会依赖环境变量 MSYSTEM 的值, MSYS2 根目录批处理文件进入的不同环境对此有不同的设置,但当前 YSLib 不依赖此变量,可以不另行设置
  • 确保能搜索到正确的 MinGW 编译器

    • 可以进入 Shell 执行命令 /usr/bin/which gcc ,确定输出的结果为 MinGW 编译器(默认为 /mingw32/bin/gcc.exe/mingw64/bin/gcc.exe 之一)而不是 MSYS 编译器(默认为 /usr/bin/gcc.exe
    • 若已确保 MSYS 根目录下 /usr/bin 目录在环境变量 PATH 中,直接进入 cmd 或 Shell 直接执行 which gcc ,方法和效果与上述方法相同
    • 可以直接在命令行执行 gcc -v 查看输出,确认 Target: 带有后缀 -w64-mingw32
  • 建议手动执行 pacman -Syu 自行升级,或 pacman -S 安装所需的包的最新版本

  • 若用于构建 YSLib ,建议获取源代码后,进入 bash (此处也可以使用其它 Shell )后运行 POSIX Shell 脚本 Tools/msys2-pacman-update.sh 以确保 YSLib 构建需要的依赖项被安装

    • 脚本不会重复安装已经安装的包

  上述脚本调用 MSYS2 的包管理器 pacman 分批下载安装或更新所需工具:首先安装必要的工具,其次安装可选(但推荐)的工具。具体内容详见脚本代码。若安装工具时需要确认,按 Y 并回车。

配置安装源

  官方镜像配置参见 pacman-mirrors

  若 pacman 下载过慢,可用文本编辑器打开 MSYS 根目录下的 /etc/pacman.d 中的配置文件,编辑对应的镜像地址。如对于 32 位的 MinGW 包,在 mirrorlist.mingw32 的其它非注释行之前插入:

## 清华大学 TUNA 镜像( 2016-09-23 已变更,注意大小写)
Server = http://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686
## 中国科学技术大学开源软件镜像(之前曾停止更新,最后更新 2015-06-18 ; 2015-11-01 已恢复)
Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686
## 北京理工大学镜像(最后更新早于 2017-02-09)
Server = http://mirror.bit.edu.cn/msys2/REPOS/MINGW/i686

  因为包 mingw-w64-x86_64-freetype 的 FreeType2 可二进制兼容, x86_64 平台只需要编译修改版本的 FreeImage 。

MSYS2 程序运行问题

  MSYS2 类似 Cygwin ,依赖 fork 调用创建新进程。这可能会出错。

  在执行以下步骤(参考这里)后,重新运行程序:

  • 关闭窗口或用任务管理器终止 sh.exebash.exe 等进程并尽量确保没有基于 MSYS2 环境的其它程序正在被运行
  • 执行 MSYS 根目录下的 autorebase.bat

  也可以参考 Cygwin 的解决方法

  混用 x86/x64 程序(不管是 Win32 还是 MSYS 程序)导致的类似问题可能经以上步骤仍然无法修复,这可由 MSYS2 在特定操作系统上的一个缺陷引起。变通做法是只使用固定目标的程序,例如只使用 i686 MSYS 基础系统执行 i686 MinGW32 GCC 。注意 i686 MinGW32 GCC 是 x86 的 Win32 程序。尽管它不是 MSYS2 程序,但可在 LTO 时调用 MSYS2 程序 make ,这时候可能出错。

  如果确定只使用少数程序,在命令行指定替换。例如 x86_64 的 MSYS2 bash 环境中使用 i686 MinGW32 GCC ,指定 LTO 调用的 make

export MAKE=/path-to-another-msys2-root/mingw32/make

  或直接替换所有 make

export make=/path-to-another-msys2-root/mingw32/make

注意 %SystemRoot%\System32\cmd.exe 在 x64 Windows 下是 x64 程序,对应的 x86 版本是 %SystemRoot%\SysWOW64\cmd.exe

GCC with the MCF thread model

  也可使用 MCF 线程模型构建的 GCC ,基于 MinGW-W64 和 mcfgthread ,使用 MCF 线程模型。

  这个发行版没有 make

  需自行编译依赖项。

  未在提交中测试。

MinGW-Builds

  也可使用 MinGW-W64 发行版,如 mingw-builds ,并自行获得和配置脚本 Tools/msys2-pacman-update.sh 中被安装的工具。

  需使用基于 POSIX 线程模型的版本,否则只可用 YBase 。

  需自行编译依赖项。

  当前未测试。

Nuwen.net

  对 x86_64 平台可使用 newen.net 提供的 MinGW 发行版,包含比较多的第三方库。

  仍需自行编译依赖项以支持 YFramework (当前不支持)。

  因为 15.2 之前的版本仅支持 Win32 线程模型,不支持 std::thread 等标准库线程 API ,不支持生成 YFramework ,只支持生成 YBase 。

  当前未测试。

Windows 子系统(subsystem)

  基本内容参见以上 PC(Win32) 平台关于 Windows 子系统(subsystem) 的介绍。

  在 MinGW 工具链的命令行中,选项 -mconsole-mwindows 对应 Microsoft VC++ 工具链的子系统选项。若没有指定,一般默认为前者。通常 -mwindows 隐式使用一些附加的库,如 -lgdi32 -lcomdlg32 。和 VC++ 不同,当前使用的 MinGW 实现一般可以支持统一使用 main 作为入口,不需要特别修改。

  对 gccg++ ,使用 -dumpspecs 查看内建支持的 specs 。 Clang/Clang++ 不适用 specs ,需要查看文档和源代码。

PC/Android

  支持的构建环境:

  • Android 开发环境(仅测试 Windows x64 宿主环境),包括:
    • 使用 make 的公共构建环境。
    • JDK(仅测试 Oracle JDK 1.8 ;注意 Android 仅支持部分 Java 8 特性)。
    • Android SDK 。
    • Android SDK Build-tools 。
    • Android NDK (仅使用独立工具链)。
    • 用于打包 APK 的私钥(用 Tools/create-android-debug-keystore.sh 可生成默认私钥)。

  支持的运行环境:

  • Android 模拟器,运行操作系统 Android 5 (对应 API level 21 ),或更高版本(未测试,可能有兼容性问题)。
  • 物理设备,操作系统要求同上(未正式测试,可能有兼容性问题)。

PC/Linux

  当前仅用于可移植性测试。要点:

  • 当前仅测试 x86-64 (提供 FreeImage 二进制文件)
  • 可用被支持版本的 G++ 或 Clang++
  • 因为不提供 freetype2 的二进制库,需要保证 freetype2 库文件可用,可以通过 pkg-source 找到或位于 /usr/lib 路径中
  • 使用 XCB 作为系统库,但功能不全

  Windows 10 可使用 WSL(Windows Subsystem for Linux)

  注意 Windows 10 秋季创意者更新(版本 1709 )的 WSL 存在已知可导致并行构建失败的缺陷 ,以及可能有的其它问题 ,本项目不针对这些问题单独提供变通。

其它构建环境

  集成开发环境是可选的,参见构建

  关于文档构建需要的依赖,参见构建文档

  关于执行工具脚本需要的环境,参见脚本