2011년 7월 10일 일요일

GLib 메인루프 이용하기

GLib API를 이용한 멀티쓰레드 프로그래밍에서 비동기 메시지 큐를 이용하는 방법은 지난 포스트에서 설명한 적이 있는데, 이번에는 애플 GCD의 libdispatch와 비교되는 GLib의 메인루프를 이용하는 방법을 정리해 보았습니다. 이 방법은 어떤 관점에서 보면 더 쉽고, 이미 많은 기능이 기본적으로 지원되기 때문에 몇몇 경우를 제외하면 더 좋은 방법입니다. 다만 API 사용법을 이해하기가 처음에 조금 까다롭다는 점이 걸림돌입니다.

일반적으로 GLib / GTK 어플리케이션은 메인 쓰레드에서 실행되는 메인 이벤트 루프 기반에서 동작합니다. 키보드 / 마우스 이벤트 처리, 화면 표시, 사용자가 등록한 Idle / Timeout 함수 처리 등이 모두 이 메인 이벤트 루프에서 처리됩니다. 그런데 이 메인 이벤트 루프라는 건 마냥 개념적인게 아니라, 실제로 GMainLoop 객체를 기반으로 동작합니다. 그런데 g_main_loop_*() 계열 함수를 살펴보면 몇 개 안됩니다. 루프 객체를 생성하고, 참조하고, 해제하고, 돌리고[g_main_loop_run()], 종료하고[g_main_loop_quit()], 돌아가는 중인지 확인하기 등의 함수만 있습니다. 아, 하나 더 있군요. 객체를 생성할때 전달하는 GMainContext 객체를 얻어오는 함수[g_main_loop_get_context()]가 있군요.

모든 GMainLoop는 하나의 GMainContext와 함께 사용됩니다. GMainContext 객체는 실행할 소스[GSource] 목록을 관리합니다. 소스는 파일, 파이프, 소켓 등의 디스크립터를 기반으로 한 이벤트 소스일 수도 있고, Idle / Timeout 등과 같은 시간 소스일 수도 있습니다. 컨텍스트는 실행 소스 각각을 검사해서 원하는 이벤트가 발생했는지, 아니면 실행할 시간이 되었는지를 판단해 등록한 콜백함수를 호출합니다. 참고로, 메인 쓰레드에서 동작하기 위한 컨텍스트[g_main_context_default()]는 기본적으로 제공합니다. 이 기본 컨텍스트는 gtk_main() 함수가 사용하는 것은 물론, g_idle_add(), g_timeout_add() 등과 같은 함수도 이 기본 컨텍스트를 사용합니다.

아무튼 조금 더 구체적이고 자세한 내용은 공식 문서를 참고하시고, 이제 이를 이용한 멀티쓰레드 프로그래밍을 해보겠습니다. 말이 길었으니 코드를 먼저 보여드리겠습니다.
#include <glib.h>

static GThread *my_thread;
static GMainLoop *my_loop;

static void
add_idle_to_my_thread (GSourceFunc    func,
gpointer       data)
{
GSource *src;

src = g_idle_source_new ();
g_source_set_callback (src, func, data, NULL);
g_source_attach (src,
g_main_loop_get_context (my_loop));
g_source_unref (src);
}

static void
add_timeout_to_my_thread (guint          interval,
GSourceFunc    func,
gpointer       data)
{
GSource *src;

src = g_timeout_source_new (interval);
g_source_set_callback (src, func, data, NULL);
g_source_attach (src,
g_main_loop_get_context (my_loop));
g_source_unref (src);
}

static gpointer
loop_func (gpointer data)
{
GMainLoop *loop = data;

g_main_loop_run (loop);

return NULL;
}

static void
start_my_thread (void)
{
GMainContext *context;

context = g_main_context_new ();
my_loop = g_main_loop_new (context, FALSE);
g_main_context_unref (context);

my_thread = g_thread_create (loop_func, my_loop, TRUE, NULL);
}

static void
stop_my_thread (void)
{
g_main_loop_quit (my_loop);
g_thread_join (my_thread);
g_main_loop_unref (my_loop);
}

