Reputation: 8699
I have a library, QPhiX, that I want to compile with a large application, Chroma. Both libraries have other dependencies, it is quite an entangled thing with around a million lines. QPhiX has compiled cleanly and I have installed it into ~/local-jureca
.
During the compilation of Chroma, the Intel C++ version 17 compiler gives me errors like these:
../../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
The compiler call is this, I have broken down the long line by hand. Some flags are replicated because the configure
picks up the flags of the used libraries and mangles them into the 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
I have looked where the function QPhiX::CommsUtils::sumDouble(double*)
gets defined. Within Chroma, there is not a single use of this function. Therefore the error is within QPhiX but one did not notice since no file there includes the header file qphix/include/qphix/comm.h
. Stripped down, this file is here:
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
The preprocessor branches look such that only one definition can be activated in this file. In the case that both QPHIX_FAKE_COMMS
and QPHIX_QMP_COMMS
were given by the build system, the #error
should have been activated.
Both error messages are caused in libchroma.a
, that must be an intermediate building step in compiling Chroma. The two definitions are in different object files (syssolver_mdagm_aggregate.o
and syssolver_linop_aggregate.o
), but neither matching C++ source file contains the function definition, they both just include the QPhiX header file. There the function sumDouble
is defined.
What happens here? Do the two definitions of sumDouble
become a problem even if it is the same of the three variants in both cases? Or does this mean that two Chroma source files include the qphix/include/qphix/comm.h
with different preprocessor flags set?
How can I fix this? Just making all the offending functions in QPhiX explicitly inline
? They seem to only delegate to the QDP++ library anyway, so inlining just be just fine.
Perhaps I got unlucky and the devel
branches of QPhiX and Chroma do not work together, but master
does not work either. So I again wonder what I am doing wrong, assuming that people developing this software can compile it just fine.
Upvotes: 0
Views: 1300
Reputation: 10591
If you define function in header file, you need to put inline before it.
Otherwise if more than one file include it, when the linker try to link, it will find multiple definition exist and report a multiple definition error (if there is inline, the linker will pick one of them).
Upvotes: 1