0

I'm trying to link three files using g++. The files are simulation.o, lattice.o and thermodynamics.o.

They're a bit long, but the gist of it is. I have a makefile:

            main: simulation.o thermodynamics.o lattice.o
                g++ simulation.o thermodynamics.o lattice.o

            simulation.o: simulation.cpp lattice.o lattice.h thermodynamics.o thermodynamics.h
                g++ -std=c++11 simulation.cpp -o simulation.o -c

            thermodynamics.o: thermodynamics.cpp
                g++ -std=c++11 thermodynamics.cpp -o thermodynamics.o -lgsl -c

            lattice.o: lattice.cpp
                g++ -std=c++11 lattice.cpp -o lattice.o -c

It passes the compile stage, but never links them. For each method I need from a different file, it simply says that it's undefined, and and refuses to find them.

The classes and methods are all defined in the .h files. But for some reason I can define an external function but not an external class.

  • Why did you put `-lgsl` on one of your compile commands instead of the link command? – Andrew Henle Mar 21 '18 at 19:00
  • one of the files needs the -lgslg flag to link with gsl library. I'm a total noob in terms of makefiles, so I don't know at which stage do I need to link the binaries. – Petrosyan Alexander Mar 21 '18 at 19:15
  • 1
    important caveat: For the linker, the file order matters. When linking in an incorrect order the linker will complain about: "undefined reference to 'some_func'". see https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc – Daniel Mar 21 '18 at 19:33
  • Show complete make output of a clean build. – Maxim Egorushkin Mar 21 '18 at 20:18
  • Got it. I was redeclaring the classes inside the .cpp files, This meant that what I thought were implementations were actually methods from a different class. – Petrosyan Alexander Mar 21 '18 at 20:25

2 Answers2

1

It fails to link because your makefile uses linker flags when compiling. Whereas the linker flags must be used when linking.

Corrections:

CXXFLAGS := -std=c++11 -Wall -Wextra

main: simulation.o thermodynamics.o lattice.o
    g++ -o main simulation.o thermodynamics.o lattice.o -lgsl

simulation.o: simulation.cpp lattice.h  thermodynamics.h
    g++ -c ${CXXFLAGS} -o simulation.o simulation.cpp 

thermodynamics.o: thermodynamics.cpp thermodynamics.h
    g++ -c ${CXXFLAGS} -o thermodynamics.o thermodynamics.cpp 

lattice.o: lattice.cpp lattice.h
    g++ -c ${CXXFLAGS} -o lattice.o lattice.cpp 
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • In general gcc seems to collect unknown symbols from your files, and expects that it'll find the actual definitions later. Your link phase is actually for the target `main` so all libraries go there. Looking at the headers you list, it looks like your dependencies are: * simulation -> lattice and thermodynamics * thermodynamics -> libgsl (from your original makefile) * lattice -> nothing So the link line above for main declares them in this order. Equivalently I think that `simulation.o lattice.o thermodynamics.o -lgsl` would also work. – Hitobat Mar 21 '18 at 19:46
  • It works if I dereference all the class and method calls. But I do need those classes (otherwise what's the point). – Petrosyan Alexander Mar 21 '18 at 19:51
  • @PetrosyanAlexander Added a note. – Maxim Egorushkin Mar 21 '18 at 20:05
  • I wrote the exact same makefil, the problem is still there. Weirdly, if I did `g++ *.cpp -o main`, it would still fail with the same error message. – Petrosyan Alexander Mar 21 '18 at 20:06
0

I figured out what went wrong. Had to do with the way I've split the classes between files.

I declared the classes in the .h files, and then redeclared them inside .cpp files. Instead I should have filled the cpp files with implementations of the form class::method(params).

Also I didn't #include the .h file inside the .cppfile.

Lastly, I also had the wrong order of linkage: as pointed out by @Maxim Egorushkin, the order of linking matters. I should have linked the files all at once, and not at the final stage.

Thanks for everyone that answered!