産廃置き場出張所

気が向いたら書きます

「強い魔法を作ろう」と20代半ばの危機

強い魔法を作ろう

play.google.com
先週公開しました。

雑感

今回は以下の事項に触ってみました。

JavaCC

JavaCCに関しては、jjファイルを突っ込めば自動でビルドしてくれるGradleプラグインがあるのですが、結局使い方が分からず仮想マシン上のLinuxでジェネレータにかけてコピーしてました。
後、JavaCCってラムダ式をパースの結果として返せないんですかね? パッケージ管理システムから入れたやつだとエラーが出てパースの結果としてラムダ式を返すパーサを生成できませんでした。
パーサジェネレータは以前触ったことがあったので、JavaCC自体の使い方をサンプル等見ながら学べば特に詰まるところはありませんでした。

drawer

drawer。左からにゅっと出てくるアレ。
背景色を指定しないと左からにゅっと出したときに出てきたもの自体が暗転することで多分数時間は空費してしまった。

ラムダ式

ラムダ式はどうでしょうね。ラムダ式自体のサポートは入ってもjava.util.functionパッケージがAPIレベルがかなり高くないと使えないので正直なところ微妙でした。(functionパッケージ内の必要なクラスをコピーして使いました)

次のネタはまだ見つかっていないですが、最近話題のKotlinを使ってみるべく、早くネタを見つけたいです。
一時期関数が第一級オブジェクトである世界にいたので、できればリフレクションとか使えるようなネタで、実際に使ってみたいです。

20代半ばの危機

以下はアプリとは全く関係のない話です。単純に自分語りがしたいだけです。

大学の推薦で応募したところに弾かれたりといろいろありましたが、何とか職を得て4月から働いています。
で、2か月弱経つわけですが何も変わっていない気がするんです。何もできることが増えている気がしない。
そして、自身ができることを棚卸しようとしても、ないんだな、それがの画像を貼りたいくらいない。
そんなこんなで本日焦燥感に駆られたのでこんなことを書きました。
会社に依存せずとも食うに困らなくなるようになりたい……(できれば技術力や遂行能力等々で)

あ、今日の晩御飯はメンチカツをおかずにして白米を食べてました。おいしかったです。

Androidアプリ開発でレイアウトXMLに埋め込んだFragmentを置き換えてはいけなかったお話

まとめ

休日の半日ほど溶かしてしまったのでメモ。
レイアウトXMLに埋め込んだFragmentの置き換えはおそらく思った通りの動作となりません。
私の中ではアプリ起動時のActivityの初期化処理(onCreateあたり?)でコード上でFragmentを追加することに落ち着きました。
参考:android - Fragmentをreplaceしても一つ前のFragmentが残る - スタック・オーバーフロー

経緯

サーモン爆破クリッカーAndroid移植中、Fragmentの置き換え後にエフェクトが表示されないというバグに遭遇しました。
画面イメージと簡単なレイアウト構成は以下の通りです。

LinearLayout
  |- 広告ビュー
  |- Fragment
  |- LinearLayout
       |- ImageButton
       ...

画面中央の何かをタップすると爆破エフェクトとともにサーモン数が増えます。
当初はFragmentも初期状態のものをレイアウトXMLに決め打ちで記述していました。

モード切替はImageButtonのリスナにFragmentのreplaceを行う処理を設定することで行っていました。
Fragmentのreplace処理を実装し、モード切替のテストをしていたところ、一度他のモードに切り替えてからクリッカーモードに戻すと表示されるはずの爆破エフェクトが表示されなくなりました。

その後、紆余曲折を経てFragmentをLinearLayoutに埋め込んでモード切替をするとFragmentの一部のViewが切り替え後も残ることが判明、冒頭の質問と回答を発見し、FragmentをActivityのonCreateメソッドで追加することで解決しました。

変更後のレイアウトはこんな感じです。

LinearLayout
  |- 広告ビュー
  |- LinearLayout <- ActivityのonCreateメソッドでFragmentをここにadd
  |- LinearLayout
       |- ImageButton
       ...

MSYS2+MinGWの環境でSML#3.2.0をビルドしたかったけどランタイムのビルドができなかったお話

結論から言いますが、SML#のランタイムのビルドでこけています。

SML#3.2.0版(書いた時点(2016/11/03)時点での最新版)を仮想マシン上ではなくWindows上で直で動かしたいと思ったが吉日、やってみたけどランタイムのビルドができなかったお話。
誰か(動かして|既に動かしている例があったら教えて)ください。

