jhc
jhc

Reputation: 1769

Compiling error (g++ and make)

I have attempted to convert a working C++ library that was compiled in the Visual Studio 2010 IDE to a generic project compilable in any standard compiler. I have apparently been successful in that objective since I have been able to compile with an Eclipse C++ IDE under Ubuntu 12.10.

I have since tried to compile the same using g++ and a Makefile in the terminal. Unfortunately I have not met with the same success. I seem to be rather close to good compilation though as I have only received these errors:

./liborbit.a(cOrbit.o): In function `Zeptomoby::OrbitTools::cEci::ScalePosVector(double)':
/home/tufts/Programs/workspace/orbitTools/Demo/../core/cEci.h:35: undefined reference to `Zeptomoby::OrbitTools::cVector::Mul(double)'
./liborbit.a(cOrbit.o): In function `Zeptomoby::OrbitTools::cEci::ScaleVelVector(double)':
/home/tufts/Programs/workspace/orbitTools/Demo/../core/cEci.h:36: undefined reference to `Zeptomoby::OrbitTools::cVector::Mul(double)'
./liborbit.a(cNoradBase.o): In function `Zeptomoby::OrbitTools::cNoradBase::FinalPosition(double, double, double, double, double, double, double, double)':
/home/tufts/Programs/workspace/orbitTools/Demo/../orbit/cNoradBase.cpp:265: undefined reference to `Zeptomoby::OrbitTools::cVector::Magnitude() const'
/home/tufts/Programs/workspace/orbitTools/Demo/../orbit/cNoradBase.cpp:285: undefined reference to `Zeptomoby::OrbitTools::cEciTime::cEciTime(Zeptomoby::OrbitTools::cVector const&, Zeptomoby::OrbitTools::cVector const&, Zeptomoby::OrbitTools::cJulian)'
collect2: ld returned 1 exit status
make: *** [compile] Error 1

It appears that the orbit library functions use the core library functions themselves.

File system organization:

orbitTools/
├── core
│   ├── cEci.cpp
│   ├── cEci.h
│   ├── cJulian.cpp
│   ├── cJulian.h
│   ├── coord.cpp
│   ├── coord.h
│   ├── coreLib.h
│   ├── cSite.cpp
│   ├── cSite.h
│   ├── cTle.cpp
│   ├── cTle.h
│   ├── cVector.cpp
│   ├── cVector.h
│   ├── exceptions.h
│   ├── globals.cpp
│   ├── globals.h
│   ├── stdafx.cpp
│   └── stdafx.h
├── Demo
│   ├── main.cpp
│   └── Makefile
└── orbit
    ├── cNoradBase.cpp
    ├── cNoradBase.h
    ├── cNoradSDP4.cpp
    ├── cNoradSDP4.h
    ├── cNoradSGP4.cpp
    ├── cNoradSGP4.h
    ├── cOrbit.cpp
    ├── cOrbit.h
    ├── stdafx.cpp
    └── stdafx.h

Note the localization of the Makefile.

The Makefile itself is:


    # COMPILER
    CC = g++

    # INCLUDE FILES DIRECTORY
    MAIND = $(PWD)/..
    COMPILE = $(MAIND)/compile
    CORE = $(MAIND)/core
    ORBIT = $(MAIND)/orbit
    INCLUDE = -I$(MAIND) -I$(CORE) -I$(ORBIT) -I.

    # OPTIONS FOR DEVELOPMENT
    CFLAGS = -g -ansi

    compile: main.o libs
        $(CC) $(INCLUDE) $(CFLAGS) main.o -L. -lcore -lorbit -lm -o demo

    main.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c main.cpp

    # CORE LIBRARY
    cEci.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/cEci.cpp

    cJulian.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/cJulian.cpp

    coord.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/coord.cpp

    cSite.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/cSite.cpp

    cTle.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/cTle.cpp

    cVector.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/cVector.cpp

    globals.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/globals.cpp

    stdafx.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(CORE)/stdafx.cpp

    core: cEci.o cJulian.o coord.o cSite.o cTle.o cVector.o globals.o stdafx.o
        ar rcs libcore.a cEci.o cJulian.o coord.o cSite.o cTle.o cVector.o globals.o stdafx.o

    # ORBIT LIBRARY
    cNoradBase.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(ORBIT)/cNoradBase.cpp -lcore

    cNoradSDP4.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(ORBIT)/cNoradSDP4.cpp -lcore

    cNoradSGP4.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(ORBIT)/cNoradSGP4.cpp -lcore

    cOrbit.o:
        $(CC) $(INCLUDE) $(CFLAGS) -c $(ORBIT)/cOrbit.cpp -lcore

    orbit: cNoradBase.o cNoradSDP4.o cNoradSGP4.o cOrbit.o stdafx.o
        ar rcs liborbit.a cNoradBase.o cNoradSDP4.o cNoradSGP4.o cOrbit.o stdafx.o

    libs: core orbit

    clean:
        rm *.o

    purge:
        rm *.a

Upvotes: 0

Views: 1573

Answers (1)

MadScientist
MadScientist

Reputation: 101061

If orbit uses core, then -lorbit MUST come before -lcore.

If core also uses orbit (cyclical dependency), then you need to do something like -lorbit -lcore -lorbit (list one of them twice).

Elucidation:

The GNU linker (like most UNIX linkers) is a "single pass linker". This means it starts with your object files and notes any unresolved symbols. Then it looks at the first library on the link line and pulls in any objects that can satisfy one or more of those unresolved symbols. At the same time, it will add any newly-unresolved symbols that were referenced by those objects it pulled in. Then it goes to the next library on the link line. Etc.

If it gets through all libraries on the link line and there are still unresolved symbols, then the link fails.

So, you need to order your libraries so that the most basic libraries, that don't depend on anything else, are at the end. The g++ front-end will automatically add -lc, the C runtime library, at the end--obviously that's the MOST basic library. Libraries that depend on nothing except the basic libraries come right before those. Etc.

Upvotes: 2

Related Questions