C++ 모듈을 만드는 법은 알았는데 디버깅 하는 법을 알 수가 없었다.

내가 사용하고 있는 툴은 Visual Studio Code이다.
이 툴을 쓰게된 이유는 미국에 사는 친구가 요즘 Node.js가 미국에서 대세고 사용하는 툴은 주로 위에 것을 쓴다고 해서, 나도 그냥 썻다.
아톰이란 것도 있길래 살짝 고민했는데, 써보니 확실히 가볍고 좋은 것 같다.

저 툴을 사용하면  - Node.js설치하고 path설정후, 재부팅해주면 - 자동으로 .js 파일들은 디버깅이 가능하다.

근데 C++로 만든 .node 모듈 파일들은 디버깅을 할 수가 없었다.
솔직히 그냥 printf가 콘솔로 출력 되면 그걸로 디버깅 하려 했지만... 되지 않았다.
그래서 디버깅을 하기 위한 여행을 떠났다.

최초로 참고한 자료는 아래의 싸이트 이다.
https://computer-vision-talks.com/how-to-debug-nodejs-addons-in-visual-studio/

How to debug node.js addons in Visual Studio

While working on CloudCV I encountered problems in node.js addon written in native code. For CloudCV I use node.js with C++ Addon to separate high-performance algorithms (C++) from high-level networking API which node provides. In this tutorial I’m going to reveal best practices on debugging C

computer-vision-talks.com


동영상도 있고, 어떻게 디버깅을 할수 있는지 자세히 적혀 있다.
반나절 넘게 끙끙거리면서 결국 성공했다.
하지만 문제점들이 있다.

1. 내가 사용 하는 Visual Studio Code가 아닌 Visual Studio 2013을 기반으로 설명하고 있다. 그래서 개발 환경을 바꿔야 했다.
     - 사실 이건 그렇게 큰 문제는 아니였다.

2. 기존에는 커맨드 창에서 node-gyp를 이용해서 컴파일을 했는데, 이 컴파일 과정에서 비쥬얼 스튜디오 2013을 동작시키고 있으면, 파일 엑세스 에러가 걸려서 컴파일이 안된다. 
     - 어떤 파일인지는 정확히 기억이 안나지만, 파일 하나를 비쥬얼 스튜디오 2013이 점유 하고 있는데 이놈때문에 컴파일 중에 에러가 난다. 그래서 매번 컴파일할 때 마다, 비쥬얼 스튜디오를 끄고 켜고를 반복해야 했다. 이러면 개발이 불가능은 아니지만, 열받아서 능률이 떠러진다.

3. 이 문제가 가장큰 문제인데, node-gyp를 통해 컴파일을 하고 나면 프로젝트 설정이 초기화 됐다. 굉장히 중요한 문제이니 잘읽어 보자.

- 우선 node-gyp가 사용 하는 컴파일러는 비쥬얼 스튜디오에서 사용하는 컴파일러와 동일하다.
- 어디에 확실히 그렇다고 쓰여있는 것을 보지는 않았는데.. node-gyp환경 구성을 보면 파이썬과, 비쥬얼 스튜디오 컴파일 환경이 필요 한데. 그곳에서 유추 할 수 있다. 
- 또한 디버깅용으로 컴파일하고 나면 binding.sln 파일이 생기는데, 이것은 비쥬얼 스튜디오 프로젝트를 생성하면 나오는 파일과 동일 하다. 
- 위에 참고한 사이트를 보면, binding.sln 파일을 비쥬얼 스튜디오 2013을 통해 열어서, 이런 저런 설정(좀있다 자세히 이야기 하겠다.)을 하는데 그 설정을 해야만 디버깅이 가능하다.
-근데 문제는 다시 node-gyp를 통해 컴파일을 하고 나면, 해놨던 설정들이 전부 원래대로 돌아간다.
-즉 매 컴파일 마다 설정을 다시해줘야 한다.

결론은 위 방법을 이용하면, 디버깅은 가능하다. 하지만 개발용 디버깅을 사실상 불가능 하다.