以下は雑多な作業ログです。

1日目

MSYS2のインストーラをダウンロードしてインストールします。x86_64の方を入れました。
MSYS2 installer
インストールからパッケージ管理システムのアップデートまでダウンロードページのドキュメントに沿ってやりました。

MinGWのツールチェインを入れます。とりあえずx86_64向けで。

$ pacman -S mingw-w64-x86_64-toolchain

インストールが終わったらMinGW64の方で起動しなおします(スタートメニューのMSYS2 64bit内の"MSYS2 MinGW 64-bit")。

とりあえずLLVM3.7.1入れます。

$ wget http://llvm.org/releases/3.7.1/llvm-3.7.1.src.tar.xz
$ tar Jxf llvm-3.7.1.src.tar.xz 
bash: tar: コマンドが見つかりません

tar入ってなかった……

$ pacman -S tar
$ tar Jxf llvm-3.7.1.src.tar.xz 
$ mkdir llvm-371-obj
$ cd llvm-371-obj
$ ../llvm-3.7.1.src/configure --prefix=$HOME --enable-shared --enable-optimized --disable-bindings
...
checking tool compatibility... configure: error: GNU Make required but not found

makeもない……

$ pacman -S make
$ ../llvm-3.7.1.src/configure --prefix=$HOME --enable-shared --enable-optimized --disable-bindings
$ make

ここまでやったのですが、LLVM-3.7.dllをmakeするルールがないと怒られているっぽい。
Bug 12795 – Linking shared library fails on Win7 64-bit with x64_64-w64-mingw32-gcc-4.6.3を(私の拙い言語運用能力で)参照してllvm-3.7.1.src/Makefile.rules内の.defを全て.a.oに入れ替えたり、nオプション付きでmakeかけて試行錯誤しているうちに気が付いたらインストールまでできた感じです。(正しくビルドできたかどうかは不明です)

とりあえず先に進みます。
入れ忘れていたGMPを入れます。

$ pacman -S gmp-devel

yajlを入れます。

$ cd
$ wget http://github.com/lloyd/yajl/tarball/2.1.0
$ mv 2.1.0 yajl-2.1.0.tar.gz
$ tar zxf yajl-2.1.0.tar.gz
$ cd lloyd-yajl-66cb08c/
$ ./configure --prefix=$HOME
== removing old build files
== running CMake in build directory
./configure: 行 41: cmake: コマンドが見つかりません

cmake入れます。

$ pacman -S cmake
$ ./configure --prefix=$HOME
...
== Configured with installation prefix: /usr/local

prefixがどうにも通っていないっぽいですが、だいぶ疲れてきていたのでmakeを強行。

$ make
...
FAILURE
 test (zerobyte): ./run_tests.sh: 行 71: diff: コマンドが見つかりません
...
$ pacman -S diffutils
$ make
なんかいろいろエラー

エラーメッセージ見たりしてるとそもそもMinGWに対応しているのかわからない。
疲れたので強行。ダメだったら後日考える。

$ cd
$ wget http://www.pllab.riec.tohoku.ac.jp/smlsharp/download/smlsharp-3.2.0.tar.gz
$ tar zxf smlsharp-3.2.0.tar.gz
$ cd smlsharp-3.2.0
$ ./configure --prefix=$HOME --with-llvm=$HOME
...
configure: error: llc is not found.

はい。
先ほど文字列を置き換えたMakefile.rulesを見たら機械的に置き換えたせいでひどいことになっていたので、NativeExportsFileのところの.defを.a.oに置き換えて再度LLVMをmake。
いろいろ試行錯誤しているうちにメインのdllの生成時のみ.a.oで、それ以外は.oになるべき箇所のような気がする(というよりそう書いてあったんじゃ)
NativeExportsFileの先ほど変更した個所を.oにしてみたのですがやはりわからない。
匙を投げる。

2日目

とりあえず前回ソースからビルドして成功していないもののアンインストールから始めます。

$ cd llvm-371-obj
$ make uninstall
$ cd ~/lloyd-yajl-66cb08c/
$ make uninstall
make: *** ターゲット 'uninstall' を make するルールがありません.  中止.

なん……だと……
仕方ないので手動で削除(あまりよくない)

$ cd /usr/local/bin
$ rm json_*
$ cd ../include
$ rm -r yajl
$ cd ../lib
$ rm libyajl*
$ cd ../share/pkgconfig
$ rm yajl.pc

