삽질하는플머

emscripten + cocos2d?

탐구생활/WEB 관련

취미로 cocos2d를 UI 엔진으로 쓰고 뼈대는 opengl es를 사용하는 삽질을 하고 있다. 

opengl 코드를 디버깅/웹퍼블리싱 하려고 GLFW를 버무리는 방법은 지난번에 정리 해 두었는데...

 

Emscripten 가지고 놀기 1. (feat. CodeLite)

Emscripten 가지고 놀기 2. (feat. GLFW, ZLib) 

Emscripten 가지고 놀기 3. (feat. event.c) 

 

 

이걸로 테스트삼아 웹버전 퍼즐 편집기를 만들었더니 

https://oranke.github.io/pharaoh-editor/

https://github.com/oranke/pharaoh-editor

 

모바일 브라우저에서는 전혀 동작하지 않는다. 터치관련 리스너가 구현되지 않았더라는...

 

어찌어찌 GLFW 를 수정해 돌아가게 했었고, 혼자 쓰기 아까워 PR을 보냈더니 오늘 머지되었다. 
https://github.com/emscripten-core/emscripten/pull/10428

 

삽질은 길어도 코드는 짧은데 AUTHORS 에도 기록해주네. (되게 기분 좋음) 

https://github.com/emscripten-core/emscripten/blob/master/AUTHORS#L458

 

 

아무튼 PR 보내느라 emscripten 최신 버전을 내려받아 잠시 돌려보았는데, 눈이 커지는 정보가 보인다. 

 

$ emcc --show-ports 
Available ports: 
    Boost headers v1.70.0 (USE_BOOST_HEADERS=1; Boost license) 
    icu (USE_ICU=1; Unicode License) 
    zlib (USE_ZLIB=1; zlib license) 
    bzip2 (USE_BZIP2=1; BSD license) 
    libjpeg (USE_LIBJPEG=1; BSD license) 
    libpng (USE_LIBPNG=1; zlib license) 
    SDL2 (USE_SDL=2; zlib license) 
    SDL2_image (USE_SDL_IMAGE=2; zlib license) 
    SDL2_gfx (zlib license) 
    ogg (USE_OGG=1; zlib license) 
    vorbis (USE_VORBIS=1; zlib license) 
    SDL2_mixer (USE_SDL_MIXER=2; zlib license) 
    bullet (USE_BULLET=1; zlib license) 
    freetype (USE_FREETYPE=1; freetype license) 
    harfbuzz (USE_HARFBUZZ=1; MIT license) 
    SDL2_ttf (USE_SDL_TTF=2; zlib license) 
    SDL2_net (zlib license) 
    cocos2d 
    regal (USE_REGAL=1; Regal license)

 

저게뭐야? 코코스가 포팅되어있었네??

 

레포지토리는 여기. 

https://github.com/emscripten-ports/Cocos2d

 

3.0 alpha 버전 기준이라고 한다. 2017년이면 한참 가지고 놀던 시점인데 왜 몰랐을까. 

다른건 몰라도 씬과 액션관리는 배울게 참 많은 엔진인데 ...

 

일단 킵 해두고 다음에 여유될 때 파보기로 함. 

 

Ubuntu + MySQL 에서 셸 커맨드 사용

탐구생활/WEB 관련

우분투 16.04 + MySQL 에서 특정 데이터가 입력될 경우 셸 커맨드를 돌려야 할 상황이 생겼다. 
오늘 요리재료는 이럴 때 안성마춤인 lib_mysqludf_sys 되시겠다. 


깃허브 링크: https://github.com/mysqludf/lib_mysqludf_sys 


먼저 MySQL 에서 플러그인 경로를 확인하자. 


mysql> show variables like 'plugin_dir';


+---------------+------------------------+

| Variable_name | Value                  |

+---------------+------------------------+

| plugin_dir    | /usr/lib/mysql/plugin/ |

+---------------+------------------------+




UDF 소스를 내려받고.  


