[CMake 입문 및 고급(2)] CMake 컴파일 설정 - 다중 소스 파일 컴파일 및 라이브러리 파일 생성(코드 포함)

여러 소스 파일       

        지난 글에서 단일 소스 파일의 cmake 컴파일에 대해 알아보았지만, 소스 파일의 예제는 의미가 없는 것 같아서 hello.h 헤더 파일과 hello.c 소스 파일을 추가해 보겠습니다. hello 함수는 hello.c 파일에 정의되어 있고, 이 함수는 main.c 소스 파일에서 호출됩니다.

        ⚫ hello.h 파일 내용

#ifndef __TEST_HELLO_
#define __TEST_HELLO_

void hello(const char *name);

#endif //__TEST_HELLO_

        ⚫ hello.c 파일 내용

#include <stdio.h>
#include "hello.h"

void hello(const char *name){
 printf("Hello %s!\n", name);
}

        ⚫ main.c 파일 내용

#include "hello.h"

int main(void){
 hello("World");
 return 0;
}

        ⚫ 그런 다음 CMakeLists.txt 파일을 준비합니다.

project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})

        프로젝트 디렉토리 구조는 다음과 같습니다.

├── build //文件夹
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

        마찬가지로 빌드 디렉토리에 들어가서 cmake를 실행하고 make를 실행하여 프로젝트를 컴파일하면 최종적으로 실행 파일인 hello를 얻게 됩니다.

        이 예제에서는 CMakeLists.txt 파일에 set 명령어를 사용하여 변수를 설정하는데 set 명령어를 사용하며, 변수가 없을 경우 변수를 생성하여 설정하고, 이 예제에서는 SRC_LIST 변수를 정의하고, SRC_LIST 변수는 소스 파일 목록이고 실행 파일 hello를 생성하는 데 필요한 소스 파일 main.c 및 hello.c를 기록하고 이 변수는 add_executable 명령에서 참조됩니다. 물론 소스 파일을 직접 작성할 수도 있습니다. 명령에서 다음과 같이 SRC_LIST 변수를 정의하지 않고 add_executable에 나열합니다.

add_executable(hello main.c hello.c)

라이브러리 파일 생성

       이 예제에서는 실행 파일인 hello를 생성하는 것 외에도 hello.c를 정적 라이브러리 파일 또는 동적 라이브러리 파일로 컴파일해야 합니다.이전 예제를 기반으로 CMakeLists.txt 파일을 다음과 같이 수정합니다.

project(HELLO)
add_library(libhello hello.c)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        빌드 디렉토리에 진입하여 cmake 실행 후 make를 실행하여 프로젝트를 컴파일하고 컴파일이 완료되면 아래와 같이 빌드 디렉토리에 hello 실행 파일과 라이브러리 파일이 생성됩니다.

         디렉토리 구조는 다음과 같습니다.

├── build
│ ├── hello
│ └── liblibhello.a
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

CMakeLists.txt 파일 설명

        이 예에서는 add_library 명령과 target_link_libraries 명령을 사용했습니다. add_library 명령은 라이브러리 파일을 생성하는 데 사용됩니다. 이 예에서는 두 개의 매개변수를 전달합니다. 첫 번째 매개변수는 라이브러리 파일의 이름을 나타냅니다. 이 이름에는 접두어와 접미어가 포함되지 않습니다. Linux에서 system, 라이브러리 파일의 접두어는 lib, 동적 라이브러리 파일의 접미사는 .so, 정적 라이브러리 파일의 접미사는 .a이므로 최종 생성되는 라이브러리 파일에 해당하는 이름은 자동으로 접두사와 접미사를 추가합니다.

        두 번째 매개변수는 라이브러리 파일에 해당하는 소스 파일을 나타냅니다.

        이 예에서 add_library 명령은 정적 라이브러리 파일 liblibhello.a를 생성합니다. 동적 라이브러리 파일을 생성하려는 경우 다음을 수행할 수 있습니다.

add_library(libhello SHARED hello.c) #生成动态库文件
add_library(libhello STATIC hello.c) #生成静态库文件

target_link_libraries 명령은 대상에 대한 종속 라이브러리를 지정합니다. 이 예에서 hello.c는 라이브러리 파일로 컴파일되고 hello 프로그램에 연결됩니다.

생성된 라이브러리 파일 이름 수정

         이 예제에서 한 가지 매우 불편한 점은 생성된 라이브러리가 liblibhello.a이고 이름이 매우 못생겼는데 libhello.a를 생성하려면 어떻게 해야 합니까? 다음과 같이 add_library 명령의 매개변수를 직접 수정할 수 있습니까?

add_library(hello hello.c)

        대답은 '아니오'입니다. 왜냐하면 hello 대상이 이미 존재하기 때문입니다(add_executable(hello main.c)), 대상 이름은 전체 프로젝트에 고유하며 동일한 이름을 가진 대상이 나타날 수 없으므로 이 방법은 절대 불가능합니다. 위에서 CMakeLists.txt 파일에 다음 명령만 추가하면 됩니다.

set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        set_target_properties는 대상의 속성을 설정하는데 사용하는데 여기서 libhello 대상의 OUTPUT_NAME 속성은 set_target_properties 명령을 통해 설정하며 hello로 설정한다.

        실험을 진행하였고 CMakeLists.txt 파일의 내용은 다음과 같습니다.