cmakeを使ったビルドに挑戦。cmake使うのは初めてです。
cmakeの使い方であったりLLVMのビルドに関しては参°ぼっくす: cmakeの使い方KMC Staff Blog:LLVM/Clang 3.7.1をMSYS2でビルドを参考にいたしました。
cmakeをLLVMのビルドで使う際のオプションは公式ドキュメントのBuilding LLVM with CMake — LLVM 4.0 documentationも参考に。

$ cd ~/lloyd-yajl-66cb08c/
$ cmake -DCMAKE_INSTALL_PREFIX=$HOME
$ make
$ make install
$ cd ~/llvm-371-obj
$ cmake ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
... (大量のエラー)

よくわからないので、参考にしたページの手順で行っていないことを行う。

$ pacman -S mingw-w64-x86_64-cmake
$ cmake ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
(エラーメッセージ)
$ cmake.exe ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
(使われたcmakeが違うという感じのエラーメッセージ)
$ rm CMakeCache.txt
$ cmake.exe ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
(なんかCコンパイラのパスが違うよ! という感じのエラーメッセージ)
$ cmake.exe ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true -DCMAKE_C_COMPILER=gcc.exe -DCMAKE_CXX_COMPILER=g++.exe
(なんか簡単なファイルもコンパイルできなかったよ! という感じのメッセージ)
$ pacman -S base-devel
$ cmake.exe ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
(同じく簡単なファイルもコンパイルできなかったよ! という感じのメッセージ)
$ rm CMakeCache.txt
$ cmake.exe -G "MSYS Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_LLVM_DYLIB=true
(同じ感じのエラー)

この後いろいろやってみましたが、どうにもLLVMのcmakeが通りません。
もしかしたら通常のconfigureでも通らないかどうか試してみましたがやはり無理でした。

Build LLVM 3.7 with MinGW w64, MSYS2, CMake · valtron/llvm-stuff Wiki · GitHubここのページを参考にもう一度だけ。

$ cd ~/llvm-371-obj/
$ cmake -G "MinGW Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;CppBackend" -DLLVM_BUILD_LLVM_DYLIB=true -DLLVM_INCLUDE_TESTS=OFF
$ rm CMakeCache.txt
$ cmake -G "MinGW Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;CppBackend" -DLLVM_BUILD_LLVM_DYLIB=true -DLLVM_INCLUDE_TESTS=OFF
(何かいろいろ見つからないというエラー)
$ cmake.exe -G "MinGW Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;CppBackend" -DLLVM_BUILD_LLVM_DYLIB=true -DLLVM_INCLUDE_TESTS=OFF
(エラーメッセージ)
$ cmake.exe -G "MinGW Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;CppBackend" -DLLVM_INCLUDE_TESTS=OFF
(エラーメッセージ)
(この間llvm-371-objディレクトリごと削除したり作り直したり)
$ cd ..
$ rm -r llvm-371-obj
$ mkdir llvm-371-obj
$ cd llvm-371-obj
$ cmake -G "MSYS Makefiles" ../llvm-3.7.1.src -DCMAKE_INSTALL_PREFIX=$HOME -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF
$ make -j4
$ make install

ライブラリやバイナリにパスを通します。

~/.bash_profileに環境変数として追加しています。個人の趣味です。

export PATH=$HOME/bin:$PATH
export CPATH=$HOME/include:$CPATH
export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH

追加して保存したらターミナル上で読み込みます。

$ source ~/.bash_profile

SML#のビルドに挑みます。

$ cd ~/smlsharp-3.2.0
$ ./configure --prefix=$HOME
(libyajlが見つからないというエラー)

configureを見たらstaticなライブラリを指定するオプションがあったのでそれで再度やってみる。

$ ./configure --prefix=$HOME --with-yajl_s
(同じくlibyajlが見つからないというエラー)

gccでテストファイルを作成し、yajlをリンクしたバイナリを生成しようとしても見つからないと言われる。なぜ?
Lオプションで手動でパスを指定してやるとうまく動くが……

LIBRARY_PATHに設定すると動いた。が、LIBRARH_PATH=$Home/lib:となっていると動かない。(コロンがなければ動く)
とりあえず.bash_profileの環境変数の設定の部分を下記のように上書きしました。(シェルスクリプトは全然書かないのでもっといいやり方があると思います)

if [ -z $PATH ]; then
    export PATH=$HOME/bin
else
    export PATH=$HOME/bin:$PATH
fi
if [ -z $CPATH ]; then
    export CPATH=$HOME/include