함수 먼저 설명하면, start_my_thread() 함수는 쓰레드를 시작하고, stop_my_thread() 함수는 쓰레드를 중지합니다. add_idle_to_my_thread() 함수는 바로 실행되는 Idle 콜백 함수를 추가하고, add_timeout_to_my_thread() 함수는 주기적으로 실행되는 Timeout 콜백 함수를 추가합니다. 마지막 두 함수의 인수는 g_idle_add(), g_timeout_add() 함수와 각각 동일합니다. 따라서, 콜백 함수가 TRUE를 리턴하면 자동으로 반복해서 계속 실행되고, FALSE를 리턴하면 한번만 실행되고 종료합니다.

위 코드의 핵심은 GMainContext 객체를 만들고 이를 기반으로 GMainLoop 객체를 만든 뒤 별도 쓰레드에서 실행하도록 하는 부분입니다. 그리고, 필요한 모든 작업은 Idle / Timeout 소스 객체를 만들어 컨텍스트에 추가(attach)해서 동작하도록 하는 겁니다. 참고로, 관련 API는 모두 쓰레드에 안전합니다.

물론 위 함수를 조금 더 확장하면 콜백함수가 종료될때 자동으로 호출되는 notify 함수도 등록할 수 있고, 우선순위도 조절할 수 있습니다. 또한 여러 쓰레드를 종류별로 만들어 필요한 쓰레드에게 해당 작업만 전달해도 됩니다. 하지만 그 정도는 응용하는데 별로 어려움이 없을 거라 생각하고 한가지만 더 설명하겠습니다.

예를 들어 네트워크 소켓(socket)을 하나 만들고 이 소켓에 읽을 데이터가 도착했을 경우에만 호출되는 함수를 등록하고 싶은 경우, 다음과 같은 코드를 사용하면 됩니다.
static gboolean
socket_read (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
/* Use g_io_channel_read_chars() to read data... */

return TRUE;
}

static void
add_socket_to_my_thread (gint sock_fd)
{
GIOChannel *channel;
GSource *src;

channel = g_io_channel_unix_new (sock_fd);
src = g_io_create_watch (channel, G_IO_IN);
g_source_set_callback (src,
(GSourceFunc) read_socket,
NULL,
NULL);
g_source_attach (src,
g_main_loop_get_context (my_loop));
g_source_unref (src);
}

자세한 내용은 위 코드와 비슷하지만 기본 메인 이벤트 루프에서 동작하도록 하는 g_io_add_watch() API 설명 부분을 참고하시기 바랍니다. 어쨌든, 기본적으로 GMainContext 객체는 유닉스 시스템의 폴링(polling) 메카니즘을 사용하기 때문에 이론적으로는 거의 모든 파일 디스크립터를 사용할 수 있습니다. 물론 비슷한 방식으로 윈도우 운영체제에서 이벤트 핸들이나 소켓 핸들도 사용할 수도 있습니다.

글머리에서 적은 것처럼 비동기 메시지 큐를 이용하는 방식보다 아주 약간의 오버헤드는 있겠지만, 훨씬 더 많은 기능을 제공하는 것 같지 않나요?

(이 글은 개인 블로그에 함께 게재되어 있습니다)

GLib 테스트 프레임워크 사용하기

GLib 라이브러리 2.16 버전부터 지원하는 테스트 프레임워크는 C 언어용 유닛테스트 도구입니다. 물론 많은 유닛 테스트 도구가 이미 존재하지만, GLib 라이브러리 기반 C 언어 프로그램이라면 굳이 다른 라이브러리를 사용하는 것보다는 이미 지원하는 훌륭한 도구를 사용하는게 더 좋겠지요. 참고로, GTK+, Clutter 등 같은 프로젝트도 이미 이 기능을 이용해 테스트 코드를 작성하고 있으므로 알아두면 도움이 됩니다. 모든게 그렇지만, 알고나면 별게 아니므로 기본 개념과 API 사용법만 충실히 이해하면 됩니다.

기본 개념 및 사용법


