不能在 cmake 脚本中包含 googletest

Can't include googletest inside cmake script

我尝试在 windows 上创建一些小项目,但是当我尝试使用 cmake 构建它时出现了很多错误。在 linux 上,此构建成功。当我使用 CMake 创建虚拟项目时,一切正常。这是我的文件夹结构:

  • extern
    • googletest
  • tests
    • ...
    • CMakeLists.txt
    • ...
  • CMakeLists.txt

根目录 CMakeLists.txt:

# Setup cmake minimal required version
cmake_minimum_required(VERSION 3.10)

# Declare project
project(mobile_speaker_driver)

# Change c++ standard
set(CMAKE_CXX_STANDARD 17)

# Adding googletest to project
option(PACKAGE_TESTS "Build the tests" ON)
if(PACKAGE_TESTS)
    enable_testing()
    include(GoogleTest)
    add_subdirectory(tests)
endif()

# Add source files to driver library
if (WIN32)
    set(SOURCE_FILES apps/main.cpp src/AudioDriver.cpp src/AudioDriverWindows.cpp)
elseif (UNIX)
    set(SOURCE_FILES apps/main.cpp src/AudioDriver.cpp src/AudioDriverLinux.cpp)
endif (WIN32)

add_executable(${PROJECT_NAME} ${SOURCE_FILES})

测试CMakeLists.txt:

set(TESTBINARY ${PROJECT_NAME}_test)

add_subdirectory("${PROJECT_SOURCE_DIR}/extern/googletest" "extern/googletest")

add_executable(${TESTBINARY} main.cpp AudioDriverTest.cpp)

target_link_libraries(${TESTBINARY} gtest gtest_main)

错误:

D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h: In function 'int testing::internal::posix::StrCaseCmp(const char*, const char*)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h:1985:10: error: '_stricmp' was not declared in this scope; did you mean 'strncmp'?
 1985 |   return _stricmp(s1, s2);
      |          ^~~~~~~~
      |          strncmp
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h: In function 'char* testing::internal::posix::StrDup(const char*)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h:1987:47: error: '_strdup' was not declared in this scope
 1987 | inline char* StrDup(const char* src) { return _strdup(src); }
      |                                               ^~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h: In function 'int testing::internal::posix::FileNo(FILE*)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h:1995:40: error: '_fileno' was not declared in this scope; did you mean 'file'?
 1995 | inline int FileNo(FILE* file) { return _fileno(file); }
      |                                        ^~~~~~~
      |                                        file
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h: In function 'FILE* testing::internal::posix::FDOpen(int, const char*)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/include/gtest/internal/gtest-port.h:2072:56: error: 'fdopen' was not declared in this scope; did you mean 'fopen'?
 2072 | inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
      |                                                        ^~~~~~
      |                                                        fopen
In file included from D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-all.cc:41:
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest.cc: In static member function 'static bool testing::internal::String::CaseInsensitiveWideCStringEquals(const wchar_t*, const wchar_t*)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest.cc:2077:10: error: '_wcsicmp' was not declared in this scope; did you mean 'wcsncmp'?
 2077 |   return _wcsicmp(lhs, rhs) == 0;
      |          ^~~~~~~~
      |          wcsncmp
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest.cc: In member function 'int testing::UnitTest::Run()':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest.cc:5253:21: error: '_OUT_TO_STDERR' was not declared in this scope
 5253 |     _set_error_mode(_OUT_TO_STDERR);
      |                     ^~~~~~~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest.cc:5253:5: error: '_set_error_mode' was not declared in this scope
 5253 |     _set_error_mode(_OUT_TO_STDERR);
      |     ^~~~~~~~~~~~~~~
In file included from D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-all.cc:42:
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc: In function 'void testing::internal::DeathTestAbort(const string&)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:296:5: error: '_exit' was not declared in this scope; did you mean '_cexit'?
  296 |     _exit(1);
      |     ^~~~~
      |     _cexit
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc: In member function 'virtual void testing::internal::DeathTestImpl::Abort(testing::internal::DeathTest::AbortReason)':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:527:3: error: '_exit' was not declared in this scope; did you mean '_cexit'?
  527 |   _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
      |   ^~~~~
      |   _cexit
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc: In member function 'virtual testing::internal::DeathTest::TestRole testing::internal::WindowsDeathTest::AssumeRole()':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:771:24: error: '_MAX_PATH' was not declared in this scope; did you mean 'MAX_PATH'?
  771 |   char executable_path[_MAX_PATH + 1];  // NOLINT
      |                        ^~~~~~~~~
      |                        MAX_PATH
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:773:65: error: 'executable_path' was not declared in this scope
  773 |                                                                 executable_path,
      |                                                                 ^~~~~~~~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:308:38: note: in definition of macro 'GTEST_DEATH_TEST_CHECK_'
  308 |     if (!::testing::internal::IsTrue(expression)) { \
      |                                      ^~~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:797:11: error: 'executable_path' was not declared in this scope
  797 |           executable_path, const_cast<char*>(command_line.c_str()),
      |           ^~~~~~~~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-death-test.cc:308:38: note: in definition of macro 'GTEST_DEATH_TEST_CHECK_'
  308 |     if (!::testing::internal::IsTrue(expression)) { \
      |                                      ^~~~~~~~~~
In file included from D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-all.cc:43:
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-filepath.cc: In static member function 'static testing::internal::FilePath testing::internal::FilePath::GetCurrentDir()':
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-filepath.cc:49:26: error: '_MAX_PATH' was not declared in this scope; did you mean 'MAX_PATH'?
   49 | # define GTEST_PATH_MAX_ _MAX_PATH
      |                          ^~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-filepath.cc:101:12: note: in expansion of macro 'GTEST_PATH_MAX_'
  101 |   char cwd[GTEST_PATH_MAX_ + 1] = { '[=12=]' };
      |            ^~~~~~~~~~~~~~~
D:/Projects/mobile-speaker-driver/extern/googletest/googletest/src/gtest-filepath.cc:102:27: error: 'cwd' was not declared in this scope
  102 |   return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
      |                           ^~~
make.exe[2]: *** [tests/extern/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj] Ошибка 1
make.exe[1]: *** [tests/extern/googletest/googletest/CMakeFiles/gtest.dir/all] Ошибка 2
make.exe: *** [all] Ошибка 2

出现问题是因为我强制使用 c++17 标志构建 googletest。只需将 CMAKE_CXX_STANDARD 放在主 CMakeLists.txt.

中的 googletest include 之后