競技プログラミングはじめました
年末だけど、なにかあたらしいことを始めたいなぁとおもったので、以前から興味があった競技プログラムを始めてみました。
多くの競技プログラムサイトは英語圏のものなのですが、上記のAtCoderは完全日本語なので、「問題文が読めない!」という問題はないので安心して始められます(笑)
TopCoderなどの英語圏にもチャレンジしたいけど、まずは競技プログラムに慣れるところからということで。
競技プログラムはアルゴリズム要素が多くなるのだけれど、いままで勉強してこなかったので初歩の初歩から楽しんで取り組める感じ。
ケアレスミスもあったりして、改めて自分のプログラマーとしての実力もまだまだだということを実感しました。
他の人の回答も見られるので、学習効果は高いと思います。
仕事のプログラムは他人の解法と比べることはできませんからね。
Qemu を使いこなすために
組み込みを仕事にしているため、よく機材不足や新規基盤の開発遅れなどのトラブルが起きます。
そこで、Qemu を活用できればと思っていたところに良い記事が見つかったので写経してみました。
ところが、ドライバの作成でコンパイルエラーが発生!!
ハードとして x86_64 環境、カーネルは 4.2 を選んだけど、組み合わせの問題はありがちなので解決していく。
> make make -C path/to/linux-4.2/ M=/path/to/custom_d evices/test_pci modules make[1]: Entering directory `/path/to/linux- 4.2' CC [M] /path/to/custom_devices/test_pci/test_pci_driver.o In file included from ./arch/x86/include/asm/bitops.h:16:0, from include/linux/bitops.h:36, from include/linux/kernel.h:10, from include/linux/list.h:8, from include/linux/module.h:9, from /path/to/custom_devices/test_pci/test_pci_driver.c:7: ./arch/x86/include/asm/arch_hweight.h: In function ‘__arch_hweight64’: ./arch/x86/include/asm/arch_hweight.h:53:42: error: expected ‘:’ or ‘)’ before ‘POPCNT64’ asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT) ^ MENT’ b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n\t" ^ ./arch/x86/include/asm/arch_hweight.h:53:7: note: in expansion of macro ‘ALTERNATIVE’ asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT) ^ In file included from ./arch/x86/include/asm/pgtable_types.h:250:0, from ./arch/x86/include/asm/processor.h:18, from ./arch/x86/include/asm/thread_info.h:49, from include/linux/thread_info.h:54, from ./arch/x86/include/asm/preempt.h:6, from include/linux/preempt.h:64, from include/linux/spinlock.h:50, from include/linux/seqlock.h:35, from include/linux/time.h:5, from include/linux/stat.h:18, from include/linux/module.h:10, from /path/to/custom_devices/test_pci/test_pci_dri ver.c:7: ... 省略 ...
どうやら、標準ヘッダの 64bit 依存部分に問題があるらしい。
と思ったら、 ARCH
と CROSS_COMPILE
を指定し忘れているだけだった。
obj-m += test_pci_driver.o export ARCH = arm export CROSS_COMPILE = /path/to/buildroot/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi- KERNELDIR = /path/to/buildroot/output/build/linux-4.2/ all: make -C $(KERNELDIR) M=$(PWD) modules clean: make -C $(KERNELDIR) M=$(PWD) clean
すぐに気づいたけど、ダサすぎる。
ドライバ作成とか慣れていないのがバレバレである。
ビルドができたところで、問題が発生した。
ビルド環境は docker のコンテナ内に作成しているのだが、コンテナにはループバックデバイスがないため、 Qemu のルートファイルシステムがマウントできないのである!
> sudo mount -t ext2 -o loop,rw ../../buildroot/output/images/rootfs.ext2 /mnt/ mount: Could not find any loop device. Maybe this kernel does not know about the loop device? (If so, recompile or `modprobe loop'.)
いろいろ調べたけど、今のコンテナの状態ではできないっぽい。( rootfs をホストから隔離しなければできたり、 loop デバイスをコンテナにも見せたりできるらしいけど、本筋からずれるから今はやらない。でも、開発環境として本格的に利用するのであれば後者を試してみないと)
rootfs は buildroot で作成しているので(カーネルもだけど)、直接組み込むことで解決した。
$ qemu-system-arm -m versatilepb -kernel output/images/zImage -drive file=output/images/rootfs.ext2,if=scsi -append "root=/dev/sda console=ttyAMA0,115200" -nograpic -device test_pci
insmod
してみたけど、 Oops になってしまった。。。
今後は、問題を解決してアプリを作成→業務で使っているデバイスに近づくように拡張。と進めていこう。
# insmod test_pci_driver.ko test_pci 0000:00:0d.0: enabling device (0100 -> 0103) *** /home/embryo/workspa(321) test_pci_probe: PCI enabled for test_pci *** /home/embryo/workspa(327) test_pci_probe: mmio_base: 50002000, mmio_length: 50002000, m mio_flags: 1000 *** /home/embryo/workspa(346) test_pci_probe: pio_base: 1400, pio_length: 100, pio_flags: 4 0101 ------------[ cut here ]------------ kernel BUG at arch/arm/mach-versatile/pci.c:87! Internal error: Oops - BUG: 0 [#1] ARM Modules linked in: test_pci_driver(O+) CPU: 0 PID: 71 Comm: insmod Tainted: G O 4.2.0 #1 Hardware name: ARM-Versatile PB task: c79d6380 ti: c79e8000 task.ti: c79e8000 PC is at __pci_addr.isra.1+0x24/0x2c LR is at versatile_read_config+0x1c/0xb8 pc : [<c00148d8>] lr : [<c001498c>] psr: 20000093 sp : c79e9d20 ip : c0014970 fp : 38623d9c r10: 00000001 r9 : bf001798 r8 : 00000000 r7 : bf001960 r6 : 0000fefe r5 : 00000002 r4 : 00000068 r3 : 00000002 r2 : 0000fefc r1 : 00000068 r0 : 00000000 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 00093177 Table: 07b14000 DAC: 00000015 Process insmod (pid: 71, stack limit = 0xc79e8190) Stack: (0xc79e9d20 to 0xc79ea000) 9d20: c79e9d64 60000013 bf0012f0 c017efb0 c79e9d3c c79e9d44 c7870800 00000000 9d40: bf0012f0 c7870800 bf001960 bf000c08 00001400 00000100 00040101 20000013 9d60: bf001750 00000000 c7870800 c7870868 bf001750 00000000 c7870800 bf00171c 9d80: bf001798 c01883a4 c0188330 c7870868 c042bfe0 bf001750 c03f0b40 00000003 9da0: c79dc280 c01cbd48 c7870868 bf001750 c787089c c03f0b40 00000000 c01cbf70 9dc0: 00000000 bf001750 c01cbee4 c01ca470 c7823d0c c7861d50 bf001750 c7b181e0 9de0: 00000000 c01cb5b4 bf0012f0 c79dc288 bf001750 bf001750 c03ddf20 c79d8760 9e00: bf003000 c01cc730 bf001790 c03ddf20 c03ddf20 c0009604 c03f0920 c0036a38 9e20: 00000000 00000000 00000000 c0025f98 000080d0 00000000 c79e9e38 c79e9e38 9e40: bf001828 c7b08000 c03dde00 c7fec9c0 c7ef9000 00000000 00000000 00000000 9e60: c79dc280 00000001 bf0017e0 c79dc288 c79d8720 bf0017e0 bf001828 00000001 9e80: 38623d9c c02cf920 c79e9f48 c79dc288 c79e9f48 c79dc288 00000001 c0056768 9ea0: bf0017ec 00007fff 00000000 c0054238 00000000 00000000 00000000 00000124 9ec0: c898b170 bf00193c bf0017ec 00000000 00000000 c0085004 00000004 c0085cd8 9ee0: ff000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9f00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9f20: c0056bc8 00003545 00000000 000bb55d c898c545 000b8008 c79e8000 00000000 9f40: 00000000 c0056c38 c8989000 00003545 c898ac98 c898ab49 c898c018 00001970 9f60: 00001b60 00000000 00000000 00000000 0000001f 00000020 00000017 00000000 9f80: 00000011 00000000 00000000 beb60f45 000b8008 000b8018 00000080 c000a444 9fa0: c79e8000 c000a2c0 beb60f45 000b8008 000b8018 00003545 000b8008 00000000 9fc0: beb60f45 000b8008 000b8018 00000080 000b669c 00000000 b6fa0f70 00000000 9fe0: b6f4c3c8 beb60c94 0001c994 b6f4c3d8 a0000010 000b8018 00000000 00000000 [<c00148d8>] (__pci_addr.isra.1) from [<c001498c>] (versatile_read_config+0x1c/0xb8) [<c001498c>] (versatile_read_config) from [<c017efb0>] (pci_bus_read_config_word+0x4c/0x60) [<c017efb0>] (pci_bus_read_config_word) from [<bf000c08>] (test_pci_probe+0x1d8/0x558 [test _pci_driver]) [<bf000c08>] (test_pci_probe [test_pci_driver]) from [<c01883a4>] (pci_device_probe+0x74/0x c8) [<c01883a4>] (pci_device_probe) from [<c01cbd48>] (driver_probe_device+0x124/0x2c0) [<c01cbd48>] (driver_probe_device) from [<c01cbf70>] (__driver_attach+0x8c/0x90) [<c01cbf70>] (__driver_attach) from [<c01ca470>] (bus_for_each_dev+0x70/0xa0) [<c01ca470>] (bus_for_each_dev) from [<c01cb5b4>] (bus_add_driver+0x188/0x210) [<c01cb5b4>] (bus_add_driver) from [<c01cc730>] (driver_register+0x78/0xf8) [<c01cc730>] (driver_register) from [<c0009604>] (do_one_initcall+0x80/0x1e0) [<c0009604>] (do_one_initcall) from [<c02cf920>] (do_init_module+0x58/0x1b4) [<c02cf920>] (do_init_module) from [<c0056768>] (load_module+0x18f0/0x1cf4) [<c0056768>] (load_module) from [<c0056c38>] (SyS_init_module+0xcc/0x124) [<c0056c38>] (SyS_init_module) from [<c000a2c0>] (ret_fast_syscall+0x0/0x38) Code: e1801401 e1810002 e28004e9 e12fff1e (e7f001f2) ---[ end trace d58ace19ffed3147 ]--- Segmentation fault # main-loop: WARNING: I/O thread spun for 1000 iterations
、、、
ケアレスミスがいくつか合ったけど、無事ロードができた。
# insmod test_pci_driver.ko test_pci 0000:00:0d.0: enabling device (0100 -> 0103) *** /home/embryo/workspa(321) test_pci_probe: PCI enabled for test_pci *** /home/embryo/workspa(327) test_pci_probe: mmio_base: 50002000, mmio_length: 1000, mmio_flags: 40200 *** /home/embryo/workspa(346) test_pci_probe: pio_base: 1400, pio_length: 100, pio_flags: 40101 *** /home/embryo/workspa(361) test_pci_probe: PCI Vendor ID: fefe, Device ID: 1 *** /home/embryo/workspa(366) test_pci_probe: success allocate I/O region *** /home/embryo/workspa(369) test_pci_probe: device irq: 94 *** /home/embryo/workspa(400) test_pci_probe: test_pci driver(major 253) installed. *** /home/embryo/workspa(420) test_pci_probe: cdma_addr: 7886000
後は、アプリを作ってアクセスしてみよう!
ビルド環境の構築を行う
どんなツールを使うのか
メインで利用するのは C 言語になるので、C 言語界隈の気になるツールを片っ端から導入し試してみる。
私は組み込み開発従事者なので、どうしてもGUIやIDEなどの派手なツールの利用は機会がありません。(大抵のプロジェクトで利用できるCUI最高!という感じ)
ツール | 目的 | 備考 |
---|---|---|
Vim | エディタ | 経験値はひよこレベル |
ag | 検索 | 高速 grep 。ファイル名も grep の 50% !! |
cmake | ビルドスクリプト | gnu make の Makefile ジェネレータ? |
GCC | コンパイラ | 言わずと知れた業界標準コンパイラ |
LLVM+Clang | コンパイラ | 次世代のコンパイラ。これからの時代は複数コンパイラに対応しないとね |
ClangFormat | フォーマッタ | Clangに含まれるツール。コードレビューでスタイルを指摘するのはうんざり |
cpplint | フォーマットチェッカ | Phython の単一コードなのでカスタマイズすれば利用の幅が広がるかも |
CppUTest | ユニットテスト | 組み込みも意識した GoogleTest と双璧をなすツール |
CppCheck | 静的アナライザ | フリーツールの中では標準か!? |
Valgrind | 動的アナライザ | 使ったこと無いけど、歴史は長い。 |
Git | バージョン管理 | 業界の新標準。 |
bugspots | バグ予測 | Google 謹製。 Git のコミット履歴から予測する |
Vim をインストールする
Vim 自体はすでにインストール済みなのですが、標準では Lua を利用できないため NoeBundle の力をフル活用できません。
そのため、 Lua を利用できるようにするため、 vim-nox パッケージをインストールします。
$ sudo apt-get install -y vim-nox
- vim-nox インストール前
$ vim --version VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jan 2 2014 19:39:32) ... +dialog_con -lua +rightleft +windows ...
- vim-nox インストール後
$ vim --version VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Jan 2 2014 19:39:34) ... +dialog_con +lua +rightleft +windows ...
次に、 Vim を便利に使うための NeoBundle 周りの環境を構築する。
もう、数回目の構築になるが、毎回ベストプラクティスを探して数時間かかってしまう。。。
何はともあれ、 ~/.vimrc に NeoBundle の設定(インストールするプラグイン)を記載していく。
$ cat ~/.vimrc " neobundle settings {{{ if has('vim_starting') set nocompatible if !isdirectory(expand('~/.vim/bundle/neobundle.vim/')) echo 'install neobundle...' :call system('git clone git://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim') endif set runtimepath+=~/.vim/bundle/neobundle.vim endif call neobundle#begin(expand('~/.vim/bundle')) let g:neobundle_default_git_protocol='https' NeoBundleFetch 'Shougo/neobundle.vim' NeoBundle 'Shougo/unite.vim' NeoBundle 'Shougo/neomru.vim', { \ 'depends' : 'Shougo/unite.vim' \ } NeoBundle 'Shougo/unite-outline', { \ 'depends' : 'Shougo/unite.vim' \ } NeoBundle 'Shougo/vimproc', { \ 'build' : { \ 'windows' : 'make -f make_mingw32.mak', \ 'cygwin' : 'make -f make_cygwin.mak', \ 'mac' : 'make -f make_mac.mak', \ 'unix' : 'make -f make_unix.mak' \ } \ } if has('lua') NeoBundleLazy 'Shougo/neocomplete.vim', { \ 'depends' : 'Shougo/vimproc', \ 'autoload' : { 'insert' : 1, } \ } endif NeoBundleLazy 'Shougo/vimshell', { \ 'depends' : 'Shougo/vimproc', \ 'autoload' : { \ 'commands' : [{ 'name' : 'VimShell', 'complete' : 'customlist,vimshell#complete' }, \ 'VimShellExecute', 'VimShellInteractive', \ 'VimShellTerminal', 'VimShellPop'], \ 'mappings' : ['<Plug>(vimshell_switch)'] \ } \ } NeoBundle 'Townk/vim-autoclose' NeoBundleLazy 'tpope/vim-endwise', { \ 'autoload' : { 'insert' : 1 } \ } NeoBundleLazy 'Shougo/neosnippet', { \ 'depends' : 'Shougo/neosnippet-snippets', \ 'autoload' : { \ 'insert' : 1, \ 'filetypes' : 'snippet' \ } \ } NeoBundle 'Shougo/neosnippet-snippets' NeoBundle 'itchyny/lightline.vim' NeoBundle 'nathanaelkane/vim-indent-guides.git' NeoBundle 'tomasr/molokai' " install check for plugin NeoBundleCheck call neobundle#end() " }}} " neocomplete settings {{{ let g:neocomplete#enable_at_startup = 1 let g:neocomplete#auto_completion_start_length = 3 let g:neocomplete#enable_ignore_case = 1 let g:neocomplete#enable_smart_case = 1 let g:neocomplete#enable_camel_case = 1 let g:neocomplete#use_vimproc = 1 let g:neocomplete#sources#buffer#cache_limit_size = 1000000 let g:neocomplete#sources#tags#cache_limit_size = 30000000 let g:neocomplete#enable_fuzzy_completion = 1 let g:neocomplete#lock_buffer_name_pattern = '\*ku\*' " }}} " vimshell settings {{{ nmap <silent> vs :<C-u>VimShell<CR> nmap <silent> vp :<C-u>VimShellPop<CR> " }}} " neosnippet settings {{{ imap <C-k> <Plug>(neosnippet_expand_or_jump) smap <C-k> <Plug>(neosnippet_expand_or_jump) " }}} " common settings {{{ filetype plugin indent on colorscheme molokai set t_Co=256 set background=dark syntax on set list set listchars=tab:>.,trail:_,extends:>,precedes:<,nbsp:%,eol:$ function! ZenkakuSpace() highlight ZenkakuSpace cterm=reverse ctermfg=DarkMagenta gui=reverse guifg=DarkGray endfunction if has('syntax') augroup ZenkakuSpace autocmd! autocmd ColorScheme * call ZenkakuSpace() autocmd BufNew,BufRead * match ZenkakuSpace /!!/ augroup END call ZenkakuSpace() endif set number set ts=4 set sw=4 set showmatch set ruler set scrolloff=7 set laststatus=2 set showmode set showcmd set encoding=utf-8 set fileencodings=iso-2022-jp,euc-jp,euc-jisx0213,sjis,utf-8 set fileformats=unix,dos,mac set formatoptions+=mm if exists('&ambiwidth') set ambiwidth=double endif set pastetoggle= set wrapscan set ignorecase set smartcase set incsearch set hlsearch set nobackup set noswapfile " }}}
いつもながら結論が出ないな。ファイラも入れたいが、 vimfiler も NERDTree もどこか合わなかったので、今回は見合わせた。
ag のインストール
最新を使いたいので、ソースからインストールする。
手順は 公式 の通りに。
ビルドに必要なツールのインストール
$ sudo apt-get install -y automake pkg-config libpcre3-dev zlib1g-dev liblzma-dev
ビルド
$ tar zxvf 0.31.0.tar.gz $ cd the_silver_searcher-0.31.0/ $ ./build.sh $ sudo make install $ ag --version ag version 0.31.0 Features: +jit +lzma +zlib
cmake のインストール
公式で配布されるインストールスクリプトは、対話的になっているため、圧縮ファイルからインストールする。
### ファイルのダウンロード&展開 $ curl -LO https://cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz $ tar zxvf cmake-3.3.2-Linux-x86_64.tar.gz $ sudo cp -af cmake-3.3.2-Linux-x86_64 /opt/toolchain/cmake $ sudo chown root:root -R /opt/toolchain/cmake/ ### 環境変数へパスを通す $ echo 'PATH="/opt/toolchain/cmake/bin:$PATH"' >> ~/.profile $ . ~/.profile ### 実行確認 $ cmake --version cmake version 3.3.2 CMake suite maintained and supported by Kitware (kitware.com/cmake).
GCC のインストール
インストール済みのため省略!
LLVM+Clang のインストール
以前の記事を参考にインストールします。
$ sudo apt-get install -y libpython2.7 libpython2.7-dev swig libedit2 libedit-dev libncurses5-dev libxml2-dev $ git clone http://llvm.org/git/llvm.git $ cd llvm $ (cd tools && git clone http://llvm.org/git/clang.git) $ (cd projects && git clone http://llvm.org/git/libcxx) $ (cd projects && git clone http://llvm.org/git/libcxxabi) $ (cd projects && git clone http://llvm.org/git/compiler-rt) $ (cd tools && git clone http://llvm.org/git/lldb) $ (cd tools && git clone http://llvm.org/git/lld) $ mkdir build $ cd build $ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/toolchain/llvm+clang -DCMAKE_C_COMPILER=/usr/ bin/gcc -DCMAKE_CXX_COMPILER=/usr/bin/g++ .. $ make -j 2 $ sudo make install $ echo 'PATH="/opt/toolchain/llvm+clang/bin:$PATH"' >> ~/.profile $ . ~/.profile
cpplint のインストール
Github からクローンします。
$ git clone https://github.com/google/styleguide.git $ sudo mv styleguide /opt/analyzer/ $ sudo chown root:root -R /opt/analyzer/styleguide
これから使うので、最終的なビルドシステムからは外すかも。
CppUTest のインストール
こちらも、 Github からクローンしインストールします。
$ git clone https://github.com/cpputest/cpputest.git $ cd cpputest $ mkdir cpputest $ cd cpputest $ cmake -DCMAKE_INSTALL_PREFIX=/opt/toolchain/cpputest -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCOVERAGE=ON .. $ make $ sudo make install
CppCheck のインストール
こちらも、 Github からクローンし、インストールします。
有料の静的解析ツール(e.g. coverity)については、プロジェクトにより利用できるかどうかが変わるため、基本的な品質をキープするために確実に導入できるツールが必要になると考えています。
$ git clone https://github.com/danmar/cppcheck.git $ cd cppcheck $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/opt/analyzer/cppcheck -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release .. $ make $ sudo make install $ sudo bash -c 'echo "/opt/analyzer/cppcheck/lib" > /etc/ld.so.conf.d/cppcheck.conf' $ echo 'PATH="/opt/analyzer/cppcheck/bin:$PATH"' >> ~/.profile $ . ~/.profile
Valgrind のインストール
ソースからインストールします。
$ curl -LO http://valgrind.org/downloads/valgrind-3.11.0.tar.bz2 $ tar jxvf valgrind-3.11.0.tar.bz2 $ cd valgrind-3.11.0 $ ./configure --prefix=/opt/analyzer/valgrind $ make $ sudo make install $ echo 'PATH="/opt/analyzer/valgrind/bin:$PATH"' >> ~/.profile
Valgrind も、使ったこと無いので、どんな感じになるのかは試してからのお楽しみ。
Git のインストール
すでに導入済みなので省略。
bugspots のインストール
bugspots は ruby せいなので、 gem でインストールできます。
$ gem install bugspots
bugspots はコミットログを解析するため、コミットログに工夫をする必要があります。(デフォルトでは、 fix
が含まれるコミットログを不具合修正コミットとみなす)
この辺りは、ルール付けをして新しいコミットから適用すれば、すんなり運用に乗せられそう。
あとは、 cmake の代わりに gyp とかも気になるけど、情報量が少ないのでひとまず cmake を使い込んでみる。
cmake に不満がでたら gyp も検討してみよう。
ドキュメント系ツールを一斉に導入してみる
気になるところ
ドキュメント系ツールについては、どの程度業務でも活用できそうなのか記になるので、早速環境を作成してみる。
pandoc のインストール
pandoc は Haskell という(私には)あまり馴染みが無い言語で作成されているので、まずは Haskell の実行環境からインストールする。
$ sudo apt-get install -y haskell-platform
直接、 apt から pandoc をインストールすることもできるが、バージョンが古いっぽいので、地道にインストールしていく。
そうすると、 apt と似たような、 Haskell のパッケージマネージャである cabal が利用できるようになるので、 pandoc をインストールする。
まずは、 cabal 自身をアップデートする
$ cabal update $ cabal install Cabal cabal-install
古い(1.18以前の) cabal ではこの後使う sandbox コマンドが利用できないので、今更新した cabal にパスを通し直す。
export PATH=~/.cabal/bin:$PATH
~/.profile
などに同じパスを記載しておくこと。
サンドボックスを作成する
$ mkdir ~/pandoc $ cd ~/pandoc $ cabal sandbox init
ビルドする
$ cabal install pandoc
かなりの時間がかかるので、コーヒーブレイクでも入れましょう。
ビルドが終わったら、オブジェクトを ~/.cabal/bin などにコピーし、シェルから参照できるようにします。
asciidoctor のインストール
本家 AsciiDoc は Python 製なのですが、普及度などを調べると GitHub でも採用されている(らしい) Ruby 製の AsciiDoctor のほうが良さそう(バージョンアップも活発)なので、そちらをインストールしてみる。
ruby のインストール
手順は Setup Ruby On Rails on Ubuntu 14.04 Trusty Tahr を参考にしてみた。
まずは、 ruby のビルドに必要なライブラリのインストールを行う。( Python に比べてインストールのハードル高すぎ。。。)
$ sudo apt-get update $ sudo apt-get install zlib1g-dev libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev libffi-dev
rbenv ( Python の virtualenv のようなもの?)をインストールして、 rbenv 環境に ruby をインストールする。
$ cd $ git clone git://github.com/sstephenson/rbenv.git .rbenv $ echo 'PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.profile $ echo 'eval "$(rbenv init -)"' >> ~/.profile $ $ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build $ echo 'PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.profile $ $ git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash $ $ . ~/.profile $ $ rbenv install 2.2.3 $ rbenv global 2.2.3 $ ruby -v
これで、以下の様な表示が出れば、 ruby のインストールは完了となる。
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
AsciiDoctor のインストール
公式の手順 によれば、
$ gem install asciidoctor
とすれば良いのだけれど、SSL 関係でエラーが発生します。
$ gem install asciidoctor ERROR: Could not find a valid gem 'asciidoctor' (>= 0), here is why: Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/specs.4.8.gz)
そこで、一時的に HTTP で更新できるようにします。
$ ~$ gem source --add http://rubygems.org https://rubygems.org is recommended for security over http://rubygems.org Do you want to add this insecure source? [yn] y http://rubygems.org added to sources
再び、 AsciiDoctor のインストールにトライします。
$ gem install asciidoctor Fetching: asciidoctor-1.5.2.gem (100%) Successfully installed asciidoctor-1.5.2 Parsing documentation for asciidoctor-1.5.2 Installing ri documentation for asciidoctor-1.5.2 Done installing documentation for asciidoctor after 4 seconds WARNING: Unable to pull data from 'https://rubygems.org/': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/specs.4.8.gz) 1 gem installed $ asciidoctor --version Asciidoctor 1.5.2 [http://asciidoctor.org] Runtime Environment (ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]) (lc:US-ASCII fs:US-ASCII in:- ex:US-ASCII)
今度は、(SSL の警告がでつつも)インストールできました。
最後に、HTTP による更新を無効にします。
$ gem source --remove http://rubygems.org http://rubygems.org removed from sources
でも、根本的なエラーの原因は取り除けていないため、都度 HTTP での更新をできるようにしないとダメなのがダサいな。。。
オプションのインストール
後は、それっぽいオプションをインストールします。
$ gem install --no-ri --no-rdoc asciidoctor-diagram $ gem install --no-ri --no-rdoc coderay pygments.rb thread_safe
graphviz のインストール
手抜きのため、 apt でインストールします。
$ sudo apt-get install -y graphviz
最新版( 2.38 )じゃないけど気にしない。
$ dot -V dot - graphviz version 2.36.0 (20140111.2315)
texlive のインストール
GitHub で Ubuntu 用のインストールスクリプトが 公開 されているので、ありがたく利用する。
$ sudo bash -c "curl -L https://github.com/scottkosty/install-tl-ubuntu | bash" $ echo 'PATH="/usr/local/texlive/2015/bin/x86_64-linux:$PATH"' >> ~/.profile $ . ~/.profile
かなり時間がかかるので、散歩にでも出かけましょう。
完了すれば、 TeX 関連コマンドが利用可能になります。
$ tex --version TeX 3.14159265 (TeX Live 2015) kpathsea version 6.2.1 Copyright 2015 D.E. Knuth. There is NO warranty. Redistribution of this software is covered by the terms of both the TeX copyright and the Lesser GNU General Public License. For more information about these matters, see the file named COPYING and the TeX source. Primary author of TeX: D.E. Knuth.
最後に、公式サイトの TeX Live パッケージをインストールした場合、 apt で TeX Live に依存したパッケージをインストールしてしまうと、ついでに apt でも TeX Live (古いバージョン)がインストールされてしまうらしいので、ダミーパッケージを apt でインストールして、依存関係で問題が出ないようにします。
Integrating vanilla TeX Live with Debian
$ sudo mkdir /tmp/tl-equivs $ cd /tmp/tl-equivs/ $ sudo equivs-control texlive-local $ sudo vim texlive-local ### 編集内容は後述 $ sudo equivs-build texlive-local $ sudo dpkg -i texlive-local_2015-1_all.deb
texlive-local の内容は、サンプル の通りです。
sphinx のインストール
手順は 日本語公式 の通りに行う。
$ sudo pip install sphinx
最新版を使いたかったので pip でインストールすることにした。
$ sphinx-build --version Sphinx (sphinx-build) 1.3.1
doxygen のインストール
手っ取り早く動かしたいため、公式から Linux バイナリをダウンロードしてインストールすることに。
$ curl -LO ftp://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.10.linux.bin.tar.gz $ tar zxvf doxygen-1.8.10.linux.bin.tar.gz $ cd doxygen-1.8.10 $ ./configure --prefix /opt/toolchain/doxygen Checking for GNU install tool... using /usr/bin/install Created Makefile from Makefile.in... $ sudo make install /usr/bin/install -d /opt/toolchain/doxygen/bin /usr/bin/install -d /opt/toolchain/doxygen/doc/doxygen /usr/bin/install -m 755 bin/doxygen /opt/toolchain/doxygen/bin /usr/bin/install -m 755 bin/doxytag /opt/toolchain/doxygen/bin /usr/bin/install: cannot stat 'bin/doxytag': No such file or directory make: *** [install] Error 1
なんと!公式のバイナリでインストール失敗してしまった。。。
解決方法を探してみたが、手順ミスではなさそう。どういうこと!?
調べてみたが、 doxytag は別に必要なさそうなので、インストール対象から外すことに。(ついでに、存在しない examples ディレクトリも外す)
$ diff -u Makefile.in.orig Makefile.in $ diff -u Makefile.in.orig Makefile.in --- Makefile.in.orig 2015-09-26 17:26:45.702458300 +0000 +++ Makefile.in 2015-09-26 17:29:11.238458300 +0000 @@ -2,7 +2,7 @@ $(INSTTOOL) -d $(INSTALL)/bin $(INSTTOOL) -d $(INSTALL)/doc/doxygen $(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin - $(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin + #$(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin #$(INSTTOOL) -m 755 bin/doxywizard $(INSTALL)/bin cp -r html $(INSTALL)/doc/doxygen - cp -r examples $(INSTALL)/doc/doxygen + #cp -r examples $(INSTALL)/doc/doxygen
再度、インストールを行う。
### インストール先の設定を行う $ ./configure --prefix /opt/toolchain/doxygen $ sudo make install ### 環境変数にパスを通す $ echo 'PATH="/opt/toolchain/doxygen/bin:$PATH"' >> ~/.profile $ . ~/.profile ### 実行確認を行う $ doxygen --version 1.8.10
RedPen のインストール
RedPen を動作させるには、 Java 実行環境が必要になるので、 Java からインストールする。
Java のインストール
手順は以下をを参考にしました。
$ sudo add-apt-repository ppa:webupd8team/java $ sudo apt-get update $ sudo apt-get install oracle-java8-installer
インストール中には、ライセンスやらオプションの確認が行われるので、回答する。
インストール後、(よくわからないが、)環境設定などを行ってくれるパッケージをインストールして完了となる。
$ sudo apt-get install oracle-java8-set-default $ java -version java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
本体のインストール
RedPen は Java 製ということで、バイナリをダウンロードしてコピーするだけのインストールになる。
GitHubのリリースページ から最新のバイナリをダウンロードする。
$ curl -LO https://github.com/redpen-cc/redpen/releases/download/v1.3.0/redpen-1.3.0.tar.gz $ tar zxvf redpen-1.3.0.tar.gz $ sudo cp -a redpen-distribution-1.3/ /opt/redpen $ sudo chown root:root -R /opt/redpen/ $ JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre redpen --version 1.3.0
これらのツールをうまく活用できれば、やりたいことに時間を使えるようになる。かもしれない。
とりあえずコンテナ作ってみる
試行錯誤のための環境づくり
まだ、 Docker には十分慣れていないので(そして、以前試した時よりだいぶバージョンが上がっているので)、試行錯誤用のコンテナを作成する。
このコンテナでインストール手順の確率や、破壊的な変更などを試してみる。
Dockerfile を作成する
Docker を使って、オリジナルのコンテナを作成する場合は、何はともあれ Dockerfile
が必要になる。
作成にあたり、参考にしたのは以下のサイト。
- Dockerfile reference(公式
- Best practices for writing Dockerfiles(公式)
- 私家版 Dockerfile Pattern
- Dockerfile チートシート
とりあえず、以下の様なコンテナを作成してみた。
あとは、作成したコンテナの中で、ツールのビルド手順を確立していき、各コンテナの Dockerfile
を作成していく。
# # Dockerfile for Embryo Container. # # Pull base image. FROM ubuntu:14.04 # Author. MAINTAINER kenz_san # Install packages. RUN sed -i -e 's/\/\/archive.ubuntu.com/\/\/ftp.jaist.ac.jp/g' /etc/apt/sources.list && \ apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y python-software-properties \ software-properties-common RUN add-apt-repository -y ppa:git-core/ppa && \ add-apt-repository -y ppa:mercurial-ppa/releases RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \ DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential \ byobu \ curl \ git \ mercurial \ openssh-server \ python-dev \ python-setuptools \ python-pip \ python-virtualenv \ unzip \ vim \ wget RUN curl -Lo /tmp/subversion_installer.sh http://opensource.wandisco.com/1.9/scripts/subversion_installer_1.9.sh && \ echo yn | bash /tmp/subversion_installer.sh # Create user. RUN useradd -d /home/embryo -m -s /bin/bash embryo && \ echo "embryo:embryo" | chpasswd && \ echo "embryo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ echo -e "LANG='ja_JP.UTF-8'" > /etc/default/local # Setup sshd. RUN sed -i -e '/^UsePAM\s+yes/d' /etc/ssh/sshd_config && \ mkdir -p /var/run/sshd && \ /etc/init.d/ssh start && /etc/init.d/ssh stop && \ sed -i 's/.*session.*required.*pam_loginuid.so.*/session optional pam_loginuid.so/g' /etc/pam.d/sshd # Set environment variables. ENV HOME /home/embryo # Define working directory. WORKDIR /home/embryo # EXPOSE 22 # Define default command. CMD ["/usr/sbin/sshd", "-D"]
こんな感じで。
開発に必要そうなパッケージは詰め込んで、SSH だけ有効にしている。
$ docker build -t kenz_san/embryo . $ docker run -d -i -t -p 22:22 kenz_san/embryo
Ubuntu 14.04.3 の環境準備を行う
Ubuntu のインストール
Docker もインストールするつもりなので、 64bit 版であることは必須。
更に、GUIは要らないので、軽量化を重視して Server エディションをインストールしました。
とりあえず、言語は日本語で。(コンソールの表示は文字化けするけど、基本 SSH でアクセスするから関係ないよね!)
apt リポジトリを近場に切り替える
標準のままだと、海外のサーバに対してパッケージの取得などを行うため、ネットワーク速度がかなり遅い。
そこで、近場(日本国内)の安定したサーバにリポジトリを変更する。(今回は JAIST にした)
$ sudo sed -i".bak" -e 's/\/\/jp.archive.ubuntu.com/\/\/ftp.jaist.ac.jp/g' /etc/apt/sources.list
これで、 apt 操作は快適になる。
コアに必要なパッケージをインストールする
基本的な開発環境としての機能は、 Docker 上に構築するつもりなので、必要最低限のパッケージのみインストールする。
その前に、おもむろにアップデートする。
$ sudo apt-get update $ sudo apt-get upgrade -y
何はともあれ、ネットワークディレクトリの準備
まずは、母艦からファイルにアクセスするために SAMBA 環境を構築する。
Docker でコンテナを動作させるときも、コード編集などのファイルアクセスについては、(コンテナの共有機能を使って) Docker を動作させている Ubuntu 上にだけアクセスすれば良いようにする。
複数のサービス(今回は SAMBA )をどう出させることはリソースの無駄なので、母艦のスペック上、冗長な処理は省いていく
Ubuntu Server インストール時に、追加インストールパッケージとして選択していたので、すでにパッケージはインストール済み。
まだ入っていない場合は、
$ sudo apt-get install -y samba
とすればインストールできるはず。
次に、 SAMBA で公開するディレクトリの設定を行う。(この辺りは、好みが分かれる設定だと思うので、他の人がどうするか気になります)
$ sudo vim /etc/samba/smb.conf
--- /etc/samba/smb.conf.orig 2015-09-13 09:36:50.780300850 +0900 +++ /etc/samba/smb.conf 2015-09-13 09:41:54.088300850 +0900 @@ -190,28 +190,29 @@ # Un-comment the following (and tweak the other settings below to suit) # to enable the default home directory shares. This will share each # user's home directory as \\server\username -;[homes] -; comment = Home Directories -; browseable = no +[homes] + comment = Home Directories + browseable = no # By default, the home directories are exported read-only. Change the # next parameter to 'no' if you want to be able to write to them. -; read only = yes + read only = no + writable = yes # File creation mask is set to 0700 for security reasons. If you want to # create files with group=rw permissions, set next parameter to 0775. -; create mask = 0700 + create mask = 0775 # Directory creation mask is set to 0700 for security reasons. If you want to # create dirs. with group=rw permissions, set next parameter to 0775. -; directory mask = 0700 + directory mask = 0775 # By default, \\server\username shares can be connected to by anyone # with access to the samba server. # Un-comment the following parameter to make sure that only "username" # can connect to \\server\username # This might need tweaking when using external authentication schemes -; valid users = %S + valid users = %S # Un-comment the following and create the netlogon directory for Domain Logons # (you need to configure Samba to act as a domain controller too.) @@ -234,23 +235,23 @@ ; create mask = 0600 ; directory mask = 0700 -[printers] - comment = All Printers - browseable = no - path = /var/spool/samba - printable = yes - guest ok = no - read only = yes - create mask = 0700 +;[printers] +; comment = All Printers +; browseable = no +; path = /var/spool/samba +; printable = yes +; guest ok = no +; read only = yes +; create mask = 0700 # Windows clients look for this share name as a source of downloadable # printer drivers -[print$] - comment = Printer Drivers - path = /var/lib/samba/printers - browseable = yes - read only = yes - guest ok = no +;[print$] +; comment = Printer Drivers +; path = /var/lib/samba/printers +; browseable = yes +; read only = yes +; guest ok = no # Uncomment to allow remote administration of Windows print drivers. # You may need to replace 'lpadmin' with the name of the group your # admin users are members of.
さらに、ユーザの作成も行います。
$ sudo smbpasswd -a <ユーザ名> New SMB Password: <パスワード> Retype new SMB Password: <パスワード>
設定変更後は、 SAMBA の再起動が必要です。
$ sudo service smbd restart
Docker をインストールする
基本的な手順は、 公式 の通りにすれば良い。
$ curl -sSL https://get.docker.com/ | sh
あれ?1.3の頃と比べて、格段に簡単になってる。
インストールが完了すると、
$ sudo usermod -aG docker <ユーザ名>
と表示されるので実行しておく。( sudo しなくても docker コマンドが使用できるようになる)
以前は、
$ sudo gpasswd -a <ユーザ名> docker Adding user <ユーザ名> to group docker
としていたけど、同じ効果となる。
とりあえず、 VirtualBox 上で直接動作する Ubuntu については以上で設定終わり。(不足が見つかったら加筆します)