Question

I'm attempting to build a project with nvcc. I am getting the most vexing nvlink error: messages I've ever seen.

Here is the link statement:

nvcc    -rdc=true -arch=sm_21 -O3 -Xcompiler -fPIC -I"/usr/local/ACE_wrappers" -I"/usr/local/ACE_wrappers/TAO" -I"/usr/local/DDS" -I"/usr/include/Qt" -I"/usr/include/QtCore" -I"/usr/include/QtGui" -I"../../include" -I"../../include/DDS" -I"../../include/CoordinateTransforms" -I"../../include/DDS/IDLBrokerTemplates" -I"../../def/IDL" -I"../../def/CMD" -I"../../def/XSD" -I"../../src/NetAcquire" -I"/usr/local/ACE_wrappers/TAO/orbsvcs" -I"/usr/local/include/lct.7.5.4" -L"." -L"/usr/local/ACE_wrappers/lib" -L"/usr/local/DDS/lib" -L"/usr/lib64" -L"/usr/local/lib64" -L"../../def/IDL/lib" -L"../../def/XSD" -L"/usr/local/lib" .obj/../../src/Component.o .obj/../../src/COM.o .obj/../../src/DDS/EntityManager.o .obj/../../src/IDLBrokerTemplates/CommandManager.o .obj/../../src/IDLBrokerTemplates/OptionManager.o .obj/../../include/ApplicationProcessStateReporter_moc.o .obj/../../src/Application.o .obj/../../src/CoordinateTransforms/Site.o .obj/../../src/CoordinateTransforms/Geodesy.o .obj/../../src/CoordinateTransforms/Earth.o .obj/../../src/CoordinateTransforms/StateVector.o .obj/../../src/CoordinateTransforms/KeplerianImpact.o .obj/../../src/CoordinateTransforms/GeodeticPosition.o .obj/../../src/IDLBrokerTemplates/MeasurandSubscription.o .obj/../../src/NetAcquire/NetAcquire.o .obj/DataLossFlightTimeImpl.o .obj/DataLossFlightTime.o .obj/DftTable.o .obj/OptionListener.o .obj/PrimaryListener.o .obj/MissionTimeListener.o .obj/DeadMan.o .obj/main.o .obj/../../src/XML/spline.o .obj/../../src/XML/FpTable.o -l"naps-x86_64" -l"naio-x86_64" -l"nalct-x86_64" -l"curl" -l"TAO_Messaging" -l"TAO_Valuetype" -l"TAO_PI_Server" -l"TAO_PI" -l"TAO_CodecFactory" -l"TAO_CosNaming" -l"armadillo" -l"boost_filesystem" -l"boost_system" -l"xerces-c" -l"jarssXSD" -l"OpenDDS_Tcp" -l"JARSSRTv10" -l"QtNetwork" -l"fontconfig" -l"QtGui" -l"QtCore" -l"OpenDDS_Rtps_Udp" -l"OpenDDS_Rtps" -l"OpenDDS_Multicast" -l"OpenDDS_Udp" -l"OpenDDS_InfoRepoDiscovery" -l"OpenDDS_Dcps" -l"TAO_PortableServer" -l"TAO_AnyTypeCode" -l"TAO" -l"ACE"  -o "DFT"

And I'm getting

nvlink error   : Undefined reference to '_ZN5JARSS15KeplerianImpactC1ERKdS2_S2_S2_S2_S2_'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact9getStatusEv'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact13getImpactTimeEv'
nvlink error   : Undefined reference to '_ZNK5JARSS15KeplerianImpact11getPlhStateEv'
nvlink error   : Undefined reference to '_ZN5JARSS15KeplerianImpactD1Ev'
nvlink error   : Undefined reference to '_ZN5JARSS7Geodesy12EFG2GeodeticERKdS2_S2_PdS3_S3_'

I'm certain that these functions/files are included in the compile. You can see from the compile that KeplerianImpact.cpp and Geodesy.cpp are in there.

Is there any way to make the link output easier to read so I can debug this?

Was it helpful?

Solution 3

I figured this out.

I needed to define my functions in the correct files. For example, in Foo.h:

class Foo {
public:
    __host__ __device__
    Foo();
}

and the function definition in Foo.cu not Foo.cpp as I originally thought.

 Foo::Foo() {}

For the constant variables, I needed to implement a slightly different strategy.

Here is an example of the C++ class that I started with:

class Foo {
public:
    static double const epsilon;
    static void functionThatUsesEpsilon();
    /**/
}

Had to be converted to use the global namespace as the epsilon def'n

namespace foo {
    extern __constant__ double epsilon;
} 

class Foo {
public:
    // same stuff as before with the addition of this function
    __host__ __device__
    static inline double getEpsilon() {
#ifdef __CUDACC__
         return foo::epsilon;
#else
         return epsilon;
#endif
    }  

    static void functionThatUsesEpsilon() {
        if (bar < getEpsilon()) { // etc }
    }
};

The ifdef above will return the correct version of the variable for either the host or the device code. Everywhere I had referenced Foo::epsilon I needed to replace with Foo::getEpsilon() so the correct epsilon was returned.

Hope this helps someone in the future. Thanks to @RobertCrovella for getting me thinking.

OTHER TIPS

Use c++filt to demangle the names. For instance:

$ c++filt _ZN5JARSS15KeplerianImpactC1ERKdS2_S2_S2_S2_S2_ JARSS::KeplerianImpact::KeplerianImpact(double const&, double const&, double const&, double const&, double const&, double const&)

Faced this problem earlier, I guess you haven't linked the device object using device linker.

Generate relocatable code for the device by compiling as shown below (-dc is the device equivalent of -c, see the manual for more information)

nvcc –arch=sm_21 –dc a.cu b.cu

Link the device parts of the code by calling nvlink or dlink before the final host link

nvlink -arch=sm_21 a.o b.o -o link.o (or)
nvcc –arch=sm_21 –dlink a.o b.o –o link.o

Finally form a executable using host compiler,

g++ a.o b.o link.o –L<path> -lcudart
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top