Как использовать библиотеки (* .a файлы) в C ++ при использовании cmake - PullRequest
0 голосов
/ 12 февраля 2020

Так что недавно я снова начал программировать на C ++. Я хочу научиться правильно использовать Cmake, а также начать писать правильные тесты для своих хобби-проектов.

Я просто хочу интегрировать GTest в свой проект. Я установил каталог TestProject и сделал следующее:

  1. клонировал репозиторий GTest
  2. собрал код в репозитории googletest с помощью cmake
  3. скопировал каталог googletest/build/lib в TestProject/
  4. скопировал каталог 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

Я был бы очень рад понять, в чем причина проблемы:)

Ответы [ 3 ]

2 голосов
/ 13 февраля 2020

Я решил свою проблему, используя предложенный ответ @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 решает проблему так, как я хотел решить это первым. Хотя я еще не пробовал.

Спасибо всем !!!

0 голосов
/ 13 февраля 2020

Краткое объяснение

В вашем 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

Затем я вызываю g++ непосредственно из оболочки, набирая следующую строку (пытаясь имитировать ваш вызов стратегия)

g++ src/main.cpp --std=c++11 -o main -Iinclude -Llib -lgtest -pthread

Значение флагов

  • GoogleTest требуется c++11 совместимый компилятор, поэтому нам нужен --std=c++11 flag
  • -Iinclude требуется для использования заголовков в include без указания include имя каталога
  • -Llib указывает путь, в котором gtest библиотека существует
  • pthread требуется для использования Goo gleTest, хотя можно создать GoogleTest таким образом, чтобы его можно было использовать однопоточным образом

Он работает без проблем

Затем я имитировал ваш 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})

0 голосов
/ 12 февраля 2020

g ++ -o main -lgtest src / main. cpp "libname" .a

...