우선, 무시할 수없는 일반적인 디렉토리 이름이 있습니다. 이는 Unix 파일 시스템의 오랜 전통을 기반으로합니다. 이것들은:
trunk
├── bin : for all executables (applications)
├── lib : for all other binaries (static and shared libraries (.so or .dll))
├── include : for all header files
├── src : for source files
└── doc : for documentation
최소한 최상위 수준에서는이 기본 레이아웃을 고수하는 것이 좋습니다.
헤더 파일과 소스 파일 (cpp) 분할에 대해서는 두 가지 방식이 모두 매우 일반적입니다. 그러나 나는 그것들을 함께 보관하는 것을 선호하는 경향이 있으며, 파일을 함께 보관하는 것이 일상적인 작업에서 더 실용적입니다. 또한 모든 코드가 하나의 최상위 폴더 (예 : 폴더) 아래에있을 때 trunk/src/
다른 모든 폴더 (bin, lib, include, doc 및 일부 테스트 폴더)가 최상위 수준에 있음을 알 수 있습니다. 소스 외부 빌드의 "build"디렉토리는 빌드 프로세스에서 생성 된 파일 만 포함하는 모든 폴더입니다. 따라서 src 폴더 만 백업하거나 버전 제어 시스템 / 서버 (예 : Git 또는 SVN)에 보관하면됩니다.
그리고 대상 시스템에 헤더 파일을 설치할 때 (결국 라이브러리를 배포하려는 경우) CMake에는 파일 설치 명령이 있습니다 (암시 적으로 "설치"대상을 생성하여 "make install"수행). 모든 헤더를 /usr/include/
디렉토리 에 넣는 데 사용할 수 있습니다 . 이 목적을 위해 다음 cmake 매크로를 사용합니다.
# custom macro to register some headers as target for installation:
# setup_headers("/path/to/header/something.h" "/relative/install/path")
macro(setup_headers HEADER_FILES HEADER_PATH)
foreach(CURRENT_HEADER_FILE ${HEADER_FILES})
install(FILES "${SRCROOT}${CURRENT_HEADER_FILE}" DESTINATION "${INCLUDEROOT}${HEADER_PATH}")
endforeach(CURRENT_HEADER_FILE)
endmacro(setup_headers)
어디 SRCROOT
내가 src 폴더로 설정하는 cmake 변수이며, INCLUDEROOT
내가 헤더에 갈 필요가 어디든지 구성하는 것이 cmake 변수입니다. 물론이 작업을 수행하는 다른 많은 방법이 있으며 내 방식이 최선이 아니라고 확신합니다. 요점은 헤더 만 대상 시스템에 설치하면된다는 이유만으로 헤더와 소스를 분할 할 이유가 없다는 것입니다. 특히 CMake (또는 CPack)에서는 헤더를 선택하고 구성하는 것이 매우 쉽기 때문입니다. 별도의 디렉토리에 두지 않고도 설치할 수 있습니다. 그리고 이것은 제가 대부분의 도서관에서 본 것입니다.
인용구 : 두 번째로 사용하기 쉬운 것처럼 보이는 코드 단위 테스트를 위해 Google C ++ 테스트 프레임 워크를 사용하고 싶습니다. 예를 들어 "inc / gtest"또는 "contrib / gtest"폴더에이 코드를 내 코드와 함께 묶는 것이 좋습니다. 번들로 제공되는 경우 fuse_gtest_files.py 스크립트를 사용하여 수 또는 파일을 줄이거 나 그대로 두는 것이 좋습니까? 번들로 제공되지 않는 경우이 종속성은 어떻게 처리됩니까?
라이브러리와 종속성을 번들로 묶지 마십시오. 이것은 일반적으로 매우 끔찍한 아이디어이며, 그렇게하는 라이브러리를 구축하려고 할 때 항상 싫어합니다. 마지막 수단이되어야하며 함정에주의하십시오. 종종 사람들은 끔찍한 개발 환경 (예 : Windows)을 대상으로하거나 해당 라이브러리의 이전 (더 이상 사용되지 않는) 버전 (종속성) 만 지원하기 때문에 라이브러리와 종속성을 번들로 묶습니다. 주된 함정은 번들 된 종속성이 동일한 라이브러리 / 애플리케이션의 이미 설치된 버전과 충돌 할 수 있다는 것입니다 (예 : gtest를 번들로 제공했지만 라이브러리를 빌드하려는 사람이 이미 최신 (또는 이전) 버전의 gtest를 설치 한 경우) 두 사람이 충돌하여 그 사람에게 매우 심한 두통을 줄 수 있습니다.) 그러니 제가 말했듯이 위험을 감수하고 그리고 나는 마지막 수단으로 만 말할 것입니다. 라이브러리를 컴파일하기 전에 사람들에게 몇 가지 종속성을 설치하도록 요청하는 것은 번들 된 종속성과 기존 설치 간의 충돌을 해결하려는 것보다 훨씬 덜 악합니다.
인용구 : 테스트 작성과 관련하여 일반적으로 어떻게 구성됩니까? 각 클래스에 대해 하나의 cpp 파일 (예 : test_vector3.cpp)을 가질 생각 이었지만 모두 쉽게 함께 실행할 수 있도록 하나의 바이너리로 컴파일 되었습니까?
제 생각에는 클래스 당 하나의 cpp 파일 (또는 작은 응집력있는 클래스 및 함수 그룹)이 더 일반적이고 실용적입니다. 그러나 "모두 함께 실행될 수 있도록"모든 파일을 하나의 바이너리로 컴파일하지 마십시오. 정말 나쁜 생각입니다. 일반적으로 코딩에 관해서는 합당한만큼 분할하고 싶을 것입니다. 단위 테스트의 경우 하나의 바이너리가 모든 테스트를 실행하는 것을 원하지는 않습니다. 이는 라이브러리의 내용을 조금만 변경해도 해당 단위 테스트 프로그램을 거의 전체적으로 재 컴파일 할 수 있음을 의미하기 때문입니다. , 재 컴파일을 기다리는 데 몇 분 / 시간이 소요됩니다. 간단한 계획을 고수하십시오 : 1 단위 = 1 단위 테스트 프로그램. 그때,
인용구 : gtest 라이브러리는 일반적으로 cmake 및 make를 사용하여 빌드되므로 내 프로젝트도 이와 같이 빌드하는 것이 합리적이라고 생각했습니다. 다음 프로젝트 레이아웃을 사용하기로 결정한 경우 :
차라리이 레이아웃을 제안합니다.
trunk
├── bin
├── lib
│ └── project
│ └── libvector3.so
│ └── libvector3.a products of installation / building
├── docs
│ └── Doxyfile
├── include
│ └── project
│ └── vector3.hpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── src
│ └── CMakeLists.txt
│ └── Doxyfile.in
│ └── project part of version-control / source-distribution
│ └── CMakeLists.txt
│ └── vector3.hpp
│ └── vector3.cpp
│ └── test
│ └── test_vector3.cpp
│_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
│
├── build
└── test working directories for building / testing
└── test_vector3
여기서 주목해야 할 몇 가지 사항이 있습니다. 첫째, src 디렉토리의 하위 디렉토리는 include 디렉토리의 하위 디렉토리를 미러링해야합니다. 이것은 단지 일을 직관적으로 유지하기위한 것입니다 (또한 폴더의 깊은 중첩으로 인해 하위 디렉토리 구조를 합리적으로 평평하게 (얕게) 유지하려고합니다.) 다른 무엇보다 번거 롭습니다.) 둘째, "include"디렉토리는 설치 디렉토리 일 뿐이며 그 내용은 src 디렉토리에서 헤더를 선택하는 것과 같습니다.
셋째, CMake 시스템은 최상위 수준에서 하나의 CMakeLists.txt 파일이 아닌 소스 하위 디렉터리에 배포되도록되어 있습니다. 이것은 사물을 지역적으로 유지하고 좋은 것입니다 (물건을 독립적 인 조각으로 나누는 정신에서). 새 소스, 새 헤더 또는 새 테스트 프로그램을 추가하는 경우 다른 항목에 영향을주지 않고 해당 하위 디렉토리에서 작고 간단한 CMakeLists.txt 파일 하나를 편집하기 만하면됩니다. 이를 통해 디렉토리를 쉽게 재구성 할 수 있습니다 (CMakeList는 로컬이며 이동중인 하위 디렉토리에 포함됨). 최상위 CMakeLists에는 대상 디렉터리 설정, 사용자 지정 명령 (또는 매크로), 시스템에 설치된 패키지 찾기와 같은 대부분의 최상위 구성이 포함되어야합니다. 하위 수준 CMakeList에는 헤더, 소스,
인용구 : CMakeLists.txt는 라이브러리 또는 라이브러리와 테스트 만 빌드 할 수 있도록 어떻게 표시되어야합니까?
기본적인 대답은 CMake를 사용하면 "all"( "make"를 입력 할 때 빌드 된 것)에서 특정 대상을 구체적으로 제외 할 수 있으며 특정 대상 번들을 만들 수도 있다는 것입니다. 여기서 CMake 자습서를 수행 할 수는 없지만 직접 알아내는 것은 상당히 간단합니다. 그러나이 특정 경우에 권장되는 솔루션은 물론 CTest를 사용하는 것입니다. CTest는 CMakeLists 파일에서 단위로 표시된 여러 대상 (프로그램)을 등록하는 데 사용할 수있는 추가 명령 집합입니다. 테스트. 따라서 CMake는 모든 테스트를 특수한 빌드 범주에 넣을 것이며, 이것이 정확히 요청한 것이므로 문제가 해결되었습니다.
인용구 : 또한 bin 디렉토리에 빌드 광고가있는 꽤 많은 프로젝트를 보았습니다. 빌드가 빌드 디렉토리에서 발생하고 바이너리가 bin 디렉토리로 이동합니까? 테스트 용 바이너리와 라이브러리가 같은 장소에 있습니까? 또는 다음과 같이 구성하는 것이 더 합리적일까요?
소스 외부에 빌드 디렉토리를 갖는 것 ( "out-of-source"빌드)은 실제로 할 수있는 유일한 정상적인 일이며 요즘에는 사실상 표준입니다. 따라서 CMake 사람들이 권장하는 것처럼 소스 디렉토리 외부에 별도의 "build"디렉토리를 갖고 내가 만난 모든 프로그래머가 그렇듯이 확실히해야합니다. bin 디렉토리에 관해서는, 그것은 관습이며,이 게시물의 시작 부분에서 말했듯이 그것에 충실하는 것이 아마도 좋은 생각 일 것입니다.
인용구 : 또한 doxygen을 사용하여 내 코드를 문서화하고 싶습니다. cmake 및 make와 함께 자동으로 실행되도록 할 수 있습니까?
예. 가능 이상으로 굉장합니다. 얼마나 멋지게 얻고 싶은지에 따라 몇 가지 가능성이 있습니다. CMake에는 find_package(Doxygen)
일부 파일에서 Doxygen을 실행할 대상을 등록 할 수있는 Doxygen 용 모듈 (예 :)이 있습니다. Doxyfile에서 버전 번호를 업데이트하거나 소스 파일에 대한 날짜 / 작성자 스탬프를 자동으로 입력하는 것과 같은 더 멋진 작업을 수행하려면 약간의 CMake kung-fu로 모두 가능합니다. 일반적으로 이렇게하려면 토큰을 찾아 CMake의 구문 분석 명령으로 대체 할 수있는 소스 Doxyfile (예 : 위의 폴더 레이아웃에 넣은 "Doxyfile.in")을 유지해야합니다. 에서 내 최상위 CMakeLists 파일 , 당신은 cmake-doxygen이의 함께 몇 가지 멋진 일을 CMake 쿵후의 하나 개의 조각을 찾을 수 있습니다.