그래서 나는 Visual Studio Code를 통해서 컴파일도 하고, 디버깅을 할 수 있도록 도전해 봤다. 사실 printf만 콘솔창에 나왔어도 나는 안했을 것이다. 내가 만들려는 모듈은 아주 작은 모듈인데.. 배보다 배꼽이 큰 상황이다.

위 과정을 통해 알게된 사실들을 나열한다.

1. node-gyp에서 사용하는 컴파일러는 비쥬얼 스튜디오 환경에서 사용하는 C++ 컴파일러와 동일하다.

2. .node파일(node.js addon 파일)은 동적 라이브러리 파일 .dll과 동일하다. 때문에 C++ 디버거로 디버깅이 가능하다.

3.디버깅을 할때 사용하는 디버거는 (로컬 Windows 디버거)이다.

4. 디버깅을 실행 할때, '디버거를 설정 하는 부분'과, '디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지' 두가지를 설정 해야 한다.

5. 디버깅을 하기위해 프로그램 실행하는 방법은 아래 그림과 같이.
   - 명령어  : 프로그램을 실행시킬 프로그램 (C:\경로\node.exe)
   - 명령인수(인자)  :  처음으로 시작하는 js 파일 (app.js)
   - 작업 디렉터리 :  sln파일이 있는 곳에서 한 경로 위쪽 (..)
등등을 설정 해야 하는구나.

디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지 설정


위에 나열한 내용을 토대로 문제를 풀어 갔다.

자 같이 문제를 풀어 보자.

우선 아까 이야기한 사이트
https://computer-vision-talks.com/how-to-debug-nodejs-addons-in-visual-studio/
의 내용을 토대로 진행했으니, 이곳에서 하라는 순서를 기반으로 이야기하겠다.

시작전

1. node-gyp를 설치하세요
    npm install -g node-gyp

- 위에 명령어 하나로 해결되면 좋은데.. 나는 그리 안됐다.
https://oj-tube.tistory.com/entry/Nodejs-C-%EB%AA%A8%EB%93%88-%EC%A0%9C%EC%9E%91-%ED%95%98%EA%B8%B0 를 참고하면 해결 가능하다.

Node.js C++ 모듈 제작 하기

C++ 언어로 모듈을 제작해서 간단한 출력을 하는 것 까지의 내용이다. 그 이후에 진행 되는 내용들이 있지...

blog.naver.com



2. nan을 설치하세요
npm install -g nan

nan은 모듈 개발 API인데 내가 진행할 예제는 필요없다.
하지만 위에 사이트에서 사용한 예제는 nan을 사용했다.
이놈을 이용하면 좀 더 간편하게 모듈을 제작할수 있고, 이러 저러한 단점을 보안해놨다. 하지만 결론적으로 v8에 의존적이라 v8 버전이 바뀌면 다시 컴파일 해야한다는 문제는 해결하지 못했고, 그 것을 해결하기 위해 n-api라는 프로젝트가 현재 진행 중이다. 하지만 n-api를 사용해서 컴파일하면, 하직 시험적 단계라는 경고문이 뜬다. 아무튼 지금 신경쓸 단계는 아니다. 우리는 디버깅이 목적이다.


3. node.js 소스를 받아 debug 모드로 빌드 하세요.

이 과정이 필요한 이유는 디버깅하면서 내가 만든 모듈 외에 node.js 관련 소스 부분도 디버깅이 가능하기 때문이다. 근데 내가 해보니 꼭 이거 안해도, 내가 만든 모듈은 그냥 릴리즈용 node.exe에서도 가능했다.

소스를 받았던 사이트는.. 
https://nodejs.org/ko/download/

다운로드 | Node.js

최신 LTS 버전: 8.11.1 (includes npm 5.6.0) 플랫폼에 맞게 미리 빌드된 Node.js 인스톨러나 소스코드를 다운받아서 바로 개발을 시작하세요. LTS 대다수 사용자에게 추천 현재 버전 최신 기능 Windows Installer node-v8.11.1-x86.msi macOS Installer node-v8.11.1.pkg Source Code node-v8.11.1.tar.gz Windows Installer (.msi) 32-bit 64-bit Windows Binary (.zip) 32-bit 64-bi

