MSYS2 の構成が大きく変更
最近(最近でもないか・・)、MSYS2 の構成が大きく変更になり、昔の環境と大きく様変わりしています。
自分は、主に MSYS2 の下で clang や gcc コンパイラを使って、OpenGL、GLFW、などを利用したアプリを実装していました。
最近、RXマイコン関係の作業を継続して行っていて PC 環境用アプリを触らない状況が長く続いていました。
そんな折 PC 環境用アプリを作ろうと思い、そーいえば、MSYS2 のアップデートをしてないなぁーと思い、MSYS2 の環境整備から始めました。
ところが、MSYS2 のアップデートが上手く出来ないのです・・・
どうやら、システムが大きく変更になり、昔の環境は廃止になったようで、コンフリクトを起こしているようです。
そこで、MSYS2 の古い環境を一応保持して、新規に MSYS2 をインストールして、最初から環境を作り直す事にしました。
MSYS2 の本体は、C:/msys64 なので、それを単純に、リネームして残してあります。
新しい MSYS2 には、複数のショートカットが増えている。
新規に、「MSYS2 CLANG64」、「MSYS2 UCRT64」が増えています。
※ショートカットには無いですが、実際には「CLANG32」もあります。
今まで、「clang」は、「MINGW64」と同居していましたが、分離したようです。
「UCRT64」は何でしょうか?
ここで、MSYS2 の解説を観に行きました。
Overview
Name | Prefix | Toolchain | Architecture | C Library | C++ Library |
---|---|---|---|---|---|
msys | MSYS | /usr | gcc | x86_64 | cygwin |
ucrt64 | UCRT64 | /ucrt64 | gcc | x86_64 | ucrt |
clang64 | CLANG64 | /clang64 | llvm | x86_64 | ucrt |
clangarm64 | CLANGARM64 | /clangarm64 | llvm | aarch64 | ucrt |
clang32 | CLANG32 | /clang32 | llvm | i686 | ucrt |
mingw64 | MINGW64 | /mingw64 | gcc | x86_64 | msvcrt |
mingw32 | MINGW32 | /mingw32 | gcc | i686 | msvcrt |
どうやら上記のような違いがあるようです。
MSYS2 のパッケージは一般的な Linux ディストリビューションのパッケージのように動作します。
それに加えて、Windows 依存のツールキットライブラリで API を叩く事が出来るので、プログラミングの幅が広がります。
自分は、この環境が非常に心地よく、色々な事をやるのに便利なので長らく使い続けています。
良く、C++ なら VisualStudio を使えば良いのにと言われる事がありますが、オープンソースのコードをコンパイルして組み込むのに適しているし。
Linux や Mac 環境にも親和性が高いので、当分この環境を離れられません。
CLANG64 環境に色々パッケージをインストール
MSYS2 のパッケージマネージャーは、「Arch Linux」で知られる「pacman」が使われています。
最近の実装では、マルチスレッドで複数パッケージをインストールするなど、かなり便利に使えるようになっています。
キーワードでパッケージを探す:
% pacman -Ss xxxxx
パッケージのインストール:
% pacman -S xxxxx
CLANG64 環境のパッケージをインストール:
pacman は、どの環境で動かしても、良く、各環境毎にプレフィックスを追加するだけです。
たとえば、libpng は、環境毎に以下のような名称になっています。
% pacman -Ss libpng
clangarm64/mingw-w64-clang-aarch64-libpng 1.6.39-1
A collection of routines used to create PNG format graphics (mingw-w64)
mingw32/mingw-w64-i686-libpng 1.6.39-1
A collection of routines used to create PNG format graphics (mingw-w64)
mingw64/mingw-w64-x86_64-libpng 1.6.39-1 [インストール済み: 1.6.38-1]
A collection of routines used to create PNG format graphics (mingw-w64)
ucrt64/mingw-w64-ucrt-x86_64-libpng 1.6.39-1 [インストール済み: 1.6.38-1]
A collection of routines used to create PNG format graphics (mingw-w64)
clang32/mingw-w64-clang-i686-libpng 1.6.39-1
A collection of routines used to create PNG format graphics (mingw-w64)
clang64/mingw-w64-clang-x86_64-libpng 1.6.39-1 [インストール済み: 1.6.38-1]
A collection of routines used to create PNG format graphics (mingw-w64)
CLANG64 用パッケージは「mingw-w64-clang-x86_64-libpng」となります。
俺俺アプリケーションのビルド
自分のアプリケーションビルドに必要な各種パッケージをインストールします。
pacman -S mingw-w64-clang-x86_64-clang
pacman -S mingw-w64-clang-x86_64-boost
pacman -S mingw-w64-clang-x86_64-glfw
pacman -S mingw-w64-clang-x86_64-freetype
pacman -S mingw-w64-clang-x86_64-glew
pacman -S mingw-w64-clang-x86_64-libjpeg-turbo
pacman -S mingw-w64-clang-x86_64-openjpeg2
pacman -S mingw-w64-clang-x86_64-libpng
pacman -S mingw-w64-clang-x86_64-faad2
pacman -S mingw-w64-clang-x86_64-libmad
pacman -S mingw-w64-clang-x86_64-ffmpeg
次に、自分のアプリをビルドしようとしますが、意味不明のエラーで先に進みません・・・
In file included from C:/msys64/clang64/include/c++/v1/__type_traits/apply_cv.h:16:
In file included from C:/msys64/clang64/include/c++/v1/__type_traits/remove_reference.h:13:
C:/msys64/clang64/include/c++/v1/cstddef:50:9: error: no member named 'nullptr_t' in the global namespace
using ::nullptr_t;
~~^
In file included from main.cpp:7:
これは、単に、Makefile で与えているインクルードパスが余計な為でした・・・
clang++ -c -O2 -std=c++17 -DWIN32 -DBOOST_USE_WINDOWS_H -DHAVE_STDINT_H -DNDEBUG -isystem /clang64/include -isystem /clang64/include/freetype2 -isystem /clang64/include/openjpeg-2.5 -isystem /clang64/include/openjpeg-1.5 -I. -I../common -Wall -Werror -Wno-unused-private-field -Wno-unused-variable -Wno-unused-function -Wno-unused-but-set-variable -o release/main.o main.cpp
※「-isystem /clang64/include」が不必要
clang コンパイラは、起動すると、自身の環境に適した順序で、標準的なインクルードパスを内部で設定します。
この仕組みは結構複雑で、このような指定は、それを阻害するようです。
取り除いたら、素直にコンパイル出来ました。
以前の、mingw64 の時は、この指定が無いと、逆に正しくコンパイル出来なかった覚えがあります。
「freetype」や「openjpeg」では、ルートのディレクトリーを追加で指定する必要があるので、以下のように「Makefile」に記述しています。
LOCAL_INC_PATH := /clang64/include
INC_SYS = $(LOCAL_INC_PATH)/freetype2 $(OPENJPEG_PATH) \
$(INC_USR)
openjpeg はバージョンがあるので、簡易的に、バージョン番号を取り込むようにしています。
OPENJPEG_PATH := $(shell ls -r -d $(LOCAL_INC_PATH)/openjpeg*)
これらは CMake などを使うと、もっとスマートに出来るものと思いますが、自分のアプリ環境はそこまで複雑では無いので、Makefileだけで何とかしています。
この Makefile には、従属規則の生成も自動化してあります。
※タイムスタンプを評価してコンパイルを自動化する。
ちなみに、Makefile には、マルチプラットホーム環境に対応したスクリプトを入れてあります。
# platform switcher (Windows, Linux, OS-X)
ifeq ($(OS),Windows_NT)
FEXT = .exe
SYSTEM := WIN
CPP_VER := -std=c++17
LOCAL_INC_PATH := /clang64/include
LOCAL_LIB_PATH :=
OPTLIBS = opengl32 glu32 glew32 openal glfw3 \
comdlg32 hid setupapi ksguid
CPMM = g++
CCMM = gcc
CFLAGS += -DWIN32
PFLAGS += -DWIN32 -DBOOST_USE_WINDOWS_H
LFLAGS +=
else
FEXT =
UNAME := $(shell uname -s)
ifeq ($(UNAME),Linux)
SYSTEM := LINUX
CPP_VER := -std=c++17
CFLAGS +=
PFLAGS +=
LFLAGS +=
endif
ifeq ($(UNAME),Darwin)
SYSTEM := OSX
OSX_VER := $(shell sw_vers -productVersion | sed 's/^\([0-9]*.[0-9]*\).[0-9]*/\1/')
CPP_VER := -std=c++17
CFLAGS +=
PFLAGS +=
LFLAGS += -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \
-Wl,-search_paths_first -Wl,-headerpad_max_install_names \
-framework AGL -framework Cocoa -framework OpenGL -framework IOKit \
-framework CoreFoundation -framework CoreVideo -framework OpenAL
LOCAL_INC_PATH := /opt/local/include
LOCAL_LIB_PATH := /opt/local/lib
OPTLIBS = glfw GLEW
else
LOCAL_INC_PATH := /usr/local/include
LOCAL_LIB_PATH := /usr/local/lib
endif
CPMM = clang++
CCMM = clang
endif
mintty の設定
最近の MSYS2 コンソールは、mintty が標準になっています。
ただ、何もしないと、多少見ずらいので、自分は以下の設定を、ホームディレクトリ以下に「.minttyrc」でセーブしてあります。
# mintty Settings
BoldAsFont=no
FontHeight=11
Columns=110
Rows=40
Locale=ja_JP
Charset=UTF-8
Term=xterm-256color
CopyOnSelect=yes
BackspaceSendsBS=yes
IMECursorColour=255,0,0
VSCode を使う
テキストエディタは、emacs を昔から使ってきました。
今でも使いますが、最近では、VSCode を使っています。
※emacsのキーバインドがあるのが大きいです。
MSYS2 環境で clang を使う場合、「c_cpp_properties.json」に設定を追加します。
※ネットで拾った記述に自分用の物を追加しています。
インテリセンスを正しく動作させるには、パスが重要なのですが、良く判っていません・・
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceRoot}",
"C:/msys64/clang64/include",
"C:/msys64/clang64/include/**",
"C:/msys64/clang64",
"C:/msys64/clang64/include/c++/v1",
"C:/msys64/clang64/lib/clang/15.0.4/include",
"C:/msys64/clang64/lib/clang/15.0.4/include/**",
"${workspaceFolder}/**",
"C:/msys64/clang64/bin",
"C:/msys64",
"D:/Git/glfw_app/glfw_app/common"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/msys64/clang64/bin/clang++.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"C:/msys64/clang64/include",
"C:/msys64/clang64/include/**",
"C:/msys64/clang64/include/c++/v1",
"C:/msys64/clang64/lib/clang/15.0.4/include",
"C:/msys64/clang64/lib/clang/15.0.4/include/**",
"${workspaceRoot}",
"C:/msys64/clang64/bin",
"C:/msys64",
"D:/Git/glfw_app/glfw_app/common"
],"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 4
}
GLFW OpenAL などを使ったアプリ開発
GLFW、OpenAL などを使う事で、マルチプラットホームで、2D/3Dグラフィックス、オーディオを使ったアプリを開発出来ます。
まぁ、そのようなフレームワークは、沢山ありますが、自分は、初期の頃から、自分用フレームワークを構築していて、小回りが利き自分には使いやすいです。
全ソースコードは github に上げてあり、MIT ライセンスで公開してあります。
元々、GLFW が出る以前に OpenGL,OpenAL のみを使って実装していたので、「gl_fw」と言うネーミングになっています。(現在は、glfw3_app)
中途な物や、実験的な物など色々ありますが、参考として、MMD のファイルをプレビューする為に作った物のスクリーンショットを載せておきます。
※MMDのファイルを読んで、レンダリングするだけの物で、アニメーションとかは実装中です・・・
機能的に、イマイチな部分もありますが、GUI など、何かアプリを作る場合に必要な機能は、大体あります。
このフレームワークの特殊性として、描画は全て OpenGL によって行っており、リアルタイムで表示しています。
最近のマシンは、描画性能が極めて高いので、リッチな物でもビクともしません。
漢字や日本語も、freetype でビットマップを生成して、それをテクスチャに登録して管理しています。
このような特異な手法は、ゲームのような場面に向いていて、ダブルバッファで描画するので応答が良く、リアルタイムに何か操作するような用途に向いていると思います。