何らかの理由で、インターネット上にqbsに関するドキュメントがほとんどないため、この状況を少し修正することにしました。 QtCreatorが何のためにでも何でもコンパイルできるようにするために、何をする必要があるかを物語の形で説明しようとします。
どういうわけか、1つのプラットフォームだけで何かをする必要があるプロジェクトが事実上消えてしまったことが判明しました。 通常、スマートフォンまたはデスクトップ用のマイクロコントローラーおよび制御プログラム用のファームウェアを作成する必要があります。 開発環境で各デバイスのコードを記述するという、昔ながらの方法ですべてを実行できます。
しかし、私を信じて、これは非常に高速にシャットダウンします。 Windows-MSVC、ARM-CooCoxまたはKeil(IARの下で動作するよう強制された人に哀myの意を表します)、MSP-CCS、android-eclipse、ios-Xcode、peaks-MPLAB それでいいのですが、これらすべてで作業できますが、イチジク:いたるところにトラブル、微妙さ、不明確なルールがあります。 これはすべて、非常に人気のある日食の一般的な遅延に、メーカーからのkrivorukyの追加が掛け合わされています。
少し前に、1つのプラットフォームでモバイルアプリケーションとデスクトップアプリケーションの開発をすべて削減し始めました。 インターネットでかなり長いチャットをした後、私の選択はQtでした。 必要なものはすべて揃っています。必要に応じて、ネイティブコードを取得できます。 一般に、タスクは閉じられました。
しかし、マイクロコントローラーの場合、状況は明確に発展することを望みませんでした。 いたるところに彼らのウィッシュリストとウィッシュリストがあるという事実による。 さて、私はすでにそれについて不平を言っていました。 QBSの簡単な説明に突然出くわすまで、私は長い間苦しんでいました。
希望する人は自分でインターネット上で探し回ることができますが、要するに、これは通常のプログラミング言語を使用して、すべての種類のmakeとcmakeの代わりになります。 そして、QtCreator自身がそれを使用しようとしています。つまり、彼女はすでに彼女のパンティーから出ています...
はい、いつものようにそれに関するドキュメント、猫は泣きましたが、誰もまだソースをキャンセルしていませんでしたので、私はこれが実際に私が探していたものであることに気づきました。 自分で判断してください:同じ開発環境(非常に快適で高速)に座っており、いくつかのプラットフォームのファイルを静かに作成および編集します。 そして、あなたは、コードライターとして、「ネイティブ」環境でのあらゆる種類のトラブルの存在を気にしません。
溢れんばかりの、試してみる時間。 デスクトップとマイクロコントローラーのコンポーネントを持つ非常にシンプルなプロジェクトを作成しましょう。
QtCreatorを開き、Qt以外のプロジェクトの作成を選択して(まだ気にしないように)、CとQbsが存在する場所を選択します。 プラットフォームに依存しない楽しい言葉に注意してください
その結果、1つのmain.cとqbsを取得します。 すでに「ビルド」をクリックして、Hello Worldの出力を取得できます。
qbsを開き、何も理解していません。 したがって、私たちはすべてを消去し、インターネットで武装し、書き始めます。 Javascriptとそのすべて。
import qbs
ですから、ここでは明らかなようです。 qbsが機能するために必要なすべてをインポートします。
Project { name: "simple" }
左パネルからmain.cの消失を保存して観察します。 プロジェクトを開始しようとすると、QtCreatorから次の質問が表示されます。 原則として、これまでのところすべてが論理的です。
qbsの用語では、プロジェクトは何で構成されていますか? 製品から。 そして、いくつかあるかもしれませんが、今のところ私は1つをします。
Project { name: "simple" Product { name: "desktop" } }
ここで、「デスクトップ」のソースを示します。
Project { name: "simple" Product { name: "desktop" files: "main.c" } }
コンパイルしようとしても何も変わりません。 チュートリアルをいくつか見て、cppに依存関係を追加し、このアプリケーションが実際に
Project { name: "simple" Product { name: "desktop" files: "main.c" Depends {name: "cpp"} type: "application" } }
そして今、アプリケーションを構築しようとすると、QtCreatorがディスクで少しざわめき、目的の出力がアプリケーション出力パネルに表示されます
ええ、それから私たちは正しい軌道に乗っています。 まさに2つの魔法の行が何をするかを理解することは残っています。
Depends {name: "cpp"}
ドキュメントを読み、このコマンドを使用して、cppというモジュールに依存するようにプロジェクトを設定することを理解します。 はっきりした? しません
簡単な検索で、/ usr / share / qtcreator / qbs / share / qbs / modules /に似たものが見つかりました(異なるOSを使用している場合は、おそらくQtCreatorの近くに同じ場所があります)。 つまり、プラットフォームに応じて、このプラットフォーム用のコンパイラを選択するjavascriptがたくさんあります。 そのように完全に繰り返すのは理にかなっていないので、そのままにします。
type: "application"
ドキュメントから: 製品のターゲット成果物に一致するファイルタグ 。 アーティファクト... アーティファクトは、ルールまたはトランスフォーマーによって生成された単一のファイルを表します... ... ep ...ルール? 入力タグのトランスフォーマーを作成します。 sepulkariy ...変圧器についての状況を思い出させますか? 通常は他のファイルからファイルを作成します
手頃な価格でクロールし、これはビルドシステムにコンパイル済みのコンパイル方法を指示するほぼ特定のルールセットであることを理解しています。 大まかに言えば、出力では、アプリケーション、ライブラリ、または他の一般的なものを取得する必要があります。 繰り返しますが、それは少し明確になりましたが、それほどではありません。 繰り返しますが、当然のことと考えましょう。
しかし、プロジェクトに戻りましょう。 マイクロコントローラ専用の別の製品を追加しましょう
Project { name: "simple" Product { name: "desktop" files: "main.c" Depends {name: "cpp"} type: "application" } Product { name: "micro" files: "blink.c" } }
何かを行おうとすると、blink.cファイルが実際にはないというメッセージがすぐに表示されます。 まあ、まあ、blink.cファイルをプロジェクトに追加します。 名前が示すように、これはマイクロコントローラーのみの同じHelloWorldです。 マイクロコントローラファミリmsp430の例を取り上げました。
#include <msp430.h> int main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR |= 0x01; while (1) { P1OUT ^= 0x01; __delay_cycles(1000000); // 1 second @ 1MHz } return 0; }
コンパイルされ、フラッディングされると、1秒間隔でP1.0でタグ付けが開始されます。 また、ほとんどのデモおよび開発ボードにはこの脚にLEDがあるため、点滅します。
現在、QtCreatorは誓いませんが、マイクロコントローラにも何も注ぎ込まれていません。 奇妙なね?
Depends {name: "cpp"}を追加しても意味がありません。システムにインストールされたネイティブgccはそのようなプラットフォームの存在を認識していないためです。
ここで、以前に出会った神聖な手紙の断片を使用します。
そもそも、ファイル内の各機能をマイクロコントローラープロジェクトでペイントすることを好みます。 手で各ファイルを記録しますか? 怠azine。 ソリューションを見て、ブロックを書き換えます
Product { name: "micro" Group { name: "msp430 sources" files: 'src/*.c' fileTags: ['c'] } }
ここで、「msp430ソース」と呼ぶファイルのグループを作成し、src / *マスクに適合するすべてのファイルをそのファイルに愚かに含めます。 さらに作業するには、文字Cでタグ付けします。
それらをどうするか? この場合、QbsにはRuleとTransformerの2つのことがあります。 実際、それらは近いですが、わずかに異なります。 私の指の違いを説明しようとします。
ルールは、何かに該当するすべてのファイルで起動できます。 各ファイルに対して1回(たとえば、コンパイラーを呼び出すために)トリガーすることができ、すべて(リンカー)に対して1回トリガーすることもできます。
Transformerは、定義済みの名前を持つ1つのファイルのみで動作するように設計されています。 たとえば、フラッシャーやトリッキーなスクリプト。
OK、「s」とマークされたすべてのファイルで機能するルールを追加します。
Product { name: "micro" Group { name: "msp430 sources" files: 'src/*.c' fileTags: ['c'] } Rule { inputs: ["c"] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "file passing" cmd.silent = false; cmd.highlight = "compiler"; cmd.sourceCode = function() { print("Nothing to do"); }; return cmd; } } }
原則として、すべては構文から明らかです。 入力があり、準備があり、javascriptが推力され、必要なことを実行します。 この場合、Compile Outputウィンドウにファイルの受け渡しが表示され、どこにも何もしないことが表示されます。 まあ、ドキュメントは次のようになります。
すべての再コンパイルを開始し、見ます。 私はあなたのことは知りませんが、何も見えません。 なんで? qbsは非常にスマートであり、そのドキュメントにはギャップがあるためです。
qbsはシステムでアクションを実行せず、それに依存するものはないと信じているため、ルールは機能しません。 原則として、これは現実に対応しますが、検証を行うことは難しくなります。
わかりました、これらの同じアーティファクトはこれに責任があります。 これらは、ルールまたはトランスフォーマーの結果です。 これはコンパイルによって最もよく説明されます。 .sファイルをコンパイルすると、出力はオブジェクトファイルになります。 さらにリンクするにはこれが必要ですが、一方で、削除することもできます。そのため、再び落ち着いて再生成できるからです。
再度、ドキュメントから例をコピーし、わずかにアップグレードします。
Rule { inputs: ["c"] Artifact { fileTags: ['obj'] filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Compiling "+ input.fileName cmd.silent = false; cmd.highlight = "compiler"; cmd.sourceCode = function() { print("Nothing to do"); }; return cmd; } }
ここで、作業後に.objディレクトリにアーティファクトが残ると言います(今作業中のファイルの出力を追加しました)。 始めます。 繰り返しますが、見返りはありません。 なんで? 答えは同じです-'obj'タグを持つファイルは誰も必要としません。
さて、検証のために必要になるようにします。 そして一般的に、私たちのアプリケーションは1つの連続したオブジェクトです。
Product { name: "micro" type: "obj" Group { name: "msp430 sources" files: 'src/*.c' fileTags: ['c'] } Rule { inputs: ["c"] Artifact { fileTags: ['obj'] filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Compiling "+ input.fileName cmd.silent = false; cmd.highlight = "compiler"; cmd.sourceCode = function() { print("Nothing to do"); }; return cmd; } } }
頑張って頑張ってね! 憧れの「Compiling blink.c」がウィンドウに表示されました。 それでは、実際にコンパイルし、すぐにコーダーによる方法で、つまり、必要なものをすべて1つのパイルにバカにすることで、すぐにコンパイルできることを付け加えましょう。
prepare: { var args = []; args.push("-mmcu=cc430f5137") args.push("-g") args.push("-Os") args.push("-Wall") args.push("-Wunused") args.push('-c'); args.push(input.filePath); args.push('-o'); args.push(output.filePath); var compilerPath = "/usr/bin/msp430-elf-gcc" var cmd = new Command(compilerPath, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; }
すべてをゼロから再コンパイルし、.objディレクトリを調べます
$ ls -R1 .: f27fede2220bcd32 ./f27fede2220bcd32: blink.co
やった! ファイルが表示されました。 今、検証のために、hz.sというトリッキーな名前の別のファイルを作成しています。 私が正しい場合は、再コンパイル後、その隣に別のオブジェクトファイルが表示されます。
出力が現れました
compiling blink.c compiling hz.c
そしてカタログ
./f27fede2220bcd32: blink.co hz.co
すべてが大丈夫のようです。 次に、このすべてをリンクする必要があります。 繰り返しになりますが、今はリンクのみです。
Rule { multiplex: true inputs: ['obj'] Artifact { fileTags: ['elf'] filePath: project.name + '.elf' } prepare: { var args = []; args.push("-mmcu=cc430f5137") for (i in inputs["obj"]) args.push(inputs["obj"][i].filePath); args.push('-o'); args.push(output.filePath); var compilerPath = "/usr/bin/msp430-elf-gcc" var cmd = new Command(compilerPath, args); cmd.description = 'linking ' + project.name; cmd.highlight = 'linker'; return cmd; } }
違いはどこですか? まず、マルチプレックスフラグが追加されました。これは、このルールが特定のタイプのすべてのファイルを一度に一括処理することを示しています。 次に、入力パラメータの入力が消えました。 このタイプのファイルの配列である入力が現れました。 まあ、私は製品の名前を使用して、最終的なファームウェアの名前を取得しました。
アプリケーションelfのタイプを入れて、ビルドを試みます。 しばらくすると、アセンブリディレクトリにsimple.elfファイルが見つかります。
$ file simple.elf simple.elf: ELF 32-bit LSB executable, TI msp430, version 1, statically linked, not stripped
それが必要です。 すでにボードに入力して、点滅するLEDを楽しむことができます。
最初の目標は達成されました:編集とコンパイルの両方の1つの開発環境ですべてを行っています。
念のため、最後のqbs
import qbs Project { name: "simple" Product { name: "desktop" files: "main.c" Depends {name: "cpp"} type: "application" } Product { name: "micro" type: "elf" Group { name: "msp430 sources" files: 'src/*.c' fileTags: ['c'] } Rule { inputs: ["c"] Artifact { fileTags: ['obj'] filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o' } prepare: { var args = []; args.push("-mmcu=cc430f5137") args.push("-g") args.push("-Os") args.push("-Wall") args.push("-Wunused") args.push('-c'); args.push(input.filePath); args.push('-o'); args.push(output.filePath); var compilerPath = "/usr/bin/msp430-elf-gcc" var cmd = new Command(compilerPath, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; } } Rule { multiplex: true inputs: ['obj'] Artifact { fileTags: ['elf'] filePath: project.name + '.elf' } prepare: { var args = []; args.push("-mmcu=cc430f5137") for (i in inputs["obj"]) args.push(inputs["obj"][i].filePath); args.push('-o'); args.push(output.filePath); var compilerPath = "/usr/bin/msp430-elf-gcc" var cmd = new Command(compilerPath, args); cmd.description = 'linking ' + project.name; cmd.highlight = 'linker'; return cmd; } } } }
PS私はあなたの良心のより便利な場所に「ハードコードされた」変数の除去を残します、これはすでにjavascriptチュートリアルですから。