cmake_minimum_required(VERSION 3.5)
project(HELLO)
add_library(libhello SHARED hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
add_executable(hello main.c)
target_link_libraries(hello libhello)

        set_target_properties 명령어 추가 외에 현재 프로젝트에 필요한 cmake의 최소 버전 번호를 설정하는 cmake_minimum_required 명령어도 추가했는데, 물론 필수는 아니지만 추가하는 것이 가장 좋다. 빌드 디렉토리로 이동하여 cmake+make를 사용하여 전체 프로젝트를 컴파일하고 컴파일이 완료되면 생성된 라이브러리 파일이 liblibhello.a가 아닌 libhello.a임을 알 수 있습니다.

├── build
│ ├── hello
│ └── libhello.so
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

소스 파일을 다른 디렉토리로 구성

        위의 예에서는 소스 파일을 여러 개 추가했는데, 이 소스 파일들은 모두 같은 디렉토리에 배치되어 있어 그다지 형식적이지 않습니다. 저자는 프로젝트의 소스 코드를 구성했으며 현재 디렉토리 구조는 다음과 같습니다.

├── build #build 目录
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
 ├── CMakeLists.txt
 └── main.c

        프로젝트 디렉터리에 src, libhello 디렉터리를 만들고 hello.c, hello.h 파일을 libhello 디렉터리로 옮기고, main.c 파일을 src 디렉터리로 옮기고, 최상위 디렉터리에 libhello 디렉터리와 src를 옮겼다. 디렉토리 아래에 CMakeLists.txt 파일이 있습니다. CMakeLists.txt 파일 수가 1개에서 3개로 바뀌었고 갑자기 조금 준비가 안 된 느낌이 들었습니다! 다행히도 그들 중 어느 것도 복잡하지 않습니다! 각 CMakeLists.txt 파일의 내용을 살펴보겠습니다.

        ⚫ 최상위 CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(HELLO)
add_subdirectory(libhello)
add_subdirectory(src)

        ⚫ src 디렉토리의 CMakeLists.txt

include_directories(${PROJECT_SOURCE_DIR}/libhello)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        ⚫ libhello 디렉토리 아래의 CMakeLists.txt

add_library(libhello hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        add_subdirectory 명령은 최상위 CMakeLists.txt에서 사용되어 cmake에게 하위 디렉터리에서 새 CMakeLists.txt 파일을 찾아 구문 분석하도록 지시하고, src의 CMakeList.txt 파일에는 새로운 include_directories 명령이 추가되어 여기서 헤더 파일은 경로에 위치하며, 경로를 가리키는 PROJECT_SOURCE_DIR 변수가 사용되며, 이 변수는 이름에서부터 프로젝트 소스 코드의 디렉토리를 나타냅니다.

        이전과 같이 빌드 디렉토리로 이동하여 빌드 및 컴파일하고 마지막으로 실행 파일 hello(build/src/hello) 및 라이브러리 파일 libhello.a(build/libhello/libhello.a)를 가져옵니다.

├── build
│ ├── libhello
│ │ └── libhello.a
│ └── src
│   └── hello
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
 ├── CMakeLists.txt
 └── main.c

생성된 실행 파일 및 라이브러리 파일을 별도의 디렉토리에 배치

        아직은 전면에 약간의 불편함이 있는데, 기본적으로 make 컴파일로 생성된 실행 파일과 라이브러리 파일은 cmake로 생성된 중간 파일(CMakeCache.txt, CmakeFiles, cmake_install.cmake 및 Makefile 등)과 섞이게 됩니다. 명령, 즉 같은 디렉토리에 있습니다. 실행 파일을 bin 디렉토리에 별도로 배치하고 라이브러리 파일을 lib 디렉토리에 별도로 배치하려면 다음과 같이 하십시오.

├── build
├── lib
│ └── libhello.a
└── bin
  └── hello

        빌드 디렉토리 아래 lib 디렉토리에 라이브러리 파일을 저장하고 빌드 디렉토리 아래 bin 디렉토리에 실행 파일을 저장합니다. 이때 2개의 변수를 통해 구현할 수 있으며, src 디렉토리의 CMakeList.txt 파일을 다음과 같이 수정합니다.

include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        그런 다음 libhello 디렉터리에서 CMakeList.txt 파일을 다음과 같이 수정합니다.

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(libhello hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        수정이 완료되면 단계에 따라 프로젝트를 다시 빌드하고 컴파일합니다. 이때 생성된 실행 파일 hello는 build/bin 디렉터리에, 라이브러리 파일 libhello.a는 build/lib 디렉터리에 배치됩니다. 우리의 요구 사항에 따라 디렉토리. 최종 디렉토리 구조는 다음과 같습니다.

├── build
│ ├── bin
│ │ └── hello
│ └── lib
│   └── libhello.a
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
  ├── CMakeLists.txt
  └── main.c

        실제로 이 요구 사항을 실현하는 것은 매우 간단합니다. LIBRARY_OUTPUT_PATH 및 EXECUTABLE_OUTPUT_PATH 변수를 설정하면 됩니다.

추천

출처blog.csdn.net/cj_lsk/article/details/131001173