keropoの備忘録

しらべたことをメモるブログ

ARMクロスコンパラUpdate(gcc-5.4.0)

以前作成したクロスコンパイラがちょっと古くなったのでUpdate

ソース

  • gcc-5.4.0
  • binutils-2.26
  • gmp-6.1.1
  • mpfr-3.1.4
  • mpc-1.0.3
  • eglibc-2_18
  • linux-4.6.4

事前

  • BISON

バージョンが3.0以上だと、eglibcのビルドに失敗するので、2.7にバージョンダウン

  • MAKE

MAKEのバージョンが4.X台だと、eglibcのconfigureに失敗する。
configureを修正するか、makeのバージョンを3.XX台にダウングレード

ソース修正

eglibcのソースはちょっと修正が必要

  cd ${GLIBC_SRC}/libc/ports/sysdeps/unix/sysv/linux/arm/nptl
  mv unwind-forcedunwind.c unwind-forcedunwind.c.org
  mv unwind-resume.c unwind-resume.c.org
  sed -e "25s/;/ __attribute_used__;/" unwind-forcedunwind.c.org > unwind-forcedunwind.c
  sed -e "23s/;/ __attribute_used__;/" unwind-resume.c.org > unwind-resume.c

ビルド

gccのビルド以外は前回と同じ。
gcc1回目から3回目までのビルド手順は以下

gcc 1回目

  $../configure \
        --target=$TARGET \
        --prefix=$CROSS \
        --without-headers \
        --without-ppl \
        --with-newlib \
        --disable-shared \
        --disable-threads \
        --disable-libssp \
        --disable-libgomp \
        --disable-libmudflap \
        --disable-libquadmath \
        --disable-libatomic \
        --disable-nls \
        --with-gmp=$CROSS \
        --with-mpfr=$CROSS \
        --with-mpc=$CROSS \
        --enable-languages=c
  $make
  $make install

gcc 2回目

  $../configure \
        --target=$TARGET \
        --prefix=$CROSS \
        --with-sysroot=$ROOTDIR \
        --with-headers=$ROOTDIR/usr/include \
        --with-libs=$ROOTDIR/usr/lib \
        --disable-multilib \
        --disable-libstdcxx-pch \
        --disable-libssp \
        --disable-libgomp \
        --disable-libmudflap \
        --disable-libquadmath \
        --disable-libatomic \
        --with-gmp=$CROSS \
        --with-mpfr=$CROSS \
        --with-mpc=$CROSS \
        --enable-languages=c

   $make
   $make install

gcc 3回目

  $../configure \
        --target=$TARGET \
        --prefix=$CROSS \
        --with-headers=${ROOTDIR}/usr/include \
        --with-libs="${ROOTDIR}/usr/lib ${ROOTDIR}/lib" \
        --disable-multilib \
        --disable-libstdcxx-pch \
        --disable-libssp \
        --disable-libgomp \
        --disable-libmudflap \
        --disable-libquadmath \
        --disable-libatomic \
        --with-gmp=$CROSS \
        --with-mpfr=$CROSS \
        --with-mpc=$CROSS \
        --enable-languages=c,c++
  $make
  $make install

理由はちょっと不明だが、configureのoptionで、「--with-sysroot」を指定していると、libstdc++-v3のconfigureで

link tests are not allowed after GCC_NO_EXECUTABLES

となり、失敗する。libcが見えていないみたい。
"--with-sysroot"で、クロスコンパイラのルートパスを指定しているのに理由不明
結局、"--with-sysroot"の指定は削除し、以下を追加した。l

  --with-headers=${ROOTDIR}/usr/include \
  --with-libs="${ROOTDIR}/usr/lib ${ROOTDIR}/lib" \

Linuxデバイスドライバ基礎② procインタフェース

procインタフェースを利用してユーザランドからカーネル(ドライバ)と通信するサンプル

procfs.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>

MODULE_LICENSE("GPL");

#define PROC_NAME "driver/example"

static int proc_open(struct inode *node, struct file *fp)
{
        printk("open\n");
        return 1;
}

