Canonicalのworkshopを使って、mingwを使ったWindows向けC++プログラム環境を作ってみた。
workshopって何?
googleのAIによると
Canonicalの「Workshop」は、LXDを基盤としたYAML駆動型のコンテナ開発環境ツールです。コンポーネント指向のSDKを用いて、ローカルLLM(Ollama等)、CUDA、各種言語の実行環境をコマンド一つで安全なサンドボックス内に素早く構築・再現できます。
ようは仮想環境上に開発環境を作ってくれるので、ホスト環境を汚さないで開発環境が作れる。今回はこれを使ってmingw環境を作ってみた。
workshopのインストール。
get startの通り、snapを使ってlxdとworkshopをインストール。
sudo snap install --channel=6/stable lxd
sudo snap install --classic workshop
なぜかworkshopコマンドがPATHに載らないので、
export PATH="/snap/bin:$PATH"
を“${HOME}/.zshrcに追加。
プロジェクトの取得
今回はEC1ToJRETSの開発環境を作るので、まずはこれをclone。
WorkShopの初期化
cloneしたディレクトリに入って
workshop init dev --sdks vscode-remote --base ubuntu@24.04
を実行。sdksにvscode-remoteを、コンテナのベースにはubuntu 24.04を指定して初期化した。
まずはこのまま
workshop launch
で開発環境を起動。
mingwのSDKを追加
sdkとは、ベースになるOSに追加するパッケージのようなもので、今回はVSCodeのリモート開発に必要になるものを初期化時に指定している。
公式でも色々出ているようだけど、mingw環境のSDKは無いっぽいので自作する。
workshop sketch-sdk --eject --name mingw
sketch-sdkは自作SDKを作るテンプレートを作ってくれるコマンド。--ejectオプションでプロジェクトディレクトリにSDKを作るように指定。--name mingwで名前をmingwに指定。
実行すると.workspace/mingw以下に色々とファイルやディレクトリができる。
$ tree .workshop
.workshop
├── dev.yaml
└── mingw
├── hooks
│ ├── setup-base
│ └── setup-project
└── sdk.yaml
3 directories, 4 files
今回は初回起動時にmingwとcmakeとmakeをインストールしたいので、初回起動時やworkshop refreshで再構成するときに実行される.workshop/mingw/hooks/setup-baseファイルを編集。
apt-get update
apt-get install -y cmake make g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 clang-format clang-tidy
これ自体は普通のシェルスクリプトなので、パッケージを更新してから必要なものをインストール。mingwと言いつつ、clang-formatやclang-tidyも入れてるけど、これは後で分離したほうがいいかもしれない。
修正したら.workshop/dev.yamlにSDKの追加を記載。
name: dev
base: ubuntu@24.04
sdks:
- name: vscode-remote
- name: project-mingw
sdksに- name: project-mingwを追加してworkshop refreshで仮想環境を再構築。
actionsの追加
actionsは仮想環境内で実行するタスクを追加するところ。今回はbuildとcleanでビルドとビルドディレクトリの掃除を実装してみる
actions:
build: |
if [ ! -d build ]; then
mkdir build
cd build
CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ CMAKE_RC_COMPILER=x86_64-w64-mingw32-windress cmake .. -DCMAKE_SYSTEM_NAME=Windows
cd ..
fi
cd build
make
clean: |
if [ -d build ]; then
rm -rf build
fi
これで実装完了。workshop run -- buildするとbuildディレクトリを(無かったら)作ってcmakeを初期化してmakeしてくれる。workshop run -- cleanすると、ビルドディレクトリを消す。
これで、基本的な開発環境は完成。
vscodeで接続できるようにする。
ここがめっちゃ困った。なんせWSL環境の上に仮想環境ができているので、Windowsからは直接は見えない。なので
workshop exec ip addr
で仮想環境のIPアドレスを取得したあと
ssh -L 8888:localhost:22 workshop@${IPアドレス} -N
でWSLのポート8888に来た通信を仮想環境にトンネル。
Windows側で
code --remote ssh-remote+workshop@localhost:8888 /project
を実行したら

無事に開発環境に接続成功。
C++開発の設定
C++のプラグインを入れてIntelliSenseが有効になった途端に大量のエラーが発生。
どうもmingwを正しく認識できていないようだったので、.vscode/c_cpp_properties.jsonに設定を追加
{
"configurations": [
{
"name": "mingw",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"UNICODE",
"_UNICODE"
],
"cStandard": "c23",
"cppStandard": "c++20",
"intelliSenseMode": "windows-gcc-x64",
"compilerPath": "x86_64-w64-mingw32-g++"
}
],
"version": 4
}
EC1ToJRETSは内部的にはUnicodeを使っているので、definesでUNICODEを有効にするマクロを追加。
コンパイラにmingwのg++を指定したらエラーは無事に消えたので開発環境構築完了。
できた
workshop run -- buildでビルドしたあと、exeとdllを取り出して配置したら

ちゃんと動いた。
試しにobjdumpでDLLの依存関係を調べてみたところ
$ objdump -p EC1ToJRETS.exe | grep DLL
vma: Hint Time Forward DLL First
DLL Name: COMCTL32.dll
DLL Name: GDI32.dll
DLL Name: KERNEL32.dll
DLL Name: msvcrt.dll
DLL Name: USER32.dll
余計なものはリンクしてなさそうだ。
TODO
あとやっといたほうが良さそうなこととして
- cpp_util SDKを作って、cmake, make, clang-format, clang-tidyはそっちでインストールするようにする
- 好みの問題な気もする
- ec1tojrets_package SDKを作って、パッケージ作成に必要なzipとpandocをインストールする
- clang-formatとclang-tidyするactionを作る
- パッケージするactionを作る
- vscodeの呼び出すコマンドは固定なので、aliasを作る
- sshトンネル作るコマンドを自動化したい
それはそうと
workshopって名前が一般的すぎてすっごい情報検索しにくい。canonical workshopにしないと、全然関係ないのがヒットしまくる。