Reputation: 1769
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.
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
.
# 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
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