Windowsから降りるための第一歩としてのClang
2年前、実際にWindows PCによる制御環境を本格的に導入し始めた。 去年から、様子が変わった。 Windowsの挙動が変わり始めた。 信頼性が、低下し始めた。
制御用途でWindows PCを使うというのは、FAの世界では珍しくない選択だ。HMIを作るにも、データ収集にも、上位通信にもWindowsは便利だった。過去形で書いているのが、今日の話の出発点になる。
挙動の変化は、ここ数年、折に触れて感じていた。特に Windows 11 24H2 以降、信頼性が一段落ちた個人感覚がある。
個別の問題は、いずれも「対処できる」レベルではある。だが、積み重なったときに見えてくる構造がある。
FAの前提と、Windowsの設計思想のズレ
FAの世界には、暗黙の前提がある。10年前の装置を、10年後も動かす。設備投資は何千万、何億の単位で、そう簡単には更新できない。ソフトウェアも、同じ時間軸で生きることを期待される。
ここ数年のWindowsは、この前提と折り合わなくなってきた。
サポート期間が短くなった
アップデートの制御権限が縮小した
ハードウェア要件が恣意的に引き上げられる(TPM 2.0、対応CPUリスト)
セキュリティ名目で振る舞いが増え続ける(SmartScreen、Defender、VBS…)
これは「バグが多い」とか「使いにくい」という話ではない。MicrosoftがWindowsを、制御用途に向かないOSとして再設計している、という話だ。クラウド連携とコンシューマ向けセキュリティが最優先になり、10年単位で動き続ける産業用PCの居場所が、今の設計思想の中にない。
個別のバグなら直せばいい。だが、設計思想が自分の用途と噛み合わないのは、対処のしようがない。
Windowsから降りる、という視点
そうなると、考えることは一つしかない。Windowsから降りる。
移行先はLinuxになる。Debian/Ubuntu LTSの10〜12年サポート、カーネルバージョンの自分での選定、アップデートの完全な制御。産業用Linuxボード(Armadillo等)という選択肢も、この10年で実運用に耐えるレベルに育った。
ただし、いきなり降りるのは無理だ。
既存のソフトウェア資産はMSVCでビルドされたC/C++のコードベースで、Windows APIをあちこちで叩いている。Linuxに持っていっても、コンパイルすら通らない。一人開発で、過渡期も現場は動かし続けなければならない。
そこで、二段構えを考える。

まずコンパイラだけを先に替える。 OSはWindowsのまま、MSVCをClangに差し替える。
これだけで次のことが起きる。
MSVC固有拡張への依存が炙り出される
Windows API直叩きの箇所が可視化される(Clangの方が警告が厳しい)
ビルドシステムをCMakeに寄せる動機ができる
コードが「標準C/C++」に近づいていく
このフェーズで、コードの地金を整える。OSを替える前に、コード側を移行可能な状態にしておく。一段ジャンプではなく、踊り場を経由する形だ。
自分の現場で、この戦略が通る条件
私の現場では、この二段構えが比較的通しやすい条件が揃っている。これは偶然ではなく、かつての判断が効いている。
昔は制御ソフトがHWライブラリを直接叩き、FL-NETドライバや現場I/Oとベッタリ繋がっていた。これを数年前、中間PLC経由に作り替えた。アプリケーションは中間PLCとEthernet(TCP/IP)で話すだけ。HWの世話は中間PLCがやる。

