[Fedora 11]

GTK+ を利用したクロスコンパイル

GTK+ (The GIMP Toolkit) は GIMP の実装のために開発された GUI ツールキットです。Linux や BSD などの X Window System 上で動作する GNOME デスクトップ環境のツールキットとしても採用されています。GTK+ ライブラリの使用および配布条件は、GNU LGPL 2.1 に従っています。


GTK+ クロスコンパイル環境

GTK+ のクロスコンパイル環境を整えるには、いくつかのパッケージをインストールしておく必要があります。Fedora 11 で利用できる、主要な GTK+ のクロスコンパイル用パッケージ群を列挙しておきました。なお、他に依存するパッケージは省略しています。

Table: MinGW クロスコンパイル環境における GTK+ の基本パッケージ

パッケージ名 説  明
mingw32-atk ATK (Accessibility Tool Kit) は、アプリケーションのユーザインタフェースをナビゲートするための操作性に関するツールの集まりです。
mingw32-cairo Cairo(カイロ)は、様々なバックエンドに対応したフリーのグラフィックライブラリで、デバイスに依存しないベクトルベースの API を提供します。
mingw32-glib2 GLib は、クロスプラットフォームのユーティリティライブラリの一種です。異なる CPU や OS 間でのアプリケーションの移植性を確保するライブラリとしても利用されています。
mingw32-gtk2 GTK+ は、グラフィカルユーザインターフェース (GUI) を提供するためのツールキット(ライブラリ) で、効率的で高い柔軟性と使いやすさを備えています。GTK+ は C 言語で記述されていますが、オブジェクト指向の手法を取り入れており、一貫したプログラミングインターフェースの提供を可能にしています。
mingw32-pango Pango は、国際化されたテキストをレイアウトおよびレンダリングするためのフレームワークです。
ページ先頭に戻る

最初は Hello World

GTK+ ライブラリを用いたクロスコンパイルでも、最初は Hello World プログラムを扱います。サンプルは、Hello World in GTK を使いました。なお、英文のコメント文は削除し、表示するメッセージを日本語に代え、さらに main 関数の最初に、gtk_set_locale() を加えてあります。

List: hello_gtk.c

#include <gtk/gtk.h>

static void
hello (GtkWidget * widget, gpointer data)
{
  g_print ("Hello World!\n");
}

static gboolean
delete_event (GtkWidget * widget, GdkEvent * event, gpointer data)
{
  g_print ("delete event occurred\n");

  return TRUE;
}

static void
destroy (GtkWidget * widget, gpointer data)
{
  gtk_main_quit ();
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_init (&argc, &argv);
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  g_signal_connect (G_OBJECT (window), "delete_event",
		    G_CALLBACK (delete_event), NULL);
  g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);

  gtk_container_set_border_width (GTK_CONTAINER (window), 10);
  button = gtk_button_new_with_label ("こんにちは、世界!");

  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (hello), NULL);
  g_signal_connect_swapped (G_OBJECT (button), "clicked",
			    G_CALLBACK (gtk_widget_destroy),
			    G_OBJECT (window));

  gtk_container_add (GTK_CONTAINER (window), button);
  gtk_widget_show (button);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}

コンパイルは、pkg-config を使って次の様にします。コンパイルの前に、クロスコンパイル環境における .pc ファイルを検索するパスを、環境変数 PKG_CONFIG_PATH に設定しておく必要があります。

pkg-config を利用したクロスコンパイル

$ export PKG_CONFIG_PATH=/usr/i686-pc-mingw32/sys-root/mingw/lib/pkgconfig
$ i686-pc-mingw32-gcc -Wall -g hello_gtk.c -o hello.exe \
> `pkg-config gtk+-2.0 --cflags` `pkg-config gtk+-2.0 --libs`
$ ./hello.exe &

hello.exe の実行例 (Wine)

ページ先頭に戻る

SourceForge.net Logo   MinGW クロスコンパイル用 pkg-config の入手先
  [UTIL] pkg-config

i686-pc-mingw32-pkg-config の利用

クロスコンパイル用に、環境変数 PKG_CONFIG_PATH を設定したり、元に戻したりすることが面倒だと感じましたので、私は MinGW コンパイル用に i686-pc-mingw32-gcc と同様に、クロス pkg-config (i686-pc-mingw32-pkg-config) を用意して使用しています。これは MinGW の Minimalist(*) の精神に反しているかもしれません。しかし、次で説明する Autotools を利用する時には、少しだけ設定が簡単になります。手作業でコンパイルするときは、却って入力が長くなり面倒かもしれませんが、次の様になります。

