安裝 GraalVM... 後面再補上 (下載, 解壓, 設定 PATH...)

安裝相依

$ sudo apt-get install build-essential clang libsqlite3-0 libgtk-3-dev

準備 source code. 用到了 glib 相關的 shared libraries, 在運行 lli 時要告知載入. 用了 gmodule 在運行時載入了 libsqlite3.so 並取得其中的 symbol 並呼叫 sqlite3_open_v2sqlite3_close 用以測試.

#include <glib.h>
#include <gmodule.h>

typedef void *sqlite3;

typedef int (*sqlite3_open)(const char *filename, sqlite3 *inst);

typedef int (*sqlite3_close)(sqlite3 inst);

int main() {
        GMainLoop *loop = g_main_loop_new(NULL, FALSE);
        GModule *libsqlite = g_module_open("/usr/lib/x86_64-linux-gnu/libsqlite3.so.0.8.6", G_MODULE_BIND_LOCAL);
  sqlite3_open db_open;
  sqlite3_close db_close;
        sqlite3 db = NULL;

        g_print("libsqlite = %p\n", libsqlite);
        if(! g_module_symbol(libsqlite, "sqlite3_open_v2", (gpointer *) &db_open)) {
                g_error("failed to lookup symbol 'sqlite3_open'");
        }
        g_print("db_open = %p\n", db_open);

        if(! g_module_symbol(libsqlite, "sqlite3_close", (gpointer *) &db_close)) {
                g_error("failed to lookup symbol 'sqlite3_close'");
        }
        g_print("db_close = %p\n", db_close);

        g_print("Opening a in memory database\n");
        if(! db_open(":memory", &db)) {
                g_error("failed to create in memory database");
        }

        g_print("Closing database\n");
        db_close(db);
        db = NULL;
        g_print("Database closed\n");

        g_print("Enter event loop...\n");
        g_main_run(loop);

        return 0;
}

Build 成 native executable (故意用 gcc 交叉比對)

$ gcc -o test-glib test-glib.c $(pkg-config --cflags glib-2.0 gmodule-2.0) $(pkg-config --libs glib-2.0 gmodule-2.0)
$ ./test-glib 
libsqlite = 0x556c2632b890
db_open = 0x7f891087d4d0
db_close = 0x7f891082f310
Opening a in memory database
Closing database
Database closed
Enter event loop...

改用 GraalVM 運行 (這裡的 lli 是 GraalVM 提供的, 不是 llvm 自帶的)

$ clang -c -emit-llvm -g -O2 -o test-glib.bc test-glib.c $(pkg-config --cflags glib-2.0 gmodule-2.0)
$ lli -L /usr/lib/x86_64-linux-gnu/ --lib libglib-2.0.so --lib libgmodule-2.0.so ./test-glib.bc
libsqlite = 0x5fbf1e0
db_open = 0x7f6e90ffe4d0
db_close = 0x7f6e90fb0310
Opening a in memory database
Closing database
Database closed
Enter event loop...

當然, 運行帶 GUI 的程式也不是問題

#include <gtk/gtk.h>

int main() {
        GtkWidget *win = NULL;

        gtk_init(NULL, NULL);

        win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_widget_show(win);
        g_signal_connect(win, "delete-event", G_CALLBACK(gtk_widget_destroy), win);
        g_signal_connect(win, "destroy", G_CALLBACK(gtk_main_quit), NULL);

        gtk_main();

        return 0;
}

用 gcc 編譯及運行

$ gcc -o test-gtk test-gtk.c $(pkg-config --cflags gtk+-3.0) $(pkg-config --libs gtk+-3.0) && ./test-gtk

運行結果
Screenshot-from-2018-12-14-18-07-57

改用 GraalVM 運衙

$ clang -c -emit-llvm -g -O2 -o test-gtk.bc test-gtk.c $(pkg-config --cflags gtk+-3.0) && lli -L /usr/lib/x86_64-linux-gnu/ --lib libgtk-3.so ./test-gtk.bc

運行結果
Screenshot-from-2018-12-14-18-10-12

看起來一切正常! 這樣要用 GraalVM 加速其他語言只是時間的問題了.