C/C++のプリプロセッサを使ってHTMLやJavaScriptのデバッグ用コードを操作する。
HTMLやJavaScriptにデバッグやテストのためだけのコードを書いておき、リリース時は消しておきたいといというシチュエーションがあると思います。 gulpなどを使うのかなと思って、調べたら意外にC/C++のプリプロセッサを使う方法が出てきました。
前提
プリプロセッサってなに?
Wikipediaによると
コンパイル処理において、プリプロセッサ(preprocessor)とは、コンパイラがソースコードをコンパイルする前に、一旦ソースコードに処理を施すためのプログラムである。
処理内容
以下のようなものがある。
とのことです。 今回はコンパイル条件によるソースコードの部分的選択という機能を使ってデバッグ用コードをフィルタして取り除いてしまいます。(ということがオプションで選択できるので良いねという話)
準備
MacOSXの場合、XCodeのインストール時にclangというコンパイラがインストールされます。 コンソールからも確認できます。
$ which clang /usr/bin/clang
Unix/Linuxの場合ディストリビューションによってclangやgccがあると思います。 今回使う程度の機能はclangでもgccでも大差なく備えている機能なので、好きな方を使いましょう。 大体の環境ではccコマンドでシステムデフォルトのコンパイラが使えます。
$ which cc /usr/bin/cc $ cc --version Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) Target: x86_64-apple-darwin14.3.0 Thread model: posix
ソースコードを編集
例えば以下の様なJavaScriptソースコードがあったとします。
function is_bigger(a, b) { console.log('is_bigger(' + a + ',' + b ');'); // デバッグ用 return a > b; }
ここでデバッグ用の行を以下のように囲みます。
function is_bigger(a, b) { #ifndef NDEBUG console.log('is_bigger(' + a + ',' + b ');'); // デバッグ用 #endif return a > b; }
なんとなくわかると思いますが、#ifndef ~ #endif部分はNDEBUGという定数が定義された場合、出力されなくなります。ここでのNDEBUGはJavaScriptの変数とは関係ないプリプロセッサのオプションみたいなものです。
プリプロセッサを実行する
ソースコードをsample.jsなどの名前で保存しておきます。
コマンドラインから以下のようにccを起動すると、
$ cc -E -C -P -x c -Wno-invalid-pp-token sample.js
function is_bigger(a, b) { console.log('is_bigger(' + a + ',' + b ');'); // デバッグ用 return a > b; }
また、以下のようにccを起動すると、
$ cc -E -C -P -x c -Wno-invalid-pp-token -DNDEBUG sample.js
function is_bigger(a, b) { return a > b; }
-DNDEBUGオプションでプリプロセッサにNDEBUGという定義を渡しています。これがifndefで評価されることで該当部分のソースコードの出力を制御しています。 引用元には-Eオプションと-Wno-invalid-pp-tokenがありませんでした。-Eばプリプロセッサだけ実行(指定しないとコンパイルしようとしてエラーになる)、-Wno-invalid-pp-tokenは余計な警告(C/C++だと文法的におかしいトークン)を無視しています。 同様の操作でHTML(というか、行頭の#記号に意味が与えられていないファイル)でもデバッグ用コードを操作することができます。 プリプロセッサ自体にはフィルタ以外にもイロイロ機能があります。
活用すればもっと楽ができそうです。 欠点として、
- 出力結果のJavaScriptやHTMLの行がプリプロセッサ分変化するので、ブラウザで出力された行数と修正対象の行数が異なる
- エディタによってはインデントがおかしくなる(かもしれない)
チョット使う場所を選びそうです。