사용자 도구

사이트 도구


raylib:컴파일_및_makefile
컴파일 및 makefile

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
raylib:컴파일_및_makefile [2023/11/21 23:18] 이거니맨raylib:컴파일_및_makefile [2023/11/24 00:46] (현재) – 더 읽기 이거니맨
줄 122: 줄 122:
 ===== raylib 소스파일을 바꿔보기 ===== ===== raylib 소스파일을 바꿔보기 =====
  
-==== 다양한 비트맵 폰트를 써보기 ====+==== 1. 다양한 비트맵 폰트를 써보기 ====
  
 다음 파일을 다운 받자. 다음 파일을 다운 받자.
줄 143: 줄 143:
 그리고 폰트는 stb_image 등을 이용한다. 따라서 '/raylib/src/external' 등을 참조해 줘야 한다. 그리고 폰트는 stb_image 등을 이용한다. 따라서 '/raylib/src/external' 등을 참조해 줘야 한다.
  
-위와 같이 하여 컴파일 하면 한글이 다 안 보인다. +위와 같이 하여 컴파일 하면 컴파일은 잘 되는데 실행해보면 한글이 다 안 보인다. 
  
 raylib의 기본 비트맨 폰트 로더는 폰트 아틀라스를 하나만 로드하기 때문이다. 그렇다면 어떻게 해야 할까?  raylib의 기본 비트맨 폰트 로더는 폰트 아틀라스를 하나만 로드하기 때문이다. 그렇다면 어떻게 해야 할까? 
 +
 +==== 2. RAYLIB 소스파일 수정하기 ====
  
 'raylib/src'폴더에 가보면 rtext.c라는 파일이 있다.  'raylib/src'폴더에 가보면 rtext.c라는 파일이 있다. 