static ssize_t proc_read(struct file *fp, char *buf, size_t size, loff_t *off)
{
        printk("read\n");
        return size;
}


static ssize_t proc_write(struct file *fp, const char *buf, size_t size, loff_t *off)
{
        printk("write\n");
        return size;
}

static struct file_operations example_proc_fops = {
        .owner = THIS_MODULE,
        .open = proc_open,
        .read = proc_read,
        .write = proc_write,
};

static __init int procfs_init(void)
{
        struct proc_dir_entry *ent;

        ent = proc_create(PROC_NAME, S_IRUGO | S_IWUGO | S_IXUGO, NULL, &example_proc_fops);
        if (ent == NULL)
        {
                return -ENOMEM;
        }

        printk("proc example loaded\n");
        return 0;
}

static __exit void procfs_exit(void)
{
        printk("delete dirver\n");
        remove_proc_entry(PROC_NAME, NULL);
}

module_init(procfs_init);
module_exit(procfs_exit);

Linuxデバイスドライバ基礎①

ロスコンパイラでデバイスドライバをビルドする時のサンプルMakefileとスケルト
まあ、簡単なので、特に説明なしです。

Makefile

KERNEL_SRC=${カーネルソースフォルダ}

obj-m := hogehoge.o
CROSS_COMPILE=arm-unknown-gnueabi-  ※クロスコンパイラのプレフィックス
ARCH=arm  ※アーキテクチャ

MAKE_CMD=$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)

all:
    $(MAKE_CMD) -C $(KERNEL_SRC) -M $(PWD) modules

clean:
    $(MAKE_CMD) -C $(KERNEL_SRC) -M $(PWD) clean

hogehoge.c

#include <linux/module.h>
#include <linux/init.h>

static init __init hoge_init(void)
{
    printk("hello hoge_init\n");

    return 0;
}

static void __exit hoge_exit(void)
{
    printk("hoge goodby\n");
}

module_init(hoge_init);
module_exit(hoge_exit);

MODULE_AUTHOR("keropo");
MODULE_DESCRIPTION("hogehoge");
MOUDLE_LICENSE("GPL");

ロードとリムーブ

  ドライバをカーネルにロード
  #insmod hoge.ko

 ドライバをカーネルからリムーブ
  #rmmod hoge

v8 engineのサンプルプログラム

せっかく、v8をコンパイルしたので、サンプルプログラムをオフィシャルサイト等々を参考に作成してみた。
APIの仕様だったり、クラスのメンバー関数の構造が変わったらしく、ネットでよく見かけるサンプルプログラムではコンパイルが通らなかった。
一応、試行錯誤しながら、動くものが完成した。
サンプルとしては、v8にオリジナルの関数とクラスを組み込むサンプルになります。

