ROS 패키지의 CMakeList.txt에서 일반적으로 사용되는 여러 명령의 기능에 대해——————(1)

 

목차

(1)find_package(catkin 필수 구성 요소 ...)

(2)include_directories() 

(3)add_executable( src1 src2 ...) (간단한 작성 방법)

주요 명령 요약:  

참조 링크:


우선, CMakeLists.txt가 소스 코드의 문자열로 간주될 수 있다는 것을 알아야 합니다. CMakeLists.txt에는 함께 제공되는 일부 "시스템 변수"가 있습니다. 그 안의 각 명령은 "함수"이며 함수도 "변수", 이러한 "함수"를 통해 일부 요구 사항이나 구성을 Cmake에 전달한 다음 makefile에 일련의 자동 "쓰기"를 수행하고 마지막으로 make를 사용할 수 있습니다. makefile을 사용하여 소스 코드를 컴파일하는 명령입니다.

이러한 "시스템 변수" 중 일부는 CMakeLists.txt에 명시적으로 기록되지 않습니다. 예를 들어 패키지 A의 헤더 파일 경로는 A_INCLUDE_DIRS 변수로 표시됩니다. 이는 "시스템 변수"이며 "함수(명령어)를 통해 전달될 수 있습니다. )"의 find_package. 패키지 A의 헤더 파일 경로를 자동으로 찾도록 cmake 도구에 지시하고 이를 A_INCLUDE_DIRS 변수에 "함수 반환 값"으로 작성하여 후속 CMakeLists.txt에서 A_INCLUDE_DIRS 변수를 명시적으로 사용할 수 있도록 합니다. . 이 " 시스템 변수"는 일반적으로 ${A_INCLUDE_DIRS} 형식을 사용하여 참조됩니다.

(1)find_package(catkin 필수 구성 요소 ...)

(발췌 [1]) find_package는 cmake에게 지정된 검색 경로에서 우선순위에 따라 Findxxx.cmake 파일과 xxxConfig.cmake 파일을 검색하라고 지시합니다(여기서 xxx는 라이브러리 이름을 나타냅니다. 대소문자라는 사실에 특히 주의하세요). -sensitive), 기본적으로 두 파일 사이에는 차이가 없습니다. cmake는 이 두 파일 중 하나를 찾을 수 있으며 라이브러리를 성공적으로 사용할 수 있습니다. 즉, 라이브러리에 내장된 Cmake 변수를 사용할 수 있습니다. 라이브러리 헤더 파일과 라이브러리 파일의 경로 정보가 들어 있으며, 일반적으로 라이브러리 작성자가 이 두 파일을 제공하지만 설치 후에는 찾을 수 없는 경우도 있습니다. cmake.. 명령을 실행하면 Cmake는 CMakeLists.txt의 코드를 읽고 실행합니다. find_package() 명령이 실행되면 Cmake는 특정 경로에서 Findxxx.cmake 파일 또는 xxxConfig.cmake 파일을 찾습니다. , Cmake는 파일을 찾은 후 이 파일을 실행하면 이 파일이 실행된 후 일부 Cmake 변수가 설정됩니다 . Cmake는 다음 변수를 사용합니다(NAME은 라이브러리 이름을 나타냅니다. 예를 들어 Opencv를 사용하여 Opencv 라이브러리를 나타낼 수 있습니다).

<NAME>_FOUND      //是否找到该库的标志位
<NAME>_INCLUDE_DIRS or <NAME>_INCLUDES   //该库的头文件地址
<NAME>_LIBRARIES  or  <NAME>_LIBS    //该库的静态或者动态链接文件地址
<NAME>_DEFINITIONS        //不懂这个

일반적으로 사용되는 xxx_FOUND, xxx_INCLUDE_DIRS, xxx_LIBS는 각각 라이브러리 플래그, 라이브러리 헤더 파일 경로, 라이브러리 파일 경로의 발견 여부를 나타냅니다. find_package()에는 위의 Findxxx.cmake 및 xxxConfig.cmake 파일에 각각 해당하는 모듈 모드와 구성 모드의 두 가지 모드가 있습니다. cmake는 기본적으로 모듈 모드에 우선 순위를 부여하며 구성 모드는 대안입니다.

