我正在使用 CMake 按照 此模板构建一个项目。
链接阶段失败,并发现我的头文件中有重复的符号。
...
[100%] Linking CXX executable ../bin/user
duplicate symbol 'structures::BarStruct::dump()' in:
...build/src/CMakeFiles/user.dir/user.cpp.o
libLearn.a[2](FooUser.cpp.o)
duplicate symbol 'structures::FooStruct::dump()' in:
.../build/src/CMakeFiles/user.dir/user.cpp.o
libLearn.a[2](FooUser.cpp.o)
duplicate symbol 'structures::FinalStruct::dump()' in:
.../CMakeFiles/user.dir/user.cpp.o
libLearn.a[2](FooUser.cpp.o)
ld: 3 duplicate symbols
我的项目布局如下。
├── CMakeLists.txt
├── README.md
├── cmake
│ └── Config.cmake.in
├── include
│ ├── FooHeader.hpp
│ └── FooUser.hpp
├── src
│ ├── CMakeLists.txt
│ ├── FooUser.cpp
│ └── user.cpp
└── tests
src/CMakeLists.txt
if(BUILD_TESTING)
# Required for self registrering unit tests for a library target.
set(PROJECT_TYPE OBJECT)
else()
# Without unit tests, build the target as a normal static library.*
set(PROJECT_TYPE STATIC)
endif()
add_library(${PROJECT_NAME} ${PROJECT_TYPE})
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_sources(${PROJECT_NAME}
PRIVATE
FooUser.cpp
)
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:include>/
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
FooUser.cpp
)
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
add_executable(user user.cpp)
target_link_libraries(user PRIVATE ${PROJECT_NAME})
set_target_properties(user PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
)
包括/FooHeader.hpp
#ifndef FOOHEADER_H
#define FOOHEADER_H
#include <iostream>
namespace structures {
struct FooStruct {
std::vector<double> cost;
std::vector<char> type;
std::vector<int> count;
void dump();
};
struct BarStruct {
std::vector<double> cost;
std::vector<char> count;
void dump();
};
struct FinalStruct {
std::vector<int64_t> numcust;
std::vector<double> totalacctbal;
void dump();
};
} // namespace
void structures::FooStruct::dump() {
std::cout << "\nFOoO";
}
void structures::BarStruct::dump() {
std::cout << "\nBar";
}
void structures::FinalStruct::dump() {
std::cout << "\nFinal";
}
#endif //
包括/FooUser.hpp:
#ifndef FOOUSER_H
#define FOOUSER_H
#include "FooHeader.hpp"
namespace work {
void headerFunc1(const structures::FooStruct& in,
const structures::BarStruct& out);
void headerFunc2(const structures::BarStruct& in,
structures::FinalStruct& out);
} // namespace
//
#endif
src/FooUser.cpp:
#include "FooHeader.hpp"
#include "FooUser.hpp"
void work::headerFunc1(const structures::FooStruct& in,
const structures::BarStruct& ret) {
std::cout << "Working on Foo -> Bar";
}
void work::headerFunc2(const structures::BarStruct& in, structures::FinalStruct& ret) {
std::cout << "Working on Bar -> Final";
}
src/user.cpp
#include "FooUser.hpp"
#include <cassert>
bool verifyOutput(structures::FinalStruct &test) {
test.dump();
return test.numcust.size() > 0;
}
int main() {
structures::FooStruct foo;
structures::BarStruct bar;
structures::FinalStruct finalstruct;
work::headerFunc1(foo, bar);
work::headerFunc2(bar, finalstruct);
return 0;
}
CMakeLists.txt(顶层)
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(Learn CXX)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# GoogleTest requires at least C++14
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.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_subdirectory(src)
我理解这个错误,但我不确定我的 CMake 中的什么原因导致文件被多次包含。
我期待 ifndef 宏能够解决这个问题。我可以通过将文件压缩在一起来实现此目的,但我想学习如何将两个头文件分开。
平台:MacOS 15.2 和 Apple Clang。