2012-08-12 11 views
5

Estoy usando Google Mock para mi proyecto, y las instrucciones dicen que es mejor construir la biblioteca junto con el proyecto, porque diferentes indicadores de compilación pueden presentar errores. No quiero agregar el directorio gmock/a mi repositorio; Prefiero tener las fuentes como una dependencia externa y conectarlo a mi proceso de compilación. Lo que me lleva a mi pregunta: ¿cómo puedo instruir a CMake para que extraiga el directorio fuente externo en la compilación (es decir, compilarlo en el directorio de compilación de mi proyecto)? Encontré un similar question aquí, pero las respuestas requieren una ubicación de directorio rígida, y prefiero tener ese configurable. ¿Alguna otra forma de hacerlo?Agregue un directorio fuente externo a una compilación de CMake

Respuesta

6

Veo que Google Mock es compatible con CMake. En este caso sólo se puede añadir esta línea

add_subdirectory(${GOOGLE_MOCK_SOURCE_DIR}) 

en la raíz CMakeLists.txt y dejar que el usuario establece GOOGLE_MOCK_SOURCE_DIR variable durante la etapa de configuración:

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 Aunque todavía se necesitaría un par de '' include_directories' pide $ {} GOOGLE_MOCK_SOURCE_DIR/googlemock/include' y '$ {GOOGLE_MOCK_SOURCE_DIR}/googlemock/gtest/include', creo. – Fraser

+0

Además, esto realmente no "lleva el directorio de origen externo a la compilación", pero eso quizás no sea importante. – Fraser

+0

No funcionará, a menos que el directorio fuente esté dentro de mi árbol (no lo es). Eso es lo primero que intenté. :-) –

7

usted podría utilizar ExternalProject_Add para esto, ya que le permite descargar , configure y cree gmock desde el árbol de compilación de su proyecto, y luego vincule a las bibliotecas de gmock.

@ arrowdodger's answer es probablemente la forma más habitual de hacerlo. Usando su método, normalmente no tienes las fuentes de gmock en tu árbol de compilación. Esto podría ser bueno o malo dependiendo de lo que quieras.

Utilizando ExternalProject_Add, las fuentes de gmock se extraen (actualización svn) cada vez que se crea gmock o un objetivo dependiente. Esto hace que la compilación sea un poco más lenta, pero claramente mantiene las fuentes actualizadas y es conveniente (es una dependencia menos para que los desarrolladores se instalen). Para un proyecto como gmock que no cambia a menudo, la sobrecarga de actualizar todo el tiempo puede ser demasiado para ti.

El siguiente CMakeLists.txt funciona con Visual Studio 2010 & 2012 - puede ser necesario ajustarlo para otras plataformas. En particular, gtest actualmente no puede construir el cuadro utilizando Visual Studio 2012 (consulte este bug report), de ahí el archivo de parche y PATCH_COMMAND en la llamada ExternalProject_Add.

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

Si crea esto como CMakeLists.txt en un directorio vacío (por ejemplo MyTest), entonces:

cd MyTest 
mkdir build 
cd build 
cmake .. 

Esto debe crear un main.cpp básica en MyTest/src y crear un archivo de proyecto (MyTest/build/Test.sln en Windows)

Al compilar el proyecto, debe descargar las fuentes de gmock a MyTest/build/ThirdParty/src/googlemock y compilarlas en MyTest/build/ThirdParty/src/googlemock-build. Entonces debería poder ejecutar el objetivo MainTest con éxito.

Para más información sobre el comando ExternalProject_Add, ver this article entitled Building External Projects with CMake 2.8

Aquí está a gist que contiene este CMakeLists.txt

+0

CMake ignora 'CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG' y' CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE' cuando va a compilar googlemock . He intentado parchear googleack's CMakeLists.txt 'cmake_minimum_required' a' cmake_minimum_required (VERSIÓN 2.8.10) '. Todavía no tiene efecto. No creo que sea posible tener distintas depuraciones y versiones optimizadas de googletest o googlemock. Elimine las porciones 'debug' y' DebugLibs' (y toda la línea 'optimizada') y esto se compilará. – gotgenes

+0

¿Qué plataforma? Esto funciona como anteriormente con carpetas de salida separadas en Windows con VC++ 2010 y con VC++ 2012 con un par de parches menores agregados a gtest. – Fraser

+0

He agregado el código de parche para VC++ 2012 ahora también. – Fraser

Cuestiones relacionadas