CLionが最強かもしれない

WebStorm大好きっ子な私ですが、WebStormはWEB系技術をターゲットとしていてC/C++IDEサポートはありません。Go言語関連がGoLandに製品格上げなされた結果としてプラグイン提供がなくなってしまったのと同様にC/C++プラグインもどうやらWebStormに提供されていない。素のWebStormでもかろうじてカラーリングやカッコ対応などの静的テキストファイルの範囲で頑張れるような機能はあったので、メモ帳よりはマシだと考えてましたがヘッダを見るのにもSpotlight検索かよ、と、気が短くなった中高年には無理無理。C++「も」気持ちよく書ける環境を模索して構築します。前提はTypeScriptで気持ちよく書けることで、さらに同じその上でC++

CLion

www.jetbrains.com

信頼するJetBrainsの製品群を眺めてそれっぽいのをピックアップしました。ReSharper C++なるものはVisualStudioのプラグインだって書いてありますから初見除外すると、CLionとAppCodeというのになります。まずMac向けっぽい体裁のAppCodeをトライアルして見ましたがいきなりXCodeが無くて動かないぞエラーを出すので即アンインストールしました。私はXCodeを入れずにcommandline-toolsで凌いでいるし、今後もフルのXCodeを入れる予定は無い。またAppCodeはメインとしてSwiftとObjective-Cを対象としてMac向けに閉じていました。次いでCLionをトライアル。CLionはプラグイン設定で「NodeJS」と「Vue.js」それぞれのサポートプラグインをインストールできました。なぜか製品デフォルトでTypeScriptとTslintのサポート(当然上位のJavaScriptサポートやHTML5関連なども)は入ってたので私のWebStormの使い方にC++が加わったセットを容易に構成完了。既に動かす前からガッツポーズな気分。node/TypeScript/tslint/Jestは一通り動かして問題ない。

CMake

CLionでC++の新プロジェクトを作る場面でいきなり直面するのは、CMakeを用いた開発への強い推し姿勢です。IDEを一貫してCMake中心に考えてられているように見受けます。これまでCMakeは使ってなかったので手元環境には入れてなかったのですが、/Applications/CLion.app/Contentsを掘って確認すると、clang・cmake・gdb・lldbを含んでいました。CMakeはBrewだともっと新しいバージョンになりますが、CLionがサポートしているバージョンが一個古いものまでなので逆らわずに/usr/local/binへリンクを作って、IDE外部からの利用でも同じものを使うようにします。

$ cd /usr/local/bin
$ sudo ln -s /Applications/CLion.app/Contents/bin/cmake/bin/cmake

CLionもその他のIDEでもnode-gypを綺麗にサポートしているものは無いと断じられる中、同じ効能をCMakeベースで構築し直したというCMake.jsがありました。これのチュートリアルをざっと流してみて(10分程度で完了します)。。。ちゃんとビルドできるし、node-gypで実現されていたみたいに自動コンフィギュアかつ自動ツールチェーンで動きます。よしよし。あくまで短時間での感触ですが、CLion-CMake-CMake.jsの組み合わせは筋が良さそうな気がする。

$ yarn add nan cmake-js bindings

WebStormが初年度$129.00/Yなのに対してCLionが初年度$199.00/Yなので、この値段差に柔軟性の違いがあるのでしょう。年末までWebStormのサブスクリプション残しているけど、CLion欲しいな。30日トライアルし尽くして気持ち変わらなければWebStormの半年分がもったいないけど切り替えよう。

とりあえずの設定

CMake.jsがNodeアドオンを作るために必要な環境の情報をかき集めてCMakeの設定を行ってくれるので、それをIDEにも教えてあげないといけない。

$ yarn cmake-js print-configure --debug

このコマンドで、CMake.jsがどんな情報収拾し、CMAKEに設定しているかがダンプされます。

