C++ の Hello World とキュートなハートレス レインボー

これは、「Hello World」アプリケーションを作成するシリーズのパート 2 です。パーティーに遅れる場合は、まずパート 1 を確認することをお勧めします。

それで、上司が私たちの進捗状況をチェックするためにやって来ました。彼らは、3 行のアプリケーションを新しいシステムに移植するのになぜ丸一日かかるのか疑問に思い始めていました。しかし、彼らが訪問した本当の理由は、新しい機能を求めることでした。当社の「Hello world」ビジネスは活況を呈していますが、マーケティング部門は、グラフィカル UI の欠如が売り上げに悪影響を及ぼしていると考えています。

ほら、誰もソフトウェアの肥大化から逃れることはできません。

まだ。上司に Linux で MSVC をセットアップするのにかかる時間を忘れさせたいと思った私は、さらに先を行き、アプリを完全に書き直しました。

#include <QMessageBox>
#include <QApplication>

int main(int argc, char** argv) {
 QApplication a(argc, argv);
 QString message = "Hello, World !!!!!!!";

 QMessageBox::information(nullptr, "Hello World v2.0", message,
 QMessageBox::Yes | QMessageBox::No);
 return 0;
}

もちろん、小さな気の利いたビルド ファイルも提供しています。

import qbs 1.0

QtGuiApplication {
 name : "helloworld-gui"
 files : ["helloworld.cpp"]

 Depends {
 name : "Qt.widgets"
 }

 Group {
 name: "app"
 fileTagsFilter: "application"
 qbs.install: true
 qbs.installDir: "bin"
 }
}

Linux 版はまだ正常にビルドされています。

熱心に Windows 版をビルドしましょう:

https://www.qt.io/download で Qt をダウンロードしました。そのサイトは日ごとに悪化しています。 Qt 社は、人々がオープン ソース バージョンを入手するのを思いとどまらせようとしています。しかし、https://download.qt.io/ にアクセスすると、すべての tarball とインストーラーがあります。

インストーラーといえば、Windows 用の 64 ビット バージョンは提供されていません。 2018 年。32 ビット ビルドに制限し、それを WINE で抽出する必要があるかもしれません。ただし、Qt インストーラー フレームワークにはサイレント モードがなく (明らかに、100 行の JavaScript でサイレント モードをスクリプト化できます)、WINE でサポートされていない Windows メソッドを使用しているため、機能しません。

どうでも。 Qt を自分でビルドして、私の WINE ツールチェーンがいかに優れているかを証明します。そして64ビットになります。私は昇進し、PHD 4 のインターンがカプチーノを持ってきてくれます。多分人々は私の名前を動詞として使うかもしれません (まだゴッドボルトを知らないなら、ぜひチェックしてみてください!)

を除外する。 Qt は今でも qmake を使用して自身をビルドしています。また、qmake は、cmake をクールでモダンに見せるためだけに存在します。 qbs を使用して Qt を構築する取り組みが進行中です。これは非常にエキサイティングなことですが、このブログにとっても、少し最先端すぎるかもしれません。

そのため、qmake に行き詰まっています。qmake は、残念ながらツールチェーンとビルド システムを混同するビルド システム ジェネレーターです。 Wine ツールチェーンの構成を作成しようとしましたが、実際にはかなり単純で、適切なコマンドでいくつかの Makefile を生成しました。しかし、それらは、元の make と完全に互換性がないフォーマットではありますが、Windows 用の make に似たツールである nmake の Makefile でした。 nmake を使用してみました (正常に動作します) が、その後のすべての cl.exe / link.execalls はワイン環境で発生します。つまり、ラッパーではなく実際の cl.exe を実行するため、粗いスラッシュからバックスラッシュへの変換スクリプトが実行されます。 cl.exe は / で始まるものを想定しているため、決して実行されず、コンパイルは失敗します。 はオプションです。また、nmake は Windows プロセスであり、Windows は ELF を認識していないため、nmake に偽の cl.exe ラッパーを呼び出すことはできません。

Windows が \ を使用して何百万ドルを計算するかは、読者の演習として残します。 パス区切りとして業界にコストをかけています。

解決策は、qmake にパッチを適用することです。 qmake のメンテナーでさえ、積極的に避けることです。ですから、それはやめましょう。

