2012-08-12 3 views
5

프로젝트에 Google Mock을 사용하고 있는데, 다른 컴파일러 플래그로 인해 버그가 발생할 수 있으므로 프로젝트와 함께 라이브러리를 빌드하는 것이 좋습니다. 내 저장소에 gmock/디렉토리를 추가하고 싶지 않습니다. 차라리 소스를 외부 종속성으로 사용하고 빌드 프로세스에 연결할 것입니다. 어느 날 내 질문에 가져온다 : 나는 외부 소스 디렉토리를 빌드 (즉, 프로젝트의 빌드 디렉토리에 빌드)로 가져 오기 위해 CMake에게 어떻게 지시 할 수 있습니까? 여기서 similar question을 찾았지만 응답에 엄격한 디렉토리 배치가 필요하며 구성 가능하도록하는 것이 좋습니다. 다른 방법으로 할 수 있습니까?CMake 빌드에 외부 소스 디렉토리 추가

답변

6

Google Mock이 CMake를 지원합니다. 이 경우 당신은 루트 CMakeLists.txt에이 라인

add_subdirectory(${GOOGLE_MOCK_SOURCE_DIR}) 

를 추가하고 사용자가 구성 단계에서 GOOGLE_MOCK_SOURCE_DIR 변수를 설정할 수 있습니다 : 그것은 다운로드 할 수 있기 때문에

set(GOOGLE_MOCK_SOURCE_DIR "" CACHE PATH "Path to the GMock source") 
if(NOT ${GOOGLE_MOCK_SOURCE_DIR} OR NOT EXISTS "${GOOGLE_MOCK_SOURCE_DIR}/CMakeLists.txt") 
    message(FATAL_ERROR "GOOGLE_MOCK_SOURCE_DIR isn't set properly!") 
endif() 
+0

하나를 포함하는 것 참조 googlemock/include' 그리고'$ {GOOGLE_MOCK_SOURCE_DIR}/googlemock/gtest/include'라고 생각합니다. – Fraser

+0

또한, 이것은 "외부 소스 디렉토리를 빌드로 끌어들이는"것은 아니지만 중요한 것은 아닐 수도 있습니다. – Fraser

+0

소스 디렉토리가 내 트리 안에 있지 않으면 작동하지 않습니다 (그렇지 않습니다). 그게 제가 시도한 첫 번째 것입니다. :-) –

7

당신은이에 대한 ExternalProject_Add을 사용할 수 있습니다 프로젝트의 빌드 트리에서 gmock을 설정하고 빌드 한 다음, gmock 라이브러리에 링크하십시오.

@ arrowdodger 's answer은 아마도이 문제를 해결하는 일반적인 방법 일 것입니다. 그의 방법을 사용하면 일반적으로 빌드 트리에 gmock 소스가 없습니다. 이것은 당신이 원하는 것에 따라 좋거나 나쁠 수 있습니다.

ExternalProject_Add을 사용하면 gmock 소스는 gmock 또는 종속 타겟을 빌드 할 때마다 가져옵니다 (svn 업데이트). 이로 인해 빌드가 약간 느려지지만 소스가 최신 상태로 유지되고 편리합니다 (개발자가 설치하는 것이 더 적은 종속성입니다). gmock과 같이 자주 변경되지 않는 프로젝트의 경우, 항상 업데이트하는 오버 헤드가 너무 많이들 수도 있습니다.

다음 CMakeLists.txt는 Visual Studio 2010 & 2012를 사용하여 작동합니다. 다른 플랫폼에 맞게 조정해야 할 수도 있습니다. 특히, gtest는 Visual Studio 2012 (bug report 참조)를 사용하여 상자를 빌드하지 못했습니다. 따라서 ExternalProject_Add 호출에 패치 파일과 PATCH_COMMAND이 생성됩니다.

cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) 
project(Test) 