cmake "/Users/masataka_k/Projects/clpoc" --no-warn-unused-cli -G"Unix Makefiles" -DCMAKE_JS_VERSION="3.7.3" -DCMAKE_BUILD_TYPE="Debug" -DCMAKE_LIBRARY_OUTPUT_DIRECTORY="/Users/masataka_k/Projects/clpoc/build/Debug" -DCMAKE_JS_INC="/Users/masataka_k/.cmake-js/node-x64/v10.1.0/include/node;/Users/masataka_k/Projects/clpoc/node_modules/nan" -DNODE_RUNTIME="node" -DNODE_RUNTIMEVERSION="10.1.0" -DNODE_ARCH="x64" -DCMAKE_CXX_FLAGS="-std=c++11 -D_DARWIN_USE_64_BIT_INODE=1 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -DBUILDING_NODE_EXTENSION -w" -DCMAKE_SHARED_LINKER_FLAGS="-undefined dynamic_lookup"

ながーいコマンド行のうちのオプション部分をコピーしてCLionの設定画面に流し込む。

f:id:masataka_k:20180522060034p:plain

メニューでCLion > Preferences > Build, Execution, Deployment > CMAKE を選び、「CMake Options」にペースト。これでプロジェクトを背後でシンボルの構築が行われてIDEにおよそ期待する機能が動作し始めます。

このオプション群は、チュートリアルでコピペしたCMakeLists.txtに流し込まれてくる。

cmake_minimum_required(VERSION 2.8)

# Name of the project (will be the name of the plugin)
project(addon)

# Build a shared library named after the project from the files in `src/`
file(GLOB SOURCE_FILES "src/*.cc" "src/*.h")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})

# Gives our library file a .node extension without any "lib" prefix
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")

# Essential include files to build a node addon,
# You should add this line in every CMake.js based project
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_JS_INC})

# Essential library files to link to a node addon
# You should add this line in every CMake.js based project
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})

これらの環境変数で穴開けてるところに当てはまるのをなぞると、だいたい何が行われているのかが想像できます。ここまでくるとあと必要なのはIDEではなく「そのもの」の知識ですね。チュートリアルはOKでも、CMakeの使い方の詳しいところはこれから習得しないといけない。

OSXの.frameworkを探す

# 〜省略
if(APPLE)
    find_library(CORETEXT CoreText)
    message("CORETEXT= ${CORETEXT}")

    find_library(FOUNDATION Foundation)
    message("FOUNDATION= ${FOUNDATION}")

    set(CMAKE_JS_LIB ${CMAKE_JS_LIB} ${CORETEXT} ${FOUNDATION})
    message("CMAKE_JS_LIB= ${CMAKE_JS_LIB}")
endif(APPLE)

target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})

練習としてOSXの.frameworkを探す定義を書いてみました。find_libraryの第1引数は変数名で第2引数以降に色々探す方法を書くのだけど、今回の場合はCoreText.frameworkの頭の部分だけ「CoreText」を書けば見つけてくれる。よってFoundation.frameworkは「Foundation」。チュートリアルでコピペしたCMakeLists.txtでは、CMAKE_JS_LIBが書かれてたけど実際は使われていなかった。もしかするとどっかから飛んでくることがあるのかもしれないけど、今のところは何も。見つけたライブラリを跡地利用としてsetを用いてCMAKE_JS_LIBに積んでみた。プラットフォームの切り分けは、if(APPLE) - endif()でできる。endifに引数渡さなくても問題ないと思うけど、引数「APPLE」を渡すこの書き方の方が読みやすいです。

ごちゃごちゃやってる後の対応

ごちゃごちゃ色々やってる後で、突然今までなんでもなかったところでコンパイルエラーをエディタが表示し始めることがあった。でもコマンドラインからcmake rebuildを実行すると何事もなくビルドが通る。これはIDEのキャッシュが疑わしい。実際にググって見つけたヘルプの通りにinvalidしてrestartしたら元に戻った。