大変申し訳ありませんが、Windows VM に戻り、そこから Qt をビルドします。

それは単純なはずですよね?

もちろん、VC ビルド ツールは環境を適切にセットアップできません。

ビルド環境をセットアップするのに何人の Microsoft エンジニアが必要ですか? 20 ほどのファイルで、その目的を果たす約 1900 行のバッチ スクリプトを見つけることができたので、確かにかなりの数です。おそらくもっとあります。

私は自分の環境を3行でソートすることに成功しました。ビルド システムがどれほど複雑であっても、いくつかの変数に要約されることを忘れないでください。コンパイラはあまり必要としません。

set "INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.12.25827\include; %INCLUDE%"
set "LIB=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.12.25827\lib\x64\;%LIB%"
set "PATH=%PATH%;C:\Users\cor3ntin\Documents\qtbase-everywhere-src-5.10.0\gnuwin32"

あとは、Qt 5.10 をダウンロードして x64 ビルド環境をセットアップするだけでした (私は vcvars64.bat + 上記の 3 行を使用しましたが、手動で PATH をセットアップすることができ、vcvars.bat はまったく気にしません)。

perl がインストールされ、PATH にあることを確認してください。

この記事では、Qt Base (Core、Gui、Network など) のみが必要なので、それを構築しています。クロムを使用する QtWebEngine の構築は、もう少し複雑です。

configure -release -opensource -confirm-license \
 -platform win32-msvc -nomake examples -nomake tests
nmake
nmake install

Qt のビルドが完了したら、フォルダーを Linux ホストにコピーして戻します。少なくとも bin、include、lib、plugins が必要です。それらを新しいディレクトリに配置します。私の名前は qt5_10base-x64 です。

src を参照するインクルードに問題がありました。したがって、Windows の Qt ディレクトリから perl bin\syncqt.pl -copy -windows -version 5.10.0 -outdir cpy を実行し、 cpy で生成された include フォルダーを使用できます。それでも、いくつかのファイル (qconfig.h、q{core,gui,widgets,network,xml}-config.h) を src フォルダーからそれぞれのインクルード フォルダーに手動でコピーする必要がありました。確かに少し面倒ですが、最終的にはそこにたどり着きます.

これでQtができました。しかし、実際にそれを使用するように QBS に指示するにはどうすればよいでしょうか?

QBS のプロファイル システムは、QBS の優れた点の 1 つです。コンパイラ ツールチェーンをグローバルに設定し、あるツールチェーンから別のツールチェーンに簡単に切り替えることができます。

ただし、Qt で動作するには、qbs はプロファイルごとに完全なモジュール セットを必要とします。先ほど使用した gcc プロファイルは、各 Qt ライブラリとコンポーネントを設定する 160 個の qbs ファイルで構成されています。

幸いなことに、この便利なツールを呼び出すだけで済みます。

qbs-setup-qt -h
This tool creates qbs profiles from Qt versions.

Usage:

 qbs-setup-qt [--settings-dir <settings directory>] --detect

 qbs-setup-qt [--settings-dir <settings directory>] <path to qmake> <profile name>

 qbs-setup-qt -h|--help

The first form tries to auto-detect all known Qt versions, looking them
up via the PATH environment variable.

The second form creates one profile for one Qt version.

ただし、ビルドされた qmake は Windows 上で実行されることが想定されている Windows アプリケーションであるため、Linux からそのツールを呼び出すことはできません。願わくば、いつの日か qmake を完全に取り除くことを願っていますが、今のところは Windows マシンに戻してください。

最初に qbs の Windows ビルドをインストールし、ツールを実行します。

qbs-windows-x86_64-1.10.0\bin\qbs-setup-qt.exe \
 --settings-dir . bin\qmake.exe msvc14-x64-qt

これにより、適切な Qt 構成で qbs フォルダーが作成されます。そのフォルダーを、前に作成した qt5_10base-x64 フォルダー内の Linux マシンに移動します。

.qbs ファイル、たとえば 1.10.0/profiles/msvc14-x64-qt/modules/Qt/gui/gui.qbs を開くと、パスへの参照に気付くでしょう。何らかの理由で、私の場合は /usr/local/Qt-5.10.0 です。 Windowsパスが必要なので、どこかを台無しにしたと思います。いずれにせよ、そのパスを Linux マシン上の Qt の実際の場所に変換する必要があります。これは簡単で、sed を使用するだけです。

