Android NDK(Cmake)を使ったプロジェクトで native libraryのsoの場所を android_gradle_build.json を使って探す

小ネタです。プロジェクトのフォルダで以下のコマンド叩けばsoの場所がわかります。

Linuxです。楽したいのでjqも使ってます。

例:

$ find . -name "android_gradle_build.json" | grep debug | grep armeabi-v7a | xargs jq '.libraries | .[].output'
"/home/kaki/Practice/Android/GlApplication/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so"

途中に挟まってるgrepを消すと、各flaver、各abiのjsonファイルが見つかるはずです。

そもそも出来る場所くらい知ってるよという話はあってそれはそうなんですが、勝手に用意してくれる android_gradle_build.json からコンパイルオプションだとかファイルだとかが取れるので何か便利に使いたいなーという気持ちがありました。 android_gradle_build.json については

CMake | Android Developers

に記述がありました。そのほか「releaseビルドでもstripされてない(APKにするときにstripされる)」とか、一通り読むとへぇ〜な事が書いてありました。 上の例ではsoの場所を出してるだけですがそれなりに情報が入ったjsonになってます。

buildCommandとか書かれてるので、ここらへんに何かねじ込んで実験してみるのも面白そうですねどうなるんでしょう

 GlApplication find . -name "android_gradle_build.json" | grep debug | grep armeabi-v7a | xargs jq '.libraries'
{
  "native-lib-Debug-armeabi-v7a": {
    "abi": "armeabi-v7a",
    "artifactName": "native-lib",
    "buildCommand": "/home/kaki/sdk/android-sdk-linux/cmake/3.6.4111459/bin/cmake --build /home/kaki/Practice/Android/GlApplication/app/.externalNativeBuild/cmake/debug/armeabi-v7a --target native-lib",
    "buildType": "debug",
    "files": [
      {
        "flags": "  --target=armv7-none-linux-androideabi --gcc-toolchain=/home/kaki/sdk/android-sdk-linux/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 --sysroot=/home/kaki/sdk/android-sdk-linux/ndk-bundle/sysroot  -Dnative_lib_EXPORTS -isystem /home/kaki/sdk/android-sdk-linux/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem /home/kaki/sdk/android-sdk-linux/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -isystem /home/kaki/sdk/android-sdk-linux/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/backward  -isystem /home/kaki/sdk/android-sdk-linux/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=23 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -std=c++14 -fexceptions -O0 -fno-limit-debug-info  -fPIC    -c ",
        "src": "/home/kaki/Practice/Android/GlApplication/app/src/main/cpp/native-lib.cpp",
        "workingDirectory": "/home/kaki/Practice/Android/GlApplication/app/.externalNativeBuild/cmake/debug/armeabi-v7a"
      }
    ],
    "output": "/home/kaki/Practice/Android/GlApplication/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so",
    "toolchain": "2304076354519640188"
  }
}

NDK使った開発も compilation_database みたいなものが入って、どんどんベンリになっていくのは嬉しいですね! そんなに開発してないですけど!!

以上です、お疲れ様でした。

Thinkpad T460s で ArchLinux の カーネルを 4.13.3-1 にしたら正常にシャットダウンできなくなったときの話

解決(回避方法)を見つけたし、現在 core に上がっている linux 4.13.5-1 では問題は発生しませんが最近書いてないなと思ったのでメモを残します。

発生していた問題&回避方法

備考

shutdown したときに cgroup: group2: unknown option "" とか出たあと数行画面に進行状態を出した上で進まなくなっちゃう状態でした。