유닛테스트 개념은 스몰토크, 자바, C++처럼 언어적으로 객체지향 개념을 지원하는 언어에서 시작했기 때문에 C 언어에 그대로 적용하기에는 조금 까다로운 점이 많습니다. 그래서 GLib 테스트 프레임워크는 유닛테스트에서 기본 개념과 테스트 실행 방식만 빌려옵니다. 우선 알아야하는 기본 개념은 다음과 같습니다.

  • 테스트 케이스 (Test Case) : 가장 기본이 되는 하나의 테스트 단위입니다. GLib에서는 하나의 테스트 함수(function)가 이 역할을 합니다.

  • 픽스쳐 (Fixture) : 고정 설치된 물건이라는 뜻처럼, 테스트 케이스 실행 전후에 항상 실행하는 함수를 의미합니다. 실제로는, 테스트 함수를 실행하기 위해 필요한 환경을 미리 구축하거나(setup) 실행 후 리소스를 정리하는(teardown) 함수, 그리고 이와 함께 사용되는 사용자 데이터(data)로 구성됩니다. 참고로, GLib에서는 각 테스트간 의존성을 피하기 위해 모든 테스트 케이스를 실행할때마다 매번 픽스쳐를 새로 구성하는 방식(fresh fixture)을 사용합니다.

  • 테스트 슈트 (Test Suite) : 여러 테스트 케이스를 묶은 그룹입니다. 트리 구조처럼 테스트 슈트 여러개를 묶어 더 큰 테스트 슈트를 구성할 수도 있습니다. GLib에서는 테스트 경로(path)라는 개념으로 사용합니다.


개념은 조금 복잡한 것 같지만, 복잡하고 다양한 테스트 케이스를 그룹화하면 나중에 테스트 슈트별로 테스트를 진행할 수도 있는 등 많은 장점이 있습니다. 그리고 GLib이 제공하는 커맨드라인 도구를 이용하면 테스트 결과를 XML로 출력할 수도 있고, HTML 문서로 자동 변환할 수도 있는데 이 경우에도 테스트 슈트를 구성해 두면 많은 도움이 됩니다.

물론 GLib은 정교하게 테스트 슈트와 테스트 케이스, 픽스쳐를 구성할 수 있는 많은 API를 제공하지만, 복잡한 과정을 API 호출 하나로 처리할 수 있는 기능도 제공합니다.
g_test_add_func ("/onvif/nvc-connections", test_onvif_nvc_connections);

위 예제에서 g_test_add_func() 함수는 "onvif" 테스트 슈트 밑에 "nvc-connections" 이름의 테스트 케이스를 추가합니다. 테스트시 실행할 함수는 사용자가 직접 구현한 test_onvif_nvc_connections() 함수입니다. g_test_add_func() 함수가 테스트 슈트를 자동으로 생성해 주기 때문에 별도의 추가 작업이 불필요합니다. 비슷한 기능의 g_test_add_data_func() 함수는 테스트 함수에 데이터를 전달할 수 있어서, 한 함수로 데이터만 바꿔서 테스트하고자 할때 유용합니다. 하지만, 두 API는 픽스쳐를 지정할 수 없으므로, 픽스쳐를 사용하려면 g_test_add() 함수를 이용해야 합니다.일단, 간단한 예제 코드를 보여드리면 다음과 같습니다. ("Writing Unit Tests with GLib" 글에서 발췌했습니다)
#include <glib.h>

static void
simple_test_case (void)
{
/* a suitable test */
g_assert (g_bit_storage (1) == 1);

/* a test with verbose error message */
g_assert_cmpint (g_bit_storage (1), ==, 1);
}

int
main (int argc, char **argv)
{
/* initialize test program */
g_test_init (&argc, &argv, NULL);

/* hook up your test functions */
g_test_add_func ("/Simple Test Case", simple_test_case);

/* run tests from the suite */
return g_test_run ();
}

이 코드를 g-test-sample1.c 파일로 저장하고 컴파일 후 실행하면 다음과 같은 결과를 볼 수 있습니다.
$ gcc -o g-test-sample1 g-test-sample1.c `pkg-config --cflags --libs glib-2.0`
$ ./g-test-sample1
/Simple Test Case: OK

이 결과를 재활용하기 위해 XML 형식으로 저장하거나, HTML 문서로 만들고 싶다면 gtester / gtester-report 프로그램을 사용하면 됩니다.
$ gtester -o sample-log.xml g-test-sample1
TEST: g-test-sample1... (pid=2771)
PASS: g-test-sample1
$ gtester-report sample-log.xml > sample-log.html