모듈 모드(Findxxx.cmake 파일만 찾기):

Cmake는 CMAKE_MODULE_PATH 에 지정된 경로를 검색하는 데 우선 순위를 부여합니다 . CMAKE_MODULE_PATH가 CMakeLists.txt에 Findxxx.cmake를 저장할 경로로 설정되지 않은 경우, 즉 다음 지침이 없습니다.

set(CMAKE_MODULE_PATH "Findxxx.cmake文件所在的路径")

그러면 Cmake는 CMAKE_MODULE_PATH에 지정된 경로를 검색하지 않습니다. 이때 Cmake는 두 번째 우선순위 경로인 <CMAKE_ROOT>/share/cmake-xy/Mdodules를 검색합니다  (참고: xy는 버전 번호를 나타냅니다. 내 버전은 3.10입니다). CMAKE_ROOT는 Cmake를 설치할 때 시스템 경로입니다. 설치 경로를 지정하지 않았기 때문에 시스템의 기본 경로입니다. 제 시스템(ubuntu16.04)에서는 시스템의 기본 경로가 /usr/loacl입니다. 설치 시 사용했다면

cmake -DCMAKE_INSTALL_PREFIX=自己dir路径 

그러면 CMAKE_ROOT는 이때 작성한 경로를 나타냅니다. 방금 1순위 경로 검색에서 Findxxx.cmake 파일이 발견되지 않으면 2순위 경로에서 검색된다고 말씀드렸습니다. Cmake가 두 경로 모두에서 Findxxx.cmake 파일을 찾지 못하는 경우. 그러면 Cmake가 구성 모드로 들어갑니다.

구성 모드(xxxConfig.cmake 파일만 검색):

Cmake는 xxx_DIR  에 지정된 경로 검색에 우선순위를 부여합니다 . 이 cmake 변수가 CMakeLists.txt에 설정되지 않은 경우. 즉, 다음과 같은 지시가 없습니다.

set(xxx_DIR "xxxConfig.cmkae文件所在的路径")

그러면 Cmake는 xxx_DIR에 지정된 경로를 검색하지 않습니다. 이때 Cmake는 두 번째 우선순위 경로인 /usr/local/lib/cmake/xxx/에 있는 xxxConfig.cmake 파일을 자동으로 검색합니다.

위 내용은 주로 Cmake의 검색 모드에 대해 설명합니다. Cmake가 두 모드에서 제공하는 경로에서 해당 Findxxx.cmake 및 xxxConfig.cmake 파일을 찾지 못하는 경우 시스템은 상위 오류 메시지를 표시합니다.

요약하다:

  • 우선 간단하게 말하면 find_package는 일부 패키지 경로, 헤더 파일 경로 및 기타 정보를 찾는 데 사용됩니다. 예를 들어 A의 CMakeList.txt에서 find_package(B)를 설정합니다. 이 명령은 cmake에게 해당 프로젝트를 직접 알리지 않습니다. A는 B에 의존해야 합니다. cmake에게 B를 찾은 다음 일부 관련 변수를 반환하도록 지시합니다.
  • set 명령을 통해 필요한 라이브러리 경로를 수동으로 설정할 수 있습니다(실제로 해당 Findxxx.cmake 및 xxxConfig.cmake 파일 경로). 이 기능은 매우 중요합니다. 첫째: 시스템이 어떤 이유로 필요한 라이브러리 파일을 찾을 수 없는 경우, 수동으로 지정해야 합니다. 둘째: PCL1.7과 PCL1.8이 공존하는 경우와 같이 시스템에 특정 라이브러리의 여러 버전이 포함되어 있는 경우 set 명령을 통해 필요한 라이브러리를 수동으로 선택할 수 있습니다.

ROS에서 사용: 

find_package의 표준 명령 형식은 다음과 같습니다.

