2017-12-13 15 views
5

프로젝트의 경우 CMake와 함께 Android gradle 스크립트를 사용하고 있습니다. gradle 플러그인은 버전 3 : 0 : 0, CMake 버전 3.6입니다. gradle과 CMake 파일 모두 꽤 간단하고 흥미롭지 않습니다 (사용되는 파일을 정의하는 것입니다 - 필자는 필요에 따라 복사하여 붙여 넣을 수 있습니다).CMake 공유 프로젝트 하위 디렉토리 재구성 방지

다음 프로젝트 구조가 있습니다. 기본적으로 수십 개의 .so 파일 (apk에 패키징되어 '실행 파일'이라고 불리는 안드로이드 패키지의 네이티브 부분)을 생성하는 코드베이스이며, 모두 동일한 공유 라이브러리 코드 (정적 라이브러리, 따라서 '라이브러리 '). 라이브러리 코드는 여전히 (상대적으로) 휘발성이므로 실행 파일을 프로젝트 수준의 종속성으로 유지하여 실행 파일을 빌드 할 때마다 코드가 변경 될 때마다 라이브러리를 필요할 때 다시 빌드 할 수 있습니다. 라이브러리 'CMakeLists이

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName}) 

실행 파일의 프로젝트

add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})... 
"정상적으로"라이브러리에 대한 종속성을 추가하여 Bin 폴더에 자신의 출력을 재

+ LibProjects/ 
---Bin/ (Originally empty) 
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) 
... 
---Lib10/CMakeLists.txt (same) 
+ Executables/ 
---Executable1/CMakeLists.txt (source files here) 
--------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt) 
... 
---Executable40/CMakeLists.txt 

: 같은 구조가 보인다

의미있는 실행 파일을 얻을 수 있다는 의미에서 모든 것이 거의 작동하며 실행 파일은 라이브러리 빌드를 트리거합니다.

문제는 실행 파일을 순차적으로 빌드 할 때 각 파일은 다른 파일의 라이브러리 프로젝트 출력을 재사용하지 않는다는 것입니다. Executable1을 빌드하면 모든 라이브러리 (정상)가 빌드 된 다음 빌드됩니다. 이후에 Executable2를 빌드하면 Executable1 용으로 이미 빌드 된 라이브러리가 재사용되지 않습니다. 이렇게하면 빌드 시간이 10 배 정도 증가합니다.

예상대로/Bin 폴더 안에 각 라이브러리의 빌드 결과가 있지만 실행 파일간에 다시 사용되지는 않습니다. - bin 폴더에 CMake "프로젝트 파일"(정확한 용어 임)이 없습니다. , 모두 실행 가능 빌드 디렉토리에 생성됩니다.

내가 해결하려고하는 문제는 각 라이브러리가 각 실행 파일에 대해 다시 빌드된다는 사실에서 기인하는 빌드 시간입니다.

현재 내가 고려하고있는 솔루션은 어떻게 든 CMake가 실행 파일 대신 자신의 폴더에있는 각 라이브러리의 작업 폴더로 Bin 폴더 (또는 다른 폴더)를 사용하도록 지시하고, gradle android plugin cmakefiles도 객체 파일도 재생성 할 필요가 없으며 재 구축을 피할만큼 현명합니다.

내가 가진 제한은 코드베이스 자체를 재구성 할 수없고 각각의 실행 파일이 다른 파일과 별도로 빌드 가능해야한다는 것입니다. 최상위 레벨 CMake의 가능성은 전혀 없습니다. 각 실행 파일이 트리거 될 수 있어야합니다. 그 자체로.

+0

AndroidFiles는 실행 파일 1 이하입니까? 아니면이 중 40 개가 있습니까? –

+0

종속성 문제처럼 보입니다. 대상이 모든 대상에 대한 종속성을 명시 적으로 나열하고 있는지 확인할 수 있습니까? 또한 라이브러리와 실행 파일에 대한'CMakeLists.txt'를 게시 할 수 있다면. – AmeyaVS

+0

AndroidFiles 저는 40 개 있습니다. CMakeList를 게시 할 수는 있지만 아무 것도 말하지 않을 것입니다. 의존성은 말 그대로 게시 한 것입니다. 그 행동이 * 예상 * 그것이 단지 내가 원하는 바가 아니란 점에서 "의존성 문제"는 아닙니다. 아래의 Oliv의 대답을보십시오. –

답변

2

CMake는 현재 빌드 디렉토리에서 정보를 읽음으로써 빌드가 최신인지를 추측 할 수 있습니다.