위와 같이 실행하여 생성한 HTML 문서 결과는 다음과 같습니다.



참고로, gtester 프로그램의 인수로 여러 테스트 실행 파일을 한꺼번에 전달하면 모든 테스트 실행 파일의 테스트 슈트가 하나의 결과로 통합됩니다.

위 코드에서 사용한 테스트 코드를 보면 제일 먼저 g_test_init() 함수가 나타납니다. 이 함수는 테스트 기능을 초기화하는데, 리퍼런스 매뉴얼을 보시면 프로그램 실행 인수를 통해 사용자가 여러 테스트 옵션을 지정할 수 있는 걸 알 수 있습니다. 물론 특정 테스트 슈트만 실행하게 하는 옵션도 인수로 지정할 수 있습니다.

테스트 함수를 보면 g_assert_cmpint()라는 다소 생소한 API가 보이는데, GLib은 테스트 코드를 위해 이와 비슷한 매크로를 더 제공합니다.
#define g_assert             (expr)
#define g_assert_not_reached ()
#define g_assert_cmpstr (s1, cmp, s2)
#define g_assert_cmpint (n1, cmp, n2)
#define g_assert_cmpuint (n1, cmp, n2)
#define g_assert_cmphex (n1, cmp, n2)
#define g_assert_cmpfloat (n1,cmp,n2)
#define g_assert_no_error (err)
#define g_assert_error (err, dom, c)

위 매크로를 사용하여 테스트 코드를 작성하면 더 친절하고 자세한 에러 메시지를 출력합니다. 예를 들어 다음 코드는,
gchar *string = "foo"; g_assert_cmpstr (string, ==, "bar");

이런 메시지를 출력합니다.
ERROR: assertion failed (string == "bar"): ("foo" ==  "bar")

물론 기본적으로 실패한 경우에만 메시지를 보여줍니다.

그 외 더 많은...

지금까지 설명한 기본 기능 외에도 표준출력 / 표준에러 메시지를 표시하지 않도록 한 뒤 이 메시지에서 특정 문자열을 확인한다든가, 항상 동일한 패턴의 난수를 생성하여 이를 테스트에 이용하거나, 테스트에 시간이 얼마나 더 걸리는지 측정할 수도 있습니다. 프로그램을 종료시키는 치명적인 에러가 발생하는 경우도 테스트할 수 있고, 여러가지 테스트 모드(quick / slow / performace 등)를 두어 프로그램 인자를 이용해 원하는 테스트 코드만 실행할 수도 있습니다.

더 많은 활용 예제가 GLib 자체 테스트 코드에(glib/tests/testing.c) 있으므로, 별로 길지 않으니, 직접 확인해 보시기 바랍니다.

프로젝트에 활용하기

MVP 개발 모델과 TDD + 유닛테스트 도구를 이용하여 응용 프로그램을 개발하면(Presenter First 개발) 더 빠르고 쉽게 튼튼한 코드를 만들 수 있으니, 한 번 검토해 보시기 바랍니다. 개발자가 TDD 방법론을 주저하는 이유 중 하나가 테스트 코드까지 만들다 보니 늘어나는 코드량과 늘어나는 개발 시간 때문인데, 테스트 코드를 그대로 실제 코드로 재활용할 수 있다면 얘기가 달라지겠죠.

프로젝트 일일빌드시 테스트 루틴도 동작하도록 한뒤 자동으로 테스트 결과를 웹사이트에 게재하는 것도 좋은 개발 습관입니다. 아예 코드 수정 후 저장소에 커밋하면 반드시 모든 테스트 케이스를 통과해야만 커밋되도록 저장소를 설정할 수도 있지만, 엄청난 서버 부하를 야기할 수 있으므로, 테스트 케이스를 통과한 코드만 커밋할 수 있도록 가이드라인을 규정하는 것도 좋습니다.