i686-pc-mingw32-pkg-config を利用したクロスコンパイル

$ i686-pc-mingw32-gcc -Wall -g hello_gtk.c -o hello.exe \
> `i686-pc-mingw32-pkg-config gtk+-2.0 --cflags` \
> `i686-pc-mingw32-pkg-config gtk+-2.0 --libs`
$ ./hello.exe &

(*) 必要最小限を目指す手法を実践する人や集団。

ページ先頭に戻る

Autotools の利用

GNU Autotools とは autoconf, autoheader, automake, libtool などのツール群のことです。これらは、#!/bin/sh で起動するシェルスクリプトで、マクロがたくさん定義されています。使いこなすために、直感的には憶えづらいマクロをたくさん使わなければならず、最初は取っつきにくいと感じることでしょう。

しかし、このツールを使用すると、パッケージをビルドする際にビルド/インストールする環境をツールがチェックして、インストールまでの全工程を自動化することができます。Linux をはじめとした UNIX 系のパッケージ開発において広く利用されています。

一般に、Autotools を利用できるパッケージでは、次のようなコマンドを入力するだけでビルド/インストールできます。

$ ./configure
...
$ make
...
$ make install

Autotools は、MinGW クロスコンパイル用にも、もちろん利用可能です。むしろ、MinGW クロスコンパイル環境における開発にこそ、積極的に Autotools を活用すべきだと思います。なぜなら、Autotools を利用すると、ソースを変更せずに Linux 用にも Win32 用にも、パッケージをビルドすることが可能になるからです。

ここでは、hello_gtk.c を例にして、Autotools を利用してみましょう。Autotools を駆使するとたくさんのことができますが、ここではビルドするための必要最低限の設定だけをします。今回は、Autotools がバージョンのチェックなどで GTK+ ライブラリの情報を利用するので、目的が MinGW のクロスコンパイルをするためだけであっても、gtk2-devel パッケージが必要になります。インストールされていなければ、あらかじめ yum でインストールしておいてください。

用意するファイル

Autotools を利用するために用意するファイルは、次の2つです。

  • configure.ac
  • Makefile.am

まず、configure スクリプトを生成するための設定ファイル configure.ac を生成します。configure.acautoscan プログラムを実行して生成される雛形ファイル configure.scanconfigure.ac にファイル名を変更して、これをもとに編集します。

