Bazel on Bash on Ubuntu on Windows 14393

はじめに

とにかく Bash on Ubuntu on Windows で Bazel を動かしてみます。 Getting StartedHello World まで実行してみます。

環境

実施

JDK をインストール (JDK 1.7) します。

$ sudo apt-get install default-jdk

Bazel をインストール します。

Using Bazel custom API repository (recommended) の通り JDK 1.7 版をインストールします。

$ echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.7" | sudo tee /etc/apt/sources.list.d/bazel.list

$ curl https://storage.googleapis.com/bazel-apt/doc/apt-key.pub.gpg | sudo apt-key add -

$ sudo apt-get update && sudo apt-get install bazel

普通に bazel を実行すると JVM がハングします。

Java running issues (Consolidated) を参考に、 JIT を無効化して WSL の不具合を回避します (-Xint オプション)。

※追記(2016-10-01): Cumulative Update for Windows 10 Version 1607: September 29, 2016 (Build 14393.222) で回避が不要になっていることを確認。

$ touch WORKSPACE

$ cat > BUILD <<'EOF'
genrule(
  name = "hello",
  outs = ["hello_world.txt"],
  cmd = "echo Hello World > $@",
)
EOF

$ bazel --host_jvm_args="-Xint" build :hello
.
WARNING: Sandboxed execution is not supported on your system and thus hermeticity of actions cannot be guaranteed. See http://bazel.io/docs/bazel-user-manual.html#sandboxing for more information. You can turn off this warning via --ignore_unsupported_sandboxing.
INFO: Found 1 target...
Target //:hello up-to-date:
  bazel-genfiles/hello_world.txt
INFO: Elapsed time: 6.135s, Critical Path: 0.09s

$ cat bazel-genfiles/hello_world.txt
Hello World

Building LLVM/Clang on Bash on Ubuntu on Windows

はじめに

Bash on Ubuntu on Windows 上で Bazel を試してみたい。 ウォーミングアップに LLVM/Clang のビルドを実施してみる。

環境

実施

必要なツールのインストール

~/win/ubuntu/refs$ sudo apt-get install gcc g++ make cmake subversion

LLVM/Clang のビルド

の通りにソースファイルを入手。

~/win/ubuntu/refs$ ls llvm
bindings        CODE_OWNERS.TXT  docs      lib            llvm.spec.in  RELEASE_TESTERS.TXT  test       utils
cmake           configure        examples  LICENSE.TXT    projects      resources            tools
CMakeLists.txt  CREDITS.TXT      include   LLVMBuild.txt  README.txt    runtimes             unittests

~/win/ubuntu/refs$ mkdir build

~/win/ubuntu/refs$ cd build

~/win/ubuntu/refs/build$ cmake -G "Unix Makefiles" ../llvm
CMake Error at CMakeLists.txt:3 (cmake_minimum_required):
  CMake 3.4.3 or higher is required.  You are running version 2.8.12.2