유닛테스트는 특정 객체나 모듈의 모든 API가 항상 정상적으로 동작하는지를 검사하기 위해 사용합니다. 그래서 가장 기본적인 사용법은 공개 함수를 다양한 인수로 호출한 뒤 그 결과값을 확인하는 방식입니다. 하지만 실무에서는 그렇게 단순한(?) 버그만 존재하는게 아니라서, 특정 시나리오나 특정 조건을 만족할 경우에만 버그 현상이 재현되는 경우도 많습니다. 이러한 경우, 버그에 대한 테스트 케이스를 추가하고 이 케이스에 대한 테스트가 통과할때까지 디버깅을 합니다. 이렇게 해두면 동일한 버그가 나중에 재발하는 걸 방지할 수 있습니다. 대부분 회사에서는 버그(이슈)관리시스템을 사용하므로 g_test_bug() API를 사용하면 편리합니다.

참고로, GTK+ 라이브러리는 GLib 테스트 프레임워크를 기반으로 마우스 버튼 동작이나 키보드 입력을 에뮬레이션하는 기능처럼 GUI 프로그램 테스트용 API를 제공합니다. 더불어 Xvfb 같은 더미 X서버를 이용하면 원격 터미널이나 cron 작업처럼 실제 X서버가 없는 환경에서도 GUI 프로그램 테스트 진행이 가능합니다. 꼭 GTK+ 프로그램이 아니더라도, 폰트 렌더링 루틴이 정확한 그래픽 비트맵을 생성하는지, 특정 항목을 선택하고 특정 행동을 취했을때 정상적으로 문자열이 표시되는지 등도 테스트 케이스로 작성할 수 있습니다.

테스트 케이스 실행 방식 및 테스트 코드 위치

위 예제처럼 테스트 케이스를 특정 주제별로 나누어 각각의 실행파일로 만들어도 되지만, 테스트 케이스를 초기화하는 부분을 잘 정리하여 테스트 케이스를 여러 모듈로 분리한 뒤, 모든 테스트 케이스를 통째로 하나의 실행파일로 만들어도 됩니다. 이렇게 하면 추가적인 스크립트나 도구의 도움없이도 명령어 한번 실행으로 모든 테스트 케이스를 실행할 수 있기 때문에 더 편리할 수 있습니다. 또는 Clutter 프로젝트처럼 테스트 모듈을 각각 공유라이브러리로 만들어 플러그인처럼 로드해서 실행하는 방법도 있습니다.

하지만, 위 방식은 모두 실제 코드와 테스트 코드가 서로 다른 파일에 존재하는 방식입니다. 테스트 코드가 실제 코드와 하나의 파일에 존재한다면 테스트 코드 작성이 더 일상화되고 자연스러워질 수 있습니다. 그러므로, 프로그램 실행 파일 크기가 별로 문제가 되지 않는다면, 또는 릴리스 / 디버그 모드를 분리하여 컴파일하도록 구성된 프로젝트라면, 프로그램에 특정 옵션을 주었을 경우에만 테스트 케이스 실행 모드로 동작하게 하면 됩니다. 물론 특정 테스트 프로그램은 예제로 사용하기 위해 분리할 수도 있겠지만, 모듈이나 객체의 고유 기능만 테스트하는 코드라면 같은 파일에 있는게 더 자연스러울 수 있습니다. 예를 들어 GObject 객체라면, 속성(properties) / 시그널(signal) 이름이 갑자기 변경되었을때 이를 참조하는 모듈이 문제를 일으키지 않도록 하기 위해, 'validate-properties', 'validate-signals' 등의 테스트 케이스를 추가한뒤 통과하지 못했을 경우 g_test_message() 등을 이용해 이를 참조하는 모듈을 찾아 수정하라는 강조 메시지를 표시하는 것도 가능합니다. 또한 특정 시그널이 정상적으로 발생하는지, 순서대로 발생하는지 확인할 수 있습니다. 그리고 무엇보다도, 같은 파일에 있으면 내부 자료구조에도 접근할 수 있으므로 내부 로직에 대한 테스트 코드를 작성하는 것도 가능해집니다.

따라서 무조건 한 가지 방식만 고집하기보다, 적절하게 필요에 따라 알맞는 방식을 선택하는 것이 중요합니다.

결론

