風で飛んでいくチラ裏

気ままに雑記メモ書き殴り。古い記事は別blogからの引っ越しなのでレイアウトがアレです。

MPLAB IDEの起動の仕方によってカスタムビルドコマンドが失敗する?

手短に

MPLAB IDEのビルドからカスタムビルドを実行する場合、これは当然、IDEの実行時のディレクトリがカレントディレクトリになってるので、直でIDE起動した場合とプロジェクトファイルから起動した場合で違いを吸収できるようにマクロを使いましょうね。という話。

 

以下詳しく

MPLAB IDEで、カスタムビルドを利用しているんだけど、 どうもIDEの起動の仕方によって実行できたりできなかったりする。


原因

・カスタムビルドの実行ファイルを相対パス指定にしている

IDEの起動の仕方によって作業ディレクトリが異なる

ためしにカスタムビルドオプションでpwdを実行(※cygwin入れてるので実行できます) IDEをスタートメニューやショートカットから起動し、ワークスペースを読み込んだ場合は、 C:/Program Files/Microchip/MPLAB IDE/Core ワークスペースファイルをダブルクリックして標準関連付けされているIDEを開いた場合は、 [ワークスペースのファイルがあるディレクトリ] でした。なんてこったい。


何が困るの?

IDEをスタートメニューとかから起動したときに、相対パス指定しているカスタムビルドが ちゃんと実行されない。 .\script\script.bat とか書いてあると、スタートメニューから起動したIDEだと C:/Program Files/Microchip/MPLAB IDE/Core/script/script.bat を実行しようとする。バッチファイルはプロジェクトディレクトリ下にあるので、 もちろんこれは実行できない。 プロジェクトをバージョン管理とかしてると、絶対パス指定は使いたくない。 バージョン管理してなくてもプロジェクトのフォルダ名変更しただけで使えなくなるとか嫌だし。 相対パス指定にして上の問題が起こると、何が悪いのかパッと見分からない。 (IDE内では「コマンド実行失敗したよ」、しか出てこないので)


解決方法

こういうのはプロジェクトの開いているディレクトリを置換してくれるマクロっぽいものが あるはず、ということでヘルプを調べたらありました。 $(ProjectDir) とすれば、実行時にプロジェクトディレクトリのパスに置換してくれました。 ついでに、MPLAB IDEのカスタムビルドは pre(ビルド前) と post(ビルド後) にそれぞれ1行ずつ しか書けないので、複数処理するときはバッチファイルを書くなりするわけですが、 バッチファイル内部のパスもプロジェクトディレクトリを意識したものにする必要があります。 ただし、$(ProjectDir)はバッチファイル内部まで置換してくれない(当たり前ですが)ので、 バッチファイル実行時の引数としてパスを渡してあげましょう。


直してみる

というわけで、例えば、プロジェクトディレクトリ下のscriptディレクトリに batch.bat を置いて、これをビルド前に実行したいと思ったとき、 Pre-Build Stepに下のように書いていたものを、 .\script\batch.bat こんな風に直します。 $(ProjectDir)\script\batch.bat $(ProjectDir) バッチファイル内でプロジェクトディレクトリのパスを使うには %1 で引数から ひっぱってきましょう。


その他

プロジェクト開いた瞬間に作業ディレクトリをそのプロジェクトのディレクトリに移動したりって 普通のプログラムじゃできないのかな? MPLAB IDEがやってないだけ? この機能があれば、ただの相対パスでも上手くいくと思うんだけど…。

今度調べてみよう。

※9/2追記↓

==== とりあえず、 unistd.h をインクルードすることで カレントディレクトリを変更する chdir() と、カレントディレクトリを取得する getcwd() がありますね。 Win32APIでも、 GetCurrentDirectory() SerCurrentDirectory() があるので…ってまあ普通はできるよな。 MPLABがワークスペースファイルを開いたときにカレントディレクトリを変更しないのは なんでだろうなぁ… …複数プロジェクトを管理するから? うーん。。

(function(document){ var pres = document.getElementsByTagName("pre") for(var i=pres.length; i--; ){  var el = makeOl(pres[i]) pres[i].appendChild(el) } function makeOl(pre){ var ol = document.createElement("ol") , li = document.createElement("li") , df = document.createDocumentFragment() , br = pre.innerHTML.match(/\n/g) ol.className = "preLine" ol.setAttribute("role", "presentation") for(var i=br.length; i--; ){ var li2 = li.cloneNode(true) df.appendChild(li2) } ol.appendChild(df) return ol } })(document)