CMake에서 GLOB 또는 각 파일을 사용하여 소스 파일을 개별적으로 지정하는 것이 더 낫습니까?
CMake는 대상의 소스 파일을 지정하는 몇 가지 방법을 제공합니다. 하나는 예를 들어 globbing ( documentation ) 을 사용하는 것입니다 .
FILE (GLOB dir/*)
다른 하나는 각 파일을 개별적으로 지정하는 것입니다.
어떤 방법을 선호합니까? 글 로빙은 쉬워 보이지만 단점이 있다고 들었습니다.
전체 공개 : 원래는 단순함을 위해 글로브 방식을 선호했지만, 수년에 걸쳐 파일을 명시 적으로 나열하는 것은 대규모의 다중 개발자 프로젝트에서 오류가 덜 발생한다는 것을 인식하게되었습니다.
원래 답변 :
globbing의 장점은 다음과 같습니다.
디스크에서 한 곳에만 나열되므로 새 파일을 쉽게 추가 할 수 있습니다. globbing하지 않으면 복제가 발생합니다.
CMakeLists.txt 파일이 더 짧습니다. 파일이 많으면 큰 장점입니다. globbing하지 않으면 거대한 파일 목록에서 CMake 논리가 손실됩니다.
하드 코드 된 파일 목록을 사용하면 다음과 같은 장점이 있습니다.
CMake는 디스크에서 새 파일의 종속성을 올바르게 추적합니다. glob를 사용하면 CMake를 실행할 때 처음으로 glob되지 않은 파일이 선택되지 않습니다.
원하는 파일 만 추가해야합니다. 글 로빙은 원하지 않는 길잃은 파일을 선택할 수 있습니다.
첫 번째 문제를 해결하려면 touch 명령을 사용하거나 변경없이 파일을 작성하여 glob을 수행하는 CMakeLists.txt를 "터치"하면됩니다. 그러면 cmake가 강제로 다시 실행되어 새 파일을 가져옵니다.
두 번째 문제를 해결하려면 코드를주의해서 디렉토리에 정리하면됩니다. 최악의 경우 list (REMOVE_ITEM) 명령을 사용하여 globbed 파일 목록을 정리할 수 있습니다.
file(GLOB to_remove file_to_remove.cpp)
list(REMOVE_ITEM list ${to_remove})
이것이 물릴 수있는 유일한 실제 상황은 git-bisect 와 같은 것을 사용 하여 동일한 빌드 디렉토리에서 코드의 이전 버전을 시도하는 경우입니다. 이 경우 목록에서 올바른 파일을 확보하기 위해 필요 이상으로 정리하고 컴파일해야 할 수도 있습니다. 이것은 코너링 케이스이며 이미 발가락에있는 경우 실제로 문제가되지 않습니다.
CMake에서 소스 파일을 지정하는 가장 좋은 방법은 명시 적으로 나열하는 것 입니다.
CMake의 제작자는 스스로 globbing을 사용 하지 말 것을 권고 합니다.
참조 : https://cmake.org/cmake/help/v3.15/command/file.html?highlight=glob#file
(GLOB를 사용하여 소스 트리에서 소스 파일 목록을 수집하지 않는 것이 좋습니다. 소스를 추가하거나 제거 할 때 CMakeLists.txt 파일이 변경되지 않으면 생성 된 빌드 시스템이 CMake의 재생성 시점을 알 수 없습니다.)
물론 단점이 무엇인지 알고 싶을 수도 있습니다 .
글 로빙이 실패 할 때 :
globbing의 가장 큰 단점은 파일 생성 / 삭제가 빌드 시스템을 자동으로 업데이트하지 않는다는 것입니다.
파일을 추가하는 사람이라면이 방법이 허용 가능한 타협으로 보일 수 있지만, 이로 인해 다른 사람들이 코드를 작성하는 데 문제가 생길 수 있습니다. 프로젝트를 버전 관리에서 업데이트하고 빌드를 실행 한 다음 연락하여
"빌드가 부서진".
설상가상으로, 실패는 일반적으로 문제의 원인에 대한 힌트를 제공하지 않는 링크 오류를 발생시키고 문제 해결에 시간이 손실됩니다.
내가 작업 한 프로젝트에서 globbing을 시작했지만 새 파일을 추가 할 때 불만이 너무 많아서 globbing 대신 파일을 명시 적으로 나열 해야하는 충분한 이유가있었습니다.
또한 일반적인 git 워크 플로우
( git bisect
및 기능 분기 간 전환) 가 중단 됩니다.
그래서 나는 이것을 추천 할 수 없었습니다. 이로 인해 발생하는 문제는 편리함을 능가합니다.이 때문에 누군가가 소프트웨어를 만들 수 없을 때 문제를 추적하거나 포기하는 데 많은 시간이 걸릴 수 있습니다.
또 다른 메모, 터치 만 기억하는 것만으로 CMakeLists.txt
는 충분하지 않습니다. 글 로빙을 사용하는 자동화 된 빌드에서는 마지막 빌드 이후 파일 이 추가 / 제거 될 수 있기 때문에 모든 빌드cmake
전에 실행 해야했습니다 *.
규칙의 예외 :
globbing이 바람직한 경우가 있습니다.
CMakeLists.txt
CMake를 사용하지 않는 기존 프로젝트 의 파일을 설정합니다 .
모든 소스를 참조하는 빠른 방법입니다 (빌드 시스템이 실행되면 명시 적 파일 목록으로 globbing 대체).- CMake가 기본 빌드 시스템 으로 사용되지 않는 경우, 예를 들어 CMake를 사용하지 않는 프로젝트를 사용하고 있고 자체 빌드 시스템을 유지하려는 경우.
- 파일 목록이 자주 변경되어 유지 관리가 불가능한 상황에 해당합니다. 이 경우 유용 할 수 있지만 , 신뢰할 수 있고 올바른 빌드를 얻을 때마다
cmake
빌드 파일을 생성하기 위해 실행을 수락해야합니다 (CMake의 의도와 반대 됨-구성을 빌드에서 분리하는 기능) .
* 네, 갱신 전후 디스크에있는 파일의 트리를 비교하는 코드를 작성 수도 있지만, 더 나은 빌드 시스템에 달려 그런 좋은 해결하고있는 것이 아닙니다.
종속성을 유지하기 위해 추가 파일을 희생하여 안전하게 구할 수 있습니다.
다음과 같은 기능을 어딘가에 추가하십시오.
# Compare the new contents with the existing file, if it exists and is the
# same we don't want to trigger a make by changing its timestamp.
function(update_file path content)
set(old_content "")
if(EXISTS "${path}")
file(READ "${path}" old_content)
endif()
if(NOT old_content STREQUAL content)
file(WRITE "${path}" "${content}")
endif()
endfunction(update_file)
# Creates a file called CMakeDeps.cmake next to your CMakeLists.txt with
# the list of dependencies in it - this file should be treated as part of
# CMakeLists.txt (source controlled, etc.).
function(update_deps_file deps)
set(deps_file "CMakeDeps.cmake")
# Normalize the list so it's the same on every machine
list(REMOVE_DUPLICATES deps)
foreach(dep IN LISTS deps)
file(RELATIVE_PATH rel_dep ${CMAKE_CURRENT_SOURCE_DIR} ${dep})
list(APPEND rel_deps ${rel_dep})
endforeach(dep)
list(SORT rel_deps)
# Update the deps file
set(content "# generated by make process\nset(sources ${rel_deps})\n")
update_file(${deps_file} "${content}")
# Include the file so it's tracked as a generation dependency we don't
# need the content.
include(${deps_file})
endfunction(update_deps_file)
그런 다음 globbing로 이동하십시오.
file(GLOB_RECURSE sources LIST_DIRECTORIES false *.h *.cpp)
update_deps_file("${sources}")
add_executable(test ${sources})
You're still carting around the explicit dependencies (and triggering all the automated builds!) like before, only it's in two files instead of one.
The only change in procedure is after you've created a new file. If you don't glob the workflow is to modify CMakeLists.txt from inside Visual Studio and rebuild, if you do glob you run cmake explicitly - or just touch CMakeLists.txt.
In CMake 3.12, the file(GLOB ...)
and file(GLOB_RECURSE ...)
commands gained a CONFIGURE_DEPENDS
option which reruns cmake if the glob's value changes. As that was the primary disadvantage of globbing for source files, it is now okay to do so:
# Whenever this glob's value changes, cmake will rerun and update the build with the
# new/removed files.
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.cpp")
add_executable(my_target ${sources})
However, some people still recommend avoiding globbing for sources. Indeed, the documentation states:
We do not recommend using GLOB to collect a list of source files from your source tree. ... The
CONFIGURE_DEPENDS
flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even ifCONFIGURE_DEPENDS
works reliably, there is still a cost to perform the check on every rebuild.
Personally, I consider the benefits of not having to manually manage the source file list to outweigh the possible drawbacks. If you do have to switch back to manually listed files, this can be easily achieved by just printing the globbed source list and pasting it back in.
Specify each file individually!
I use a conventional CMakeLists.txt and a python script to update it. I run the python script manually after adding files.
See my answer here: https://stackoverflow.com/a/48318388/3929196
'Programing' 카테고리의 다른 글
CoffeeScript에서 댓글을 어떻게 작성합니까? (0) | 2020.06.21 |
---|---|
어셈블리 'mscorlib에서'System.Runtime.CompilerServices.ExtensionAttribute '유형을로드 할 수 없습니다. (0) | 2020.06.21 |
HTML 본문에 Chrome 개발자 도구를 사용하여 cz-shortcut-listen =“true”? (0) | 2020.06.21 |
장치 메모리에 충분한 여유 공간이 있어도 "사용 가능한 스토리지 부족" (0) | 2020.06.21 |
LoDash : 객체 속성 배열에서 값 배열 가져 오기 (0) | 2020.06.21 |