グレインの備忘録

プログラミング関係とかをつらつらと。

Vim(NeoVim)を導入したらとりあえずしとく設定

インデント関連

set autoindent "自動インデント
set tabstop=4 "タブ幅
set shiftwidth=4 "自動インデント幅
set noexpandtab "タブをスペースに展開しない
set softtabstop=0 "タブ幅(入力時)

その他表示関連

set number "行番号表示
syntax on "シンタックスハイライト

便利そうなキーバインド(必要に応じて)

"Ctrl+Gでエスケープ
inoremap <C-g> <Esc>
nnoremap <C-g> <Esc>
vnoremap <C-g> <Esc>
"挿入モードでもCtrl+hjklでカーソル移動
inoremap <C-h> <Left>
inoremap <C-j> <Down>
inoremap <C-k> <Up>
inoremap <C-l> <Right>
"Ctrl+pで貼り付け
inoremap <C-p> <Esc>"*pa
nnoremap <C-p> "*p
"TerminalモードでEsc,Ctrl+Gでエスケープ(NeoVimのみ)
tnoremap <ESC> <C-\><C-n>
tnoremap <C-g> <C-\><C-n>
"TerminalモードでCtrl+Wでウィンドウ切り替え(NeoVimのみ)
tnoremap <C-w> <C-\><C-n><C-w>

括弧とクォーテーションの補完(一応)

