我正在使用Google Mock作为我的项目,并且说明指出最好与项目一起构建库,因为不同的编译器标志可能会引入错误。我不想将gmock /目录添加到我的存储库;我宁愿将源代码作为外部依赖项并将其插入到构建过程中。这使我想到了我的问题:我如何指示CMake将外部源目录拖放到构建中(即,将其构建在我的项目的构建目录中)?我在这里发现了一个similar question,但答案需要一个刚性目录放置,我宁愿有可配置。任何其他方式来做到这一点?将外部源代码目录添加到CMake内部
回答
我看到Google Mock支持CMake。在这种情况下,你可以加入这一行
add_subdirectory(${GOOGLE_MOCK_SOURCE_DIR})
到根CMakeLists.txt
,让用户在配置步骤设置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()
您可以使用ExternalProject_Add
对于这一点,因为它可以让您下载,从项目的构建树中配置和构建gmock,然后链接到gmock库。
@ arrowdodger的answer可能是更常见的方法去做这件事。使用他的方法,通常不会在构建树中使用gmock源代码。这可能是好的或坏的取决于你想要什么。
使用ExternalProject_Add
时,每当您构建gmock或依赖目标时,gmock源将被拉动(svn update)。这使得构建稍微慢一点,但显然保持了源代码的最新性,并且方便(开发人员安装时,它的依赖性更小)。对于像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})
如果你在一个空目录下创建这个作为的CMakeLists.txt(比如MyTest的),则:
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建造。然后,您应该能够成功运行MainTest目标。
有关ExternalProject_Add
命令的进一步信息,请参阅this article entitled Building External Projects with CMake 2.8
下面是一个包含a gist此的CMakeLists.txt
当它开始构建googlemock时,CMake忽略“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'部分(以及整个'优化'行),这将生成。 – gotgenes 2013-03-06 17:18:41
什么平台?这与上面的工作方式一样,在Windows上使用单独的输出文件夹,使用VC++ 2010,VC++ 2012使用gtest添加一些小补丁。 – Fraser 2013-03-06 21:02:37
我现在也添加了VC++ 2012的补丁代码。 – Fraser 2013-03-06 21:31:19
- 1. 下载Android源代码,外部目录
- 2. 如何将外部jar文件添加到gingerbread源代码
- 3. 将预处理器定义添加到cmake外部项目
- 4. Cmake外部资源
- 5. 安装了python软件包,内部源代码目录除外
- 6. 在多部分cmake项目中获取外部源代码的正确方法
- 7. 将子目录中的源添加到cmake项目
- 8. Android将外部库添加到项目
- 9. 将外部库添加到LibGdx项目
- 10. 将外部库添加到Symfony2项目
- 11. 将外部库添加到项目中
- 12. 从外部资源添加外部资源到另一个项目的gradle
- 13. 如何将外部文件添加到项目资源?
- 14. 从外部来源将内容添加到SharePoint
- 15. VS2015:递归添加外部内容目录到AppX
- 16. CMake:将文件从build目录复制到源代码中
- 17. Eclipse RCP:将外部目录添加到类路径
- 18. 可以将外部目录添加到现有的Git仓库
- 19. 在CMake中添加外部库(linux)
- 20. Cmake外部可选包添加
- 21. 化石添加外部目录
- 22. Maven:添加外部资源
- 23. 使用源代码外部cmake构建的共享ReSharper设置
- 24. 将源代码附加到android eclipse项目中的外部jar中
- 25. CSS问题(将代码从内部传输到外部文件)
- 26. 当点击外部按钮时,将代码添加到CKeditor中
- 27. 将外部库.jar添加到Spring引导.jar内部/ lib
- 28. CMake:添加一个外部项目,但从目标中排除“全部”
- 29. 如何将include目录添加到内核源代码的makefile中?
- 30. 将外部错误代码映射到内部代码的最佳方法
+1虽然你还是会需要几个'include_directories'为'$ {} GOOGLE_MOCK_SOURCE_DIR电话/ googlemock/include'和'$ {GOOGLE_MOCK_SOURCE_DIR}/googlemock/gtest/include'我想。 – Fraser 2012-08-12 11:31:36
另外,这并不真正“将外部源目录拖入内部版本”,但这可能并不重要。 – Fraser 2012-08-12 11:34:05
它不起作用,除非源目录在我的树内(不是)。这是我尝试的第一件事。 :-) – 2012-08-12 12:38:09