多定义链接 C++ 项目构建与 cmake
Multiple definition linking c++ project build with cmake
首先,如果这以一个菜鸟问题结尾,我很抱歉,但我正在掌握 CMake,我找不到这里的问题。这是一个多重定义错误,但据我所知我有:
- 正确包含我的 headers(在下面发布)。
- 在headers中声明但未定义的变量给出了错误。
- 在 CMakeLists.txt 中包含 headers 并正确添加到可执行文件中。
显然其中有些是谎言,因为我在链接我的可执行文件时遇到了下一个错误:
CMakeFiles/helloworld.dir/src/test.cpp.o:(.bss+0x0): multiple definition of `b'
CMakeFiles/helloworld.dir/src/main.cpp.o:(.bss+0x0): first defined here
CMakeFiles/helloworld.dir/src/test.cpp.o:(.bss+0x4): multiple definition of `_patata'
CMakeFiles/helloworld.dir/src/main.cpp.o:(.bss+0x4): first defined here
我的 C++ 项目结构如下;
- /贵
- CMakeLists.txt
- /include/gui/
test.hpatata.h
- /src/
main.cpp test.cpp patata.cpp
在我的 CMakeLists.txt 中,我将文件夹包含在 headers 中,并添加一个名为 helloworld 的可执行文件,以从 src 文件夹中的文件构建。
cmake_minimum_required (VERSION 3.1.0)
project(gui)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QTDIR})
# Dependencies
find_package(Qt5 COMPONENTS Widgets REQUIRED)
# Files
file(GLOB_RECURSE SRCS "${PROJECT_SOURCE_DIR}/src/*.c*")
# Include
include_directories("${PROJECT_SOURCE_DIR}/include" "${PROJECT_BINARY_DIR}/src")
# Target
add_executable(helloworld
${SRCS}
)
# Libs
target_link_libraries(helloworld Qt5::Widgets)
# Logs
message(STATUS "SOURCES DIR => ${PROJECT_SOURCE_DIR}/src/")
message(STATUS "SOURCES FILES => ${SRCS}")
我检查了我的 headers 多次,以确保我没有在它们上面定义任何东西,我什至还设置了防护装置:
test.h
#pragma once
#ifndef TEST_H
#define TEST_H
#include <string>
#include <gui/patata.h>
//std::string meh;
int b;
patata _patata;
std::string message();
#endif
test.cpp
#include <gui/test.h>
#include <gui/patata.h>
std::string message(){
//meh = "print";
b=1;
std::cout << b << std::endl;
std::cout << _patata.rn() << std::endl;
std::string meh = "snn";
return meh;
}
我知道问题出在链接中,但我不知道为什么链接器会看到变量的两个定义。 test.cpp 是否编译了两次?如果是这样,我该如何防止这种情况发生?我认为所有的 .cpp 文件都应该添加到编译器无法找到声明的可执行文件中,但也许我错了。
我的 main.cpp 看起来像这样:
#include <QCoreApplication>
#include <QDebug>
#include <gui/test.h>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout << message() << std::endl;
qDebug() << "Hello World";
return a.exec();
}
您已在 test.h 中声明 b
和 _patata
。由于 test.cpp 和 main.cpp 都包含 test.h,因此 test.cpp 和 main.cpp 翻译单元都有一个名为 b
和 [=11= 的全局变量].现在每个都有两个。每个只能有一个。解决方案是将 int b;
和 patata _patata;
移动到 test.cpp 中,因为它们不需要在 test.h 中。
阅读 C++ 链接规则。
首先,如果这以一个菜鸟问题结尾,我很抱歉,但我正在掌握 CMake,我找不到这里的问题。这是一个多重定义错误,但据我所知我有:
- 正确包含我的 headers(在下面发布)。
- 在headers中声明但未定义的变量给出了错误。
- 在 CMakeLists.txt 中包含 headers 并正确添加到可执行文件中。
显然其中有些是谎言,因为我在链接我的可执行文件时遇到了下一个错误:
CMakeFiles/helloworld.dir/src/test.cpp.o:(.bss+0x0): multiple definition of `b'
CMakeFiles/helloworld.dir/src/main.cpp.o:(.bss+0x0): first defined here
CMakeFiles/helloworld.dir/src/test.cpp.o:(.bss+0x4): multiple definition of `_patata'
CMakeFiles/helloworld.dir/src/main.cpp.o:(.bss+0x4): first defined here
我的 C++ 项目结构如下;
- /贵
- CMakeLists.txt
- /include/gui/
test.hpatata.h - /src/
main.cpp test.cpp patata.cpp
在我的 CMakeLists.txt 中,我将文件夹包含在 headers 中,并添加一个名为 helloworld 的可执行文件,以从 src 文件夹中的文件构建。
cmake_minimum_required (VERSION 3.1.0)
project(gui)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{QTDIR})
# Dependencies
find_package(Qt5 COMPONENTS Widgets REQUIRED)
# Files
file(GLOB_RECURSE SRCS "${PROJECT_SOURCE_DIR}/src/*.c*")
# Include
include_directories("${PROJECT_SOURCE_DIR}/include" "${PROJECT_BINARY_DIR}/src")
# Target
add_executable(helloworld
${SRCS}
)
# Libs
target_link_libraries(helloworld Qt5::Widgets)
# Logs
message(STATUS "SOURCES DIR => ${PROJECT_SOURCE_DIR}/src/")
message(STATUS "SOURCES FILES => ${SRCS}")
我检查了我的 headers 多次,以确保我没有在它们上面定义任何东西,我什至还设置了防护装置:
test.h
#pragma once
#ifndef TEST_H
#define TEST_H
#include <string>
#include <gui/patata.h>
//std::string meh;
int b;
patata _patata;
std::string message();
#endif
test.cpp
#include <gui/test.h>
#include <gui/patata.h>
std::string message(){
//meh = "print";
b=1;
std::cout << b << std::endl;
std::cout << _patata.rn() << std::endl;
std::string meh = "snn";
return meh;
}
我知道问题出在链接中,但我不知道为什么链接器会看到变量的两个定义。 test.cpp 是否编译了两次?如果是这样,我该如何防止这种情况发生?我认为所有的 .cpp 文件都应该添加到编译器无法找到声明的可执行文件中,但也许我错了。
我的 main.cpp 看起来像这样:
#include <QCoreApplication>
#include <QDebug>
#include <gui/test.h>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::cout << message() << std::endl;
qDebug() << "Hello World";
return a.exec();
}
您已在 test.h 中声明 b
和 _patata
。由于 test.cpp 和 main.cpp 都包含 test.h,因此 test.cpp 和 main.cpp 翻译单元都有一个名为 b
和 [=11= 的全局变量].现在每个都有两个。每个只能有一个。解决方案是将 int b;
和 patata _patata;
移动到 test.cpp 中,因为它们不需要在 test.h 中。
阅读 C++ 链接规则。