# Create main.cpp which uses gmock 
file(WRITE src/main.cpp "#include \"gmock/gmock.h\"\n\n") 
file(APPEND src/main.cpp "struct A {\n virtual void Do() {}\n};\n\n") 
file(APPEND src/main.cpp "struct MockA : public A {\n MOCK_METHOD0(Do, void());\n};\n\n") 
file(APPEND src/main.cpp "TEST(A, Do) {\n") 
file(APPEND src/main.cpp " MockA mock_a;\n") 
file(APPEND src/main.cpp " EXPECT_CALL(mock_a, Do()).Times(testing::AtLeast(1));\n") 
file(APPEND src/main.cpp " mock_a.Do();\n}\n\n") 
file(APPEND src/main.cpp "int main(int argc, char **argv) {\n") 
file(APPEND src/main.cpp " testing::InitGoogleTest(&argc, argv);\n") 
file(APPEND src/main.cpp " return RUN_ALL_TESTS();\n") 
file(APPEND src/main.cpp "}\n") 

# Create patch file for gtest with MSVC 2012 
if(MSVC_VERSION EQUAL 1700) 
    file(WRITE gtest.patch "Index: cmake/internal_utils.cmake\n") 
    file(APPEND gtest.patch "===================================================================\n") 
    file(APPEND gtest.patch "--- cmake/internal_utils.cmake (revision 643)\n") 
    file(APPEND gtest.patch "+++ cmake/internal_utils.cmake (working copy)\n") 
    file(APPEND gtest.patch "@@ -66,6 +66,9 @@\n") 
    file(APPEND gtest.patch "  # Resolved overload was found by argument-dependent lookup.\n") 
    file(APPEND gtest.patch "  set(cxx_base_flags \"\${cxx_base_flags} -wd4675\")\n") 
    file(APPEND gtest.patch "  endif()\n") 
    file(APPEND gtest.patch "+ if (MSVC_VERSION EQUAL 1700)\n") 
    file(APPEND gtest.patch "+  set(cxx_base_flags \"\${cxx_base_flags} -D_VARIADIC_MAX=10\")\n") 
    file(APPEND gtest.patch "+ endif()\n") 
    file(APPEND gtest.patch "  set(cxx_base_flags \"\${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32\")\n") 
    file(APPEND gtest.patch "  set(cxx_base_flags \"\${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN\")\n") 
    file(APPEND gtest.patch "  set(cxx_exception_flags \"-EHsc -D_HAS_EXCEPTIONS=1\")\n") 
    file(APPEND gtest.patch "Index: include/gtest/internal/gtest-tuple.h\n") 
    file(APPEND gtest.patch "===================================================================\n") 
    file(APPEND gtest.patch "--- include/gtest/internal/gtest-tuple.h (revision 643)\n") 
    file(APPEND gtest.patch "+++ include/gtest/internal/gtest-tuple.h (working copy)\n") 
    file(APPEND gtest.patch "@@ -1,3 +1,4 @@\n") 
    file(APPEND gtest.patch "+#include <tuple> /*\n") 
    file(APPEND gtest.patch " // This file was GENERATED by command:\n") 
    file(APPEND gtest.patch " //  pump.py gtest-tuple.h.pump\n") 
    file(APPEND gtest.patch " // DO NOT EDIT BY HAND!!!\n") 
    file(APPEND gtest.patch "@@ -197,8 +198,8 @@\n") 
    file(APPEND gtest.patch " class tuple<> {\n") 
    file(APPEND gtest.patch " public:\n") 
    file(APPEND gtest.patch " tuple() {}\n") 
    file(APPEND gtest.patch "- tuple(const tuple& /* t */) {}\n") 
    file(APPEND gtest.patch "- tuple& operator=(const tuple& /* t */) { return *this; }\n") 
    file(APPEND gtest.patch "+ tuple(const tuple& t) {}\n") 
    file(APPEND gtest.patch "+ tuple& operator=(const tuple&) { return *this; }\n") 
    file(APPEND gtest.patch " };\n") 
    file(APPEND gtest.patch " \n") 
    file(APPEND gtest.patch " template <GTEST_1_TYPENAMES_(T)>\n") 
    file(APPEND gtest.patch "@@ -946,7 +947,7 @@\n") 
    file(APPEND gtest.patch " template <>\n") 
    file(APPEND gtest.patch " struct SameSizeTuplePrefixComparator<0, 0> {\n") 
    file(APPEND gtest.patch " template <class Tuple1, class Tuple2>\n") 
    file(APPEND gtest.patch "- static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {\n") 
    file(APPEND gtest.patch "+ static bool Eq(const Tuple1&, const Tuple2&) {\n") 
    file(APPEND gtest.patch "  return true;\n") 
    file(APPEND gtest.patch " }\n") 
    file(APPEND gtest.patch " };\n") 