find -name "*.qbs" -exec sed -i -e \
 's\#/usr/local/Qt-5.10.0\#/home/cor3ntin/dev/cross-compilers/windows/qt-5.10-msvc-x64\#g' {} \;

次に、これらの qt モジュールを使用するように qbs.conf を変更する必要があります。パート 1 で作成した QBS ファイルを編集して、それらを参照します:

qt-project\qbs\profiles\msvc14-x86_64\preferences\qbsSearchPaths=\
 /home/cor3ntin/dev/Qt/qbs-wine-toolchain,/home/cor3ntin/dev/cross-compilers/windows/qt5_10base-x64/qbs/1.10.0/profiles/msvc14-x64-qt

私はそれがすべて少しトリッキーであることを理解しています.しかし最終的には、qbs を実行して、Windows 用の Qt ベースの hello world をコンパイルできます。

Qt dll が見つからないため、実行されません。 dll をビルド ディレクトリにコピーするか、DLL が PATH にあることを確認します。 windows/wine PATH です。

私が見つけた唯一の方法は、regedit を実行することです。必ず適切な WINEPREFIX から実行し、Qt の bin ディレクトリの場所を HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment の下にあるパスに追加してください。 .

それをスクリプト化する方法を知っている場合は、お知らせください。

また、ビルドした helloworld.exe バイナリの隣に qt.conf ファイルを配置して、プラグインのロード元を Qt に指示する必要があります。私の場合

[Paths]
Prefix=/home/cor3ntin/dev/cross-compilers/windows/qt5_10base-x64/
Plugins = plugins

以上です !さほど難しくありませんでしたよね?

そして、Microsoft Studio Visual C++ コンパイラはこれまでで最高のものです!

未就学児 2 人を対象に実施された最近の調査によると、ミレニアル世代は虹が好きです。私はすぐに、アプリをもっとレインボー風にするように頼まれました。あいまいなラベルの付いたボタンは、明らかに終末のふりをした騎士であるため、それらも削除します。

必要なことは、文字列を繰り返し処理し、各文字の周りに HTML マークアップを挿入して、異なる色でレンダリングされるようにすることです。

一部のコンテナーを反復処理するには、range-v3 を使用する必要があります。 文字通り

いいですね?

しかし、msvc が range-v3 をコンパイルできないことを知ったら、きっとびっくりするでしょう。私は知っています、それは完全な打撃であり、完全な失望です.

Microsoft Studio Visual C++ コンパイラが無効になりました。

私たちにできることは絶対にありません。 range-v3 の msvc 互換ポートや、文字列を変換する他の方法が存在するわけではありません。範囲を使用して msvc をレインボーで倒すことができるように、わざとでっち上げの話を作ったと言うのはやめてください。それは意地悪だろう .

唯一の合理的な方法は、msvc を捨てて別のものに置き換えることです。でも何? Mingw は MSVC ヘッダーとライブラリを理解していません。icc は非常に高価であり、Cfront はもう維持されていません。

ここまで来れば、私がどこに向かっているのか、確かにわかりますよね?クランクル! clang-cl について知らなかった場合、これは実際には clang であることを除いて cl.exe の代わりとなるドロップ インであるため、内部が暖かくぼやけます。

Clang は適切に設計されており、多くの理由で素晴らしいツールですが、最も重要なのは:

    <リ>

    すべての主要な OS で動作します

    <リ>

    コンパイル時に OS 固有の機能をアクティブにするのではなく、実行時にアクティブにします。

    <リ>

    つまり、どこからでも何でもターゲットにできるということです。

    <リ>

    msvc のドライバーと互換性のあるドライバー (必要に応じてコマンド ライン インターフェイス) を提供します

    <リ>

    構築するのは簡単です (GCC を構築しようとしたことがあるなら、コンパイラの構築がいかに難しいかをご存知でしょう)。

    <リ>

    これはオープンソースであり、その設計は政治的動機によって積極的に制約されることはありません。

それでは、Clang を使用しましょう!

Linux ディストリビューションのドキュメントに従って clang を使用していない場合は、デフォルトで clang-cl が付属しているはずです (これは単に clang へのシンボリック リンクです)。