012ake에서 CMake manualy를 실행할 때 cmake는 Executable/<x> 디렉토리와 관련된 빌드 디렉토리에서 정보를 검색합니다. 그런 다음 빌드 된 파일의 타임 스탬프가이 빌드 디렉토리에서 수행 된 마지막 빌드에 해당하는지 확인합니다. 그렇지 않은 경우 다시 작성합니다.그러면 Lib1Executable1을 빌드하고 Executalbe2에서 cmake를 실행하고 Lib1 대상 파일의 타임 스탬프를 비교하여이 파일이 cmake 빌드의이 인스턴스에서 생성되지 않았는지 확인한 다음 lib를 다시 빌드하면 라이브러리 파일이 빌드됩니다 . 등등.

1 어느 라이브러리를 구축하고 bin 디렉토리에있는 대상 파일을 설치 (install cmake 명령과 exemple에 대한 make install bash는 명령을 사용하여) :

그래서 두 가지 옵션이 있습니다. 그런 다음 Executalbe<x>/CMakeLists에서 add_subdirectory 대신 find_library 명령을 사용합니다.

+ supper_project 
---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)... 
    + LibProjects/ 
    ---Bin/ (Originally empty) 
    ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) 
    ... 
    ---Lib10/CMakeLists.txt (same) 
    + Executables/ 
    ---Executable1/CMakeLists.txt (source files here) 
    --------------/AndroidFiles/build.gradle (and other android project files) 
    (not any more:points to the CMakeLists.txt) 
    ... 
    ---Executable40/CMakeLists.txt 
+0

불행히도이 대답은 "미안합니다. 대답이 없습니다"입니다. 옵션 1은 피하고 싶지 않은 것 중 하나입니다 (2 단계 제작). 옵션 2는 옵션이 아닙니다. 빌드는 혼합 및 일치입니다. 단일체. 모두가 공평합니다. 나는 누군가가 무엇이 떠오르는지를보기 위해 잠시 기다릴 것이다. 그렇지 않으면이 것을 수여 할 것이다. –

+0

설명 - 현실에 실망했지만 대답은 아닙니다. –

+0

@Gerasimos 믹스 앤 매치는 무엇을 의미합니까? 당신은 정말로 당신의 생각과 당신의 질문을 명확히해야합니다. 제 대답은 당신이하고있는 일에 대한 추측입니다. 각 디렉토리에 대해 cmake 명령을 실행하여 각 실행 가능 디렉토리에서 빌드를 수행한다고 가정합니다. 그러나 당신의 마지막 코멘트는 나를 혼란스럽게합니다. 나는 분명히 당신의 의도와 당신이 실제로하고있는 것을 파악하지 못했습니다. – Oliv

0

나는 문제는 당신이 당신의 종속성을 정의한 방식에있다 생각 :

2- 또는 당신은 다음과 같은 구조를 가지고 슈퍼 프로젝트를 만듭니다.

각 실행 파일에 대해 add_subdirectory를 사용하여 별도의 대상을 만듭니다. 예 : 실행 파일 1의 경우 add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1})이고 실행 파일 2의 경우 add_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1})이기 때문에 cmake는 실행 파일의 각 서브 디렉토리에 동일한 library1에 대해 두 개의 개별 대상을 작성하므로 별도의 타임 스탬프와 캐시 파일이 작성됩니다. 그래서 같은 라이브러리를 여러 번 빌드하는 것으로 보이지만 사실 cmake의 경우 서로 다른 대상입니다.

이 문제를 해결하려면 add_subdirectory을 사용하여 최상위 CMakeLists.txt의 모든 라이브러리를 포함하고 각 실행 파일의 CMakeLists.txt에 add_dependencies 명령을 사용하여 종속성을 추가하십시오.

+0

나는 "최상위"cmake의 가능성을 가지고 있지 않습니다 - 각 "실행 파일"은 각 "라이브러리"에 따라 별도의 엔티티입니다. –

+0

라이브러리에서'CMAKE_BINARY_DIR'을 실행 파일이나'CMAKE_CURRENT_BINARY_DIR'을 절대 경로로 설정할 수 있습니다. –

+0

자세히 설명해 주시겠습니까? –

0

나는이 문제를 해결할 수 있었지만, 결국에는 CMake가 아닌 주위에서 일하는 것이었다.

내가 CMakeFile 수준의 종속 (add_subdirectory)를 제거하고 오직 그 뒤 연결 수준에서 라이브러리 (target_link_libraries 실행 [라이브러리 파일])

을 왼쪽, 나는 각 라이브러리에 대한 Gradle을 스크립트와 이들에 대한 추가 종속성을 생성 스크립트를 각 응용 프로그램의 gradle 스크립트에 포함시켜 라이브러리의 빌드가 CMake 종속성 대신 gradle 종속성에 의해 트리거되도록합니다. 그것은 gradle을 피할 수있을 때보 다 느리지 만 매번 다시 빌드하는 것보다 훨씬 빠르며 오버 헤드가 최소한 일정합니다 (프로젝트 당 몇 초).