当時の判断の狙いは、「PLCがEthernetで普通に制御できるようになった以上、アプリ側をEthernetで完結させれば、将来の移行コストが下がる」というものだった。具体的なOS移行を想定していたわけではない。ただ、HW依存を抱えた制御アプリは長期的に動かせないという感覚はあった。だから、HWの責務はPLCに寄せて、アプリは"ただの通信アプリ"にする方針を選んだ。
結果として、今、OS移行の最大の障壁だったHW依存は、既に取り除かれている。アプリ側に残っているWindows依存は、スレッド、時刻、ソケット、ファイルパス程度で、いずれもC++標準ライブラリか薄いラッパで吸収できる粒度だ。
この条件なら、Clangを経由してのLinux移行は、絵空事ではなく現実的な選択肢になる。
余談:Ethernet化できない領域
ちなみに、この「中間PLC化」戦略にも、完全には解決できない領域がある。COM2ポート(RS-232C)だ。
タイミングがシビアなシリアル制御は、Ethernet変換器を挟むと揺らぎやバッファリングで噛み合わないケースがある。文字間時間が厳密な相手、制御線(RTS/CTS/DTR/DSR)のリアルタイムな状態変化、Modbus RTUのようなタイミング依存のプロトコル。このあたりは、物理シリアルのまま運ぶしかない。
幸い、これはLinuxに移っても物理COMポートとして同じ形で扱える。WindowsのCOM2がLinuxでは/dev/ttyS1や/dev/ttyUSB0になるだけで、挙動の本質は変わらない。
Ethernet化できないレガシーが、逆にOS移行の友になる、という皮肉な構造。
脱出権で選ぶ
技術選定の軸を、もう一つ書いておきたい。
これから私は、脱出権で選ぶようにしようと思っている。
「MS製だから避ける」のは感情論だ。「脱出権のないものを避ける」のはエンジニアリングの判断だ。結論が同じになることも多いが、根拠が違うと判断が安定する。
脱出権あり
Clang — GCCへ逃げられる。OSS
CMake — OSS、事実上の標準
VS Code — VSCodium というOSS版がある
脱出権なし
MSVC — 代替実装が存在しない
MSBuild — 事実上MS専用
Clangを選ぶのは、「LLVMが完璧だから」ではない。GCCという代替実装が、別組織で独立して開発され続けているからだ。LLVM Foundationに何かあっても、C/C++のコードは死なない。この代替実装の存在が、脱出権を担保する。
MSVCは、MSが仕様を変えたらついていくしかない。この非対称性が、長期プロジェクトでは効いてくる。
そして、最大の課題
ここまで、Clangを軸にした技術的な移行戦略を書いた。コンパイラを替え、ビルドシステムを整え、OS依存を剥がし、中間PLC化でHW依存を分離する。段階的に降りる、現実的なプランだ。
だが、この戦略には、技術以前の問題がある。
PC側の制御ソフトとPLCラダーの、両方を読める人間が足りない。
FAの現場では、PCソフトの開発者とPLCエンジニアは、別の職能として扱われることが多い。C/C++を書ける人間は、ラダー図を読まない。ラダーを書ける人間は、TCP/IPの実装を追わない。中間PLC化という設計は、この両方が見える人間がいないと、設計も保守も引き継ぎもできない。
そして、その両方が見える人間は、業界全体で高齢化している。20代・30代でこの両方を深く扱える人は、私の知る限り、ほとんどいない。
※そもそも、FA系の若手技術者自体をあまり見なくなり始めてる。
Clangに移行することも、Linuxに降りることも、技術的には私一人で進められる。だが、私の次を引き継げる人間がいないという問題は、私一人では解決できない。
これは私個人の問題であり、同時に業界全体の構造問題でもある。技術選定をどれだけ丁寧にやっても、読める人がいなければコードは死んだも同然だ。
Clangを選ぶ理由の一つに「脱出権」を挙げた。だが、脱出権を行使するのもまた人間だ。脱出権を持ったコードを、誰が読むのか。
現時点のAIはテクニックは持っているが、こういうシステムアーキテクトは作れない。また、体も持たないから現場で導入もできない。
答えは、まだ持っていない。
第一歩として
これはMicrosoftに対する批判の記事ではない。Windowsは、クラウドとコンシューマ向けのOSとしては進化を続けている。ただ、自分が必要としているOSではなくなった、というだけの話だ。
2年前、私はWindows上でこの制御環境を組んだ。あの時点での判断は、たぶん正しかった。去年までは、まだ通用していた。今年、設計思想のズレが無視できないレベルになってきた。だから、降りる準備を始める。
Clangは、その第一歩になる。魔法ではない。銀の弾丸でもない。だが、今動いているコードを殺さずに、降り始めることができる手段ではある。
