使用 cmake 时如何在 C++ 中使用库(*.a 文件)
How to use libraries (*.a files) in C++ when using cmake
所以最近我又开始编程C++了。我想学习如何正确使用 Cmake,并从现在开始为我的爱好项目编写适当的测试。
我基本上只是想在我的项目中集成GTest。我设置了一个 TestProject 目录并执行了以下操作:
- 克隆了 GTest repository
- 使用 cmake 在 googletest 存储库中构建代码
- 已将
googletest/build/lib
目录复制到 TestProject/
- 已将
googletest/include
目录复制到 TestProject/
现在,当我尝试使用 cmake 时,链接时出现以下错误:
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x24): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x39): undefined reference to `pthread_key_delete'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED2Ev[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED5Ev]+0x24): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED2Ev[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED5Ev]+0x39): undefined reference to `pthread_key_delete'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::GetOrCreateValue() const':
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv]+0x25): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv]+0x88): undefined reference to `pthread_setspecific'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE9CreateKeyEv[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE9CreateKeyEv]+0x27): undefined reference to `pthread_key_create'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE9CreateKeyEv[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE9CreateKeyEv]+0x27): undefined reference to `pthread_key_create'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::GetOrCreateValue() const':
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv]+0x25): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv]+0x88): undefined reference to `pthread_setspecific'
我的项目目录下的文件是:
TestProject/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(LIB "${ROOT_DIR}/lib")
set(INCLUDE "${ROOT_DIR}/include")
link_directories("${LIB}")
include_directories("${INCLUDE}")
message("INCLUDE PATH: ${INCLUDE}")
set(SOURCES "${SRC}/main.cpp" "${INCLUDE}/gtest/gtest.h")
add_executable(main "${SOURCES}")
target_link_libraries(main libgtest.a)
TestProject/src/main.cpp
:
#include "gtest/gtest.h"
#include <iostream>
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
std::cout << "Hello world!" << std::endl;
return RUN_ALL_TESTS();
}
如果我使用命令
用系统gtest手动编译它,它工作正常
g++ src/main.cpp -o main -lgtest
我很乐意了解导致问题的原因:)
g++ -o main -lgtest src/main.cpp "libname".a
简短说明
在你的CMakeLists.txt
- 您还没有为
c++11
设置 GoogleTest 要求的标志
- 您还没有链接
pthread
库,因此 GoogleTest 找不到与此相关的定义
详细说明
虽然有一些更好的方法可以实现相同的目的,但我将坚持您为您的应用程序遵循的构建策略。
我假设以下目录结构
├── CMakeLists.txt
├── include
│ └── gtest
│ ├── gtest-death-test.h
│ ├── gtest.h
│ ├── gtest-matchers.h
│ ├── gtest-message.h
│ ├── gtest-param-test.h
│ ├── gtest_pred_impl.h
│ ├── gtest-printers.h
│ ├── gtest_prod.h
│ ├── gtest-spi.h
│ ├── gtest-test-part.h
│ ├── gtest-typed-test.h
│ └── internal
│ ├── custom
│ │ ├── gtest.h
│ │ ├── gtest-port.h
│ │ ├── gtest-printers.h
│ │ └── README.md
│ ├── gtest-death-test-internal.h
│ ├── gtest-filepath.h
│ ├── gtest-internal.h
│ ├── gtest-param-util.h
│ ├── gtest-port-arch.h
│ ├── gtest-port.h
│ ├── gtest-string.h
│ └── gtest-type-util.h
├── libs
│ ├── libgmock.a
│ ├── libgmock_main.a
│ ├── libgtest.a
│ └── libgtest_main.a
├── main
└── src
└── main.cpp
然后我直接从 shell 调用 g++
并键入以下行(试图模仿您的调用策略)
g++ src/main.cpp --std=c++11 -o main -Iinclude -Llib -lgtest -pthread
标志的含义
- GoogleTest 需要
c++11
兼容的编译器,因此我们需要 --std=c++11
标志
-Iinclude
需要在include
下使用headers而不指定include
目录名
-Llib
指定gtest
库所在的路径
pthread
是使用 GoogleTest 所必需的,尽管可以构建 GoogleTest,使其可以 single-threaded 方式使用
它可以正常工作,不会引起任何问题
然后我模仿了你的 CMakeLists.txt
并添加了一些下面突出显示的东西(工作没有任何问题)
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
# added the line below to find libraries for threading
find_package(Threads)
set(CMAKE_CXX_STANDARD 11)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(LIB "${ROOT_DIR}/lib")
# added the line below to enable c++11 features
set(INCLUDE "${ROOT_DIR}/include")
link_directories("${LIB}")
include_directories("${INCLUDE}")
message("INCLUDE PATH: ${INCLUDE}")
set(SOURCES "${SRC}/main.cpp" "${INCLUDE}/gtest/gtest.h")
add_executable(main "${SOURCES}")
# modified the line below to express link dependency on gtest and thread libraries
# lib prefix can be omitted here
target_link_libraries(main gtest ${CMAKE_THREAD_LIBS_INIT})
我使用@squareskittles 提出的答案解决了我的问题。我的 CMakeLists.txt
现在也更干净了,看起来像这样
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
enable_testing()
find_package(GTest REQUIRED)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(SOURCES "${SRC}/main.cpp")
add_executable(test "${SOURCES}")
target_link_libraries(test GTest::GTest GTest::Main)
我确定@SALEH 提供的答案正在按照我想首先解决的方式解决问题。不过我还没试过。
谢谢大家!!!
所以最近我又开始编程C++了。我想学习如何正确使用 Cmake,并从现在开始为我的爱好项目编写适当的测试。
我基本上只是想在我的项目中集成GTest。我设置了一个 TestProject 目录并执行了以下操作:
- 克隆了 GTest repository
- 使用 cmake 在 googletest 存储库中构建代码
- 已将
googletest/build/lib
目录复制到TestProject/
- 已将
googletest/include
目录复制到TestProject/
现在,当我尝试使用 cmake 时,链接时出现以下错误:
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x24): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED2Ev[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEED5Ev]+0x39): undefined reference to `pthread_key_delete'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::~ThreadLocal()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED2Ev[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED5Ev]+0x24): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED2Ev[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEED5Ev]+0x39): undefined reference to `pthread_key_delete'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::GetOrCreateValue() const':
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv]+0x25): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE16GetOrCreateValueEv]+0x88): undefined reference to `pthread_setspecific'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE9CreateKeyEv[_ZN7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE9CreateKeyEv]+0x27): undefined reference to `pthread_key_create'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<std::vector<testing::internal::TraceInfo, std::allocator<testing::internal::TraceInfo> > >::CreateKey()':
gtest-all.cc:(.text._ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE9CreateKeyEv[_ZN7testing8internal11ThreadLocalISt6vectorINS0_9TraceInfoESaIS3_EEE9CreateKeyEv]+0x27): undefined reference to `pthread_key_create'
/usr/bin/ld: ./libgtest.a(gtest-all.cc.o): in function `testing::internal::ThreadLocal<testing::TestPartResultReporterInterface*>::GetOrCreateValue() const':
gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv]+0x25): undefined reference to `pthread_getspecific'
/usr/bin/ld: gtest-all.cc:(.text._ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv[_ZNK7testing8internal11ThreadLocalIPNS_31TestPartResultReporterInterfaceEE16GetOrCreateValueEv]+0x88): undefined reference to `pthread_setspecific'
我的项目目录下的文件是:
TestProject/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(LIB "${ROOT_DIR}/lib")
set(INCLUDE "${ROOT_DIR}/include")
link_directories("${LIB}")
include_directories("${INCLUDE}")
message("INCLUDE PATH: ${INCLUDE}")
set(SOURCES "${SRC}/main.cpp" "${INCLUDE}/gtest/gtest.h")
add_executable(main "${SOURCES}")
target_link_libraries(main libgtest.a)
TestProject/src/main.cpp
:
#include "gtest/gtest.h"
#include <iostream>
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
std::cout << "Hello world!" << std::endl;
return RUN_ALL_TESTS();
}
如果我使用命令
用系统gtest手动编译它,它工作正常g++ src/main.cpp -o main -lgtest
我很乐意了解导致问题的原因:)
g++ -o main -lgtest src/main.cpp "libname".a
简短说明
在你的CMakeLists.txt
- 您还没有为
c++11
设置 GoogleTest 要求的标志 - 您还没有链接
pthread
库,因此 GoogleTest 找不到与此相关的定义
详细说明
虽然有一些更好的方法可以实现相同的目的,但我将坚持您为您的应用程序遵循的构建策略。
我假设以下目录结构
├── CMakeLists.txt
├── include
│ └── gtest
│ ├── gtest-death-test.h
│ ├── gtest.h
│ ├── gtest-matchers.h
│ ├── gtest-message.h
│ ├── gtest-param-test.h
│ ├── gtest_pred_impl.h
│ ├── gtest-printers.h
│ ├── gtest_prod.h
│ ├── gtest-spi.h
│ ├── gtest-test-part.h
│ ├── gtest-typed-test.h
│ └── internal
│ ├── custom
│ │ ├── gtest.h
│ │ ├── gtest-port.h
│ │ ├── gtest-printers.h
│ │ └── README.md
│ ├── gtest-death-test-internal.h
│ ├── gtest-filepath.h
│ ├── gtest-internal.h
│ ├── gtest-param-util.h
│ ├── gtest-port-arch.h
│ ├── gtest-port.h
│ ├── gtest-string.h
│ └── gtest-type-util.h
├── libs
│ ├── libgmock.a
│ ├── libgmock_main.a
│ ├── libgtest.a
│ └── libgtest_main.a
├── main
└── src
└── main.cpp
然后我直接从 shell 调用 g++
并键入以下行(试图模仿您的调用策略)
g++ src/main.cpp --std=c++11 -o main -Iinclude -Llib -lgtest -pthread
标志的含义
- GoogleTest 需要
c++11
兼容的编译器,因此我们需要--std=c++11
标志 -Iinclude
需要在include
下使用headers而不指定include
目录名-Llib
指定gtest
库所在的路径pthread
是使用 GoogleTest 所必需的,尽管可以构建 GoogleTest,使其可以 single-threaded 方式使用
它可以正常工作,不会引起任何问题
然后我模仿了你的 CMakeLists.txt
并添加了一些下面突出显示的东西(工作没有任何问题)
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
# added the line below to find libraries for threading
find_package(Threads)
set(CMAKE_CXX_STANDARD 11)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(LIB "${ROOT_DIR}/lib")
# added the line below to enable c++11 features
set(INCLUDE "${ROOT_DIR}/include")
link_directories("${LIB}")
include_directories("${INCLUDE}")
message("INCLUDE PATH: ${INCLUDE}")
set(SOURCES "${SRC}/main.cpp" "${INCLUDE}/gtest/gtest.h")
add_executable(main "${SOURCES}")
# modified the line below to express link dependency on gtest and thread libraries
# lib prefix can be omitted here
target_link_libraries(main gtest ${CMAKE_THREAD_LIBS_INIT})
我使用@squareskittles 提出的答案解决了我的问题。我的 CMakeLists.txt
现在也更干净了,看起来像这样
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(TestGoogleTest)
enable_testing()
find_package(GTest REQUIRED)
set(ROOT_DIR "${PROJECT_SOURCE_DIR}")
set(SRC "${ROOT_DIR}/src")
set(SOURCES "${SRC}/main.cpp")
add_executable(test "${SOURCES}")
target_link_libraries(test GTest::GTest GTest::Main)
我确定@SALEH 提供的答案正在按照我想首先解决的方式解决问题。不过我还没试过。
谢谢大家!!!