find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]

             [REQUIRED] [[COMPONENTS] [components...]]

             [OPTIONAL_COMPONENTS components...]

             [NO_POLICY_SCOPE])

 ROS에서는 CMakeList.txt를 작성할 때 최소한 "catkin" 패키지를 찾도록 지정해야 합니다. 직접 작성한 다른 catkin_packages에 의존해야 하는 경우 catkin 패키지의 COMPONENTS로 찾는 것이 가장 좋습니다. 예를 들면 :

catkin_packages가 많이 있는 것 같지만 실제로는 catkin 패키지의 구성 요소입니다! ! !

자신의 catkin_package를 catkin의 구성 요소로 취급하면 장점은 자신이나 다른 시스템에서 작성한 이러한 catkin_package 패키지의 포함 경로, 라이브러리 경로 등이 자동으로 catkin_ 변수에 추가된다는 것입니다. 즉, catkin_INCLUDE_DIRS는 catkin 패키지 자체를 포함할 뿐만 아니라 포함 경로에는 위의 모든 COMPONENTS(구성 요소) 경로도 포함됩니다. 마찬가지로 catkin_LIBRARIES에는 이러한 구성 요소의 라이브러리 경로도 포함되어 있어 매우 편리합니다!

예를 들어, catkin 패키지 A가 catkin 패키지 B의 헤더 파일 bh를 호출할 때 패키지 A의 CMakeList.txt와 find_package에만 작성하면 됩니다.

find_package(catkin REQUIRED  COMPONENTS  B)

그리고 B가 A보다 먼저 빌드되도록 종속성을 선언합니다.

add_dependencies(<A的target> <依赖的B的target>)

이렇게 하면 B의 헤더 파일을 정상적으로 사용할 수 있습니다. 일반적으로 bh와 해당 b.cpp는 A에서 실행 파일 구성에 참여하므로 A의 CMakeList.txt 파일에 있는 include_directories(B_INCLUDE_DIRS)를 사용하여 bh에 대한 참조를 나타내고, target_link_libraries(A_target B_LIBRARIES)를 사용하여 다음 링크를 나타냅니다. 도서관 B.

하지만 B를 catkin의 컴포넌트로 사용하는 경우 수동으로 추가하지 않고 다음과 같이 기본 명령을 사용하면 됩니다.

include_directories( ${catkin_INCLUDE_DIRS})
target_link_libraries(<A的target>  ${catkin_LIBRARIES})

 참고: 따라서 위의 두 문장에서는 패키지 B를 지정할 필요는 없지만 find_package에는 지정해야 하며, 그래야만 B의 변수를 catkin_variables에 추가하여 함께 사용할 수 있습니다!

이 점에 대한 보다 자세한 설명은 공식 설명 http://wiki.ros.org/catkin/CMakeLists.txt 를 참고하는 것이 좋습니다.

(2)include_directories() 

