2012-08-12 5 views
5

Ich verwende Google Mock für mein Projekt, und die Anweisungen sagen, es ist besser, die Bibliothek zusammen mit dem Projekt zu erstellen, da verschiedene Compiler-Flags Fehler verursachen können. Ich möchte das Verzeichnis gmock/nicht zu meinem Repository hinzufügen. Ich hätte lieber die Quellen als externe Abhängigkeit und stecke sie in meinen Build-Prozess. Das bringt mich zu meiner Frage: Wie kann ich CMake anweisen, das externe Quellverzeichnis in den Build zu ziehen (d. H. Es im Build-Verzeichnis meines Projekts zu erstellen)? Ich habe eine similar question hier gefunden, aber die Antworten erfordern eine starre Verzeichnisplatzierung, und ich würde eher konfigurierbar haben. Irgendeine andere Möglichkeit, es zu tun?Hinzufügen eines externen Quellverzeichnisses zu einem CMake-Build

Antwort

6

Ich sehe, dass Google Mock CMake unterstützt. In diesem Fall können Sie nur diese Zeile hinzufügen

add_subdirectory(${GOOGLE_MOCK_SOURCE_DIR}) 

in die Wurzel CMakeLists.txt und lassen Sie Benutzer eingestellt GOOGLE_MOCK_SOURCE_DIR Variable bei der Konfiguration Schritt:

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

+1 Obwohl Sie noch ein paar 'include_directories' für' $ {GOOGLE_MOCK_SOURCE_DIR} Anrufe bräuchten/googlemock/include' und '$ {GOOGLE_MOCK_SOURCE_DIR}/googlemock/gtest/include' denke ich. – Fraser

+0

Auch das "zieht das externe Quellverzeichnis nicht wirklich in den Build", aber das ist vielleicht nicht wichtig. – Fraser

+0

Es wird nicht funktionieren, es sei denn, das Quellverzeichnis befindet sich in meiner Struktur (ist es nicht). Das ist das erste, was ich ausprobiert habe. :-) –

7

Sie ExternalProject_Add dafür verwenden könnten, da es Sie ermöglicht zum Download Konfigurieren Sie gmock in der Baumstruktur Ihres Projekts, und erstellen Sie sie, und verknüpfen Sie sie anschließend mit den gmock-Bibliotheken.

@ arrowdodgers answer ist wahrscheinlich der üblichere Weg, dies jedoch zu tun. Mit seiner Methode haben Sie normalerweise nicht die Gmock-Quellen in Ihrer Build-Struktur. Dies kann gut oder schlecht sein, je nachdem, was Sie wollen.

Mit ExternalProject_Add werden die Gmock-Quellen jedes Mal, wenn Sie gmock oder ein abhängiges Ziel erstellen, abgerufen (svn update). Dies macht den Build etwas langsamer, aber hält die Quellen auf dem neuesten Stand und ist bequem (es ist eine Abhängigkeit weniger, um Entwickler zu installieren). Für ein Projekt wie gmock, das sich nicht oft ändert, ist der Aufwand für die Aktualisierung allzeit zu groß.

Die folgende CMakeLists.txt funktioniert mit Visual Studio 2010 & 2012 - es möglicherweise für andere Plattformen angepasst werden muss. Insbesondere kann gtest derzeit die Box nicht mit Visual Studio 2012 aufbauen (siehe bug report), daher die Patch-Datei und PATCH_COMMAND im ExternalProject_Add Aufruf.

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}) 

Wenn Sie dies als CMakeLists.txt in ein leeres Verzeichnis (zB MyTest) erstellen, dann:

cd MyTest 
mkdir build 
cd build 
cmake .. 

Dies sollte eine grundlegende main.cpp in MyTest/src erstellen und eine Projektdatei erstellen (MyTest/build/Test.sln unter Windows)

Wenn Sie das Projekt erstellen, sollte es die Gmock-Quellen in MyTest/build/ThirdParty/src/googlemock herunterladen und in MyTest/build/ThirdParty/src/erstellen. googlemock-build. Sie sollten dann in der Lage sein, das MainTest-Ziel erfolgreich auszuführen.

Für weitere Informationen über das ExternalProject_Add Befehl finden this article entitled Building External Projects with CMake 2.8

a gist dieses CMakeLists.txt Ist hier enthalten

+0

CMake ignoriert 'CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG' und' CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE' wenn es um den Aufbau von googlemock geht . Ich habe versucht, goglemocks CMakeLists.txt 'cmake_minimum_required' auf' cmake_minimum_required (VERSION 2.8.10) 'zu patchen. Es hat immer noch keinen Effekt. Ich denke nicht, dass es möglich ist, unterschiedliche Debug- und Release-/optimierte Builds von googletest oder googlemock zu haben. Entfernen Sie die 'debug' und' DebugLibs' Teile (und die ganze 'optimierte' Zeile) und dies wird erstellt. – gotgenes

+0

Welche Plattform? Dies funktioniert wie oben mit separaten Ausgabeordnern unter Windows mit VC++ 2010 und mit VC++ 2012 mit einigen kleineren Patches, die zu gtest hinzugefügt wurden. – Fraser

+0

Ich habe jetzt auch den Patch-Code für VC++ 2012 hinzugefügt. – Fraser