$ git clone https://github.com/mysqludf/lib_mysqludf_sys.git

$ cd lib_mysqludf_sys/



포함된 Makefile 을 참조해 빌드 테스트. -fPIC을 주라는 에러가 나오니 그대로 따른다. 

$ sudo apt-get install libmysqlclient-dev
$ gcc -Wall -I/usr/include/mysql -I. -fPIC  -shared lib_mysqludf_sys.c -o lib_mysqludf_sys.so


빌드 확인한 뒤, Makefile 수정. 

Makefile 

LIBDIR=/usr/lib/mysql/plugin

install:
        gcc -Wall -I/usr/include/mysql -I. -fPIC -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so



빌드 및 설치


$ sudo ./install.sh



MySQL 실행 후 테스트. 


mysql> select sys_exec('touch /tmp/test_mysql') ;

+-----------------------------------+

| sys_exec('touch /tmp/test_mysql') |

+-----------------------------------+

|                             32512 |

+-----------------------------------+

1 row in set (0.01 sec)



내부적으로 sys() 함수를 사용하는데 왠 31512 에러... 역시 한 번에 되는 건 하나도 없군. 


구글께 여쭈니 apparmor 에서 UDF 실행을 막는다는 신탁을 내려주심. 

https://www.cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands/



먼저 apparmor 의 상태를 확인. 


$ sudo apparmor_status


apparmor module is loaded.

16 profiles are loaded.

16 profiles are in enforce mode.

......

   /usr/sbin/mysqld

...



mysqld 를 대상에서 제거


$ sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/

$ sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld


# 상태 다시 확인

# sudo apparmor_status



apparmor 와 mysql 재구동


$ sudo /etc/init.d/mysql restart

$ sudo /etc/init.d/apparmor restart



MySQL 에서 sys_exe() 재시도


mysql> select sys_exec('touch /tmp/test_mysql');

+-----------------------------------+

| sys_exec('touch /tmp/test_mysql') |

+-----------------------------------+

|                                 0 |

+-----------------------------------+

1 row in set (0.01 sec)



/tmp 에 생성된 파일 확인. 


$ ll /tmp

total ...

drwxrwxrwt 13 root    root    4096 Aug 20 22:38 ./

drwxr-xr-x 24 root    root    4096 Jul  6 14:40 ../

-rw-r-----  1 mysql   mysql      0 Aug 20 22:38 test_mysql

......



이제 트리거에서 외부 실행파일을 마음껏 실행시킬 수 있다.



참고링크

https://github.com/mysqludf/lib_mysqludf_sys

http://bernardodamele.blogspot.com/2009/01/command-execution-with-mysql-udf.html

https://www.cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands/


Emscripten 가지고 놀기 3. (feat. event.c)

탐구생활/WEB 관련

이전 글 


Emscripten 가지고 놀기 1. (feat. CodeLite)

Emscripten 가지고 놀기 2. (feat. GLFW, ZLib) 




이제 1편에서 만들었던 예제에 2편의 라이브러리들을 링크 해 보자. 

CodeLight 의 Project Settings 창을 열어 다음과 같이 설정해준다. 


타겟 

 Linker Options

 Libraries

 Debug, Release

 -framework OpenGL

 glfw;z

 Web

 -s USE_GLFW=3;-s FULL_ES2=1

 z







main.cpp 는 다음과 같이 만들어준다. 



#include <GLFW/glfw3.h>

#include <zlib.h>


#include <stdio.h>


int main(int argc, char **argv)

{

    printf("ZLib version: %s\n", zlibVersion());

    

    int major, minor, rev;

    glfwGetVersion(&major, &minor, &rev);

    printf("GLFW version: %d.%d.%d\n", major, minor, rev);

    

    return 0; 

}



실행시킨 결과는 다음과 같다. 




타겟을 Web 으로 바꿔서 빌드한 결과







GLFW의 event.c 는 베이스로 삼기에 참 좋은 예제라고 생각한다. 일부를 발췌해서 아래와 같이 만들어 보자. 