이 명령이 해결하는 주요 문제는 패키지 A의 *.cpp 파일에서 헤더 파일이 호출되는 경우(예: #include <opencv/cv.h>) gcc가 헤더 파일을 어디에서 찾습니까?

#include "/usr/local/include/opencv/cv.h"를 사용하여 헤더 파일 주소를 직접적이고 명시적으로 제공할 수 있지만 분명히 표준화되어 있지 않습니다. 이에 대해 A의 CMakeList.txt 루트 디렉터리에서 제공할 수 있습니다. 즉, 명령:

include_directories(/usr/local/include)

/usr/local/include를 기반으로 헤더 파일 opencv/cv.h를 찾도록 시스템에 알립니다.

또한, find_package() 명령어와 함께 사용하면 필요한 헤더 파일의 경로를 자동으로 채워주는 것이 매우 편리하며, 예를 들어 opencv의 경우 다음 명령어를 사용하면 헤더 파일의 경로를 자동으로 찾아준다.

find_package(opencv REQUIRED) 
include_directories(${OPENCV_INCLUDE_DIRS})

주의점:

  • 패키지 A의 자체 헤더 폴더 포함도 채워져야 하며(있는 경우), 다른 패키지의 경로보다 앞에 있어야 합니다.
  • catkin 유형과 함께 제공되는 패키지의 경우 find_package에서 지정한 후 include_directories에 해당하는 ${catkin_INCLUDE_DIRS}만 작성하면 모든 패키지를 참조할 수 있습니다.
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
include_directories(
  #下面的include指的就是自身的头文件文件夹
  include   
  #下面的是find_package指令返回的头文件路径
  ${catkin_INCLUDE_DIRS}
)

(3)add_executable(<name> src1 src2 ...) (간단한 작성 방법)

add_executable 명령을 사용하여 gcc에 <name>이라는 실행 파일을 생성하도록 지시합니다. 이 실행 파일은 src1, src2...에 의해 컴파일되고 생성됩니다. <name> 컴파일에 관련된 모든 파일이 나열되어야 합니다.

예를 들어, 패키지 A의 src 폴더에 test.cpp math.cpp matrice.cpp 3개 파일이 있고, include 폴더에 2개의 헤더 파일 math.h matrice.h가 있는데, 이들은 test.cpp(main 함수 포함)에 있습니다. .사용하다

#include"math.h"
#include"matrix.h"

Math.cpp Matrix.cpp가 호출된 다음 <name>을 테스트로 사용하여 실행 파일을 생성할 때 다음 사항을 채워야 합니다.

add_executable(test   src/test.cpp  src/math.cpp  src/matrix.cpp )

왜냐하면, 테스트 실행 파일을 생성하는 과정에서 src/test.cpp src/math.cpp src/matrix.cpp 세 파일의 obj 파일을 서로 연결해야 하기 때문입니다. 

(4)target_link_libraries(<name> lib1 lib2 ...) (간단한 작성 방법, lib는 종속 라이브러리의 경로입니다)

이 명령은 add_executable 명령 뒤에 위치해야 하며 add_executable이 실행되면 name이라는 바이너리 파일이 생성됩니다. 이때 실행 파일이 완전히 생성되지 않았습니다. 예를 들어 name 소스 코드는 다음에서 Boost 라이브러리를 호출합니다. 헤더 파일 생성 후 이름의 최종 실행 파일이 생성되면 Boost 라이브러리 파일과 연결되어야 최종 실행 파일이 생성됩니다.

add_executable의 기능은 cmake에게 방금 생성된 이름을 패키지가 최종 실행 파일을 생성하기 위해 의존하는 다른 외부 라이브러리 파일(lib1 lib2...)과 연결하도록 지시하는 것입니다. 스크린샷을 찍어 출력을 확인하세요.

주요 명령 요약: 

기본 구성을 완료하려면 다음 명령을 입력하십시오.CMakeList.txt는 기본적으로 컴파일 단계에 따라 컴파일 프로세스를 여러 단계로 나누는 것을 볼 수 있습니다.

1단계. 종속 패키지(라이브러리 및 헤더 파일)의 경로 찾기

 

find_패키지()

2단계. 자신의 소스 코드 헤더 파일 경로를 제공하세요.

 

include_directories()

3단계. 자신의 소스 코드를 객체 파일로 컴파일

 

add_executable()

4단계. 대상 파일을 다른 라이브러리 파일과 연결

 

target_link_libraries()

따라서 cmake가 오류를 보고할 때 오류를 분류하여 패키지를 찾을 수 없는지(find_package에 문제가 있을 수 있음), 헤더 파일을 찾을 수 없는지(include_directories), 링크가 실패하는지를 구분할 수 있습니다. 가능한 문제. 비교적 포괄적입니다.

다음 글은 그 외 관련된 설정 명령어들에 관한 내용인데, 일부는 꼭 필요한 것은 아니지만 매우 흔하게 사용되지만 매우 중요한 명령어이기도 합니다. 포털: https://blog.csdn.net/u012057432/article/details/103353547

참조 링크:

[1]  https://blog.csdn.net/chengde6896383/article/details/86497016   find_package 원칙

 

 

추천

출처blog.csdn.net/u012057432/article/details/103353148