뭐 다른 결론이 있을리 없을만큼 유닛 테스트와 리그레션 테스트(regression test) 등은 이미 소프트웨어 개발 분야 전반에 광범위하게 사용하고 있습니다. 다만, C 언어를 이용해 개발하는 경우 리거시(legacy) 코드가 너무 많거나, 마땅한 테스트 도구를 찾지 못했거나, 여러가지 이유로 도입하지 못하는 경우가 많은데, 함께 잘 극복하고 익숙해져서 더 좋은 방향으로 나아가야 하지 않을까... 생각해 봅니다.

(이 글은 개인 블로그에 함께 게재되어 있습니다)

The Board 소개

힘겹게 겨우 다시 한 학기를 마무리했지만, 할 일은 여전히 밀려 있습니다. 그래서 잠시 머리도 식힐겸 요즘 관심있게 지켜보고 있는 GNOME 프로젝트 중 하나인 The Board 프로젝트에 대해 간략하게 소개해볼까 합니다.

일단, 백마디 말보다 스크린샷 하나가 더 좋을 것 같군요.


이 프로그램은 쉽게 말해 다음과 같은 오프라인 보드를 컴퓨터에서 흉내내는 것입니다. 다만 아직은 개인 자료 수집용입니다.


그놈 셸(GNOME Shell)과 마찬가지로, 클러터(Clutter) 라이브러리를 이용해 자바스크립트(JavaScript) 언어로 작성되었다는 점이 흥미롭습니다. 다음은 실제 동작 화면을 캡쳐한 동영상 모음입니다.






개발 로그를 들여다보면 웹브라우저에서 직접 접근할 수 있는 인터페이스가 추가되고 있는 것도 같은데, 언젠가는 현재 인터넷의 글목록 방식 게시판이 아닌 이와 같이 실생활을 모방한 방식의 인터넷 게시판도 등장하지 않을까... 상상해봅니다.

(이 글은 개인 블로그에 함께 게재되어 있습니다)

2011년 7월 6일 수요일

GNOME3에서 주목해야할 기술!


GNOME3가 공식 출시된지 두어달이 지났습니다. 우분투11.04에서 GNOME3 대신 Unity를 선택하는 바람에 우분투 사용자가 많은 국내에서는 GNOME3를 사용하는 사용자가 많지 않을 것으로 예상합니다. 대신 최신 Fedora를 설치하면 GNOME3를 사용할 수 있습니다.

GNOME3에서는 GNOME Shell이라는 Window Manager가 새롭게 개발되었고, 상당수의 코드가 GObject Introspection기술를 이용하여 JavaScript로 개발되었습니다. 이번 글에서 이러한 기술에 관하여 간단하게 소개해볼까 합니다.

GNOME Shell
GNOME Shell은 프로그램을 실행하고, 윈도를 전환시키고, 윈도가 전환될 때나 작업 환경이 변경될 때, 각종 효과를 만들어 냅니다. 기존 GNOME2의 데스크탑, 메뉴, Panel을 대치한다고 보면 됩니다.

http://live.gnome.org/GnomeShell/Technology
위 아키텍쳐를 보면 GNOME Shell은 크게 Windows Manager, Compositing Manger 역할을 하는 Mutter와 Shell Toolkit으로 구성된 것을 알 수 있습니다. Mutter는 기존 GNOME Desktop의 Window Manager인 MetaCity의 Core를 포하고 있습니다. 서로 다른 Process로 분리된 Window Manager와 Composting Manager를 하나로 프로그램으로 통합한것입니다. Clutter는 화면을 구성하는 UI와 Animation을 구현하기 위해 사용됩니다. 실제 Mutter와 Shell Toolkit은 GObject Introspection과 JavaScript Binding을 통해 JS로 사용이 가능합니다.

Clutter
Clutter는 GPU 가속을 지원하는 3D기반의 2D Animation 엔진입니다. 직접 OpenGL API를 사용하지 않아도 쉽게 3D 효과를 UI에 적용할 수 있습니다. Stage와 Actor라는 개념을 제공하여, 직관적으로 Animation을 구현하고, 각 Actor에 3D 효과를 적용할 수 있습니다.

Mutter
Mutter는 GNOME Desktop의 새로운 Window Manager입니다. Clutter로 Compositing Manager기능을 함께 구현하여, 사용자에게 Compositing Manager를 선택할 자유를 제한했다고 약간의 논란이 있었습니다. 즉, Compiz 사용자는 Mutter를 사용할 수 없는 것이이죠. 아마, 그 이유 때문에 우분투도 GNOME-Shell을 사용하지 않는 것으로 알고 있습니다.