-- Configuring incomplete, errors occurred!```

~/win/ubuntu/refs/build$ cd ..

CMake が古いじゃないか

~/win/ubuntu/refs$ mkdir cmake 

~/win/ubuntu/refs$ cd cmake

~/win/ubuntu/refs/cmake$ wget https://cmake.org/files/v3.6/cmake-3.6.1.tar.gz

~/win/ubuntu/refs/cmake$ tar xzf cmake-3.6.1.tar.gz

~/win/ubuntu/refs/cmake$ cd cmake-3.6.1/

~/win/ubuntu/refs/cmake/cmake-3.6.1$ ./bootstrap --prefix=/home/ichi/bin
---------------------------------------------
CMake 3.6.1, Copyright 2000-2016 Kitware, Inc.
(snip)
CMake has bootstrapped.  Now run make.

~/win/ubuntu/refs/cmake/cmake-3.6.1$ make -j 8 --prefix=/home/ichi/bin
[  0%] Building C object Utilities/cmcompress/CMakeFiles/cmcompress.dir/cmcompress.c.o
(snip)
[100%] Built target ctest

~/win/ubuntu/refs/cmake/cmake-3.6.1$ make install
[  3%] Built target cmsys
(snip)
-- Installing: /home/ichi/share/cmake-3.6/completions/ctest

~/win/ubuntu/refs/cmake/cmake-3.6.1$ cd ../../build

~/win/ubuntu/refs/build$ cmake -G "Unix Makefiles" ../llvm

~/win/ubuntu/refs/build$ cmake -G "Unix Makefiles" ../llvm
-- The C compiler identification is GNU 4.8.4
(snip)
-- Build files have been written to: /home/ichi/win/ubuntu/refs/build

~/win/ubuntu/refs/build$ make -j8
Scanning dependencies of target LLVMSupport
(snip)
[100%] Built target c-index-test
~/win/ubuntu/refs/build$ sudo make install

~/win/ubuntu/refs/build$ clang
clang-4.0: error: no input files

~/win/ubuntu/refs/build$ cd ~/tmp

~/tmp$ cat > a.cpp
constexpr int fact(int n)
{
    if (n <= 0)
        return 1;
    else
        return n * fact(n-1);
}

static_assert(fact(10) == 3628800, ""); // OK
static_assert(fact(1) == 0, "");        // error

int main()
{
    return 0;
}

~/tmp$ clang --std=c++14 a.cpp
a.cpp:10:1: error: static_assert failed ""
static_assert(fact(1) == 0, "");        // error
^             ~~~~~~~~~~~~
1 error generated.

~/tmp$

Links

HOWTO: Reopen the currently loaded solution from a VS Extension

Motivation

Suppose you are developing user property sheets in your Visual C++ project. Dealing with the Property Manager is really troublesome, so you start to develop a VS extension. The VS entension manages which property sheets to import and edits property sheets.

You encounter a problem. If you edit a property sheet outside the IDE, the IDE will not automatically reload the property sheet and therefore such changes will not be reflected in the IDE. There seems to be no API for reloading property sheets. Removing the property sheet and re-adding it does not work either; property sheets seem to be cached somewhere.

In order to have the IDE reload property sheets, the only workaround I have found is reopening the entire solution. Let's do it.

Environment

Code Fragment

private void MenuItemCallback(object sender, EventArgs e)
{
    // Obtain the SVsSolution service object.
    var solutionService =
        this.ServiceProvider.GetService(typeof(SVsSolution)) as IVsSolution;

    // Check if there exists an open solution.
    object isSolutionOpen;
    solutionService.GetProperty(
        (int)__VSPROPID.VSPROPID_IsSolutionOpen,
        out isSolutionOpen);
    if (!(bool)isSolutionOpen)
    {
        return;
    }

    // Retrieve the information on the open solution.
    // Full path to the directory cotaining the .sln file
    string solutionDirectory;   
    // Full path to the .sln file
    string solutionFile;
    // Full path to the .suo file
    string userOptsFile;
    solutionService.GetSolutionInfo(
        out solutionDirectory,
        out solutionFile,
        out userOptsFile);

    // Close the entire solution. (pHier == null, docCookie == 0)
    solutionService.CloseSolutionElement(
        // Prompt the user whether to save unsaved changes.
        (uint)__VSSLNSAVEOPTIONS.SLNSAVEOPT_PromptSave, 
        null,
        0);

    // Reopen the solution.
    solutionService.OpenSolutionFile(0, solutionFile);
}

References

ARM-USB-TINY-H で Raspberry Pi を JTAG デバッグ

概要

Windows 環境から、JTAG デバッガ Olimex ARM-USB-TINY-H で Raspberry Pi に接続して、JTAG デバッグを行います。

ロスコンパイラはすでにビルドしてあるものとします。 インストール先等のパスは適宜読み替えてください。

環境

Debian Linux

MinGW 向けビルド用に、Debian Linux 環境を用意します。以下のものを入れておきます:

sudo apt-get install mingw-w64 cmake pkg-config

OpenOCD のビルド

OpenOCD は、JTAG デバッガ等を経由でターゲットに接続し、GDB プロトコルデバッグを可能にするプログラムです。

今回は、OpenOCD を MinGW 向けにビルドします。

pkg-config

https://www.flameeyes.eu/autotools-mythbuster/pkgconfig/cross-compiling.html を参考にして、 MinGW-w64 向けに *.pc ファイルのパスを変更した pkg-config を作成します。

sudo cat > /usr/bin/i686-w64-mingw32-pkg-config
sudo chmod 755 /usr/bin/i686-w64-mingw32-pkg-config

i686-w64-mingw32-pkg-config の内容は、以下の通り:

#!/bin/sh

export PKG_CONFIG_DIR=
export PKG_CONFIG_LIBDIR=/usr/i686-w64-mingw32/lib/pkgconfig/
export PKG_CONFIG_SYSROOT_DIR=/

exec pkg-config "$@"

libusb-1.0.9

libusb をビルドします。

tar xjf libusb-1.0.9.tar.bz2
./configure --build=`./config.guess` --host=i686-w64-mingw32 --prefix=/usr/i686-w64-mingw32/
make
sudo make install

libftdi1-1.1

libftdi をビルドします。

cmake -DCMAKE_TOOLCHAIN_FILE=/cmake/Toolchain-i686-w64-mingw32.cmake \
    -DCMAKE_INSTALL_PREFIX="/usr/i686-w64-mingw32" \
    -DPKG_CONFIG_EXECUTABLE=`which i686-w64-mingw32-pkg-config` \
    -DLIBUSB_INCLUDE_DIR=/usr/i686-w64-mingw32/include/libusb-1.0 \
    -DLIBUSB_LIBRARIES=/usr/i686-w64-mingw32/lib/libusb-1.0.a
make
sudo make install

README.mingw には PKG_CONFIG_EXECUTABLE を与えろと書いてあるので指定していますが、実際には参照していないようです。

openocd-0.7.0

OpenOCD をビルドします。 今回、なぜか 0.7.0 をビルドしてしまいましたが、0.8.0 でよいと思います。

sudo cp /usr/i686-w64-mingw32/include/libftdi1/ftdi.h /usr/i686-w64-mingw32/include/
tar xjf openocd-0.7.0.tar.bz2
./configure --build=`./config.guess` --host=i686-w64-mingw32 --prefix=/usr/i686-w64-mingw32/ \
    --enable-ft2232_libftdi
# ここで下記の修正を行う
make
sudo make install

ビルドエラーになるので修正します。openocd-0.7.0/src/jtag/drivers/ft2232.c (138) に以下の記述がありますが、ftdi_chip_type は ftdi.h で既に定義されているので削除しておきます。

    enum ftdi_chip_type { TYPE_2232H = 4, TYPE_4232H = 5, TYPE_232H = 6 };

また、Makefile 中で LIBS=-lftdi -lusb となっている部分を LIBS=-lftdi1 -lusb-1.0 に変更します。 たとえば、以下のようなコマンドを実行すればよいでしょう。

find -name Makefile | xargs sed -b -i "s/\-lftdi \-lusb/\-lftdi1 \-lusb\-1\.0/"

ドライバ

Olimex ARM-USB-TINY-H の公式ドライバは署名されていないため、普通には Windows 7 以降の 64-bit Windows にインストールすることができません。

Zadig を使用して、WinUSB をインストールします。 Olimex OpenOCD JTAG ARM-USB-TINY-H (Interface 0) に WinUSB (v6.1.7600.16385) を Install します。

ARM JTAG 20 コネクタと配線

ARM JTAG 20 のソケットを用意します。

今回は、2.54mm ピッチ 20p ボックスヘッダ のようなものを使用して、以下の信号線を引き出します。※向きを間違えない自信があるならピンヘッダ 2*10 でもよいと思います。

  • GND: 2,4,6,8,10,12,14,16,18,20
  • VTREF: 1
  • nTRST: 3
  • TDI: 5
  • TMS: 7
  • TCK: 9
  • TDO: 13

f:id:asmichi:20140815202522j:plain

アダプティブクロッキングを使用しないので、RTCK は接続しなくてもよいと思います。

SRST を接続しても上手くリセットできなかったのですが、リセットできたとしても後述する GPIO の設定もリセットされてしまいデバッグが継続できないはずなので、SRST を接続しても無意味だと思います。

デバッグ

準備: GPIO ポートの設定

ターゲット起動時に動作させるプログラムで、GPIO の設定を変更しておきます。

GPIO番号 ALT番号 ピン 信号名
GPIO22 ALT4 P1-15 nTRST
GPIO04 ALT5 P1-07 TDI
GPIO27 ALT4 P1-13 TMS
GPIO25 ALT4 P1-22 TCK
GPIO24 ALT4 P1-18 TDO

先ほどのコネクタから引き出した線をこれらのピンに接続します。

VTREF は、3.3V 電源のピンのいずれかに接続します。 http://elinux.org/RPi_Low-level_peripherals#General_Purpose_Input.2FOutput_.28GPIO.29 を参考にします。

接続

OpenOCD で Raspberry Pi に接続します。

まず、OpenOCD の設定ファイルを用意します。

Olimex ARM-USB-TINY-H 用の設定ファイルは、OpenOCD のソースファイル中にあります。 openocd/tcl/interface/olimex-arm-usb-tiny-h.cfg です。

Raspberry Pi 用の設定ファイルは、David Welch さんのリポジトリ のものを使わせてもらいます。armjtag/raspi.cfg です。

以下の通り、OpenOCD を起動します。デフォルトでは、TCP 3333 で GDB プロトコルのサーバが上がります。

openocd.exe -f olimex-arm-usb-tiny-h.cfg -f raspi.cfg

別のターミナルで、GDB を起動します。接続後、一度 continue しておかないと、うまくデバッグできないようです。

arm-unknown-eabi-gdb hoge.elf
> target remote localhost:3333
> continue
^C

これで、デバッグできます。

References