または、あなたが私のようである場合は、チェックアウトしてトランクを構築してください.

交換のドロップに加えて、私たちがしなければならないことがいくつかあります。 wine 用に作成した QBS ツールチェーン モジュールは、スラッシュをバックスラッシュに変換するため、まったく機能しません。

ツールチェーン モジュールをコピーし、その他の詳細を修正しました。まもなく GitHub にアップされます。

clang-cl の QBS プロファイルの作成は簡単です。wine からプロファイルをコピーし、ツールチェーン名を msvc から clang-cl に変更し、toolchainInstallPath を clang-cl と lld-link を含む場所にポイントします。

ああ、私は lld-link について言及していませんでしたか?これは、link.exe の代替品です。 lld は UNIX の ld の代替でもあり、ld や gold よりもはるかに高速なので、ぜひチェックして使用してください!

まだ終わりではありません。

Microsoft Windows は、大文字と小文字を区別しないファイル システムを中心に設計されています。当時はこれが良いアイデアに思えたに違いありません。

ただし、Linux マシンを FAT で実行するほどマゾヒスティックでない限り、ファイル システムで大文字と小文字が区別される可能性があります。これは私たちの問題です。

本当に悪いですか?さて…

**A**cl**UI**.**L**ib
ahadmin.lib
wdsClientAPI.**LIB
P**sapi.**L**ib
sensorsapi.lib
**S**etup**API**.**L**ib

これはほんの一部のファイルです。それを修正するために彼らが今できることは何もないと思います。手遅れです。

すべてのライブラリとヘッダーのファイル名を変更することで、大文字と小文字の問題を修正することができます。しかし、サードパーティのライブラリにも一貫性がないため、おそらくうまくいかないでしょう。そのため、遅かれ早かれビルド ファイルを修正しようとしても、ケースの問題が発生します。

したがって、「適切な」(適切な定義の) 解決策は、Linux カーネルをだまして大文字と小文字を区別しないようにすることです。そのためには、大文字と小文字を区別しないシステムを使用する必要があります。幸いなことに、ファイルはファイル システムである可能性があるため、Windows SDK を保持するのに十分な大きさのファイルを作成し、EXFAT などの大文字と小文字を区別しないファイル システムでフォーマットし、そこに SDK を配置します。 Windows カーネルでは大文字と小文字が区別されない場合でも、NTFS では大文字と小文字が区別されることに注意してください。

dd if=/dev/zero of=win_sdk_10.fs bs=1024 count=$((1024 * 100 * 3))
mkfs.exfat win_sdk_10.fs
mv sdk_10 sdk_10.bak
mkdir sdk_10
sudo mount win_sdk_10.fs
mv sdk_10.bak/* sdk_10

Linux を愛さなければなりません。

そして今、clang-cl でコンパイルするとうまくいきます。ただし、プログラムを実行するとバグが発生します。

それでも、仮想マシンにコピーされた同じ実行可能ファイルは問題なく動作します。

バグが実際にどこにあるのかはまだわかりません。 range-v3 またはそれを使用しているように見えますが、実行時の動作が異なることは奇妙に思えます。

しかし、それがより大きな開発環境のセットを持つことの素晴らしいところです。バグがある場合、それらは公開される可能性が高くなります. 1 つには、この厄介なグラフィックの不具合により、空白を特別なケースとして処理する必要があることに気付きました。

ああ、clang が実際に何をしているかを確認したい場合は、Microsoft の dumpbin.exe を使用できます。 msvc2017/bin/Hostx64/x64/ にあります .このツールは、UNIX の ldd および nm に相当します。

興味深いことに、clang アーティファクトは msvc で生成されたものとまったく同じように見えますが、余分なセクションはほとんどありません。 CRT と vcruntime を含む !

これが MSVC でビルドされたバイナリです。

現在、ldd-link はまだ実験段階であり、デバッグ情報をサポートしていません。一部の例外処理を除いて、clang-cl はほぼ完了しています。 cl.exe を組み合わせることができます clang-cl link.exe および lld-link .

本番環境で clang-cl を使用することをお勧めすることはできませんが (まだ実用化されつつあります)、CI および開発環境に追加するには素晴らしいツールです。

今日はここまでです。何かを学んでいただければ幸いです。

もう 1 つ…パート 3 でお会いしましょう。