[NNStreamer] 첫 번째 미팅 정리
제일 먼저 기본적인 Building
에 대해서 설명해주셨습니다.
How to Build
basic terminology
build
란? compile
이란? link
란?
가장 기본적인 의미는 프로그래밍 언어
를 기계어
로 바꾸어주는 과정입니다. 먼저 C나 java 같은 native code
에서 (native/managed 코드의 자세한 구분은 후술) *.o
파일을 만드는 것을 컴파일
이라고 합니다. (이는 개발자가 작성한 소스코드를 binary code
로 변환하는 과정을 의미합니다.) 그리고 *.o
파일에서 .exe
파일을 만드는 것을 링크
라고 합니다. 기능별로 분할된 여러 개의 native code
들이 있을 때 각각을 *.o
파일로 컴파일 하고, 다수의 *.o
파일을 하나의 *.exe
파일을 만드는 것을 링크라고 하는 것입니다. 링크라고 부르는 것은 하나의 파일에서 다른 파일의 코드를 사용해야하는데 이를 가능하도록 연결
해주기 때문이라고 기억하면 됩니다. 컴파일
과 링크
를 합쳐서 실행가능한 파일을 만드는 과정을빌드
라고 부릅니다.
native code
란? :OS
에 의해서 직접적으로 컴파일 되는 코드를 의미합니다. 예를 들어서 C/C++ 입니다.managed code
란? : 구동을 시키기 위해서interpreter
라고 불리는 다른 프로그램이 반드시 요구되는 코드를 의미합니다. 예를 들어서 C#, java입니다.- 네이비브와 메니지드를 굳이 명확해서 구분해서 사용하는 것 같지는 않습니다.
make
란?
유닉스 계열의 운영체제에서 주로 사용되는 프로그램 build
도구입니다. 여러 파일들끼리의 의존성과 각 파일에 필요한 명령을 정의함으로써 프로그램을 compile
할 수 있으며 프로그램을 만들 수 있는 과정을 서술할 수 있는 표준적인 문법을 가지고 있습니다. 만약 build
도구 없이 IDE
를 통해서 build
하고 deploy
할 때 발생하는 가장 큰 문제는 해당 프로그램의 운영환경
이 배포자의 PC에 의해서 결정된다는 것입니다. make
를 실행하기 위해서는 어떻게 make
를 할 것인지 명시해 놓은 Makefile
이 필요합니다. ROS
에서 사용하는 make
와 android
에서 사용하는 gradle
이 build tool
의 한 종류입니다.
Makefile
이란?
make
을 실행하기 전에 프로젝트의 목록 및 compile
및link
규칙을 만들어야 합니다. 이러한 규칙들을 명시해놓은 파일을 만들고 이를 Makefile
이라고 부릅니다. 예를 들면 아래와 같은 형태입니다.
helloworld:
gcc main.c -o helloworld
install: helloworld
install -m 0755 helloworld /usr/local/bin
Configure
란?
configure
스크립트
는 개발 중인 프로그램을 각기 다른 수많은 컴퓨터들에서 실행할 수 있도록 도와주도록 설계된 실행 스크립트입니다. 소스 코드로부터 컴파일하기 직전에 사용자 컴퓨터의 라이브러리의 존재 여부를 확인하고 연결시켜줍니다. 즉, 각 개발자들의 개발 환경이 달라서 빌드를 잘 해야하는데 자세하게는 configure
스크립트를 잘 작성해야한다는 뜻이 됩니다. configure
를 사용하는 방법을 구체적으로 알 필요는 당장 없어보입니다. Cmake
가 이를 알아서 해주기 때문입니다.
Cmake
란?
Cmake
도 빌드 도구중 하나입니다. 정확히는 build system
에서 필요로하는 파일을 생성하는데 그 목적이 있습니다. 프로그램을 빌드하는데 있는 것이 아닙니다. Cmake
를 사용해 프로젝트를 관리하고자 한다면, 필요/의도에 맞게 CmakeLists.txt
파일을 배치해야 합니다. 일반적으로는 Root Cmake
파일을 두는 것이 편리합니다. 많은 경우 소스코드들은 폴더를 사용해 조직화되어 있으므로, 모든 프로젝트들이 재귀적으로 폴더 폴더 내에 CmakeLists.txt
를 두고 있으면 폴더 == 프로젝트
로 생각할 수 있게 됩니다. 이것이 무엇을 의미하는지는 아래에서 설명합니다.
먼저 폴더의 상태를 직관적으로 확인하기 위해서 tree
명령어를 사용해야합니다.
```bash
$ sudo apt install tree
```
원하는 폴더를 확인하면 그래프를 그려줍니다.
```bash
$ tree ./gst-docs
```
결과는 아래와 같은 모습이 됩니다.
```bash
├── scripts
│ ├── RELEASE_README.md
│ ├── generate_sitemap.py
│ └── release.py
├── sitemap.txt
└── theme
└── extra
├── css
│ └── extra_frontend.css
├── images
│ ├── api-reference.svg
```
재귀적으로 CmakeLists.txt
를 위치시키는 모습은 아래와 같을 것입니다.
$ tree ./small-project/
./small-project # Project root folder
├── CMakeLists.txt # <--- Root CMake
├── include # header files
│ └── ...
├── module1 # sub-project
│ ├── CMakeLists.txt
│ └── ...
├── module2 # sub-project
│ ├── CMakeLists.txt
│ └── ...
└── test # sub-project
├── CMakeLists.txt
└── ...
이처럼 CmakeLists.txt
를 재귀적으로 위치시키는 이유는 프로젝트가 커질 때 쉽게 관리하기 위해서입니다. 몇 천 줄, 몇 만 줄되는 프로젝트의 모든 libraries
정보를 확인해서 하나의 CmakeLists.txt
로 만드는 것은 어렵기도 하고 나중에 수정하기도 불편할 것입니다.
Cmake
가 알아서 Configure
를 해준다고 했습니다. Cmake
를 GUI
버전으로 설치했을 때를 기준으로 설명해보겠습니다. 한 번이라도 Cmake 프로그램을 본 적이 있는 사람이라면 다음의 설명이 이해가 될 것입니다. CMake
를 사용해서 CmakeLists.txt
를 생성하기 위해서는 source files
가 들어있는 디렉토리와 build
디렉토리를 지정해야합니다. 그리고 두 개의 버튼을 클릭합니다. 첫 번째는 Configure
, 두 번째는 generate
입니다. configure
버튼을 누르면 소스 코드로부터 컴파일하기 직전에 사용자 컴퓨터의 라이브러리의 존재 여부를 확인하고 연결시켜줍니다.
CmakeLists.txt
란?
왜 CmakeLists.txt
가 필요한지는 이해하셨을테니 어떻게 작성하는지만 보면 됩니다. 아래의 코드는 제가 ROS 프로젝트를 했을 때 사용했던 코드 중 일부를 가져왔습니다.
## 인클루드 디렉터리를 설정한다.
include_directories(${catkin_INCLUDE_DIRS})
## path_publisher 노드에 대한 빌드 옵션이다.
## 실행 파일, 타깃 링크 라이브러리, 추가 의존성 등을 설정한다.
add_executable(path_publisher src/path_publisher.cpp)
add_dependencies(path_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(path_publisher ${catkin_LIBRARIES})
## path_subscriber 노드에 대한 빌드 옵션이다.
add_executable(path_subscriber src/path_subscriber.cpp)
add_dependencies(path_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(path_subscriber ${catkin_LIBRARIES})
add_executable
을 통해서 어떤 native file
들을 object file
로 만들 것인지 정해줍니다. 그리고 add_dependencies
를 통해서 어떤 의존성을 추가할 것인지 결정합니다.
dependency
란?
여기에 굉장히 잘 설명되어 있습니다. 요약하자면,
- PACKAGE A가 PACKAGE B를
recommends
한다. = A를 사용하는 많은 사람들이 B없이는 A를 사용하지 않을 것이다. - PACKAGE A가 PACKAGE B를
suggests
한다. = B는 A의 기능과 관련된 파일들을 가지고 있으므로 B를 설치하는 것이 좋을 것이다.
dependency
는 include
이후에는 안쓰입니다. text segment
에 들어가는 데이터의 크기는 커져도 의존성에 구애받지 않게됩니다. 즉, 빌드할 때 필요한 static library를 말합니다.
run-time dependency
란?
위에서 설명한 dependency
는 build dependecy
에 대한 설명이었습니다. run-time dependency
는 DLL(Dynamic Linking Livrary)
의 super-set입니다. DLL
은 run-time dependency
집합의 원소라고 생각할 수 있으니, DLL
을 설명하면 run-time dependency
가 뭔지 조금 감을 잡으실 수 있으실 것 같습니다.
DLL
은 build dependecy
처럼 “$include$한 곳에 해당하는 코드를 복-붙해서 옮겨 적으세요.”라는 의미가 아닙니다. “나중에 사용할 때 그 때 해당하는 코드를 가져와서 읽을게요.”라는 의미입니다. 멘토님이 구멍을 뚫어놓는다고 하신 부분이 이를 말씀하신 것 같습니다.
Cmake로 빌드하는 방법
예를 들어서 프로젝트 디렉토리가 다음과 같다고 해보겠습니다.
MyCMakeProject
├── CMakeLists.txt
├── include
│ └── CMakeLists.txt
└── src
└── CMakeLists.txt
빌드 하는 방법은 MyCMakeProject 폴더, 즉 소스 코드 폴더에서 터미널에 다음과 같이 치면됩니다.
$ cd {source code directory}
$ mkdir build //디렉토리 생성
$ cd build //디렉토리로 이동
$ cmake .. //빌드에 필요한 각종 코드들이 생성
$ make //빌드
What are differeces between makefile
and CMakeLists.txt
?
makefile를 사용해서 make
할 수 있습니다. 또 CMakeLists.txt
를 사용해서 빌드를 할 수 있습니다. 뭐가 다를까요?
make
는 빌드 시스템입니다. 이것은 우리의 소스코드를 빌드하기 위해서 컴파일러과 다른 build tools를 drive합니다.Cmake
는 a generator of build system입니다. 같은CMakeLists.txt
를 사용해서makefiles
를 만들 수도 있고Ninja build files
를 만들 수도 있습니다. 혹은visual studio solution
을 만들 수도 있습니다. 이와 같은 이유로 위에서 $cmake ..$를 사용해서 빌드에 필요한 각종 코드(makefile)을 만들고 $make$를 했던 것입니다.
정리
제가 이전에 작성했던 포스팅에서 gcc의 정의를 설명했었습니다.
- gcc : The GNU Compiler Collection (GCC) is a collection of compilers and libraries for C, C++, Java, … etc. Many open source projects including the GNU tools and the Linux kernel are compiled with GCC.
이제는 멘토님께서 make
를 gcc
의 확장이라고 설명해주신 부분이 조금 이해가 되네요.
처음 들어본 terminology
pbuild란? chroot란?
pbuild
는 우분투 패키지 빌딩을 위한 chroot
환경을 제공합니다. chroot
란 change-root의 약자로 현재 실행 중인 프로세스와 child 프로세스 그룹에서 Root directory를 변경하는 작업을 말합니다. 이렇게 수정된 환경에서 실행되는 프로그램은 지정된 디렉터리 트리 밖의 파일들의 이름을 지정할 수 없으므로 chroot 감옥이라고 부르기도 합니다. clean chroot
환경은 어떤 dependency가 정말로 필요하고 missing되었는지 확인해주는 역할을 합니다.
debuild란?
debuild
는 Debian package
를 빌드하는 것을 의미합니다. 이는 debian package
를 upload하기 위한 모든 파일을 생성합니다. debian
은 데비안 프로젝트가 개발하는 O/S로, 우분투가 데비안에서 나온 운영체제입니다. 데비안과 우분투는 둘 다 APT를 이용하여 패키지를 관리하며, 인터넷에서 .deb 파일을 다운로드하여 직접 설치할 수 있습니다. 다만, 우분투에서는 우분투용으로 빌드하거나 데비안용으로 빌드한 .deb 파일을 둘 다 사용할 수 있습니다. 그러나 데비안에서는 우분투용으로 빌드한 .deb 파일은 사용할 수 없는 경우가 많습니다.
debuild
가 어떻게 동작하는지는 여기를 보면 이해할 수 있습니다.
pdebuild란?
pdebuild
란 debuild
을 진행하는 pbuilder
의 방법을 말합니다. 이는 pbuilder package
와 함께 쓰입니다.
meson이란?
meson에 대해서는 여기에서 따로 포스팅하였습니다.
아카이빙Archiving이란?
아카이브(archive)
는 역사적 가치 혹은 장기 보존의 가치를 가진 기록이나 문서들의 컬렉션을 의미하며, 동시에 이러한 기록이나 문서들을 보관하는 장소, 시설, 기관 등을 의미합니다.
export란?
멘토님께서 아래 명령어를 치라고 하셨는데 이것이 무엇인지 왜 하는지 알아보겠습니다. 저는 이 명령어를 ~/.bashrc의 가장 아래에 적어두면 terminal을 열 때마다 빌드를 하기 위한 환경이 잘 잡힌다고만 알고 있습니다.
$ export GST_PLUGIN_PATH=$(pwd)/gst/nnstreamer
$ export NNSTREAMER_CONF=$(pwd)/nnstreamer-test.ini
$ export NNSTREAMER_FILTERS=$(pwd)/ext/nnstreamer/tensor_filter
$ export NNSTREAMER_DECODERS=$(pwd)/ext/nnstreamer/tensor_decoder
export
는 bash shell의 BUILTIN commmands입니다. 일반적으로 export
command는 새로 fork
된 child 프로세스들이 어디에서 환경 변수를 찾을 수 있는지 mark하는 기능을 합니다. 즉, 이 명령을 사용하면 child process에서도 환경 변수를 사용할 수 있는 것입니다. terminal을 열 때마다 export를 해주어야 하는 것은 terminal의 chile process를 새롭게 create 했기 때문이라고 생각이 됩니다.
환경 변수
는 프로그램 밖에서 값이 설정된 변수를 의미합니다. 그리고 일반적으로 운영 체제 또는 마이크로 서비스에 내장 된 기능을 통해 제공됩니다.
Agile 방법론 & 지라Jira
Agile
을 한 마디로 표현하면 “협력과 피드백을 자주! 일찍! 더 잘하는 것!”입니다. 이를 위해서 Github에는 Issue 기능을 제공합니다. 이렇나 Issue들을 더 잘 관리할 수 있도록 하는 tool이 Jira
입니다. 사실 github의 Issue도 jira
를 밴치마킹한 것이라고 합니다.
GST_DEBUG-3??
디버깅 레벨을 지정해서 자세하게 디버그 보는 방법을 의미합니다. gstreamer pipeline을 .sh 파일로 저장하고 아래와 같이 실행하면 특정 레벨까지의 출력들을 보여줍니다.
$ GST_DEBUG=4 ./gst-image-segmentation.sh
*.a file
static libraries
는 Unix-like systems에서 Windows systems보다 더 흔하게 사용됩니다. Windows에서는 static libraies를 일반적으로 .a
대신에 .lib
를 사용합니다.
*.a
파일은 C/C++ source file에 의해서 참조될 수 있는 a library of functions 와 headers를 포함합니다. 몇몇 함수를 포함할 수도 있고 3D engine과 같은 대규모 라이브러리를 포함할 수도 있습니다.
NOTE: Using static libraries may result in larger program files, but enables faster loading times compared to dynamic libraries.
Plugin V.S. Library
이 둘의 주된 차이점은 다음과 같습니다.
- plugin : 어플리케이션의 사용성을 증가시키는 확장을 말합니다.
- library : class와 function의 집합으로서 S/W 개발을 돕는 역할을 합니다.
따라서 NNstreamer는 plug-in인 동시에 library입니다.
Signed off
git commit –amend -s : Signed-oFF 내가 나임을 증명하고 의정서? 보험가입할 때 무슨 일이 생겨도 나는 책임지지 않겠다. 라고 말하는 것.
commit이 겹치면 –force 옵션을 붙혀서 git push origin my_porked_repo
gst indent
nnstreamer/tools/deveoper의 gst-indent
사용해서 코드 컨벤션 체크하기
android 부분의 기여거리
자바 nnstreamer Api를 만들었는데 이게 앱으로 돌아가는지 확인하고 싶다.
terminal command
- apt : Advanced Packaging Tool의 ab.
- apt update : 모든 패키지의 최신 버전을 얻는다.
- rm -rf [file_name] : remove –recursive –force와 같은 뜻. 재귀적으로 삭제를 강제(하위 디렉토리에 파일이 있어도 삭제)한다.
- nm : object 파일들의 symbols들을 list로 보여준다.
- pwd : print working directory의 약어. 현재 디렉토리를 출력한다.
- man : command의 명령어를 보여준다. 이제 터미널 명령어 물어봐서 욕먹지 않도록 하자..
설치:$ sudo apt install man-db
사용 :
$ man nm
결과 :
NM(1) GNU Development Tools NM(1) NAME nm - list symbols from object files SYNOPSIS nm [-A|-o|--print-file-name] [-a|--debug-syms] [-B|--format=bsd] [-C|--demangle[=style]] [-D|--dynamic] [-fformat|--format=format] //생략
Reference
native code
v.s.managed code
설명