我有一个库QPhiX,我想用一个大型应用程序Chroma进行编译。这两个库都有其他依赖项,这很纠结,大约有一百万行。 QPhiX已干净编译,我已将其安装到~/local-jureca中。

在Chroma编译期间,Intel C ++版本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*)函数的定义位置。在色度内部,没有单独使用此功能。因此该错误在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头文件。此处定义了功能sumDouble

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

我怎样才能解决这个问题?只是在QPhiX中显式地使所有令人讨厌的功能inline吗?无论如何,它们似乎只委托给QDP ++库,所以内联就好了。

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

最佳答案

如果在头文件中定义函数,则需要在其之前插入内联。



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

09-06 22:42