Ошибка множественного определения при запуске gtest с cmakeC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Ошибка множественного определения при запуске gtest с cmake

Сообщение Anonymous »

У меня проблема с запуском gtest с помощью cmake. Это началось после того, как я изменил структуру проекта, разделив код на несколько модулей с отдельными файлами CMakeList.txt. Когда у меня был один CmakeList без статической библиотеки, все работало нормально.
Теперь у меня такая структура проекта:

Код: Выделить всё

├── src
│   ├── core
│   │   ├── bot.cpp
│   │   ├── bot.h
│   │   ├── domain.h
│   │   ├── geometry.h
│   │   ├── memory_reader.cpp
│   │   ├── memory_reader.h
│   │   ├── process_tools.cpp
│   │   ├── process_tools.h
│   │   └── CMakeLists.txt
│   └── main.cpp
├── test
│   ├── bot_test.cpp
│   ├── geometry_test.cpp
│   └── CMakeLists.txt
└── CMakeLists.txt
CMakeLists.txt:

Код: Выделить всё

cmake_minimum_required(VERSION 3.26)
project(ZumaBot)

set(CMAKE_CXX_STANDARD 17)

add_compile_options(-Werror -Wall -Wextra)

set(OpenCV_DIR "C:/DevTools/opencv/install")
find_package(OpenCV REQUIRED)

add_subdirectory("src/core")
add_subdirectory("tests")

if (OpenCV_FOUND)
add_executable(main-bot WIN32 src/main.cpp)
target_link_libraries(main-bot
core
${OpenCV_LIBS}
gdiplus
ntdll)
endif ()
src/core/CMakeLists.txt:

Код: Выделить всё

cmake_minimum_required(VERSION 3.26)
project(ZumaBot)

set(CMAKE_CXX_STANDARD 17)

set(BOOST_ROOT "C:/DevTools/boost_1_85_0")
set(Boost_ARCHITECTURE "-x32")
find_package(Boost REQUIRED)

if (Boost_FOUND)
add_library(core STATIC
bot.h
bot.cpp
domain.h
geometry.h
memory_reader.h
memory_reader.cpp
process_tools.h
process_tools.cpp)

target_link_libraries(core ${Boost_LIBRARIES})
include_directories(SYSTEM ${Boost_INCLUDE_DIR})
target_include_directories(core
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
${Boost_INCLUDE_DIR}
)
endif ()
tests/CMakeLists.txt:

Код: Выделить всё

cmake_minimum_required(VERSION 3.26)
project(ZumaBot)

set(CMAKE_CXX_STANDARD 17)

include(FetchContent)
FetchContent_Declare(
googletest
# Specify the commit you depend on and update it regularl y.
URL https://github.com/google/googletest/archive/5376968f6948923e2411081fd9372e71a59d8e77.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

add_executable(test
geometry_test.cpp
bot_test.cpp)

target_link_libraries(test
core
gtest_main
)
С помощью этой структуры я могу без проблем запустить цель main-bot, но если я запущу цель с помощью тестов, я получаю следующие ошибки:

Код: Выделить всё

====================[ Build | test | Debug ]====================================
"C:\Program Files\JetBrains\CLion 2023.2.2\bin\cmake\win\x64\bin\cmake.exe" --build C:\Users\Artem\CLionProjects\ZumaBot\cmake-build-debug --target test -j 6
[1/1] Linking CXX executable tests\test.exe
FAILED: tests/test.exe
cmd.exe /C "cd .  && C:\PROGRA~1\JETBRA~1\CLION2~1.2\bin\mingw\bin\G__~1.EXE -g  tests/CMakeFiles/test.dir/geometry_test.cpp.obj tests/CMakeFiles/test.dir/bot_test.cpp.obj -o tests\test.exe -Wl,--out-implib,tests\libtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0  src/core/libcore.a  lib/libgtest_main.a  lib/libgtest.a  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
C:\Program Files\JetBrains\CLion 2023.2.2\bin\mingw\bin/ld.exe: src/core/libcore.a(bot.cpp.obj): in function `void boost::geometry::strategy::intersection::cartesian_segments::segment_intersection_info::assign_a(boost::geometry::model::point&, boost::geometry::model::referring_segment const&, boost::geometry::model::referring_segment const&) const':
C:/Users/Artem/CLionProjects/ZumaBot/src/core/geometry.h:18: multiple definition of `zuma_bot::geometry::detail::createLine(std::vector)'; tests/CMakeFiles/test.dir/geometry_test.cpp.obj:C:/Users/Artem/CLionProjects/ZumaBot/src/core/geometry.h:18: first defined here
C:\Program Files\JetBrains\CLion 2023.2.2\bin\mingw\bin/ld.exe: src/core/libcore.a(bot.cpp.obj): in function `std::pair boost::geometry::strategy::intersection::cartesian_segments::is_x_more_significant(float const&, float const&, float const&, float const&, bool, bool)':
C:/Users/Artem/CLionProjects/ZumaBot/src/core/geometry.h:27: multiple definition of `zuma_bot::geometry::Intersection(std::vector const&, std::vector const&)'; tests/CMakeFiles/test.dir/geometry_test.cpp.obj:C:/Users/Artem/CLionProjects/ZumaBot/src/core/geometry.h:27: first defined here
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Если я правильно понимаю, проблема в том, что geometry.h компилируется в основную библиотеку и также используется как подключаемый модуль, но я не могу понять, как такое может быть исправлено.
Сам файл Geometry.h выглядит так, но я не думаю, что в нем проблема:

Код: Выделить всё

#pragma once

#include "domain.h"
#include 
#include 
#include 
#include 

namespace zuma_bot::geometry {

namespace detail {

namespace bg = boost::geometry;
typedef bg::model::point point_t;
typedef bg::model::linestring  linestring_t;
typedef bg::model::multi_point  mpoint_t;

linestring_t createLine(std::vector line) {
linestring_t ls;
std::for_each(line.begin(), line.end(), [&ls](Coord c) {
bg::append(ls, point_t(c.x, c.y));
});
return ls;
}
}

std::vector Intersection(const std::vector &line_1, const std::vector &line_2) {
using namespace detail;

linestring_t ls_1 = createLine(line_1);
linestring_t ls_2 = createLine(line_2);
mpoint_t out;

bg::intersection(ls_1, ls_2, out);

std::vector result;
result.reserve(out.size());
std::for_each(out.begin(), out.end(), [&result](point_t p) {
result.push_back({p.get(), p.get()});
});

return result;
}

} // zuma_bot::geometry;
И как это используется в тестах (

Код: Выделить всё

geometry_test.cpp
):

Код: Выделить всё

#include 
#include 
#include "geometry.h"

using namespace zuma_bot;
using namespace zuma_bot::geometry;
using namespace std;

TEST(Intersection, Intersection_1) {
vector  line_1{{0, 0}, {0, 5}};
vector line_2{{1, 1}, {-1, 1}};

auto result = Intersection(line_1, line_2);

ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0], (Coord{0, 1}));
}

TEST(Intersection, Intersection_2) {
vector line_1{{0, 0}, {0, 5}};
vector line_2{{0, 0}, {-1, 1}};

auto result = Intersection(line_1, line_2);

ASSERT_EQ(result.size(), 1);
EXPECT_EQ(result[0], (Coord{0, 0}));
}

...
Если вам нужен полный проект здесь
Я попытался разделить заголовочные файлы библиотеки на другую цель, а также использовать target_include_directories по-другому, но я только еще больше запутался(

Подробнее здесь: https://stackoverflow.com/questions/786 ... with-cmake
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»