IT

가장 간단하지만 완전한 CMake 예제

lottoking 2020. 8. 8. 12:05
반응형

가장 간단하지만 완전한 CMake 예제


어떻게 든 CMake가 작동하는 방식에 혼란 스럽습니다. CMake가 작성되는 방식을 이해하는 데 점점 가까워 질 때마다 내가 읽은 다음 예제에서 사라집니다. 내가 알고 싶은 것이 내 프로젝트를 어떻게 구성 해야하는지, 그래서 내 CMake는 앞으로 최소한의 유지 관리를 필요로한다는 것입니다. 예를 들어, 다른 모든 src 폴더와 똑같이 작동하는 src 트리에 새 폴더를 추가 할 때 CMakeList.txt를 업데이트하고 싶지 않습니다.

이것이 내 프로젝트의 구조를 상상하는 방법이지만 이것은 단지 예일뿐입니다. 권장 방법이 다른 경우, 방법을 알려주십시오.

myProject
    src/
        module1/
            module1.h
            module1.cpp
        module2/
            [...]
        main.cpp
    test/
        test1.cpp
    resources/
        file.png
    bin
        [execute cmake ..]

그건 그렇고, 내 프로그램이 리소스가 어디에 있는지 아는 것이 중요합니다. 권장되는 리소스 관리 방법을 알고 싶습니다. "../resources/file.png"로 내 리소스에 액세스하고 싶지 않습니다.


몇 가지 연구 끝에 이제는 가장 간단하지만 완전한 cmake 예제의 내 버전을 얻었습니다. 여기에 대부분의 리소스 및 패키지를 다루려고합니다.

비표준을 수행하는 한 자원 처리입니다. 기본적으로 cmake는 / usr / share /, / usr / local / share / 및 Windows에서 동등한 위치에 저장됩니다. 어디서나 압축을 풀고 수있는 간단한 zip / tar.gz를 갖고 싶었습니다. 따라서 리소스는 실행 파일에 최후로로드됩니다.

cmake 명령을 이해하기위한 기본 규칙은 <function-name>(<arg1> [<arg2> ...])쉼표 또는 반색없이 다음 구문 입니다. 각 인수는 많은입니다. foobar(3.0)그리고 foobar("3.0")동일합니다. 을 사용하여 목록 / 변수를 사용할 수 있습니다 set(args arg1 arg2). 이 변수 세트 foobar(${args})foobar(arg1 arg2)동일하다. 존재하지 않는 변수는 빈 목록과 동일합니다. 목록은 내부적으로 요소를 구분하는 세미콜론이 있습니다. 따라서 하나의 요소 만있는 목록은 정의에 따라 해당 요소 일뿐 아니라 모든 문제가 발생합니다. 변수는 전역 적입니다. 내장 함수는 또는 같은 ID를 기대 사실에 의해 명명 된 인수의 형태를 제공합니다.PUBLICDESTINATION인수 목록에서 인수를 그룹화합니다. 그러나 그것은 언어 기능이 있고, 다만 ID는 사용 가능 일 뿐이며 구현에 의해 구문 분석됩니다.

github 에서 모든 것을 복제 할 수 있습니다.

cmake_minimum_required(VERSION 3.0)
project(example_project)

###############################################################################
## file globbing ##############################################################
###############################################################################

# these instructions search the directory tree when cmake is
# invoked and put all files that match the pattern in the variables 
# `sources` and `data`
file(GLOB_RECURSE sources      src/main/*.cpp src/main/*.h)
file(GLOB_RECURSE sources_test src/test/*.cpp)
file(GLOB_RECURSE data resources/*)
# you can use set(sources src/main.cpp) etc if you don't want to
# use globing to find files automatically

###############################################################################
## target definitions #########################################################
###############################################################################

# add the data to the target, so it becomes visible in some IDE
add_executable(example ${sources} ${data})

# just for example add some compiler flags
target_compile_options(example PUBLIC -std=c++1y -Wall -Wfloat-conversion)

# this lets me include files relative to the root src dir with a <> pair
target_include_directories(example PUBLIC src/main)

# this copies all resource files in the build directory
# we need this, because we want to work with paths relative to the executable
file(COPY ${data} DESTINATION resources)

###############################################################################
## dependencies ###############################################################
###############################################################################

# this defines the variables Boost_LIBRARIES that contain all library names
# that we need to link to
find_package(Boost 1.36.0 COMPONENTS filesystem system REQUIRED)

target_link_libraries(example PUBLIC
  ${Boost_LIBRARIES}
  # here you can add any library dependencies
)

###############################################################################
## testing ####################################################################
###############################################################################

# this is for our testing framework
# we don't add REQUIRED because it's just for testing
find_package(GTest)

if(GTEST_FOUND)
  add_executable(unit_tests ${sources_test} ${sources})

  # we add this define to prevent collision with the main
  # this might be better solved by not adding the source with the main to the
  # testing target
  target_compile_definitions(unit_tests PUBLIC UNIT_TESTS)

  # this allows us to use our executable as a link library
  # therefore we can inherit all compiler options and library dependencies
  set_target_properties(example PROPERTIES ENABLE_EXPORTS on)

  target_link_libraries(unit_tests PUBLIC
    ${GTEST_BOTH_LIBRARIES}
    example
  )

  target_include_directories(unit_tests PUBLIC
    ${GTEST_INCLUDE_DIRS} # doesn't do anything on Linux
  )
endif()

###############################################################################
## packaging ##################################################################
###############################################################################

# all install commands get the same destination. this allows us to use paths
# relative to the executable.
install(TARGETS example DESTINATION example_destination)
# this is basically a repeat of the file copy instruction that copies the
# resources in the build directory, but here we tell cmake that we want it
# in the package
install(DIRECTORY resources DESTINATION example_destination)

# now comes everything we need, to create a package
# there are a lot more variables you can set, and some
# you need to set for some package types, but we want to
# be minimal here
set(CPACK_PACKAGE_NAME "MyExample")
set(CPACK_PACKAGE_VERSION "1.0.0")

# we don't want to split our program up into several things
set(CPACK_MONOLITHIC_INSTALL 1)

# This must be last
include(CPack)


가장 기본적이지만 완전한 예제는 cmake 튜토리얼 에서 사용할 수 있습니다 .

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cxx)

프로젝트 예의 경우 다음이있을 수 있습니다.

cmake_minimum_required (VERSION 2.6)
project (MyProject)
add_executable(myexec src/module1/module1.cpp src/module2/module2.cpp src/main.cpp)
add_executable(mytest test1.cpp)

추가 질문에 대한 한 가지 방법은 안내에서 다시 : 코드에 포함하는 구성 가능한 헤더 파일을 만드는 것입니다. 이를 위해 configuration.h.in다음 내용으로 파일 만드십시오 .

#define RESOURCES_PATH "@RESOURCES_PATH@"

그런 다음 CMakeLists.txt추가 :

set(RESOURCES_PATH "${PROJECT_SOURCE_DIR}/resources/"
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/configuration.h.in"
  "${PROJECT_BINARY_DIR}/configuration.h"
)

# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")

마지막으로 코드에서 경로가 필요한 곳에서 다음을 수행 할 수 있습니다.

#include "configuration.h"

...

string resourcePath = string(RESOURCE_PATH) + "file.png";

참고 URL : https://stackoverflow.com/questions/21163188/most-simple-but-complete-cmake-example

반응형