List: configure.ac

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.63])
AC_INIT(hello, 1.0.0)
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([hello_gtk.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
GTK_REQUIRED_VERSION=2.0.0
GLIB_REQUIRED_VERSION=$GTK_REQUIRED_VERSION

AM_PATH_GLIB_2_0($GLIB_REQUIRED_VERSION,,
  [AC_MSG_ERROR(Test for GLib failed.)], gobject)
AM_PATH_GTK_2_0($GTK_REQUIRED_VERSION,,
  [AC_MSG_ERROR(Test for GTK failed.)])

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

次に、Makefile を生成するための基礎情報を記述した設定ファイル Makefile.am を作成します。

List: Makefile.am

bin_PROGRAMS = hello
hello_SOURCES = hello_gtk.c
hello_LDADD = $(GTK_LIBS)
hello_CFLAGS = $(GTK_CFLAGS)

設定ファイル configure.acMakefile.am から、Autotool のプログラムで必要なファイルを生成して、最後に autoconf プログラムで configure スクリプトと Makefile の雛形 Makefile.in を生成します。

configure スクリプトと Makefile の雛形を生成

$ ls
Makefile.am  configure.ac  hello_gtk.c
$ aclocal; autoheader; automake -a -c; autoconf
configure.ac:12: installing `./compile'
configure.ac:6: installing `./install-sh'
configure.ac:6: installing `./missing'
Makefile.am: installing `./depcomp'
$ ls
Makefile.am  autom4te.cache  config.h.in   configure.ac~  install-sh
Makefile.in  autoscan.log    configure     depcomp        missing
aclocal.m4   compile         configure.ac  hello_gtk.c
  1. aclocal プログラムは、configure.ac に記述してある AM_ で始まるマクロを処理するために aclocal.m4 ファイルを生成します。
  2. autoheader プログラムは、configure.ac で定義されている C プリプロセッサシンボルを見つけ config.h.in へ出力します。この config.h.in は、configure を実行する際のテンプレートになります。
  3. automake プログラムは、Makefile.am から、configure スクリプトを実行する時に必要となる Makefile の雛形ファイルである Makefile.in を生成します。
    • automake では、Makefile.am の他にいくつか設定ファイルを必要としますが、-a オプションを付加すると、不足するファイルに対してデフォルトのファイルがあれば、シンボリックリンクして使用するようにします。-c オプションは、-a オプションにおいて、シンボリックリンクを生成する代わりコピーします。
  4. autoconf プログラムは、m4 マクロプロセッサを使って configure.ac から configure スクリプトを作成します。

クロスビルド

準備が整いましたので、クロスコンパイル用に configure スクリプトを実行してターゲットのプラットフォーム用の Makefile を生成し、make します。

クロスコンパイル用に実行する configure スクリプトには、ビルドするプラットフォームを --build= オプションで、ビルドしたプログラムを実行するターゲット(ホスト)プラットフォームを --host= で指定します。

configure スクリプトの実行

$ ./configure --build=x86_64-redhat-linux --host=i686-pc-mingw32
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for i686-pc-mingw32-strip... i686-pc-mingw32-strip
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for i686-pc-mingw32-gcc... i686-pc-mingw32-gcc
checking for C compiler default output file name... a.exe
checking whether the C compiler works... yes
checking whether we are cross compiling... yes
checking for suffix of executables... .exe
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether i686-pc-mingw32-gcc accepts -g... yes
checking for i686-pc-mingw32-gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of i686-pc-mingw32-gcc... gcc3
checking whether i686-pc-mingw32-gcc and cc understand -c and -o together... yes
checking for i686-pc-mingw32-pkg-config... /usr/bin/i686-pc-mingw32-pkg-config
checking pkg-config is at least version 0.16... yes
checking for GLIB - version >= 2.0.0... cross compiling; assumed OK... 
yes (version 2.20.5)
checking for pkg-config... (cached) /usr/bin/i686-pc-mingw32-pkg-config
checking for GTK+ - version >= 2.0.0... cross compiling; assumed OK... 
yes (version 2.16.6)
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands

make の実行

$ make
make  all-am
make[1]: ディレクトリ `/home/bitwalk/work/hello_gtk' に入ります
i686-pc-mingw32-gcc -DHAVE_CONFIG_H -I.    -mms-bitfields -I/usr/i686-pc-mingw32
/sys-root/mingw/include/gtk-2.0 -I/usr/i686-pc-mingw32/sys-root/mingw/lib/gtk-2.
0/include -I/usr/i686-pc-mingw32/sys-root/mingw/include/atk-1.0 -I/usr/i686-pc-m
ingw32/sys-root/mingw/include/cairo -I/usr/i686-pc-mingw32/sys-root/mingw/includ
e/pango-1.0 -I/usr/i686-pc-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/i686-p
c-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/i686-pc-mingw32/sys-root/mi
ngw/include/pixman-1 -I/usr/i686-pc-mingw32/sys-root/mingw/include/libpng12   -g
 -O2 -MT hello-hello_gtk.o -MD -MP -MF .deps/hello-hello_gtk.Tpo -c -o hello-hel
lo_gtk.o `test -f 'hello_gtk.c' || echo './'`hello_gtk.c
mv -f .deps/hello-hello_gtk.Tpo .deps/hello-hello_gtk.Po
i686-pc-mingw32-gcc -mms-bitfields -I/usr/i686-pc-mingw32/sys-root/mingw/include
/gtk-2.0 -I/usr/i686-pc-mingw32/sys-root/mingw/lib/gtk-2.0/include -I/usr/i686-p
c-mingw32/sys-root/mingw/include/atk-1.0 -I/usr/i686-pc-mingw32/sys-root/mingw/i
nclude/cairo -I/usr/i686-pc-mingw32/sys-root/mingw/include/pango-1.0 -I/usr/i686
-pc-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/i686-pc-mingw32/sys-root/ming
w/lib/glib-2.0/include -I/usr/i686-pc-mingw32/sys-root/mingw/include/pixman-1 -I
/usr/i686-pc-mingw32/sys-root/mingw/include/libpng12   -g -O2   -o hello.exe hel
lo-hello_gtk.o -Wl,-luuid -L/usr/i686-pc-mingw32/sys-root/mingw/lib -lgtk-win32-
2.0 -lgdk-win32-2.0 -limm32 -lshell32 -lole32 -latk-1.0 -lgdk_pixbuf-2.0 -lpango
cairo-1.0 -lgio-2.0 -lcairo -lpangowin32-1.0 -lgdi32 -lpango-1.0 -lm -lgobject-2
.0 -lgmodule-2.0 -lglib-2.0 -lintl   
make[1]: ディレクトリ `/home/bitwalk/work/hello_gtk' から出ます
$ ./hello.exe

SourceForge.net Logo   GTK+ ランタイム・ライブラリの入手先
  [PRODUCT] GTK2 runtime package

Windows 上で実行

クロスコンパイルしたバイナリを Windows にコピーして実行する場合は、GTK+ のランタイム・ライブラリが必要になります。実行結果は、当然と言えばそうなのですが、ウィジェット枠のデコレーション表示などの見映えが Wine と Windows では異なる以外、動作としては同じ結果が得られます。

   

hello.exe の実行例 (Wine 左 : Windows Vista 右)

ページ先頭に戻る

ネイティブな Linux 用にビルド

同じソースファイルを、ネイティブな Linux 用にコンパイルすると以下の様になります。なお、最初に make clean で、既に生成してあるバイナリを削除してから configure スクリプトを実行しています。

configure スクリプトの実行(Linux 用)

$ make clean
test -z "hello.exe" || rm -f hello.exe
rm -f *.o
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking whether gcc and cc understand -c and -o together... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.16... yes
checking for GLIB - version >= 2.0.0... yes (version 2.20.5)
checking for pkg-config... /usr/bin/pkg-config
checking for GTK+ - version >= 2.0.0... yes (version 2.16.6)
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands

make の実行(Linux 用)

$ make
make  all-am
make[1]: ディレクトリ `/home/bitwalk/work/hello_gtk' に入ります
gcc -DHAVE_CONFIG_H -I.    -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -
I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/inclu
de/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include
/freetype2 -I/usr/include/libpng12   -g -O2 -MT hello-hello_gtk.o -MD -MP -MF .d
eps/hello-hello_gtk.Tpo -c -o hello-hello_gtk.o `test -f 'hello_gtk.c' || echo '
./'`hello_gtk.c
mv -f .deps/hello-hello_gtk.Tpo .deps/hello-hello_gtk.Po
gcc -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -
I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib6
4/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/inclu
de/libpng12   -g -O2   -o hello hello-hello_gtk.o -lgtk-x11-2.0 -lgdk-x11-2.0 -l
atk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpan
go-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0   
make[1]: ディレクトリ `/home/bitwalk/work/hello_gtk' から出ます
$ ./hello

hello の実行例 (Linux)

このように、Autotools を利用すれば、異なるプラットフォーム用でも同一のソースでコンパイルすることが可能になります。

ページ先頭に戻る

CMake の利用

[Fedora 13]

CMake は、Cross platform Make の略で、ソフトウェアのビルドを自動化するためのクロスプラットフォームなシステムです。従来の configure と make を利用する UNIX 系の開発環境において CMake とは、乱暴な表現をすれば Autotools に替わる Makefile を作成するためのツールと言えるでしょう。CMake は、その他にも Eclipse などの IDE のプロジェクトファイルを作成出来ますが、ここでは詳しくは触れません。

CMake では、CMakeLists.txt という名前の設定ファイルを、各ソースファイルのあるディレクトリに置いて、これでビルドするプロセスを制御します。Hello World プログラムでは、コンパイルするプログラムは hello_gtk.c の1ファイルだけです。同じディレクトリの次の様に記述した CMakeLists.txt を保存します。

List: CMakeLists.txt

project(Hello)
cmake_minimum_required(VERSION 2.8)
 
include(FindPkgConfig)
pkg_check_modules(GLIB2 glib-2.0)
pkg_check_modules(GTK2 gtk+-2.0)
 
include_directories(${GTK2_INCLUDE_DIRS})
link_directories(${GTK2_LIBRARY_DIRS})
link_libraries(${GTK2_LIBRARIES})
 
if(MINGW)
  set(CMAKE_C_FLAGS -mms-bitfields)
  set(CMAKE_CXX_FLAGS -mms-bitfields)
  set(CMAKE_EXE_LINKER_FLAGS -mwindows)
endif(MINGW)
 
add_executable(hello hello_gtk.c)
ページ先頭に戻る

ネイティブな Linux 用にビルド

Linux 用に CMake を利用して make でビルドする場合はとても簡単で、次の様になります。ソースファイルがあるディレクトリ内に unix とディレクトリを作成して、その中でビルドすることにします。

CMake の実行(Linux 用)

$ mkdir unix
$ cd unix
$ cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/lib64/ccache/gcc
-- Check for working C compiler: /usr/lib64/ccache/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/lib64/ccache/c++
-- Check for working CXX compiler: /usr/lib64/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- checking for module 'glib-2.0'
--   found glib-2.0, version 2.24.0
-- checking for module 'gtk+-2.0'
--   found gtk+-2.0, version 2.20.0
-- Configuring done
-- Generating done
-- Build files have been written to: /home/bitwalk/work/gtk_hello/unix
$ make
Scanning dependencies of target hello
[100%] Building C object CMakeFiles/hello.dir/hello_gtk.c.o
Linking C executable hello
[100%] Built target hello
$ ./hello
Hello World!
$ cd ..

hello の実行例 (Linux)

ページ先頭に戻る

MinGW 用にクロスビルド

CMake の標準的な設定ファイル(拡張子は .cmake)は /usr/share/cmake/Modules/ 以下に収録されているため、Linux ネイティブなビルドをする場合には簡単に Makefile を生成できますが、MinGW クロスコンパイル用に Makefile を生成する場合は、CMake に対して クロスコンパイラなどを指定する必要があります。そこで、Toolchain-i686-mingw32.cmake というファイルにクロスコンパイルに必要な内容を記述して、適当な場所(ここでは $HOME/work/cmake)に用意しておきます。

Toolchain-i686-mingw32.cmake に記述した内容は C/C++ のコンパイラ名、環境変数 PKG_CONFIG_PATH の設定, クロスコンパイル環境のトップディレクトリの3点です。

List: Toolchain-i686-mingw32.cmake

set(CMAKE_SYSTEM_NAME Windows)
 
# specify the cross compiler
set(CMAKE_C_COMPILER   /usr/bin/i686-pc-mingw32-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/i686-pc-mingw32-g++)
 
# set PKG_CONFIG_PATH for MinGW Cross Compile Environment
set(ENV{PKG_CONFIG_PATH} /usr/i686-pc-mingw32/sys-root/mingw/lib/pkgconfig)
 
# where is the target environment 
set(CMAKE_FIND_ROOT_PATH /usr/i686-pc-mingw32/sys-root/mingw)

その上で、次のようにして CMake を実行して Makefile を生成、make してビルドします。

CMake の実行(MinGW クロスコンパイル 用)

$ mkdir win
$ cd win
$ cmake -DCMAKE_TOOLCHAIN_FILE=~/work/cmake/Toolchain-i686-mingw32.cmake ..
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/i686-pc-mingw32-gcc
-- Check for working C compiler: /usr/bin/i686-pc-mingw32-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/i686-pc-mingw32-g++
-- Check for working CXX compiler: /usr/bin/i686-pc-mingw32-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- checking for module 'glib-2.0'
--   found glib-2.0, version 2.23.4
-- checking for module 'gtk+-2.0'
--   found gtk+-2.0, version 2.19.6
-- Configuring done
-- Generating done
-- Build files have been written to: /home/bitwalk/work/gtk_hello/win
$ make
Scanning dependencies of target hello
[100%] Building C object CMakeFiles/hello.dir/hello_gtk.c.obj
Linking C executable hello.exe
[100%] Built target hello
$ wine hello.exe
Hello World!
$ cd ..

hello.exe の実行例 (Wine)

ページ先頭に戻る

参考サイト

ページ先頭に戻る
(C) 2009 - 2017 Fuhito Suguri
クリエイティブ・コモンズ・ライセンス
This site by Fuhito Suguri is licensed under a Creative Commons 表示 - 継承 3.0 Unported License.
Ads by Sitemix