c++ - 诊断多重定义错误

标签 c++ linkage icc

我有一个库 QPhiX,我想用一个大型应用程序 Chroma 对其进行编译。这两个库都有其他依赖项,这是一个相当复杂的东西,大约有一百万行。 QPhiX 已编译干净,我已将其安装到 ~/local-jureca 中。

在编译 Chroma 的过程中,Intel C++ version 17 编译器给我这样的错误:

../../lib/libchroma.a(syssolver_mdagm_aggregate.o): In function `QPhiX::CommsUtils::sumDouble(double*)': 
syssolver_mdagm_aggregate.cc:(.text+0x180): multiple definition of `QPhiX::CommsUtils::sumDouble(double*)' 
../../lib/libchroma.a(syssolver_linop_aggregate.o):syssolver_linop_aggregate.cc:(.text+0x1d0): first defined here

编译器调用是这样的,我已经手工分解了长行。一些标志被复制,因为 configure 获取所用库的标志并将它们分解到 CXXFLAGS 中。

/usr/local/software/jureca/Stages/2016b/software/impi/2017.0.098-iccifort-2017.0.098-GCC-5.4.0/bin64/mpiicpc \
    -I/homec/hbn28/hbn28e/Sources/chroma/mainprogs/main \
    -I/homec/hbn28/hbn28e/Sources/chroma/lib \
    -I../../lib \
    -O2 \
    -Wall \
    -fopenmp \
    --std=c++11 \
    -I/homec/hbn28/hbn28e/local-jureca/include \
    -I/homec/hbn28/hbn28e/local-jureca/include/libxml2 \
    -I/usr/local/software/jureca/Stages/2016b/software/GMP/6.1.1-iccifort-2017.0.098-GCC-5.4.0/include \
    -O2 \
    -Wall \
    -fopenmp \
    -I/homec/hbn28/hbn28e/local-jureca/include \
    -O2 \
    -Wall \
    -fopenmp \
    -L../../lib \
    -L/homec/hbn28/hbn28e/local-jureca/lib \
    -L/usr/local/software/jureca/Stages/2016b/software/GMP/6.1.1-iccifort-2017.0.098-GCC-5.4.0/lib \
    -L/homec/hbn28/hbn28e/local-jureca/lib \
    -L../../other_libs/qdp-lapack/lib
    -o cfgtransf \
    cfgtransf.o \
    -lchroma \
    -lqdp \
    -lXPathReader \
    -lxmlWriter \
    -lqio \
    -llime \
    -L/homec/hbn28/hbn28e/local-jureca/lib \
    -lxml2 \
    -lm \
    -lqmp \
    -lqmp \
    -lintrin \
    -lfiledb \
    -lfilehash \
    -lgmp \
    -lqphix_solver \
    -lqdp-lapack

我查看了函数 QPhiX::CommsUtils::sumDouble(double*) 的定义位置。在 Chroma 中,没有一次使用此功能。因此,错误在 QPhiX 中,但没有人注意到,因为那里没有文件包含头文件 qphix/include/qphix/comm.h。精简后,这个文件在这里:

namespace QPhiX {
#ifndef QPHIX_DO_COMMS
    namespace CommsUtils {
        void sumDouble(double *d) {}
    }

#else

// I see a multiple definition error of `sumDouble` when compiling Chroma. I
// suspect that somehow both flags are passed. Therefore check that only one of
// the mutually exclusive flags is given. Perhaps it would be even better to
// use a `#else` here.
#if defined(QPHIX_FAKE_COMMS) && defined(QPHIX_QMP_COMMS)
#error                                                                         \
    "You must specify QPHIX_FAKE_COMMS xor QPHIX_QMP_COMMS when specifying QPHIX_DO_COMMS."
#endif

#ifdef QPHIX_FAKE_COMMS
    namespace CommsUtils {
        void sumDouble(double *d) {}
    };
#endif // QPHIX_FAKE_COMMS

#ifdef QPHIX_QMP_COMMS
    namespace CommsUtils {
        void sumDouble(double *d) { QMP_sum_double(d); };
    };
#endif // QPHIX_QMP_COMMS

#endif // ifndef QPHIX_DO_COMMS
}; // Namespace

预处理器分支看起来只能在这个文件中激活一个定义。如果构建系统同时提供了 QPHIX_FAKE_COMMSQPHIX_QMP_COMMS,则应该激活 #error

这两条错误消息都是在 libchroma.a 中引起的,这一定是编译 Chroma 的中间构建步骤。这两个定义在不同的目标文件中(syssolver_mdagm_aggregate.osyssolver_linop_aggregate.o),但是匹配的 C++ 源文件都不包含函数定义,它们都只包含 QPhiX header 文件。那里定义了函数 sumDouble

这里发生了什么? sumDouble 的两个定义是否会成为一个问题,即使这两种情况下的三个变体相同?或者这是否意味着两个 Chroma 源文件包含设置了不同预处理器标志的 qphix/include/qphix/comm.h

我该如何解决这个问题?只是让 QPhiX 中所有有问题的函数显式内联?他们似乎只委托(delegate)给 QDP++ 库,所以内联就好了。

也许我运气不好,QPhiX 和 Chroma 的 devel 分支不能一起工作,但是 master 也不能工作。所以我再次想知道我做错了什么,假设开发这个软件的人可以很好地编译它。

最佳答案

如果在头文件中定义函数,需要在头文件中加上inline。


否则如果多个文件包含它,当链接器尝试链接时,它会发现存在多个定义并报告多个定义错误(如果有内联,链接器将选择其中一个)。

关于c++ - 诊断多重定义错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40912355/

相关文章:

C++ STL 字符串流直接缓冲区访问

c++ - 段错误的发生取决于gcc编译命令中的cpp序列?

c++ - 如何在 Mac OS 的发布版本中包含 Qt 库?

C++ 标准:ODR 和 constexpr std::string_view

visual-studio - 如何正确构建要在我的项目中的调试和发布配置中使用的第三方库?

c++ - 英特尔++ : warning #1563: taking the address of a temporary - false positive?

c++ - pragmas simd 和 ivdep vector 之间的区别总是?

c++ - 通过选择部分或全部字符生成所有排列的算法

c++ - 在两个类实例之间共享 vector

assembly - 如何使用内联汇编访问堆栈基指针(rbp)?