ただ、 この表示は別問題で 、shutdownが最後まで正常に終わらないのは別の要因だったのです。なんてまぎわらしいんだ!(ちゃんと調べましょう

この問題は所有しているThinkpad X230では発生しなかったこと、Dell XPSや最近のLenovo Thinkpadでの発生報告が多いこと、少し前にSumsung PM961でATSの問題を踏んだことから、「またnvme ssd絡みかなー」なんて勝手に思ってたんですが バグ報告とか見る限りYoga460とかT460とかでも起こっているようで、じゃあ何が原因なんだろうか…という感じによくわかっていません。

年内にちょっとここらへんのハードに近い保護機能を調べてちょっとまとめたいなと思いつつ終わり

参考

Arch Linux Android Studio cmake "OPENSSL_1.0.0 not found" を解決する

/usr/lib/libcrypto.so.1.0.0: version `OPENSSL_1.0.0' not found

Error:FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':project:externalNativeBuildCleanDebug'.
> Build command failed.
  Error while executing process ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake with arguments {--build ${HOME}/Project/project/.externalNativeBuild/cmake/debug/armeabi --target clean}
  ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake: /usr/lib/libcrypto.so.1.0.0: version `OPENSSL_1.0.0' not found (required by ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake)
  ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake: /usr/lib/libssl.so.1.0.0: version `OPENSSL_1.0.0' not found (required by ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake)
  ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake: /usr/lib/libssl.so.1.0.0: version `OPENSSL_1.0.1' not found (required by ${HOME}/sdk/android-sdk-linux/cmake/3.6.3155560/bin/cmake)


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

適当にアップデートしてたら遭遇してしまいました。

とりあえずぐぐると一番上にStack Overflow、さすが。

stackoverflow.com

この中ではopensslパッケージをダウングレードすれば良いと書かれてますが、個人的に嫌でした。

下の方までスクロールしていくと「studio.shを編集する」という回答があります。

これでも良かったんですが、Android Studioのアップデートでパッチを当てるたびにconflictが出るのもめんどくさそうなので、別の対処法を取りました。

対処法

opensslをビルドして専用のディレクトリにインストールする。起動時にLD_LIBRARY_PATHを指定する。

微妙といえば微妙ですが、Android StudioやArch Linuxのパッケージアップデートのたびに問題起こるよりマシな感があったので……。

1. libresslをダウンロードする。
2. インストールフォルダを指定してビルドする。
3. インストールする。ちょっと小細工する。
4. 起動時に `LD_LIBRARY_PREFIX` で専用ディレクトリを指定する。
5. (๑•̀ㅂ•́)و✧

1. libresslをダウンロードする。

https://www.libressl.org/

wget https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-2.5.4.tar.gz

2. インストールフォルダを指定してビルドする。

cmakeを使っているので./configureを使う場合は適宜読み替え。

tar xvf libressl-2.5.4.tar.gz
mkdir libressl-2.5.4-build && cd libressl-2.5.4-build
cmake -D CMAKE_INSTALL_PREFIX=${YOUR_INSTALL_DIRECTORY} ../libressl-2.5.4
make -j`nproc`

3. インストールする。ちょっと小細工する。

CMAKE_INSTALL_PREFIXをつけてるのでmake installすればインストールはできるんですが、

Android Studioで入るcmakelibXXX.so.1.0.0を探すようです。 インストールしても上記のシンボリックリンクは作られないので適当に作ります。

make install
cd ${YOUR_INSTALL_DIRECTORY}/lib
ln -s libssl.so{,.1.0.0}
ln -s libcrypto.so{,.1.0.0}
# libtlsは使わないのでスルー

4. 起動時に LD_LIBRARY_PREFIX で専用ディレクトリを指定する

自分の起動方法に合わせて読み替えて下さい。僕はDesktop Entryから起動するので、

vim ~/.local/share/applications/jetbrains-studio.desktop

ファイルの内容は以下ですが、${HOME}${YOUR_INSTALL_DIRECTORY} のようなシェル変数の書き方をしてる部分は実際のパスに置き換えて下さい

[Desktop Entry]
Version=1.0
Type=Application
Name=Android Studio
Icon=${HOME}/Tools/android-studio/bin/studio.png
Exec=env LD_LIBRARY_PATH=${YOUR_INSTALL_DIRECTORY}/lib "${HOME}/Tools/android-studio/bin/studio.sh" %f
Comment=Develop with pleasure!
Categories=Development;IDE;
Terminal=false
StartupWMClass=jetbrains-studio

Execのところでenv LD_LIBRARY_PATH=${YOUR_INSTALL_DIRECTORY} を指定してます。

これで解決しました。お疲れ様でした。

Rust: bindgenで生成したコードのdoctestがコケる

RustでCのラッパーライブラリを作ろうとしてたときに発生しました。

以下で対処

[lib]
doctest = false

Cargo.tomlに書き加える。

The Manifest Format

そもそもコメント形式が違うのになんでdoctestに引っかかってるのかはわかってないけどモチベがないのでこれでよしとする。

20170410 00:18 追記:

普通にbindgenにコメント生成しないようにするメソッドがありました

bindgen::Builder - Rust

Comments are copied verbatim without checking if they might be invalid · Issue #426 · servo/rust-bindgen · GitHub

    for fname in &files {
        let _ = bindgen::builder()
            .header(format!("{}/{}.h", &header_dir, &fname))
            .raw_line("pub use super::*;")
            .hide_type("max_align_t")
            .generate_comments(false)
            .clang_arg("-std=c11")
            .generate().unwrap()
            .write_to_file(Path::new(&out_dir).join(format!("{}.rs", &fname)));
    }

手元で作業してるものはこんな感じになりました。ドキュメントはちゃんと見ましょうということで、はい。

Rustで<T: std::ops::Sub> T - T の返り値

<T: std::ops::Sub> T - T の返り値

std::ops::Sub::Outputが返り値になる。

AddとかMulとか、Overloadable operatorsはそんな感じらしい

doc.rust-lang.org

Associated typesと一緒にやったときちょっと引っかかったのでした。 Rustはまだ数回ググらないと、自分の知識では目的までたどり着けないなあ。

たいして目的のないコードを載せると、こんな感じです。

trait Contains {
    type A: Copy + ops::Sub;
    type B: Copy + ops::Sub + convert::From<Self::A>;

    fn contains(&self, &Self::A, &Self::B) -> bool;
    fn first(&self) -> Self::A;
    fn last(&self) -> Self::B;
}

fn difference<C: Contains>(container: &C) -> <C::B as ops::Sub>::Output {
    container.last() - C::B::from(container.first())
}

お疲れ様でした。

Arch LinuxでAndroid Studioを使ってC++ supportのプロジェクトを作るときにやったこと

プロジェクト作成は省略。Hello from C++を表示するまでにやったこと。 Arch Linuxではプロジェクト作ってそのままだとGradle syncがCMake実行時にコケてしまったのでメモ。

libncurses

なんかlibncurses.so.5が見つからないと言われる。 ncurses は インストール済みなのに言われるので調べたらlibncurses.so.6が入ってるんですね。

なので symbolic link を貼って解決すればいいとのこと。

[SOLVED]Cannot find libncurses.so.5 / Newbie Corner / Arch Linux Forums

sudo ln -s /usr/lib/libncursesw.so.6 /usr/lib/libncurses.so.5

libtinfo

ncursesの解決はできたものの今度は libtinfo.so.5 が見つからないとのこと。

sudo pacman -Ss libtinfo なんて適当に調べても見つからない。 おとなしくググると、 AURにはあるらしい。

なのでyaourt -S libtinfoでインストール。/usr/libの下を確認するとlibtinfo.so.6がいることを確認

sudo ln -s /usr/lib/libtinfo.so.{6,5}

これでとりあえずはGradle syncがコケなくなってHello from C++が表示できました。

お疲れ様でした。

参考:

おまけ

いつものエミュレータが起動できないlibstdc++のアレ

追記: 2017/03/14現在、確認

SDKいくつで変わったのかはわかりませんが、soが移動してました。ので

mv $ANDROID_SDK_HOME/emulator/lib64/libstdc++/libstdc++.so.6{,.back}
ln -s /usr/lib/libstdc++.so $ANDROID_SDK_ROOT/emulator/lib64/libstdc++/libstdc++.so.6

↑こんな感じで。

↓では動きません。動きませんというか、ファイルがないのでコケるはず。

mv $ANDROID_SDK_HOME/tools/lib64/libstdc++/libstdc++.so.6{,.back}
ln -s /usr/lib/libstdc++.so $ANDROID_SDK_ROOT/tools/lib64/libstdc++/libstdc++.so.6

IntelliJ IDEA で Gradle Java のプロジェクトを作ったときのsrcフォルダの場所

普段Android Studioが勝手に作ってくれてよく忘れるので覚え書き。

  • IntelliJ IDEA 2016.3.2 Community Edition での説明です。

プロジェクト作成の流れ

Create New Project(もしくはメニューの New -> Project)を選択して

Gradle -> Java を選択

f:id:norikakip:20170108171649p:plain

GroupId にはパッケージ名、ArifactIdにはプロジェクト名を入れる

f:id:norikakip:20170108171913p:plain

GradleのJavaプラグインではプロジェクトのレイアウトが決められていて(もちろん変更は可能)、ソースフォルダは

が使われるようになっている。なのでここにフォルダを作ってソースファイルを入れないと、Gradleに設定を書いていない限り、syncするたびにソースフォルダとして指定しないといけなくなります。ちょっとハマりました。

第23章 Javaプラグイン

これでプロジェクトが始められるぞー٩( ‘ω’ )و ガンバル

フォルダを自分で作りたくない

プロジェクト作成時に Create directories… にチェックを入れればフォルダは勝手に作られます。

f:id:norikakip:20170108175854p:plain

よく読もうと思いました。終わり。