/*
 * v8 javascript engine simple sample program.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <v8.h>

using namespace v8;

class ShellArrayBufferAllocator : public ArrayBuffer::Allocator
{
public:
    virtual void* Allocate(size_t length)
    {
        void *data = AllocateUninitialized(length);
        return data == NULL ? data : memset(data, 0, length);
    }

    virtual void* AllocateUninitialized(size_t length)
    {
        return malloc(length);
    }

    virtual void Free(void* data, size_t)
    {
        free(data);
    }
};

class TObject
{
private:
    int ident;

public:
    explicit TObject(int value = 0)
    :ident(value)
    {
    }

    int GetIdent() const { return ident; }
    
    Persistent<Object> *holder;
};

class TObjectIF
{
private:
    static TObject* GetThis(const Local<Object> handle)
    {
        void *This = Local<External>::Cast(handle->GetInternalField(0))->Value();
        return static_cast<TObject*>(This);
    }

    static void New(const FunctionCallbackInfo<Value>  &args)
    {
        TObject *p = NULL;

        if (args.Length() > 0)
        {
            p = new TObject(args[0]->Int32Value());
        } else {
            p = new TObject();
        }

        Local<Object> thisObject = args.This();
        thisObject->SetInternalField(0, External::New(args.GetIsolate(), p));

        Persistent<Object> *holder = new Persistent<Object>(args.GetIsolate(), thisObject);
        holder->SetWeak<TObject>(p, TObjectIF::Dispose);

        p->holder = holder;
    }

    static void Dispose(const WeakCallbackData<Object, TObject> &data)
    {
        TObject *p = data.GetParameter();
        Persistent<Object> *holder = p->holder;

        //release instance.
        holder->Reset();
        if (p != NULL) { delete p; }
    }

    static void GetIdent(const FunctionCallbackInfo<Value> &args)
    {
        TObject *p = GetThis(args.This());

        args.GetReturnValue().Set(p->GetIdent());
    }

public:
    static void InitializeTemplate(Isolate *isolate, Handle<ObjectTemplate> global)
    {
        Local<FunctionTemplate> clazz = FunctionTemplate::New(isolate, TObjectIF::New);
        clazz->SetClassName(String::NewFromUtf8(isolate, "TObject"));

        Local<ObjectTemplate> instTemplate = clazz->InstanceTemplate();
        instTemplate->SetInternalFieldCount(1);

        Local<ObjectTemplate> protoTemplate = clazz->PrototypeTemplate();

        protoTemplate->Set(
            String::NewFromUtf8(isolate, "getIdent"), 
            FunctionTemplate::New(isolate, TObjectIF::GetIdent));

        global->Set(String::NewFromUtf8(isolate, "TObject"), clazz);
    }
};

void Print(const FunctionCallbackInfo<Value> &args)
{
    HandleScope handle_scope(args.GetIsolate());
    for (int i = 0; i < args.Length(); i++)
    {
        String::Utf8Value str(args[i]);
        printf("%s", *str);
    }
    printf("\n");

    args.GetReturnValue().Set(0);
}

Handle<Context> InitBuildinFunction(Isolate *isolate)
{
    Handle<ObjectTemplate> global = ObjectTemplate::New(isolate);

    global->Set(String::NewFromUtf8(isolate, "print"), FunctionTemplate::New(isolate, Print));

    TObjectIF::InitializeTemplate(isolate, global);

    return Context::New(isolate, NULL, global);
}

int main(int argc, char **argv)
{
    V8::InitializeICU();
    V8::SetFlagsFromCommandLine(&argc, argv, true);

    ShellArrayBufferAllocator array_buffer_allocator;
    V8::SetArrayBufferAllocator(&array_buffer_allocator);

    Isolate *isolate = Isolate::New();
    Isolate::Scope isolate_scope(isolate);

    HandleScope handle_scope(isolate);

    Handle<Context> context = InitBuildinFunction(isolate);

    Context::Scope context_scope(context);

    Handle<String> source = String::NewFromUtf8(isolate, "var p = new TObject(10); print(p.getIdent());");

    Handle<Script> script = Script::Compile(source);

    Handle<Value> result = script->Run();

    String::Utf8Value utf8(result);
    printf("%s", *utf8);

    V8::Dispose();

    return 0;
}

google v8 javascript engineをコンパイル

google v8 javascript engineをビルド手順メモ

ソース取得
  $svn checkout http://v8.googlecode.com/svn/trunk/ v8
  $cd v8
  $svn co http://gyp.googlecode.com/svn/trunk build/gyp
  $svn checkout --force https://src.chromium.org/chrome/trunk/deps/third_party/icu46 third_party/icu --revision 214189
一部ソースを修正
    src/typing.cc
    +#pragma GCC diagnostic ignored "-Wuninitialized" 
    void AstTyper::VisitVariableProxy(VariableProxy* expr) {
ホスト(x86-64)環境でビルド
 $make x64.release library=shared

ビルドに成功すればout/x64.releaseにライブラリや実行ファイルが出力される
ちなみにクロスコンパイルしたい場合は以下のようにするらしい

export CC=cross-compile-gcc
export CXX=cross-compile-g++
export LINK=cross-compile-g++
make arm.release library=shared

Webkitgtk for ARMでブラウザ表示成功

仕事やら何やらで忙しく、全然更新していなかったけど、久しぶりに更新。
arm-qemu上でWebKitGtkを動かせはしたが、文字表示が変だったのと、URLにファイルシステムのパスを指定して事項すると、HTML表示できなかったが、一応、動くようになったので、メモ。

文字表示

前回、文字化けしていた理由はどうやらフォントがqemuファイルシステムイメージになかったためだった。
なので、今回は、ホスト(CentOS)にあるフォントをqemuファイルシステムイメージにコピー

  $cp -r /usr/share/fonts/default ${qemuルート}/usr/share/fonts/

あとは、rcSで以下のコマンドを発行して、フォントをキャッシュ化する。

  fc-cache -vfs

また、関連設定ファイルも修正

/etc/pango/pangorc
[Pango]
ModulesPath=/usr/lib/pango/1.6.0/modules
ModuleFiles=/etc/pango/pango.modules
[PangoFT2]
FontPath=/usr/share/fonts/default/Type1
/etc/gtk-2.0/gtkrc-2.0
style "user-font"
{
font_name="Type1"
}
widget_class "*" style "user-font"
gtk-font-name = "Type1 12"

ファイルシステム内のHTML表示

shared-mime-infoというパッケージを追加する。

  $wget http://freedesktop.org/~hadess/shared-mime-info-0.51.tar.bz2

まずコンパイルに必要なツールをインストール

  $su -
  #yum -y install intltool  cpan
  #cpan XML:Parser

shared-mime-infoをクロスコンパイル

  $CC=$CTARGET-gcc \
     LDFLAGS="-L$ROOTFS_DIR/usr/lib" \
     CPPFLAGS="-I$ROOTFS_DIR/usr/include" \
    ./configure \
     --host=$CTARGET \
     --prefix=$ROOTFS_DIR/usr
  $make
 $make install

あとは組込みLinuxrcSで、以下のコマンドを実行すればOK

  /usr/bin/update-mime-database -V /usr/share/mime

f:id:keropo:20140423000809p:plain

WebKit on DirectFB をARM cross compileの続き。

WebKitの動作確認

前回(WebKit on DirectFB をARM cross compile - keropoの備忘録)コンパイルしたWebKitをarm-qemu上で動かしてみる。

ターゲットの設定

/etc/init.d/rcS

以下の環境変数を追加

 $vi ${ターゲットルート}/etc/init.d/rcS
 export PANGO_RC_FILE=/etc/pango/pangorc
 export FONTCONFIG_FILE=/etc/fonts/fonts.conf
 export GTK2_RC_FILES=/etc/gtk-2.0/gtkrc
 export GDK_PIXBUF_MODULE_FILE=/etc/gtk-2.0/gdk-pixbuf.loaders

/etc/pango/pangorc

pangorcを新規作成

  $vi ${ターゲットルート}/etc/pango/pangorc
  [Pango]
  ModuleFiles=/etc/pango/pango.modules

pangoのロードモジュール情報の作成

  $pango-querymodules > ${ターゲットルート}/etc/pango/pango.modules

/etc/gtk-2.0/gtkrc

  $vi ${ターゲットルート}/etc/gtk-2.0/gtkrc
  gtk-font-name="sans 10"

gdk-pixbufのロードモジュール情報を作成

  $gdk-pixbuf-query-loaders > ${ターゲットルート}/etc/gtk-2.0/gdk-pixbuf.loaders

/etc/fonts

${ターゲットルート}/etc/fonts/fonts.confを開き、キャッシュフォルダのパスにコンパイル時のprefixの値が設定されているので、/var/cache/fontconfigに変更する。

実行

さて、この状態でqemu上でGtkLauncherを実行させたら、一応、ブラウザらしき画面が表示された。
f:id:keropo:20130926231230p:plain
う~~ん、文字が全部□で表示されている。
ログをみると、フォントが選択されてないとかなんとか言われている。
原因はなんだろ?j