我遇到了一个我似乎无法解决的问题。我正在尝试构建一个使用名为 spdlog 的日志库的项目,但是当我在项目中使用它时它不会构建。MinGW64 报告某些功能有多种定义:
Scanning dependencies of target Application
[ 91%] Building CXX object Application/CMakeFiles/Application.dir/src/main.cpp.obj
[100%] Linking CXX executable ..\Debug\bin\Application.exe
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `std::is_same<long double, float> fmt::v6::internal::const_check<std::is_same<long double, float> >(std::is_same<long double, float>)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:58: multiple definition of `fmt::v6::internal::assert_fail(char const*, int, char const*)'
../Debug/lib/libTools.dll.a(d000329.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `fmt::v6::format_error::~format_error()':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format.h:691: multiple definition of `fmt::v6::format_error::~format_error()'
../Debug/lib/libTools.dll.a(d000167.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `fmt::v6::internal::error_handler::on_error(char const*)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:1363: multiple definition of `fmt::v6::internal::error_handler::on_error(char const*)'
../Debug/lib/libTools.dll.a(d000735.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `std::string fmt::v6::internal::grouping_impl<char>(fmt::v6::internal::locale_ref)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:203: multiple definition of `std::string fmt::v6::internal::grouping_impl<char>(fmt::v6::internal::locale_ref)'
../Debug/lib/libTools.dll.a(d000741.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `char fmt::v6::internal::thousands_sep_impl<char>(fmt::v6::internal::locale_ref)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:206: multiple definition of `char fmt::v6::internal::thousands_sep_impl<char>(fmt::v6::internal::locale_ref)'
../Debug/lib/libTools.dll.a(d000999.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `char fmt::v6::internal::decimal_point_impl<char>(fmt::v6::internal::locale_ref)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:210: multiple definition of `char fmt::v6::internal::decimal_point_impl<char>(fmt::v6::internal::locale_ref)'
../Debug/lib/libTools.dll.a(d000994.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `int fmt::v6::internal::snprintf_float<double>(double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:1117: multiple definition of `int fmt::v6::internal::snprintf_float<double>(double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)'
../Debug/lib/libTools.dll.a(d000876.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `int fmt::v6::internal::snprintf_float<long double>(long double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:1117: multiple definition of `int fmt::v6::internal::snprintf_float<long double>(long double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)'
../Debug/lib/libTools.dll.a(d000877.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `int fmt::v6::internal::format_float<double>(double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:1045: multiple definition of `int fmt::v6::internal::format_float<double>(double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)'
../Debug/lib/libTools.dll.a(d000693.o):(.text+0x0): first defined here
../Debug/lib/libspdlogd.a(fmt.cpp.obj): In function `int fmt::v6::internal::format_float<long double>(long double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)':
D:/Development/git/cmaketest/third_party/spdlog/include/spdlog/fmt/bundled/format-inl.h:1045: multiple definition of `int fmt::v6::internal::format_float<long double>(long double, int, fmt::v6::internal::float_specs, fmt::v6::internal::buffer<char>&)'
../Debug/lib/libTools.dll.a(d000695.o):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [Application\CMakeFiles\Application.dir\build.make:88: Debug/bin/Application.exe] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:190: Application/CMakeFiles/Application.dir/all] Error 2
mingw32-make: *** [Makefile:83: all] Error 2
现在,我制作了一个单独的项目,以重现此问题所需的最低限度,希望找到解决方案,但我得到了相同的结果。我也尝试过通过 Visual Studio 进行构建,这很有效,尽管创建库的方式当然不同。还尝试了不同版本的 MinGW64,但不幸的是也没有解决它。
为了演示这个问题,这里是这个“最低限度”项目的内容。
我的项目分为 3 个部分:应用程序、第三方和工具。在这种情况下,Third_party 包含 spdlog 存储库的 git 子模块
应用程序包含一个文件 main.cpp,其内容如下
#include "Logger.h"
#include <iostream>
int main()
{
DEBUGERROR("error in main {}", 1);
getchar();
return 0;
}
工具包括以下内容:
记录器.cpp
#pragma once
#include <string>
#include <iostream>
#include <spdlog/spdlog.h>
#define DEBUGERROR(userFormat,...) spdlog::error("[{}] [{}:{}] " userFormat, __COMPONENT__, __func__, __LINE__, ##__VA_ARGS__);
#define DEBUGINFO(userFormat,...) spdlog::info("[{}] [{}:{}] " userFormat, __COMPONENT__, __func__, __LINE__, ##__VA_ARGS__);;
#define DEBUGWARNING(userFormat,...) spdlog::warn("[{}] [{}:{}] " userFormat, __COMPONENT__, __func__, __LINE__, ##__VA_ARGS__);
#define DEBUGCRITICAL(userFormat,...) spdlog::critical("[{}] [{}:{}] " userFormat, __COMPONENT__, __func__, __LINE__, ##__VA_ARGS__);
namespace Tools
{
class Logger
{
public:
void Logger::init()
{
spdlog::set_pattern("%^[thread %t] [%H:%M:%S] [%l] [%s:%#] %v%$");
}
};
}
打印机.h
#pragma once
class Printer
{
public:
Printer();
virtual ~Printer();
static void printError();
private:
};
打印机.cpp
#include "printer.h"
#include "Logger.h"
Printer::Printer()
{
}
Printer::~Printer()
{
}
void Printer::printError()
{
DEBUGERROR("printing an error {}", 1);
}
为了构建它,我创建了 3 个 cmake 文件。
根 CMakeLists.txt
cmake_minimum_required(VERSION 3.15.3)
project(AllProjects LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/bin)
add_subdirectory("third_party/spdlog")
add_subdirectory("Tools")
add_subdirectory("Application")
应用程序 CMakeLists.txt
cmake_minimum_required(VERSION 3.15.3)
project(Application LANGUAGES CXX C)
add_definitions( /D__COMPONENT__="app" )
file(GLOB_RECURSE SOURCES src/*.cpp)
set(INCLUDEDIR ${PROJECT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/Tools/include
)
include_directories(${INCLUDEDIR})
add_executable(Application ${SOURCES})
target_link_libraries (Application Tools)
工具 CMakeLists.txt
cmake_minimum_required(VERSION 3.15.3)
project(Tools LANGUAGES CXX C)
add_definitions( /D__COMPONENT__="tools" )
file(GLOB_RECURSE SOURCES src/*.cpp
)
set(INCLUDEDIR ${PROJECT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/third_party/spdlog/include
)
include_directories(${INCLUDEDIR})
add_library(Tools SHARED ${SOURCES})
target_link_libraries (Tools spdlog)
最后,我使用以下命令集来构建所有内容:
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE -G "MinGW Makefiles" ..
mingw32-make
cd ..
所以最后,项目的结构如下:
项目
- 应用
- 包括
- 源代码
- CMakeLists.txt
- 工具
- 包括
- 源代码
- CMakeLists.txt
- 第三者
- spdlog 存储库作为 git 子模块
- CMakeLists.txt
当我开始在多个文件中包含 Logger.h 时,问题才开始出现。我希望我已经提供了足够的信息来说明问题。任何帮助将不胜感激!