DIAL 샘플 빌드하기

Ydal (토론 | 기여)님의 2014년 1월 1일 (수) 14:29 판

본 문서는 http://www.dial-multiscreen.org/ 에서 제공하는 샘플 어플리케이션을 빌드 및 실행하는 방법에 대해 설명한다.


1 테스트 환경

본 문서는 아래의 환경을 기준으로 설명한다.

  • Ubuntu 13.10 64 bit
  • Firefox 25.0.1 (Mozilla Firefox for Ubuntu canonical - 1.0)
  • g++ (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
  • curl 7.32.0 (x86_64-pc-linux-gnu) libcurl/7.32.0 OpenSSL/1.0.1e zlib/1.2.8 libidn/1.28 librtmp/2.3

2 소스 구하기

http://www.dial-multiscreen.org/example-code 페이지에 게시된 파일 중 DIAL-1.0.2-1676049.tar.gz 를 다운로드 한다. 아래와 같이 압축을 해제 후 빌드를 수행한다.

mkdir dial
tar zxvf DIAL-1.0.2-1676049.tar.gz -C ./dial
cd dial/src
make

3 오류 조치 (소스 수정 및 패키지 설치)

  • 빌드 중 "fatal error: bits/c++config.h: No such file or directory" 에러가 발생하는 경우 g++ 헤더가 PC 상에 설치되지 않은 경우 이므로 gcc-4.8-multilib와 g++-4.8-multilib 패키지를 설치한다.
sudo apt-get install gcc-4.8-multilib g++-4.8-multilib
  • "main.cpp:287:12: error: ‘sleep’ was not declared in this scope" 에러가 발생하는 경우 sleep 에 대한 include를 추가해 준다. "man 3 sleep" 명령으로 어떤 헤더 파일에 sleep 함수가 정의되어 있는지 확인할 수 있다.
$ vi client/main.cpp
#include <unistd.h>
  • "DialConformance.cpp:424:33: error: ‘usleep’ was not declared in this scope" 에러도 sleep 과 동일하게 include 누락으로 발생한다.
$ vi client/DialConformance.cpp
#include <unistd.h>
  • "DialServer.cpp:27:23: fatal error: curl/curl.h: No such file or directory" 에러가 발생하는 경우 PC에 curl 헤더 파일이 존재하지 않는 경우이다. 관련 패키지를 설치한다.
sudo apt-get install libcurl4-openssl-dev
  • "/usr/include/curl/curlrules.h:143:41: error: size of array ‘__curl_rule_01__’ is negative" 에러는 curl 헤더 파일에서 32bit/64bit 체크를 위해 배열 사이즈를 이용하기 때문에 발생한다. 64bit 환경에서 빌드하기 위해서 makefile 내용 중 -m32 구문을 제거한다.
$ vi client/makefile
#         $(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -lcares -m32 -o dialclient
            $(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -lcares -o dialclient
  • "main.cpp:59:40: error: format ‘%Zu’ expects argument of type ‘size_t’, but argument 2 has type ‘int’ [-Werror=format=]" 에러는 타입 캐스팅 실패로 발생한다. %Zu에 해당하는 값을 (size_t)로 강제 캐스팅 해준다.
$ vi client/main.cpp
        printf("%Zu: Server IP[%s] UUID[%s] FriendlyName[%s] \n",
            (size_t)i+1, (*it)->getIpAddress().c_str(),
            uuid.c_str(), name.c_str() );
                   printf("Server %Zu: %s\n", (size_t)i+1, name.c_str());
  • "DialDiscovery.cpp:134:14: error: variable ‘res’ set but not used [-Werror=unused-but-set-variable]" 에러는 res 변수를 사용하지 않기 때문에 발생한다. 실제 res 변수 정의를 삭제하면 다른 부분에서 에러가 발생한다. 일반적인 회피 방법은 (void)res; 형식으로 컴파일러에 해당 변수가 참조되고 있음을 알려주는 것이다.
$ vi client/DialDiscovery.cpp
     CURL *curl;
     CURLcode res = CURLE_OK;
     (void)res;
  • "DialDiscovery.cpp:257:84: error: too many arguments for format [-Werror=format-extra-args]" 에러는 snprintf 함수에 전달된 포맷 스트링에 포함된 값 요소들(%로 정의된 파라메터) 개수와 snprintf 함수 파라메터로 전달된 값 요소의 개수가 불일치 해서 발생한다. ssdp_msearch 변수에 할당된 문자열에는 별도의 추가적인 값이 존재하지 않으므로 ip_addr과 my_port를 주석처리 한다. 주석 처리 후에는 ip_addr, my_port가 정의만 되고 사용되지 않는다고 에러가 발생한다. ip_addr, my_port의 선언 부분도 주석처리 한다.
$ vi client/DialDiscovery.cpp
     send_size = snprintf(send_buf, sizeof(send_buf), ssdp_msearch/*, ip_addr, my_port*/);
    //static char ip_addr[INET_ADDRSTRLEN] = "127.0.0.1";
    //static int my_port = 0;
  • "/usr/bin/ld: cannot find -lcares" 에러는 cares라는 라이브러리를 찾을 수 없다고 발생한다. 실제로 cares 라이브러리는 사용되지 않기 때문에 makefile에서 제거한다.
$ vi client/makefile
#         $(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -lcares -m32 -o dialclient
            $(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -o dialclient
  • "main.c:319:13: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]" 에러는 캐스팅 실패로 발생한다. 64bit 환경과 32bit 환경에서 pid_t의 크기가 달라서 발생한다. pid_t로 캐스팅 하기전 long 타입으로 캐스팅 해준다.
$ vi server/main.c
     waitpid((pid_t)(long)run_id, NULL, WNOHANG); // reap child

4 패치

아래는 위 수정 사항 모두 반영한 패치 파일이다. 패치 코드를 복사해 dial.patch로 저장하고 아래 명령을 패치를 수행할 수 있다.

patch -p1 < dial.patch
 
diff -rupN src_org/client/DialConformance.cpp src/client/DialConformance.cpp
--- src_org/client/DialConformance.cpp	2013-12-30 12:51:43.017984698 +0900
+++ src/client/DialConformance.cpp	2013-12-30 12:54:19.853987278 +0900
@@ -32,6 +32,7 @@
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 // Number of milliseconds to sleep between launches when doing a launch=ALL
 #define LAUNCH_SLEEP 6000
diff -rupN src_org/client/DialDiscovery.cpp src/client/DialDiscovery.cpp
--- src_org/client/DialDiscovery.cpp	2013-12-30 12:51:43.009984698 +0900
+++ src/client/DialDiscovery.cpp	2013-12-30 12:54:02.941987000 +0900
@@ -48,8 +48,8 @@ using namespace std;
 
 DialDiscovery *DialDiscovery::sDiscovery = 0;
 
-static char ip_addr[INET_ADDRSTRLEN] = "127.0.0.1";
-static int my_port = 0;
+//static char ip_addr[INET_ADDRSTRLEN] = "127.0.0.1";
+//static int my_port = 0;
 static struct sockaddr_in saddr;
 typedef struct
 {
@@ -132,6 +132,7 @@ static void getServerInfo( const string
 {
     CURL *curl;
     CURLcode res = CURLE_OK;
+    (void)res;
 
     if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
         fprintf(stderr, "curl_global_init() failed\n");
@@ -253,7 +254,7 @@ void * DialDiscovery::send_mcast(void *p
     pthread_attr_t attr;
     search_conn connection;
 
-    send_size = snprintf(send_buf, sizeof(send_buf), ssdp_msearch, ip_addr, my_port);
+    send_size = snprintf(send_buf, sizeof(send_buf), ssdp_msearch/*, ip_addr, my_port*/);
     ATRACE("[%s:%d] %s\n", __FUNCTION__, __LINE__, send_buf);
 
     if (-1 == (my_sock = socket(AF_INET, SOCK_DGRAM, 0))) {
diff -rupN src_org/client/main.cpp src/client/main.cpp
--- src_org/client/main.cpp	2013-12-30 12:51:43.009984698 +0900
+++ src/client/main.cpp	2013-12-30 12:52:37.113985588 +0900
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 using namespace std;
 
@@ -54,7 +55,7 @@ static void printServerList( vector<Dial
         (*it)->getFriendlyName( name );
         (*it)->getUuid( uuid );
         printf("%Zu: Server IP[%s] UUID[%s] FriendlyName[%s] \n", 
-            i+1, (*it)->getIpAddress().c_str(),
+            (size_t)i+1, (*it)->getIpAddress().c_str(),
             uuid.c_str(), name.c_str() );
     }
 }
@@ -181,7 +182,7 @@ int handleUser(DialDiscovery *pDial) {
                 {
                     string name;
                     list[i]->getFriendlyName(name);
-                    printf("Server %Zu: %s\n", i+1, name.c_str());
+                    printf("Server %Zu: %s\n", (size_t)i+1, name.c_str());
                 }
                 printf("\n*********************************\n\n");
             }break;
diff -rupN src_org/client/makefile src/client/makefile
--- src_org/client/makefile	2013-12-30 12:51:43.009984698 +0900
+++ src/client/makefile	2013-12-30 12:53:00.333985970 +0900
@@ -8,7 +8,7 @@ OBJS := main.cpp DialServer.cpp DialDisc
 
 # You may not need all these libraries.  This example uses a build of curl that needs crypto, ssl, cares, and zlib
 dialclient: $(OBJS) ${includes}
-	$(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -lcares -m32 -o dialclient
+	$(CC) -Wall -Werror -g $(OBJS) $(INCLUDES) $(LDFLAGS) -ldl -lpthread -lcurl -lz -lcrypto -lssl -o dialclient
 
 clean:
 	rm -f *.o dialclient
diff -rupN src_org/server/main.c src/server/main.c
--- src_org/server/main.c	2013-12-30 12:51:43.025984698 +0900
+++ src/server/main.c	2013-12-30 12:54:37.861987574 +0900
@@ -316,7 +316,7 @@ static DIALStatus netflix_status(DIALSer
     // Netflix application can stop
     *pCanStop = 1;
 
-    waitpid((pid_t)run_id, NULL, WNOHANG); // reap child
+    waitpid((pid_t)(long)run_id, NULL, WNOHANG); // reap child
     return isAppRunning( spAppNetflix, NULL ) ? kDIALStatusRunning : kDIALStatusStopped;
 }

5 실행

빌드된 dialserver 를 실행한 후, dialclient를 실행한다. dialclient 실행 시 dialserver에 접속 로그가 출력된다. 이후 dialclient를 통해 명령을 수행할 수 있다.

$ ./server/dialserver 
Netflix is Not Running
YouTube is Not Running
launcher listening on gDialPort 56789
SSDP listening on 172.30.1.1:56790

Sending SSDP reply to 172.30.1.1:59347
$ ./client/dialclient 
0. List DIAL servers
1. Launch Netflix
2. Kill Netflix
3. Netflix status
4. Launch YouTube
5. Kill YouTube
6. YouTube status
7. Run conformance tests
8. QUIT

6 같이 보기

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}