nodejs.org

이고, 버전은 8.11을 받았다.
참고로 컴파일은 겁나게 쉽다.
진짜 내 컴파일 역사상 가장 쉬웠다.
windows에서 진행했는데.
그냥 tar.gz파일 받아서, 압축 풀고, vcbuild.bat 파일만 더블 클릭하면 컴파일이 된다.
단, 그냥 더블 클릭하면 릴리즈 모드로 컴파일 되니, 디버그 모드로 컴파일하고 싶으면 커맨드 창 하나 실행하고, 해당 디렉토리로가서 'vcbuild.bat debug' 라고 실행 하면 된다.
근데, 참고 사이트에서는 옵션 두개를 더 붙여서..
'vcbuild.bat debug nosign x64 ' 라고 실행 하라고한다.
옵션이 무엇을 의미하는지 읽어 봤는데. 잘 기억이 안난다. x64는 64bit용이고 nosign이 무엇이엇는지 기억이 잘 안난다.
그래서 다시 한번 읽어 봤다 -_-;
서명을 안한다는 건데.. 기본이 vcbuild는 nosign이라고 한다.
결론은 옵션 2개가 전부 그냥 디폴드 값이니깐, 안써도 무방하다.

'vcbuild.bat debug' 만 하면된다.

그렇게 실행하고 나면 10~30분정도 후에 '설치경로\Debug\node.exe' 파일이 생긴다.

실험 삼아 이놈을 실행하고, console.log("hello~~"); 해보니 잘된다.
릴리즈 node.exe가 아닌 디버깅 정보가 담긴 node.exe가 만들어 진것이다. 이제 이놈을 사용해서 디버깅을 해보자.
위에도 말했지만 릴리즈 node.exe를 사용해서 모듈 디버깅 잘된다.


- 자 이제 부터는 응용 파트이다. 위에서 얻어낸 모든 정보를 동원해 원하는것을 얻어 보자.

4. Visual Studio Code와 C/C++ extension 을 설치하자.

우선 Visual Studio code는 설치됐다고 믿는다.
https://code.visualstudio.com/  여기서 다운 받자.

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com


그리고 C/C++ extension을 설치하자.
https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools 이놈을 설치해야 하는데.
Visual Studio Code를 실행후 ctrl + shift + x 누르고, 검색에 C++ 하면
가장 위에 뜨는 놈이 우리가 설치해야할 C/C++ extension이다.
MS에서 제공하는 것이고 생긴 모양은 아래와 같다.

C/C++ Extension 생긴 모양


5. 우리가 컴파일할 코드를 구성하자.
전에 쓴 글 https://blog.naver.com/ojwojwoj/221266536930에 있는 예제에 변수 a선언 하고, printf로 찍어 보는 것만 추가 했다.

파일1 - app.js
const hangle = require('./build/Debug/hangleModule.node');
console.log(hangle.hello());

파일2 - hangleModule.cc

#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
char test[] = "test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf";
args.GetReturnValue().Set(String::NewFromUtf8(isolate,test ));
int a;
a=2;
printf("hello ??? %d\n",a);


}

void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

}

파일3 - binding.gyp