event.c 의 내용과 비교해 신경써야 할 부분은 다음 두가지이다. 


1. 윈도 생성시 OpenGL ES 2.0 을 지정. 

2 루프문 처리에 emscripten_set_main_loop() 함수를 사용. 


이렇게 Emscripten에서 다르게 처리해야 하는 부분은 "#ifdef EMSCRIPTEN" 으로 묶여있으니 참고하자. 



main.cpp





Func.cpp





Debug 빌드 테스트




Web 빌드 테스트








Emscripten 에 대해 수박 겉핥기로 간단히 가지고 놀아 보았다. 

생성된 JS 파일을 열어보면 그럭저럭 읽을만 하다. 

여기까지는 로컬파일에서도 테스트가 되지만 "-O2" 이상의 최적화 옵션을 주면 asm.js 로 빌드되고 웹서버가 필요하다. 

(파이썬의 SimpleHTTPServer 추천)

"-s WASM=1" 을 추가해 요즈음 핫한 웹어셈블리도 만들어 볼 수 있으니... 모쪼록 즐거운 삽질이 되시기를...






2019.6.12.


$emcc --show-ports


Available ports:

zlib (USE_ZLIB=1; zlib license)

libpng (USE_LIBPNG=1; zlib license)

SDL2 (USE_SDL=2; zlib license)

SDL2_image (USE_SDL_IMAGE=2; zlib license)

ogg (USE_OGG=1; zlib license)

vorbis (USE_VORBIS=1; zlib license)

bullet (USE_BULLET=1; zlib license)

freetype (USE_FREETYPE=1; freetype license)

......


zlib 같은 유명한 엔진은 이미 emscripten 로 포팅되어 있음.
저 삽질은 기본 지원하지 않는 라이브러리 적용시에나 유효할 듯. 






Emscripten 가지고 놀기 2. (feat. GLFW, ZLib)

탐구생활/WEB 관련

이전 글 Emscripten 가지고 놀기 1. (feat. CodeLite)  에서 연결됨. 


OpenGL은 말 그대로 그래픽 라이브러리에 대한 표준이고 어떤 플랫폼에서건 일관적인 사용을 보장하지만

막상 이 컨텍스트를 띄우려면 윈도에서는 wgl, 모바일에서는 egl 을 써야 하는 등, 플랫폼마다 조금씩 다른 처리가 필요하다. 

GLFW는 이런 잔처리를 도와서 손발을 편안하게 해 주는 물건이다. 


Emscripten 환경에는 이 GLFW3 이 포팅되어있고 "-s USE_GLFW=3" 링크옵션으로 활성화 시킬 수 있다. 

따라서 네이티브 환경에서 GLFW를 사용해 OpenGL 윈도를 생성하고 화면을 그려주면, 큰 변환 없이 웹에서도 동작시킬 수 있게 된다. 

문서상에는 셰이더 없이 glBegin() ~ glEnd() 도 지원한다고 되어있기는 한데... 예전 1.25 버전에서 삽질하다가 진작에 포기했다. 

그냥 속 편하게 OpenGL ES 2.0 기반으로 작업하는 것을 추천한다.  


이번 포스팅에서는 네이티브 환경에 GLFW를, Emscripten 환경에는 zlib 를 추가하는 방법을 정리해 보자. 



작업을 편하게 하기 위해 wget을 설치한다. 먼저 rudix 설치.



 $ curl -O https://raw.githubusercontent.com/rudix-mac/rpm/2016.12.13/rudix.py

 $ sudo python rudix.py install rudix





wrget 설치



 $ sudo rudix install wget








glfw 빌드. 소스 다운받고 빌드 디렉토리 준비. 



 $ wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip --no-check-certificate

 $ unzip glfw-3.2.1.zip

 $ cd glfw-3.2.1

 $ mkdir build

 $ cd build