GObject Introspection
GObject Introspection은 다양한 언어에서 GObject기반 library에 쉽게 binding할 수 있도록 지원합니다. 지금까지는 API가 변경되면 binding을 수정해야했지만, 이제는 더 이상 그럴 필요가 없습니다. 좀 더 자세한 내용은 지난 GNOME3 Launch Party에서 발표된 슬라이드 자료를 참고하세요.

위와 같이 GNOME3에 Window Manager가 변경되는 등 많은 변화가 있었고, Clutter, GObject Introspection과 같은 기술로 구현되어 있습니다. 각각의 기술 또한 다양하게 활용될 수 있으므로 자세하게 살펴볼 수 있는 기회를 갖도록 하겠습니다.

고맙습니다~

2011년 7월 3일 일요일

jhbuild 사용하기

새로운 소프트웨어를 빌드하고 실행해 보는 것은 상당히 흥미있는 일이지만, 기존 시스템이 변경되어 갑자기 데스크탑 환경이 실행되지 않으면 무척 난감합니다. 게다가 의존성이 있는 라이브러리까지 모두 새롭게 빌드하려면 시간과 노력이 많이 듭니다.

이 때, 필요한 것이 바로 jhbuild입니다. jhbuild는 사용하고 있는 시스템 환경에 영향을 주지 않고, 따로 빌드와 실행 환경을 구성해주고  자동으로 소스 코드를 바로 다운로드 받아, 바로 빌드하도록 도와주는 툴입니다. 의존성 있는 라이브러리도 다운로드 받아서 함께 빌드해주니 정말 편리합니다.

jhbuild의 좋은 점이 무엇일까?

1. 모듈 세트로 소스코드를 다운로드 받아 configure, build, install이 가능

$ jhbuild build gtk+ 

gtk+관련 모듈을 다운로드 받아서 알아서 빌드한 후, ~/.jhbuildrc에 설정한 위치로 빌드된 파일을 설치해준다. 

2. 원하는 모듈을 버전 별로도 빌드 및 설치 가능

3. 시스템이 깨긋한 상태에서 모듈과 의존성 있는 모듈을 새롭게 소스코드 부터 받아서 설치까지 검증

4. 자동화 빌드 시스템 구축

처음 jhbuild를 설치하고 주의할 점

.jhbuildrc 파일에 아래 두 줄을 추가해야 합니다.
addpath('PKG_CONFIG_PATH', os.path.join(os.sep, 'usr', 'lib', 'pkgconfig'))
addpath('PKG_CONFIG_PATH', os.path.join(os.sep, 'usr', 'share', 'pkgconfig'))

이렇게 해야, /usr/lib에 설치된 다른 의존성 있는 모듈을 사용하여 빌드가 가능합니다. jhbuild가 모든 의존성 있는 라이브러리를 다운로드 받아 빌드하지는 않기 때문입니다. 즉, png, tiff 라이브러리는 apt-get으로 직접 설치해야 합니다.

참고

2011년 6월 22일 수요일

GNOME Foundation의 새 Executive Director를 소개합니다.

안녕하세요.

GNOME Foundation에서 드디어 새 Executive Director를 선임했습니다. Stormy Peters가 Mozilla로 떠난 이후, 지난 8개월동안 공석이였는데, Karen Sandler라는 분이 새로 오셨네요. 환영합니다~

Executive Director의 역할은 기본적으로 GNOME Foundation의 대외적인 업무를 맡아 Community와 회사 또는 다른 단체와의 소통을 돕습니다.  GNOME3 출시와 더불어 Executive Director로 새로 오셨으니, 뭔가 더 새롭게 발전할 모습이 기대가 됩니다.

자세한 내용은 아래 글을 확인하세요.

2011년 6월 4일 토요일

그놈 한국 블로그를 시작합니다!

그놈 한국 블로그를 시작합니다!
그놈 플랫폼 및 오픈소스 전반에 관한 글을 기고할 분을 모집합니다.
gnome.korea@지메일닷컴으로 연락주세요.

고맙습니다.