# 35. 애플리케이션에서 사용할 간단한 라이브러리 생성

이번 장에서는 간단한 라이브러를 생성한다.

일반적으로 디렉토리는 아래 경로에 존재한다.

```
<Pkg Name>/Library/<Library Name>/               <---- inf and source files for the library (=library implementation)
<Pkg Name>/Include/Library/                      <---- library headers (=library interface)
```

먼저 `SimpleLibrary` 폴더를 만든다.

```
$ mkdir -p UefiLessonsPkg/Library/SimpleLibrary/
$ mkdir -p UefiLessonsPkg/Include/Library/
```

먼저 라이브러리를 위한 인터페이스인 헤더 파일을 작성한다. `SimpleLibrary`는 `number`를 받고 `number+2`를 반환하는 함수로 `Plus2`를 포함할 것이다.

따라서 헤더 파일을`UefiLessonsPkg/Include/Library/SimpleLibrary.h`에 생성하고 아래 내용으로 작성한다.

```c
UINTN Plus2(UINTN number);
```

라이브러리 구현하기 위해 `UefiLessonsPkg/Library/SimpleLibraray/SimpleLibrary.c`를 작성한다.

```c
#include <Library/SimpleLibrary.h>

UINTN Plus2(UINTN number) {
  return number+2;
}
```

정말 간단하게 라이브러리가 생성되었다.

이제 라이브러리에 대한 INF 파일을 생성해야 한다.\
`UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf`

```
[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = SimpleLibrary
  FILE_GUID                      = 826c8951-5bd2-4d72-a9d9-f7ab48684117
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  LIBRARY_CLASS                  = SimpleLibrary | UEFI_APPLICATION

[Sources]
  SimpleLibrary.c

[Packages]
  MdePkg/MdePkg.dec
```

작성한 `*.inf` 파일에서 중요한 것은 `LIBRARY_CLASS`이다.

```
LIBRARY_CLASS = SimpleLibrary | UEFI_APPLICATION
```

이 라이브러리는 `UEFI_APPLICATION` 유형의 모듈에서만 사용할 수 있다. 만약 `UEFI_APPLICATION` 대신 `DXE_DRIVER`로 하고 UEFI 애플리케이션 중 일부에 연결하려고 하면 빌드가 실패한다.

```
build.py...
/home/kostr/tiano/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 1001: Module type [UEFI_APPLICATION] is not supported by library instance [/home/kostr/tiano/edk2/UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf]
        consumed by [/home/kostr/tiano/edk2/UefiLessonsPkg/<path to your app inf file>]
```

이제 패키지 DSC 파일 `UefiLessonsPkg/UefiLessonsPkg.dsc`에 라이브러리를 포함해야 한다.

```
[Components]
  ...
  UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf
```

빌드를 진행하면 아래와 같은 에러가 발생한다.

```
/home/kostr/tiano/edk2/UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.c:1:10: fatal error: Library/SimpleLibrary.h: No such file or directory
    1 | #include <Library/SimpleLibrary.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
```

에러가 발생하는 이유는 생성한 라이브러리 폴더가 헤더가 있을 수 있는 장소로 빌드 시스템에서 인식하지 못했기 때문이다.

문제를 해결하기 위해 `UefiLessonsPkg/UefiLessonsPkg.dec`에 `[Includes]`에 추가해야 한다.

```
[Includes]
  Include
```

그리고 `UefiLessonsPkg/UefiLessonsPkg.dec` 파일을 `UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf`의 `[Packages]`에 추가해야 한다.

```
[Packages]
  MdePkg/MdePkg.dec
  UefiLessonsPkg/UefiLessonsPkg.dec
```

빌드를 진행하면 성공하는 것을 볼 수 있다.

### SimpleLibraryUser

이제 라이브러리를 사용하는 애플리케이션을 생성한다.

`UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.c`에 아래 코드를 작성한다.

```c
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>

#include <Library/SimpleLibrary.h>

EFI_STATUS
EFIAPI
UefiMain (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  Print(L"%d\n", Plus2(3));

  return EFI_SUCCESS;
}
```

`UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.inf`에 작성한다.

```
[Defines]
  INF_VERSION                    = 1.25
  BASE_NAME                      = SimpleLibraryUser
  FILE_GUID                      = 22a1f57c-21ca-4011-9133-e3df0d01dace
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

[Sources]
  SimpleLibraryUser.c

[Packages]
  MdePkg/MdePkg.dec
  UefiLessonsPkg/UefiLessonsPkg.dec                  <--- we need to include this for the same reason as in library INF file (for the header search)

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib
  SimpleLibrary                                      <--- library is included as usual
```

이제 `UefiLessonsPkg/UefiLessonsPkg.dsc`에 추가한다.

```
[LibraryClasses]
  ...
  SimpleLibrary|UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf

[Components]
  ...
  UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.inf
```

라이브러리 클래스에 대한 구현을 추가하고 패키지 구성 요소에 새 모듈을 추가했다.

빌드 후 `SimpleLibraryUser.efi`를 실행하면 `*.c` 코드에서 전달한 3에 2가 더해진 결과 5가 반환된 것을 확인할 수 있다.

```
FS0:\> SimpleLibraryUser.efi
5
```