CMAKE를 실행 후 Conrigure 에서 "Unix Make" 선택하고 붉은 마킹이 사라지도록 설정을 아래와 같이 변경 후 Configure 실행. 

완료 후 Generate 버튼을 눌러준다. 





빌드 시작. 



 $ make




빌드된 라이브러리는 build/src 에, 예제는 build/examples 에 만들어진다. 



 $ ls -l src/lib*

 -rwxr-xr-x  1 oranke  admin  127596  3 25 11:23 src/libglfw.3.2.dylib

 lrwxr-xr-x  1 oranke  admin      17  3 25 11:23 src/libglfw.3.dylib -> libglfw.3.2.dylib

 lrwxr-xr-x  1 oranke  admin      15  3 25 11:23 src/libglfw.dylib -> libglfw.3.dylib





그냥 두고 써도 되겠지만, 개발을 편하게 하기 위해 인스톨. 



 $ sudo make install


........


[100%] Built target events

Install the project...

-- Install configuration: "Release"

-- Up-to-date: /usr/local/include/GLFW

-- Installing: /usr/local/include/GLFW/glfw3.h

-- Installing: /usr/local/include/GLFW/glfw3native.h

-- Installing: /usr/local/lib/cmake/glfw3/glfw3Config.cmake

-- Installing: /usr/local/lib/cmake/glfw3/glfw3ConfigVersion.cmake

-- Installing: /usr/local/lib/cmake/glfw3/glfw3Targets.cmake

-- Installing: /usr/local/lib/cmake/glfw3/glfw3Targets-release.cmake

-- Installing: /usr/local/lib/pkgconfig/glfw3.pc

-- Installing: /usr/local/lib/libglfw.3.2.dylib

-- Installing: /usr/local/lib/libglfw.3.dylib

-- Installing: /usr/local/lib/libglfw.dylib






zlib 빌드



 $ git clone https://github.com/madler/zlib.git

 $ cd zlib

 $ mkdir build
 $ cd build
 $ 
emcmake cmake  ..
 $ make




맥에서 빌드하고 있지만 생성되는 바이너리 파일의 확장자는 *.dylib가 아닌 *.so 이다. 

툴체인을 바꿔주는 역할을 emcmake 커맨드가 처리하는 듯 하다. 



 $ ls -l libz*

 -rw-r--r--  1 oranke  admin  208488  3 25 17:39 libz.a

 lrwxr-xr-x  1 oranke  admin       9  3 25 17:39 libz.so -> libz.so.1

 lrwxr-xr-x  1 oranke  admin      14  3 25 17:39 libz.so.1 -> libz.so.1.2.11

 -rw-r--r--  1 oranke  admin  183196  3 25 17:39 libz.so.1.2.11




이대로 써도 관계 없지만... 아무래도 편한게 좋으니 emscripten 환경에 설치되도록 하자. 



CMake-GUI 를 열어서, 설치위치를 /usr/local 이 아닌 /Volumes/Data/emsdk/emscripten/1.37.36/system/local 로 변경하고 다시 생성. 




 $ make install


......


[100%] Built target minigzip

Install the project...

-- Install configuration: ""

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/lib/libz.so.1.2.11

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/lib/libz.so.1

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/lib/libz.so

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/lib/libz.a

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/include/zconf.h

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/include/zlib.h

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/share/man/man3/zlib.3

-- Installing: /Volumes/Data/emsdk/emscripten/1.37.36/system/local/local/share/pkgconfig/zlib.pc







정리하면...


GLFW 는 이미 Emscripten 환경에 있지만 OSX 에 없으니 OSX 용으로 빌드. 

ZLib 는 OSX 에는 있지만 Emscripten 에는 없으므로 Emscripten 용으로 빌드 


한 삽질이 되시겠다. 



Emscripten 가지고 놀기 1. (feat. CodeLite)

탐구생활/WEB 관련

Emscripten 개발은... 가급적 모든 코딩과 테스트를 네이티브에서 진행한 뒤 빌드만 emcc를 사용하는 것이 편하다. 