줄 158: 줄 160:
  
  
 +==== 3. raylib 재컴파일 ====
 +
 +이제 rtext.c를 고쳤으므로 libraylib.a라는 정적 라이브러리를 재컴파일 해줘야 한다.
 +
 +raylib/src 폴더에서 다시 한번 make 명령어를 넣자. 그러면 라이브러리가 재컴파일 된다. 
 +
 +
 +==== 4. 실행 파일 재컴파일 ==== 
 +
 +이제 다시 fontatlas폴더로 가서 
 +
 +<code>
 +gcc -o main  main.c  -Wall -std=c99 -Wno-missing-braces -Wunused-result    -L../raylib/src -lraylib -lgdi32 -lwinmm -lopengl32 -I../raylib/src -I../raylib/src/external -I'../raylib/utils'
 +</code>
 +
 +명령어를 수행하자. 
 +
 +그러면 [[raylib:util:raylib_loadbmfont_extender|Load BitmapFont Extender]] 에서 볼 수 있는 것과 같이. 다양한 한글이 제대로 나온다.
 +
 +이제 앞으로는 그냥 loadfont()함수만 쓰면 한글도 제대로 잘 나온다. 
 +
 +
 +===== Makefile 만들기 ===== 
 +
 +==== 1. 준비사항 ====
 +
 +makefile은 탭을 인식한다. 따라서 탭이 에디터에서 제대로 입력되게 준비할 필요가 있다.
 +
 +만약 VS 코드라면 아래 하단 상태표시줄에서 'tab 크기'를 클릭한 후에 '탭을 사용한 들여쓰기(Indent using tab)'으로 설정을 바꾸어 줘야 한다.
 +
 +관련 [[https://www.youtube.com/watch?v=MOdWPA07bMU|동영상]]을 참조하자. 
 +
 +
 +==== 2. Makefile 만들기 =====
 +
 +위의 멀티 아틀라스 소스에 대한 Makefile을 만든다고 해보자.
 +
 +하나의 소스만 컴파일 할 때에는 위와 같이 명령창에서 gcc 혹은 g++(c++로 만들 경우)로 명령어를 넣으면 되므로, 
 +
 +여러가지 소스 파일이 있는 대상 프로젝트를 선택하자. [[raylib:flappybird:다국어_지원하기|플래피 버드]]다국어 지원하기
 +
 +위 소스의 폴더에 'Makefile'이란 파일을 만들자. 만약 VS Code로 한다고 하면, 위와 같이 탭을 사용한 들여쓰기 설정을 해놓자.
 +
 +Makefile이 이미 있다면 지우고 새로 만들자. 
 +
 +=== 가. 최초 makefile ===
 +
 +<file makefile Makefile>
 +# Define required raylib variables
 +RAYLIB_PATH        ?= C:/raylib5/raylib/src
 +# Define compiler path on Windows
 +COMPILER_PATH      ?= C:/raylib/w64devkit/bin
 +# Build mode for project: DEBUG or RELEASE
 +BUILD_MODE            ?= RELEASE
 +
 +# Define default C compiler: gcc
 +# NOTE: define g++ compiler if using C++
 +CC = g++
 +
 +# Define default make program: Mingw32-make
 +MAKE = mingw32-make tetris
 +# Compile option
 +CFLAGS += -Wall -std=c++14 -D_DEFAULT_SOURCE -Wno-missing-braces 
 +
 +ifeq ($(BUILD_MODE),DEBUG)
 +    CFLAGS += -g -O0
 +else
 +    CFLAGS += -s -O1
 +endif
 +
 +# Define include paths for required headers
 +# NOTE: Several external required libraries (stb and others)
 +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH) -I$(RAYLIB_PATH)/external -I'/utils'
 +
 +# Define library paths containing required libs.
 +LDFLAGS = -L. -L$(RAYLIB_PATH)
 +
 +# Define any libraries required on linking
 +# if you want to link libraries (libname.so or libname.a), use the -lname
 +LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
 +
 +# Define all source files required
 +SRC_DIR = .
 +OBJ_DIR = obj
 +
 +#목적 파일 만들기
 +OBJS = $(OBJ_DIR)/buttonActionMap.o $(OBJ_DIR)/config.o $(OBJ_DIR)/gui.o $(OBJ_DIR)/logo.o $(OBJ_DIR)/game.o $(OBJ_DIR)/menu.o $(OBJ_DIR)/settingscreen.o $(OBJ_DIR)/main.o
 +
 +# Default target entry
 +# NOTE: We call this Makefile target or Makefile.Android target
 +all:
 + $(MAKE)
 +
 +$(OBJ_DIR)/buttonActionMap.o : buttonActionMap.h buttonActionMap.cpp 
 + $(CC)  -c buttonActionMap.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/config.o : config.h config.cpp
 + $(CC)  -c config.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/gui.o : gui.h gui.cpp
 + $(CC)   -c gui.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/logo.o : logo.h logo.cpp
 + $(CC)  -c logo.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/game.o : game.h game.cpp
 + $(CC) -c game.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/menu.o : menu.h menu.cpp
 + $(CC)  -c menu.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/settingscreen.o : settingscreen.h settingscreen.cpp
 + $(CC)   -c settingscreen.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +$(OBJ_DIR)/main.o : main.cpp
 + $(CC)  -c main.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +
 +#Icon file path
 +ICON += $(RAYLIB_PATH)/raylib.rc.data
 +
 +#컴파일
 +tetris : $(OBJS)
 + $(CC) $(CFLAGS)  $(OBJS) -o tetris $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) $(ICON)
 +</file>
 +
 +=== 나. 설명 ===
 +
 +== (가) raylib 라이브러리 == 
 +
 +우리는 libraylib.a 라는 라이브러리를 이용할 것이다. 따라서 이에 대한 경로를 지정해 줘야 한다.
 +
 +  RAYLIB_PATH        ?= C:/raylib5/raylib/src
 +
 +로 하여 경로를 지정해 주었다.
 +
 +== (나) 컴파일러 == 
 +
 +c로 작성한 파일은 gcc로 컴파일 하고, c++로 작성한 파일은 g++로 컴파일 한다.
 +따라서 컴파일러를 지정해 주어야 한다.
 +
 +  CC = g++
 +  
 +== (다) 디버그 모드/릴리스 모드 == 
 +
 +디버그 모드와 릴리스모드의 옵션을 설정해 준다. 다음과 같이 설정해주었다.
 +
 +<code>
 +ifeq ($(BUILD_MODE),DEBUG)
 +    CFLAGS += -g -O0
 +else
 +    CFLAGS += -s -O1
 +endif
 +</code> 
 +
 +== (라) 헤더파일과 라이브러리 ==
 +
 +헤어파일과 라이브러리를 각각 그 경로를 설정해주었다. 
 +
 +== (마) 목적 파일 만들기 ==
 +
 +각 소스파일들을 기계어로 만들어야 한다. 
 +
 +그런데 우리가 배치파일(혹은 리눅스에서는 쉘 파일)을 만들지 않고 이렇게 Makefile을 만드는 이유는 뭘까?
 +
 +Makefile을 만들면 이미 만들어진 목적파일은 생략하고 변경된 소스만 다시 목적파일로 만들어 주기 때문이다. 만약 배치파일로 만든다면 목적파일의 변경여부와 상관없이 매번 목적파일을 새롭게 만들것이다. 
 +
 +따라서 목적파일이 그대로 있어야만 한다. 그런데 목적파일이 내 소스파일과 섞이면 지저분하므로, 목적파일을 위한 디렉토리를 따로 만들어주자.
 +
 +파일탐색기로 'obj'란 디렉토리를 만들자.
 +
 +그리고 위의 소스에서 보는 바와 같이 각 목적파일은 'obj'라는 폴더 내부에서 목적 파일을 만드는 것이다. 하나만 따로 떼어서 살펴보자.
 +
 +<code>
 +$(OBJ_DIR)/buttonActionMap.o : buttonActionMap.h buttonActionMap.cpp 
 + $(CC)  -c buttonActionMap.cpp $(CFLAGS) $(INCLUDE_PATHS) -o $@
 +</code>
 +
 +콜론(:)의 왼쪽, 즉 목적파일로 만들어지는 것을 타켓파일이라고 하고 오른쪽에 있는 것을 의존파일이라고 한다. 
 +
 +의존파일을 이용하여 목적파일을 만드는 것이다.
 +
 +그런데 컴파일러(g++)에서 의존파일의 명칭을 바꾸려면 아웃풋을 뜻하는 -o 플래그 뒤에 그 의존파일의 전체 이름을 넣어야 한다. 
 +
 +우리의 경우 'obj'라는 폴더 아래에 'buttonActionMap.o'라는 목적 파일을 만들 것이다. 이는 'obj/buttonActionMap.o'라고 적을 수 있다.
 +
 +이렇게 -o 플래그 뒤에 만들어질 목적 파일의 명칭을 적어야 한다. 
 +
 +Makefile에서 타켓파일을 지정한느 매크로는 '$@'이다. 따라서 이를 이용하면 타켓파일을 두번 쓸 필요는 없다. 
 +
 +== (바) 아이콘 == 
 +
 +윈도우 환경에서 파일의 아이콘을 설정해줄 수도 있다. 우리는 아이콘을 다음과 같이 링크해 줬다.
 +
 +  ICON += $(RAYLIB_PATH)/raylib.rc.data
 +  
 +== (사) 컴파일 하기 == 
 +
 +이제 만들어진 목적파일들을 링크하여줘야 한다. 
 +
 +<code>
 +#컴파일
 +tetris : $(OBJS)
 + $(CC) $(CFLAGS)  $(OBJS) -o tetris $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) $(ICON)
 +</code>
 +
 +tetris라는 이름으로 목적파일들을 컴파일 해준다. 그런데 라이브러리의 링크를 지시하는 플래그들은 맨 뒤에 와야 한다. 
 +
 +따라서 '$(LDFLAGS) $(LDLIBS) $(ICON)'까지는 반드시 맨뒤에 와야 한다. 만약 그렇지 않으면 'undefined ...'하면서 컴파일러는 에러를 내뿜을 것이다. 
 +
 +
 +== (아) 메이크의 대상 지정하기 == 
 +
 +이렇게 Makefile을 만든 뒤에는 커맨드 창에서 'make' 명령어를 누르면 Makefile에 있는 매크로를 수행하면서 컴파일이 이루어진다.
 +
 +그런데 make는 지정된 타켓만 make를 한다. 우리는 최종적으로 tetris라는 실행파일을 만들 것인데, 
 +
 +이러한 최종 실행파일은 tetris라는 이름으로 타켓이 지정되어 있다. 
 +
 +따라서 'make tetris'를 해야만 최종 목표인 컴파일까지 한다. 
 +
 +만약 아무런 지정도 안 해주고 단순히 'make'만 누르면 제일 처음에 설정한 타겟인 'buttonActionMap'만 목적파일로 만들어진다.
 +
 +그런데 이렇게 매번 'make tetris'를 누르는 것도 귀찮기 마련이다. 그냥 'make'만 했으면 좋을것다.
 +
 +따라서 
 +
 +아예 
 +
 +<code>
 +# Define default make program: Mingw32-make
 +MAKE = mingw32-make tetris
 +</code>
 +
 +라고 하여 타겟 자체를 지정해 버리자. 
 +
 +그리고는 이렇게 코드를 짜면 모든 목적파일을 검토 한 후에 tetris라는 최종 파일을 만든다.
 +
 +<code>
 +all:
 + $(MAKE)
 +</code>
 +
 +이제 커맨드 창에서 단순하게 'make'만 누르면 프로젝트 전체의 컴파일이 된다. 
 +
 +
 +===== VS Code의 환경 설정하기 =====
 +
 +==== 1. task.json 설정하기 ==== 
 +
 +우리는 위 Makefile에서 딱 한가지 분기만 만들었다. 디버그와 릴리스 모드 분기다. 
 +
 +따라서 Makefile을 실행시키는 task.json에는 다른 인자들은 설정해 줄 필요 없고, 단지 하나, 디버그 모드에서는 
 +
 +  BUILD_MODE=DEBUG
 +  
 +를 넣어주면 된다. 굳이 이를 코드로 보여주면 다음과 같다.
 +
 +<file javascript task.json>
 +{
 +    "version": "2.0.0",
 +    "tasks": [
 +        {
 +            "label": "build debug",
 +            "type": "process",
 +            "command": "make",
 +            "args": [
 +                "BUILD_MODE=DEBUG"
 +            ],
 +            "windows": {
 +                "command": "C:/raylib/w64devkit/bin/mingw32-make.exe",
 +                "args": [
 +                    "BUILD_MODE=DEBUG"
 +                ]
 +            },
 +            "group": "build",
 +            "problemMatcher": [
 +                "$gcc"
 +            ]
 +        },
 +        {
 +            "label": "build release",
 +            "type": "process",
 +            "command": "make",
 +            "args": [    ],
 +            "windows": {
 +                "command": "C:/raylib/w64devkit/bin/mingw32-make.exe",
 +                "args": [    ]
 +            },
 +            "problemMatcher": [
 +                "$gcc"
 +            ],
 +            "group": {
 +                "kind": "build",
 +                "isDefault": false
 +            },
 +            "detail": "compiler: C:\\raylib\\w64devkit\\bin\\g++.exe"
 +        }
 +    ]
 +}
 +</file>
 +
 +==== 2. launch.json ==== 
 +
 +실행할 프로그램의 경로를 정확히 설정해 주면 된다. 
 +
 +우리는 tetris.exe 하나로만 실행파일을 만들 것이므로, 
 +
 +  "program": "${workspaceFolder}/tetris",
 +  
 +이렇게만 바꾸어 주면 된다.
 +
 +
 +==== 3. c_cpp_properties.json ==== 
 +
 +에디터가 인텔리센스를 보여줄 헤더의 위치를 설정해주는 것이다. 
 +
 +다음과 같이 해당 경로를 설정해 주면 된다.
 +
 +<code>
 +            "includePath": [
 +                "C:/raylib5/raylib/src/**",
 +                "${workspaceFolder}/**",
 +                "${workspaceFolder}/utils/**"
 +            ],
 +</code>
 +
 +===== 더 읽어보기 ===== 
 +
 +[[raylib:정적_라이브러리_만들기|C / C++  에서 정적라이브러리 만들기]]도 읽어보자
raylib/컴파일_및_makefile.1700576287.txt.gz · 마지막으로 수정됨: 2023/11/21 23:18 저자 이거니맨