{
"targets": [
{
"target_name": "hangleModule",
"sources": [
"hangleModule.cc"
],
"include_dirs": ["<!(node -e \"require('nan')\")"#nan api사용시 추가. 지금은 사용안함
}
]
}





6. launch.json 파일을 구성하자.

이 파일은  위에서 언급한 '디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지'를 설정하는 부분과 비슷하다.

디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지 설정


이 정보를 통해 디버깅이 시작된다. 
어떤 디버거를 사용할지 등등을 설정하는 것이다.
이파일은 작업디렉토리에 .vscode 디렉토리 밑에 있어야한다.
이 파일과 .vscode디렉토리는 cc파일에서 f5를 눌러 디버깅을 할려고 하면, 자동으로 생성되고, 반드시 작성해야한다고 알려준다.

개 노가다 끝에 완성된 launch.json 파일은 이와 같다.

{
"version": "0.2.0",  //버전은 본인이 알아서 설정.
"configurations": [
{
"name": "C++ Launch (Windows)",  //그냥 이름이다. 
"type": "cppvsdbg",  //이거 정말 중요하다. 정말 정말
"request": "launch", //-_-; 실행하라는 거지뭐
"program": "C:\\ProjectWork\\NodeJsD\\Debug\\node.exe",  //디버깅할 대상을 실행 시킬 프로그램
// "program": "C:\\ProjectWork\\NodeJs\\node.exe",  //릴리즈 버전 node.exe
"args": [
"${workspaceRoot}\\app.js"    //node.exe app.js 이렇게 실행 시키기 위함.
],
"symbolSearchPath": "D:\\프로젝트\\18-스마트미러\\hangle\\build\\Debug",   //디버깅 정보가 담긴 파일(pdb) 위치 
"externalConsole": false,  //외부 콘솔을 사용할것인지?
"logging": { //로그 정보
"moduleLoad": true,
"trace": true
},
"cwd": "${workspaceRoot}"   //작업 드랙토리
}
]
}



위에 주석으로 대충 설명해놨는데 중요한것을 집고 넘어 가겠다.
program : 디버깅 시작시 어떤 프로그램으로 디버깅할 프로그램을 실행 시킬지 적는 부분이다. node.exe를 통해서 시작하면 된다. 우리가 위에서 진행한 디버그 버전 node.exe를 통해서 하면된다. 릴리즈용도 된다.

args : node.exe에 넘겨줄 인자다. app.js를 넘겨주면 되는데. 앞에 ${workspaceRoot} 라고 적은 이유는 처음에 내가 잘몰라서 cwd를 설정 안하고 컴파일을 했었는데.. app.js를 찾지 못하는 에러가 발생해서, 임시 방책으로 적어논것이다. 하지만 이제는 밑에 cwd를 설정 했기 떄문에 그냥 지우고 app.js만 써도 된다. ${workspaceRoot}는 현재 작업 디렉토리를 의미한다.

symbolSearchPath : 위에 적어 논대로 디버깅 정보가 담긴 파일(pdb)위치를 적으면 된다.

externalConsol : 디폴트 값이 true인데, 그렇게 되면 외부 콘솔창이 뜨고 거기서 node.exe가 실행된다. 그럼 종료 되면 획 사라지고, 또 환경 변수도 꼬이고 이런 저런 문제가 있길래 그냥 false로 했다, 그럼 visual studio code 디버그 콘솔창에서 콘솔 정보들을 볼수 있다. 그리고 printf 결과도 볼 수 있다.

cwd : 위에 언급한 그대로이다. 현재 작업 디렉토리 설정이다.

type: 우선 결론은 cppvsdbg라고 입력해야 하고, 이렇게 입력해야 디버거를 visual studio 2013에서 사용했던 디버거와 동일한 것을 사용한다.

저것을 몰라서 고생했는데. 그 이유는 다음과 같다.



1. 그냥 f5를 눌려서 생성되는 aunch.json 파일 기본들은 아래와 같다.
- 몇몇 세부 내용은 내가 채워 넣은것인데..
- type을 보면 기본으로 cppdbg로 설정되어있다.

{
// IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.
// 기존 특성에 대한 설명을 보려면 가리킵니다.
// 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요.
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "C:\\ProjectWork\\NodeJsD\\Debug\\node.exe",
"args": [
"app.js"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "/path/to/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}



type은 두가지가 가능한데.. 
cppdbg와 cppvsdbg이다.
cppvsdbg는 자동으로 비쥬얼 스튜디오 디버거를 찾아서 디버깅을 해주고,cppdbg 는 miDebuggerPath 설정을 통해 따로 디버거를 설정해줘야 한다.
내가 참고한 자료들은 전부 cppdbg  type을 사용했고, 디버거로는 mingw64를 설치해서 gdb를 이용했다.
나도 그렇게 진행했는데. 디버깅 실행까지는 됐는데..
디버깅 정보를 볼수는 없었다.

사실 당연한 것이었다.
- 디버깅 정보를 남긴 컴파일러는 비쥬얼 스튜디오에서 만든 것이고,
- 디버깅 정보를 통해 디버깅을 할려는 놈은 엉뚱한 gdb이니..
- 디버깅 정보가 gdb에서 사용하는 포맷과 다르니 ..
볼 수 없는 것이 당연한 것이다.

이 사실은 전에 같은 arm칩을 쓰더라도, armcc랑 gnu에서 만든 arm용 gcc랑 생성된 내용이 다르다는 것을 보고 알고 있었다.

만약에 .node를 만들때, gcc를 이용해서 만들었다면 gdb로 디버깅이 가능했을 것이다.
하지만 비쥬얼 스튜디오에서 제공하는 컴파일러를 이용했으니, 비쥬얼 스튜디오에서 제공하는 디버거를 이용해야만 했다.

난 그방법을 miDebuggerPath 에 로컬 윈도우 디버거 실행 파일을 지정하는 방식으로 해결하려 했다. 하지만 아무리 찾아도 윈도우 디버거 실행 파일을 찾지 못했고 포기하려고 했는데.

https://code.visualstudio.com/docs/languages/cpp 싸이트를 꼼꼼히 읽다보니 해결방법을 찾은 것이다.
type 부분이 미묘하게 달랐던 것..

아무튼 이래저래 그디어 디버깅에 성공 했다.

하지만, 컴파일을 매번 수동으로 하기 싫었는데. 

ctrl + shift + b 를 누르면 자동으로 컴파일 되는 방법이 있었다.


7. tasks.json 파일을 구성하자.

컴파일시 참조 하는 json 파일이고 이놈도 .vscode 디렉토리 밑에 있어야 한다.

이런 저런 방법이 있을텐데..
나는 아래와 같이 작성 해서 성공 했다.


{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"windows": {
"command": "./build.bat"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}



원래는 windows 안에 command가 아니고
그냥 밖에 command가 있고,
args에 인자를 넣는 형태인데.
그냥 build.bat 파일을 하나 만들고 필요한 내용을 다 때려 박고,
그 파일을 실행하는 형태로 바꿨다.

원래는 이런 형태다. (형태만 참조 할것)

{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"command": "g++",  //컴파일러
"args": [ // 넘길 인자들
"-g",  
"helloworld.cpp"
]
}
]
}


아무튼 build.bat 파일엔 다음과 같이 썼다.

set npm_config_node_gyp=C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug


npm_config_node_gyp과 PYTHON 변수 설정은 실행 하는 커맨드 창이 비쥬얼 스튜디오 code여서 적용이 안되있길래, 다시 해준것이고 (안하면 컴파일 안됨)

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug 

가 컴파일 하는 명령어이다.

아마도, pm_config_node_gyp과 PYTHON 변수 설정은 환경 변수 설정에서 해주면 전체 적용 되기 때문에 따로 안해도 될것 같고..

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug  는

위에
"command": "g++",  //컴파일러
"args": [ // 넘길 인자들
"-g",  

를 잘 이용하면 별도의 bat 파일은 안 만들어도 될것 같다.
우선 나는 이것도 충분히 괜찮아서 더이상 진행은 안했는데.
bat 파일 만들기 싫으신 분은 끙끙해 보고 성공 여부를 알려주면 좋겠다.

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug에 대해서 조금 설명하자면

--debug를 붙여야 디버깅 정보를 남긴 node 파일이 만들어지고,
--nodedir를 설정해주면 node.exe에 관련된 정보를 디버깅 할때, 소스 까지 디버깅이 가능해진다.

처음 언급한 사이트에서는 
What is really important here, is --nodedir="c:\Develop\node-v0.12.0" flag, which indicates to link against node in specified folder rather than system wide available.
라고 말한다.

아무튼 위 bat 파일을 만들고, 바로 실행 할수 있게 작업 디렉토리에 넣어 둔다.

그리고 ctrl + shift + b 를 누르면 bat파일이 실행 되면서 컴파일이 된다.

 

Visual Studio Code에서 gyp-node 컴파일 하는 장면



8. 디버깅을 해보자.

 f5를 누르면 디버깅이 가능하다.

디버깅 장면

브레이크 포인트도 잘 동작하고, 변수 내용도 잘 보인고.. 호출 스택도 보인다.

이제 원하는 모든 것을 이뤄냈다!
이제 개발만 하면된다.

- 한계점
js 파일들은.. 디버깅이 안된다. ㅠ.ㅠ
js파일일땐 node.js용 디버거가! cc파일일때 비쥬얼 스튜디어 디버거가! 동작하면 좋겠는데.. 그건 안된다.
따로 따로 디버깅을 해야한다는 단점이 있다.


- 맺으며
내가 잘 못찾아서 그런지.. 어디에도 visual studio code를 이용한 node.js  C++ 모듈 디버깅하는 법이 없어서, 글을 작성했다.

사실 누가 보겠냐만은.. 내가 본다.
기록하지 않은 내용은 몇달있으면 암것도 기억이 안난다.


옜날에 면접 볼때 면접관이 한말이 기억난다.

면접관 : 이건 어떻게 만드셨나요? 

나 : 대충 이렇게 이렇게 만들었는데.. 정확히 기억이 안나네요. 제 프로젝트 노트에 적어 놨는데...

면접관 : 그럼 이건요?

나 : 이렇게 저렁게 이렇게요.. 근데 디테일한건 기억이 기억이 잘.. 제가 만든건 맞는데.. 그것도 적어 놧어요..

면접관 : 아니 전부 까먹나요?

나 : ...그러게요 근데 제가 만든거 맞아요. 그때 엄청 고민해서 만들었어요. 지금 3년째 문제 없이 잘 돌아가고 있어요.

면접관 : ㅡㅡ+ (눈초리)

좀 억울했다. 누가 그걸 다 기억한단 말인가 ㅠ.ㅠ
그런데 있나 보다 ㅠ.ㅠ
나는 못하니 적자.

 

'개발 > Node.JS' 카테고리의 다른 글

비슷한 문자 찾아내는 Node.js C++ 모듈  (0) 2020.02.07
Node.js C++ 모듈 제작 하기  (0) 2020.02.07

C++ 언어로 모듈을 제작해서 간단한 출력을 하는 것 까지의 내용이다.

그 이후에 진행 되는 내용들이 있지만, 딱 위의 내용까지만 서술한다.

우선, Node.js는 알다시피 자바스크립트 언어를 사용한다.

편하지만 느리다는 단점이 있는데, C++ 모듈을 만들어서 그 모듈을 가져다 사용 하면 속도가 상당히 빨라진다.

그래서 사용한다고 한다.

내가 사용한 이유는 String을 bit연산도 하고..

byte 단위로 뿌셔서 검색하는 기능을 만들어야 하는데..

자바스크립트로는 자유롭게 그런 기능을 할 줄도 모르고..

할수도 없는 것 같아서, 이런 방법을 사용했다.

우선 C++를 모듈을 제작한다는 것은,

windows의 dll과 비슷하고,

linux에서는 so와 비슷하다고 생각하면 된다.

이미 이 글을 읽는 사람은 어느 정도 아는 사람이 분명하니, 자세한것은 생략 하겠다.

jni도 그렇듯이.. 네이티브 코드랑 어떤 다른 언어를 연결할 때는 항상 크로스 컴파일러가 필요하고 특정 규칙대로 코드를 짜야하는데..

이럴때 사용 하는 도구가 node-gyp이다.

저 node-gyp를 이용해서, .node확장자를 가진 모듈을 만들고 나면,

그 모듈을 node-js에서 불러다 써야 하는데..

불러다 쓰는 기능을 해주는 모듈이

node-bindings이다.

자 설치하자.

1. 우선 node-gyp를 설치하자

windows cmd 창으로 가자. 참고로 앞으로 하는 작업은 전부 관리자 권한으로 실행된 cmd 창에서 진행 하자. 관리자 권한을 요구하는 경우가 있다.

npm install node-gyp -g

이러면 글로벌로 설치되서 어디서든 node-gyp 명령을 내릴 수 있다.

2. 그다음은 node-bindings를 설치하자.

근데 이놈은 글로벌로 설치하지말고, 특정 프로젝트 폴더에서만 사용하도록 설치한다.

프로젝트 폴더로 이동하자.

npm install bindings --save

위 명령을 내리자..

내가 참고한 글에서는 node-bindings를 설치하라고 되어 있었는데..

안되서 해당 싸이트로 가서 글을 읽어보니 bindings로 바뀐 것 같다.

아무튼 설치 한후에.

이제 코딩을 하자.

3. binding.gyp 파일 만들기

node-gyp는 빌드 전에 configure를 한번 해야 하는데.

configure때 사용하는 파일이 binding.gyp이다.

위파일을 프로젝트 폴더에 만들고,

아래 내용을 적어 보자!

{

"targets": [

{

"target_name": "hangleModule",

"sources": [ "hangleModule.cc" ],

}

]

}

내가 만들 파일은 hangleModule.cc이다.

타겟 네임에 따라 .node 파일이 만들어 진다.

나같은 오류를 겪지는 안겠지만..

나는 위의 기본 폼을 ctrl + c , ctrl +v 했는데.

" 기호가 ”라는 기호로 복사가 되서 문법 에러가 났다..

둘이 가만히 보면 차이점을 찾아 내기가 쉽지 않다..

그나마 전에 이런 경험이 있어서 금방 찾기는 했다.

4. 모듈 파일 코딩하기.

우선 지금의 목적은 hello world를 출력해서 화면에 보는것이다.

그러니 코드를 너무 이해하려고 하지는 말자.

#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;

using v8::Isolate;

using v8::Local;

using v8::Object;

using v8::String;

using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {

Isolate* isolate = args.GetIsolate();

char test[] = "test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf";

args.GetReturnValue().Set(String::NewFromUtf8(isolate,test ));

}

void init(Local<Object> exports) {

NODE_SET_METHOD(exports, "hello", Method);

}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

} // namespace demo

우선 핵심만 간단히 보자면,

NODE_MODULE 로 모듈을 외부에 선언 하는 것인데 이 선언 문이 있어야만, 외부에서 가져다 쓸수 있다. 그리고 이 선언문은 끝에 ;를 빼야한다.

그리고 그안에 넣는 init함수는 반드시

void Initialize(Local<Object> exports); 이런 형태를 띄어야 한다.

즉 Initialize이름은 바뀔수 있지만 리턴 형태나 인자 형태는 바뀌면 안된다.

그리고

저 함수안에..

void init(Local<Object> exports) {

NODE_SET_METHOD(exports, "hello", Method);

}

이런식으로 내가 제작한 함수를 모듈에 포함시킨다.

당연히 여러개도 포합 시킬수 있다.

이런 형태를 꼭 지켜줘야만 한다.

혹시 jni를 제작해 보거나 리눅스 드라이버를 제작해 봤다면 이해되는 부분일 것이다.

아무튼 그런 설명은 제외하고.. 어서 빨리 hello world를 찍자.

4. configure 하기

우선 프로젝트폴더로 가서

node-gyp configure 라고 명령을 내리면 된다.

하... 근데.. 이제 부터가 진짜 어렵다.

나는 windows 환경에서 이 작업을 진행 했는데..

왠만하면 리눅스에서 하는게 속편하다.

진짜 토나오도록 잘 안된다.

아무튼 나왔던 잇슈 사항을 하나씩 나열 하겠다.

우선 node-gyp라는 도구는 두가지 작업 환경을 구축해야하는데..

하나는 파이썬이고, 다른 하나는 비쥬얼스튜디오 이다.

안그러면, node-gyp를 실행하면 파이썬이 없다고 계속 오류를 내뿜는다.

그것도 영어라, 그냥 읽기도 싫은데.. 아무튼 그렇다.

에러 메세지가 대략 이렇다.

gyp ERR! configure error

gyp ERR! stack Error: Can't find Python executable "C:\Users\user\.windows-build-tools\python27\", you can set the PYTHON env variable.

gyp ERR! stack at PythonFinder.failNoPython

우선 이것을 해결하는 방법이 엄청 많은 것들이 있는데.

대표적으로

npm --add-python-to-path='true' --debug install --global windows-build-tools

위방법이다.

파이썬을 패쓰에 추가 하라는 것과, windows-build-tools를 설치하라는 명령어 인데.

위 명령어를 내리면 파이썬과, 비쥬얼스튜디오 2015 프레임웤이 설치된다.

더이상 저 메세지가 안나올 수도 있고 나올수도 있다.

나는 나왔다.

그래서 다음 방안으로 파이썬을 그냥 수동으로 설치했다.

절대 3.0 이상의 버전을 설치하면 안된다고 한다.

2.x 버전을 설치하라고 해서 2.7을 설치 했다.

그리고 나서 해봤는데도 에러는 사라지지 않았다.

그래서 "you can set the PYTHON env variable." 라는 메세지를 보고..

고급 설정으로가서 path 설정에서, PYTHON 패쓰를 잡고,

해봤는데 안된다..

모듈 뻑나서 Node.js다시 설치해보고.. 돌고 돌아 성공한 방법이..

커맨드 창에다가..

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

라고 명령을 내렸더니 해결됐다.

실행 파일까지 패쓰에 넣어서 PYTHON을 설정해주니 에러메세지가 사라졌다.

그리고..

node-gyp configure 라고 명령을 내렸다!!

하.. 또 다른 에러가 나온다.

-----------------------------------------------------------------------

if not defined npm_config_node_gyp (node "C:\ProjectWork\NodeJs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" ) else (node "C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin" )

module.js:549

throw err;

^

Error: Cannot find module 'C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin'

at Function.Module._resolveFilename (module.js:547:15)

at Function.Module._load (module.js:474:25)

at Function.Module.runMain (module.js:693:10)

at startup (bootstrap_node.js:188:16)

at bootstrap_node.js:609:3

-------------------------------------------------------------------------------

위에것을 해결하기위해.. npm_config_node_gyp 라는 놈을 열심히 설정해보고 구글링도 해봤는데. 영 답이 안나왔다.

아무튼 npm_config_node_gyp 를 설정하면 되는가 싶어서 설정 해봤더니.. 위에 else 부분에 내가 적용한 내용이 나온다는 것을 알아 냈다...

그래서 혹시나 하고..

set npm_config_node_gyp=C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js

라고 했더니 그뎌!! 동작했다!

역사적인 순간

 

5. build 하기

node-gyp build

명령을 내리면 된다.

나는 문법 적인 오류로 인해, 여러곳을 수정했다.

그리고 여기서 파이썬이 없다는 오류가 사실 났었는데.

그것은 위에 서술한.

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

이 방법으로 해결했다.

이 과정이 끝나면

프로젝트 폴더/build/Release/hangleModule.node

파일이 생긴다.

6. 실행하기.

나는 app.js 파일을 하나 만들었고..

그안에 코드 내용은...

const addon = require('./build/Release/hangleModule.node');

console.log(addon.hello());

이렇게 넣었다

그리고 결과..

test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf

라는 문구가 출력되었다.

hello wolrd를 출력해야하는데..

분노에 차서 그만 저런 문구가 출력되었다.

맺으며.

우선 여기까지 되면 모듈을 하나 만들고, 그 모듈에서 정의한 함수를 불러다 쓸 수 있는 기본이 된 것입니다.

그다음 이런 기능 관련된 API들이 있고, 속도를 더 올리기 위한 모듈을 사용하는 부분도 있습니다.

그건 차차 하면 될 것 가고.. 저도 오늘은 위 코드를 쭉 봐보고.. 내가 한 것들이 무엇인지 정리하는 시간을 가져야 할 것 같습니다.

분명 제가 겪은 문제 말고도 다른 문제가 많을 것입니다.

구글과 함께 해결해 봅시다.

정말 첫 환경 구축은 몇년을 해도 너무 어렵습니다.

'개발 > Node.JS' 카테고리의 다른 글

비슷한 문자 찾아내는 Node.js C++ 모듈  (0) 2020.02.07
Node.js C++ 모듈 디버깅하는 법  (0) 2020.02.07

+ Recent posts