때문에 네이티브 환경을 오갈 수 있는 쓸만한 IDE가 간절해진다. (Make 방식은 아무리 들여다봐도 정이 안 감...)


윈도에서 VS와 emscripten 을 버무려둔 환경은 github 에 몇 개 보긴 했는데... 

내가 코드를 이상하게 짜는건지 VS가 이런 저런 허용을 많이 해주는건지... 다른 플랫폼으로 옮길 때 항상 삽질을 많이 하게 된다. 

 

차선책으로 XCode 에 Emscripten 툴체인을 비벼주려 한동안 고민했는데... 지식이 얕다보니 성공하지 못했다. 

다 포기하고 예전에 썼던 Code::Blocks 를 간만에 찾아봤더니 OSX 용은 13.12 버전이 마지막...   

OSX 10.12 에서 돌렸더니 크래시가 나서 사용하기가 쉽지 않다. 무엇보다 모양도 별로고...


툴체인 변경이 쉬운 대안이 어디 없을까 뒤적이다가 CodeLite 가 눈에 띄었다. 

그런데 어? 이거 물건이다! 딱 이럴 때 쓰라고 만들어진 듯 하다!!



그래서 오늘 요리는 Emscripten 과 CodeLite 버무리기. 



Emscripten 을 가지고 놀려면 먼저 CMake 를 깔아줘야 한다. 설치방법을 간단히 정리 해 둔다. 

아래 사이트에서 OSX 배포판을 받아 Application 에 설치하고

http://www.cmake.org/download/


다음과 같이 루트권한으로 실행시킨다. 



 $ sudo /Applications/CMake.app/Contents/MacOS/CMake




GUI에서 Tools -> Install For Command Line Use 선택. 



버전 확인



 $ cmake --version


 cmake version 3.11.0-rc4










CodeLite 와의 연동 설명은 현 시점에서 최신버전인 Emscripten 1.37.36 을 기준으로 한다. 

Emscripten 의 설치방법은 http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html 참고 할 것. 

내 경우 설치 위치는 "/Volumes/Data/emsdk".





CodeLite 12.0.0 설치하고 (https://codelite.org/) "안녕 세상" 예제 준비. 





Setting -> Build Setting 에서 새 툴체인 선택.





적당한 이름을 주고 GCC에서 설정을 복사. 





C++은 "em++", Archive는 "emar", 나머지는 "emcc", 쓰이지 않는 것은 모두 비운다. 






Build -> Configuration Manager 에서 Web 설정을 추가하고 ...


  



이 설정에 맞추어 예제 프로젝트에도 Web 구성을 추가한다. 




이렇게 나오게 만들면 완료. 





이제 워크스페이스의 구성에서 Web을 선택할 수 있다. 





프로젝트 우클릭 후 Settings 선택, Web 구성의 컴파일러 설정을 변경해준다. 

출력파일 확장자에 ".html" 을 덧붙여 주는 것을 빼먹지 말 것. 





WorkSpace 의 구성을 Web으로 변경하고 F7을 눌러 빌드. 





프로젝트 폴더 아래 "Web" 폴더 안에 *.html 파일이 생성된다. 





생성된 html 파일을 열어보면 "Hello World"가 예쁘게 출력되는 것을 볼 수 있다.




사실 얘는 껍데기고, 빌드된 결과물은 *.js 에 들어있다. node 로 돌려보면 다음과 같다. 





IDE가 좋은 것은 여러개의 소스를 한번에 비벼주기 편하다는 것이다. 

소스파일을 하나 더 추가해서 잘 되나 확인해보자. 



main.cpp

#include <stdio.h>


extern void TestFunc(); 


int main(int argc, char **argv)

{

    printf("hello world\n");

    TestFunc(); 

    return 0;




F7로 빌드하고 콘솔에서 찍어보면 잘 동작한다. 





일단 오늘은 여기까지. 

OpenGL 테스트를 위한 GLFW 버무리기는 다음 포스팅에서...