"(){}''""補完(C++のみ)
augroup cpp_indent_auto_setting
    autocmd!
    autocmd FileType cpp setlocal cindent | setlocal cinoptions+=l1,g0
    autocmd FileType cpp inoremap <buffer>{ {}<Left>
    autocmd FileType cpp inoremap <buffer>{<Enter> {}<Left><CR><ESC><S-o>
    autocmd FileType cpp inoremap <buffer>( ()<ESC>i
    autocmd FileType cpp inoremap <buffer>() ()
    autocmd FileType cpp inoremap <buffer>(<Enter> ()<Left><CR><ESC><S-o>
    autocmd FileType cpp inoremap <buffer>' ''<Left>
    autocmd FileType cpp inoremap <buffer>'' ''
    autocmd FileType cpp inoremap <buffer>" ""<Left>
    autocmd FileType cpp inoremap <buffer>"" ""
augroup END

Visual StudioのNDK開発でデバッグ時に「ステップできません。このメッセージは間違っているか、転送中に壊れました。」と出る

AndroidNDKのデバッグでステップできない

VisualStudioのNDK開発でデバッグ時にステップ実行をしていると

 

「ステップできません。このメッセージは間違っているか、転送中に壊れました。」

 

と出ることがある。一旦こうなると困ったもので、ステップもできないのでデバッグを終了するしかない。

余計なウォッチ式が悪さをしていた

ウォッチ式を全部消したらステップ実行が必ずうまくいった。

ステップ実行時に変数情報がうまく取得できないと、gdbserver側でSegmentation Faultが発生、プログラムごとハングしてしまうという仕組みだったらしい。

 

やれやれ。

Android NDKでboost::filesystemが使えない

前回(Android NDK r11cでboost 1.61.0をビルド - グレインの備忘録)の続き。

リンクエラーになる

boost::filesystemを使ったアプリをコンパイルするとリンカエラーが出てしまう。

libs/filesystem/src/path.cpp:function (anonymous namespace)::path_locale(): error: undefined reference to 'std::locale::locale(char const*)'


要するにstd::localeのコンストラクタがリンクできていないらしい。
アプリ側で使ってもこんな事にはならないのに一体何故だ・・・

まあ文句を言ってもしょうがないし、とりあえずlocale機能は自分は使っていないと思うので横着して済ませておく。

boostのlibs/filesystem/src/path.cppの908行目あたりの、

# else  // Other POSIX
    // ISO C calls std::locale("") "the locale-specific native environment", and this
    // locale is the default for many POSIX-based operating systems such as Linux.
    return std::locale("");
# endif

ってなってるやつを

# else  // Other POSIX
    // ISO C calls std::locale("") "the locale-specific native environment", and this
    // locale is the default for many POSIX-based operating systems such as Linux.
    #ifdef ANDROID
    return std::locale();
    #else
    return std::locale("");
    #endif
# endif

に変える。

この後boost::filesystemを再ビルドしてもう一回アプリをコンパイルしたらとりあえず通った模様。

NDKでのboostは闇が深い…

Android NDK r11cでboost 1.61.0をビルド

NDKでboost使おうと思ったら結構大変だったのでメモ。

まずビルドのやり方を調べてみて、良さげだったのがこのページ。

c++ - How to compile Boost 1.61 for Android NDK 11 - Stack Overflow

ここの2番目のポストのやり方でほぼ完全にうまくいった。

一応簡単にここにもまとめておく。

ビルド準備

MinGW or Linux環境を想定。
NDKが${NDK_ROOT}に、boostが${BOOST}にあると仮定する。

1. gcc, binutilsを入れておく

例えば、Ubuntuなら

$ sudo apt-get install gcc binutils

とか。

2. ツールチェインを準備する

例えば展開先フォルダを${TOOLCHAIN}とすると、

$ ${NDK_ROOT}/build/tools/make_standalone_toolchain.sh --arch=arm --platform=android-19 --use-llvm --install-dir=${TOOLCHAIN}

でツールチェインをエクスポートできる。 –platformは自分の必要に応じて変える。

3. ビルド設定ファイルを準備する

${BOOST}/android.clang.jam ファイルに以下の内容を記述する。(NDK_ROOTやTOOLCHAINは適宜置き換えること)

import os ;
local AndroidNDKRoot = ${NDK_ROOT} ;
using clang : android
:
${TOOLCHAIN}/bin/clang++
:
<compileflags>-fexceptions
<compileflags>-frtti
<compileflags>-fpic
<compileflags>-ffunction-sections
<compileflags>-funwind-tables
<compileflags>-Wno-psabi
<compileflags>-march=armv7-a
<compileflags>-mfloat-abi=softfp
<compileflags>-mfpu=vfpv3-d16
<compileflags>-fomit-frame-pointer
<compileflags>-fno-strict-aliasing
<compileflags>-finline-limit=64
<compileflags>-I$(AndroidNDKRoot)/platforms/android-21/arch-arm/usr/include
<compileflags>-Wa,--noexecstack
<compileflags>-DANDROID
<compileflags>-D__ANDROID__
<compileflags>-DNDEBUG
<compileflags>-O2
#<compileflags>-g
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/include
<compileflags>-I$(AndroidNDKRoot)/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include
<architecture>arm
<compileflags>-fvisibility=hidden
<compileflags>-fvisibility-inlines-hidden
<compileflags>-fdata-sections
<cxxflags>-D__arm__
<cxxflags>-D_REENTRANT
<cxxflags>-D_GLIBCXX__PTHREADS
;
4. boostをビルドする

普通にbootstrapからのb2で。

$ cd ${BOOST}
$ ./bootstrap.sh --with-toolset=gcc
$ ./b2 --user-config=android.clang.jam threading=multi link=static \
  runtime-link=static toolset=clang-android target-os=linux \
  threadapi=pthread --stagedir=android

あとはb2のオプションに -j 8とかつけるとマルチスレッドで処理してくれるので速くビルドできるかも。

ただ、コンパイルが通るやつと通らないやつがあるっぽい。一応手元でチェックしてみた結果がこんな感じ。

atomic - success
chrono - success
container - success
context - fail
coroutine - fail
coroutine2 - fail
date_time - success
exception - success
filesystem - success
graph - success
graph_parallel - success
iostreams - fail
locale - success
log - success
math - fail
metaparse - success
mpi - success
program_options - success
python - fail
random - success
regex - success
serialization - success
signals - success
system - success
test - success
thread - success
timer - success
type_erasure - success
wave - success

しかも上のリストでsuccessになってるやつでも本体のリンク時にエラーが起こったりと、結局実際に使ってみないと使えるかどうか分かんないっぽい。。。

バイナリモードのfseekとfwriteの挙動

バイナリファイルで一旦fwriteした後に前方へfseekして、もう一回fwriteすると上書きされるのか挿入されるのかたまに忘れるのでメモっとく。

結論から言うとfseekしてからfwriteすると元のデータは上書きされる。(まあ当たり前か)

例えば、新規ファイルについて

int data = 0x12345678;
fwrite(&data, 4, 1, fp);
fseek(fp, 2, SEEK_SET);
data = 0x90ABCDEF;
fwrite(&data, 4, 1, fp);

みたいにすると、ファイルの中身は

78 56 EF CD AB 90

の6バイトになる。