else
    export CPATH=$HOME/include:$CPATH
fi
if [ -z $LIBRARY_PATH ]; then
    export LIBRARY_PATH=$HOME/lib
else
    export LIBRARY_PATH=$HOME/lib:$LIBRARY_PATH
fi

一度MSYS2を再起動。
再度SML#のビルドに試みる。

$ cd smlsharp-3.2.0
$ ./configure --prefix=$HOME --with-yajl_s
...
configure: error: "RTLD_DEFAULT is required"

GitHub - dlfcn-win32/dlfcn-win32: Official dlfcn-win32 repoを入れて試してみる。

$ cd
$ wget https://github.com/dlfcn-win32/dlfcn-win32/releases/download/v1.0.0/dlfcn-win32-static-1.0.0.tar.gz
$ tar zxf dlfcn-win32-static-1.0.0.tar.gz
$ cd smlsharp-3.2.0
$ ./configure --prefix=$HOME --with-yajl_s
$ make
...
src/runtime/callback.c:9:22: fatal error: sys/mman.h: No such file or directory
 #include <sys/mman.h>

GitHub - witwall/mman-win32: mman library for Windows. mirror of https://code.google.com/p/mman-win32/を入れて試してみる。

$ cd
$ pacman -S git
$ git clone https://github.com/witwall/mman-win32
$ cd mman-win32
$ ./configure --prefix=$HOME --libdir=$HOME/lib --incdir=$HOME/include/sys
$ cd ~/smlsharp-3.2.0
$ make
...
src/runtime/prim.c:1198:31: error: 'S_IFLNK' undeclared (first use in this function)
 PRIM_CONST_FUNC(unsigned int, S_IFLNK)
                               ^
...

src/runtime/prim.cのL50くらいを以下のように変えてみる(おそらく動かない)。

#ifdef MINGW32
#include <windows.h>
#undef OBJ_BITMAP
#define S_IFLNK  0120000
#define S_IFSOCK 0140000
#define S_ISUID	 0004000
#define S_ISGID	 0002000
#define S_ISVTX	 0001000
#endif /* MINGW32 */
$ make
...
g++ -shared -Wl,--enable-auto-import,--enable-stdcall-fixup -o src/llvm/smlsharp_gc.dll src/llvm/main/smlsharp_gc.o
src/llvm/main/smlsharp_gc.o:smlsharp_gc.cpp:(.text+0x1a): undefined reference to `llvm::GCStrategy::GCStrategy()'
...

LLVMのdllをProblems building with LLVM_BUILD_LLVM_DYLIB · valtron/llvm-stuff Wiki · GitHubに従って作ることにする。

$ make
g++ -shared -Wl,--enable-auto-import,--enable-stdcall-fixup -o src/llvm/smlsharp_gc.dll src/llvm/main/smlsharp_gc.o
src/llvm/main/smlsharp_gc.o:smlsharp_gc.cpp:(.text+0x1a): undefined reference to `llvm::GCStrategy::GCStrategy()'
...
$ g++ -shared -Wl,--enable-auto-import,--enable-stdcall-fixup -o src/llvm/smlsharp_gc.dll src/llvm/main/smlsharp_gc.o -lLLVM
$ make
...
/mingw64/bin/xz -c -d ./precompiled/x86_64.ll.xz \
| \msys64\home\USERNAME/bin/llvm-as -o precompiled/x86_64.bc
/bin/sh: 行 1: msys64homeUSERNAME/bin/llvm-as: No such file or directory
xz: (stdout): Write error: Invalid argument
make: *** [Makefile:214: precompiled/x86_64.bc] エラー 127
$ /mingw64/bin/xz -c -d ./precompiled/x86_64.ll.xz | /home/USERNAME/bin/llvm-as -o precompiled/x86_64.bc
$ make
\msys64\home\USERNAME/bin/llc -load=src/llvm/smlsharp_gc.dll -mtriple=x86_64-w64-mingw32 -O2 \
-tailcallopt -filetype=obj -o precompiled/x86_64.o precompiled/x86_64.bc
LLVM ERROR: unsupported GC: smlsharp
make: *** [Makefile:219: precompiled/x86_64.o] エラー 1

なんとかSML#のビルドの開始まではこぎつけましたが、問題の切り分けが面倒厳しそうなのでギブアップ。
先頭にも書きましたが、誰か(動かして|最新版をWindowsで動かした例があったら教えて)ください。

やりたいことリスト(随時更新)

人生に悩んでいるので。随時更新予定。

続きを読む