else() 
    file(WRITE gtest.patch "") 
endif() 

# Enable ExternalProject CMake module 
include(ExternalProject) 

# Set default ExternalProject root directory 
set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/ThirdParty) 

# Add gmock 
ExternalProject_Add(
    googlemock 
    SVN_REPOSITORY http://googlemock.googlecode.com/svn/trunk/ 
    TIMEOUT 30 
    PATCH_COMMAND svn patch ${CMAKE_SOURCE_DIR}/gtest.patch ${CMAKE_BINARY_DIR}/ThirdParty/src/googlemock/gtest 
    # Force separate output paths for debug and release builds to allow easy 
    # identification of correct lib in subsequent TARGET_LINK_LIBRARIES commands 
    CMAKE_ARGS -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=DebugLibs 
       -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=ReleaseLibs 
       -Dgtest_force_shared_crt=ON 
    # Disable install step 
    INSTALL_COMMAND "" 
    # Wrap download, configure and build steps in a script to log output 
    LOG_DOWNLOAD ON 
    LOG_CONFIGURE ON 
    LOG_BUILD ON) 

# Specify include dir for googlemock and googletest 
ExternalProject_Get_Property(googlemock source_dir) 
include_directories(${source_dir}/include) 
include_directories(${source_dir}/gtest/include) 

if(MSVC_VERSION EQUAL 1700) 
    add_definitions(-D_VARIADIC_MAX=10) 
endif() 

# Add test executable target 
add_executable(MainTest ${PROJECT_SOURCE_DIR}/src/main.cpp) 

# Create dependency of MainTest on googlemock 
add_dependencies(MainTest googlemock) 

# Specify MainTest's link libraries 
ExternalProject_Get_Property(googlemock binary_dir) 
target_link_libraries(MainTest 
         debug ${binary_dir}/DebugLibs/${CMAKE_FIND_LIBRARY_PREFIXES}gmock${CMAKE_FIND_LIBRARY_SUFFIXES} 
         optimized ${binary_dir}/ReleaseLibs/${CMAKE_FIND_LIBRARY_PREFIXES}gmock${CMAKE_FIND_LIBRARY_SUFFIXES}) 

당신은 그 (MYTEST 말), 빈 디렉토리에 CMakeLists.txt으로 이것을 만들 경우 :

cd MyTest 
mkdir build 
cd build 
cmake .. 

이 MYTEST/SRC의 기본 MAIN.CPP를 작성하고 프로젝트 파일을 생성해야합니다 (Windows의 경우 MyTest/build/Test.sln)

프로젝트를 빌드 할 때 gmock 소스를 MyTest/build/ThirdParty/src/googlemock에 다운로드하고 MyTest/build/ThirdParty/src/googlemock-build. 그런 다음 MainTest 대상을 성공적으로 실행할 수 있어야합니다.

ExternalProject_Add 명령에 대한 자세한 정보를 들어

,/당신은 여전히`$ {GOOGLE_MOCK_SOURCE_DIR}을 요구 include_directories``의 몇 가지를 필요 했어하지만 여기 this article entitled Building External Projects with CMake 2.8

a gist이 CMakeLists.txt

+0

CMake는 googlemock을 빌드 할 때'CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG' 및'CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE'을 무시합니다. . googlemock의 CMakeLists.txt'cmake_minimum_required'를'cmake_minimum_required (VERSION 2.8.10)'에 패치하려고했습니다. 여전히 효과가 없습니다. 고유 한 디버그 및 출시/최적화 된 googletest 또는 googlemock 빌드가있을 수 있다고 생각하지 않습니다. 'debug'와'DebugLibs' 부분 (그리고'optimized' 라인 전체)을 제거하면 빌드됩니다. – gotgenes

+0

어떤 플랫폼입니까? 이것은 위와 같이 Windows에서 VC++ 2010을 사용하는 별도의 출력 폴더와 gtest에 추가 된 몇 가지 부수적 인 패치가있는 VC++ 2012와 함께 작동합니다. – Fraser

+0

VC++ 2012 용 패치 코드도 추가되었습니다. – Fraser