views:

1110

answers:

3

Greetings Everyone.

I'm currently trying to compile a multiple-language program (C, C++ and FORTRAN) using GNU compilers in UNIX (g++, gcc & f77 respectively).

All my sources are compiling into objects with no errors however I encounter a symbol referencing error as they are linked as shown below:

f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \
        SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\
        BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
NOTICE: Invoking /usr/bin/f90 -f77 -ftrap=%none -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o
Undefined                       first referenced
 symbol                             in file
_Znwj                               SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEED1Ev SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1Ev SA.o
_ZNKSsixEj                          main.o
_ZNSolsEPFRSoS_E                    SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode SA.o
_ZNSolsEd                           SA.o
_ZNSolsEi                           SA.o
__cxa_end_catch                     SA.o
__cxa_begin_catch                   SA.o
_ZdlPv                              SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE7is_openEv SA.o
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c SA.o
_ZSt4cerr                           SA.o
_ZSt4cout                           SA.o
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE5closeEv SA.o
_ZNSt8ios_base4InitD1Ev             main.o
_ZNSt8ios_base4InitC1Ev             main.o
_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv SA.o
__gxx_personality_v0                main.o
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc SA.o
__cxa_rethrow                       SA.o
_ZNKSs4sizeEv                       main.o
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ SA.o
ld: fatal: Symbol referencing errors. No output written to SlowDynamic.exe
*** Error code 1
make: Fatal error: Command failed for target `SlowDynamic.exe'

With the Following Makefile:

products: SlowDynamic.exe

SlowDynamic.exe: main.o SA.o mersenne.o CFE.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o MA_57.o blas.o MA_57_Depend.o Metis.o
    f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \
     SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\
     BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o

main.o: main.cpp
    g++ -c -o main.o main.cpp

SA.o: SA.cpp
    g++ -c -o SA.o SA.cpp

mersenne.o: mersenne.cpp
    g++ -c -o mersenne.o mersenne.cpp

CFE.o: CFE.c
    gcc -c -o CFE.o CFE.c

MA_57.o: MA_57.f
    f77 -c -o MA_57.o MA_57.f

blas.o: blas.f
    f77 -c -o blas.o blas.f

MA_57_Depend.o: MA_57_Depend.f
    f77 -c -o MA_57_Depend.o MA_57_Depend.f

Metis.o: Metis.f
    f77 -c -o Metis.o Metis.f

BCs.o: BCs.c
    gcc -c -o BCs.o BCs.c

EMatrix.o: EMatrix.c
    gcc -c -o EMatrix.o EMatrix.c

Numbering.o: Numbering.c
    gcc -c -o Numbering.o Numbering.c

KMatrix.o: KMatrix.c
    gcc -c -o KMatrix.o KMatrix.c

Solve.o : Solve.c
    gcc -c -o Solve.o Solve.c

clean: 
    rm *.o Main.exe *.gpi

I have read that this is typically the fault of missing libraries. I know the C & FORTRAN code compiles fine seperatly (respective libraries included) as does the C++ code when compiled on its own. This leads me to believe that it is the interface between the two programs that causes the error. Unfortunatly I've little to no experiance debugging this sort of problem and without any clues from the linker its hard to move forward. I'll include the necessary parts of my program that deal with the interface between the two sides of the program.

First the C++ part: SA.h, SA.cpp

SA.h:

class SimAnneal {
    ...
    std::vector<float> DensityArray; 
    std::vector<float> EnergyArray;
  public
    double ObjFunction ();
    ...
}

SA.ccp:

#include <math.h>
#include <iostream>
#include <fstream>    
#include <time.h>     
#include <vector>
#include "SA.h"
#include "CFE.h"
#include "randomc.h"  //Includes mersenne.cpp

double SimAnneal::ObjFunction () 
{
    CFE(&DensityArray[0], &EnergyArray[0]); 

      // sends pointers of both arrays to CFE.c and modifies EnergyArray as 
      // shown in CFE.c

    double SumStrainEnergy = 0;

    for (int i = 0; i < EnergyArray.size(); i++)
    {
     SumStrainEnergy += EnergyArray[i];  //Effectively sum of array 
                                                //engy[] from CFE.c
    }

    return SumStrainEnergy;
}

Secondly the C/FORTRAN part: CFE.h, CFE.c

CFE.h:

#ifdef __cplusplus
extern "C" {
#endif 

void CFE(float density[], float energy[]);

#ifdef __cplusplus
 }
#endif

CFE.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BCs.h"
#include "EMatrix.h"
#include "Numbering.h"
#include "KMatrix.h"
#include "fg_types.h"
#include "Solve.h"

void CFE(float density[], float energy[])
{
    ...stuff...

    float * dens;
    dens = density;  //pass pointer of array density[0] in SA.cpp to CFE.c

    ...more stuff....

    float * engy;
    engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c

    ***Modify engy in some respects****    
}

Essentially the ObjFunction in SA.cpp is called in main.cpp, which contains main().

Is there any visible fault?

Is there any way I can ask the linker to announce what causes / where the error occours in the linking?

Any help will be much appriciated.

Thank you.

+++ EDIT: Verbose feedback +++

birch $ g++ -v Hello.cpp
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs
Configured with: /sfw10/builds/build/sfw10-patch/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/ccs/bin/as --without-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath)
 /usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/cc1plus -quiet -v Hello.cpp -quiet -dumpbase Hello.cpp -mcpu=v7 -auxbase Hello -version -o /var/tmp//cc2JwHRb.s
ignoring nonexistent directory "/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3
 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/sparc-sun-solaris2.10
 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/backward
 /usr/local/include
 /usr/sfw/include
 /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/include
 /usr/include
End of search list.
GNU C++ version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) (sparc-sun-solaris2.10)
        compiled by GNU C version 3.4.3 (csl-sol210-3_4-branch+sol_rpath).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Hello.cpp:6:2: warning: no newline at end of file
 /usr/ccs/bin/as -V -Qy -s -xarch=v8 -o /var/tmp//ccvAshv7.o /var/tmp//cc2JwHRb.s
/usr/ccs/bin/as: Sun Compiler Common 10 Patch 09/04/2007
 /usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/collect2 -V -R/usr/sfw/lib -Y P,/usr/ccs/lib:/usr/lib -Qy /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crt1.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crti.o /usr/ccs/lib/values-Xa.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtbegin.o -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3 -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/lib -L/usr/ccs/lib -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../.. /var/tmp//ccvAshv7.o -lstdc++ -lm -R/usr/sfw/lib -lgcc_s -lgcc -lc -R/usr/sfw/lib -lgcc_s -lgcc -lc /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtend.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.490
+3  A: 

Some of those undefined symbols clearly relate to standard C++ classes (i.e. ostream).

You need to ensure that you've got at least the C++ library linked (-lstdc++).

To debug further:

  1. Run f77, g++, etc, in verbose mode (-v) with single language programs and see which libraries the compiler automatically includes in the link phase for each language

  2. For symbols that are in your own code, use nm to look at both the native language declarations and non-native invocations to determine how they mismatch. There are rules about underscore prefixes, etc, which are commonly applied.

(As far as I can remember, but it's 15 years since I last linked C and Fortran, C symbols are always internally prefixed with an underscore, but Fortran symbols are not).

Alnitak
Writing in -lg++ directly after -lgcc_s doesn't do it. I'm attempting to locate the file as you said by running the hello world script through the linker in verbose mode. Its indicated -lgcc and -lc but the former isn't found. Added the verbose feedback as an edit.
Raugnar
You want -lstdc++, not -lg++
Adam Rosenfield
Cheers, that did it. Fulled compiled!
Raugnar
I've fixed the library reference in my answer
Alnitak
+2  A: 

The main problem is that you're doing the linking step with the F77 compiler, which doesn't link in the C++ standard library by default. Like Alnitak said, specify -lg++ explicitly during linking to get it.

Also, if you are calling C++ functions from C code (or from F77 code), make sure you enclose the prototypes of those functions in an extern "C" {} block so that their symbol names show up in the standardized C form, rather than the mangled C++ form (this restricts you from some things, though, such as overloading). See here for more information.

Tyler McHenry
A: 

Usually, you should link a program containing any C++ code with the C++ compiler, adding the Fortran and C libraries to the link line. Further, the standard advice is to make the main() program C++, nor Fortran, since the startup sequences for C++ are different. Make the Fortran code into a function that you call from a minimal C++ main.

int main(void) // Assuming no argument handling - probably incorrect
{
    return(fortran_main_program());
}
Jonathan Leffler