When I try to compile all of my object files into an executable, I get the error
lab5.o:lab5.cpp: undefined reference to 'Card::suitMap'
I assume it's an issue with correctly linking dependencies, but I don't really know how to verify whether I'm on the right track.
Here's the source file containing the main function:
#include "Card.h"
#include "Deck.h"
#include <iostream>
using namespace std;
int main()
{
Deck* deck1 = new Deck();
Deck* deck2 = new Deck();
for(int i = 0; i < deck1->deck.size(); i++)
{
Card card = deck1->draw();
cout << card.getSuit() << " " << card.getValue() << endl;
}
deck2->shuffle();
for(int i = 0; i < deck2->deck.size(); i++)
{
Card card = deck2->draw();
cout << card.getSuit() << " " << card.getValue() << endl;
}
}
Here's my Card.h which contains suitMap
#ifndef CARD_H
#define CARD_H
#include <string>
#include <map>
class Card {
private:
int value;
int suit;
public:
std::map <int, std::string> suitMap;
Card(int value, int suit);
int getValue() { return this->value; }
std::string getSuit() { return this->suitMap.find(this->suit)->second; }
};
#endif
I'm not sure if my makefile could contain the problem, but here it is as well
CC=g++
CFLAGS=-c -Wall -g -std=c++11
LDFLAGS=
SOURCES=lab5.cpp Card.cpp Deck.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=lab5
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -f *.o $(EXECUTABLE)
You must have had suitMap previously denoted static, and somehow not obtained a clean build after changing that. Be sure to perform a full clean build after modifying headers.
Your problem is due to a flaw in the makefile. A correctly designed makefile automatically manages all dependencies and thereby eliminates the need for running make clean to fix a build.
Below is an example makefile that would have prevented your problem. Rather than doing incremental builds, it always recompiles every source file. As you create larger projects, this approach may eventually become too slow, in which case you will want to invest in a more sophisticated build management solution. For your existing project, with this makefile, builds will likely take around one second on a modern PC.
EXECUTABLE = lab5
SOURCES += lab5.cpp Card.cpp Deck.cpp
CXXFLAGS += -Wall -Werror
CXXFLAGS += -std=c++11
CXXFLAGS += -g
.PHONY: build
build:
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(SOURCES) $(LDLIBS) -o $(EXECUTABLE)
.PHONY: clean
clean:
rm -f $(EXECUTABLE)
Related
My C++ program consists of three files:
two source files 'main.cpp' and 'hellolib.cpp'
a header file 'hellolib.h'
I am creating a makefile for this program. For my assignment I need one target ('hello') that compiles all source files in an executable.
Another target ('obj') should compile all '.cpp' files into objects and link them together in an executable.
When running make I prefer the object files to be created in a seperate folder called 'bin'. The source files are would be in a folder called 'src'. These folders are siblings, the makefile is in it's parent folder.
My makefile works fine but I wish two combine the two targets 'bin/main.o' and 'bin/hellolib.o' into one to reduce the amount of rules, especially for later when I am dealing with more source files.
I imagined the replacement would look something like this, but it doesn't seem to work.
It gives me the error: "*** No rule ot make target 'bin/main.o',
needed by 'obj'. Stop.
bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Working Makefile:
CC = g++
SOURCES = ./src/main.cpp \
./src/hellolib.cpp
OBJECTS = ./bin/main.o \
./bin/hellolib.o
hello : $(SOURCES)
$(CC) -o $# $^
obj : $(OBJECTS)
$(CC) -o $# $^
bin/main.o : src/main.cpp
$(CC) -c $< -o $#
bin/hellolib.o : src/hellolib.cpp
$(CC) -c $< -o $#
clean:
#rm -rf hello obj bin/*.o
main.cpp:
#include "hellolib.h"
int main() {
Hello h("Name");
h.Print();
return 0;
}
hellolib.cpp
#include "hellolib.h"
#include <iostream>
Hello::Hello(std::string name) {
if (name.empty()) {
cout << "Name is not valid!";
return;
}
_name = name;
}
void Hello::Print() {
cout << "Hello " << _name << endl;
}
hellolib.h
#ifndef HELLO_LIB_H
#define HELLO_LIB_H
#include <string>
using namespace std;
class Hello {
std::string _name;
public:
Hello(std::string name);
void Print();
};
#endif
You need to change:
OBJECTS = ./bin/main.o \
./bin/hellolib.o
to:
OBJECTS = bin/main.o \
bin/hellolib.o
(Removing leading "./"). Either that, or change your pattern rule to include the leading "./":
./bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Make rule matching uses text matching. It's not based on filenames, so "./././foo" and "foo" are not the same thing.
Personally I recommend rewriting like this:
SOURCES = src/main.cpp \
src/hellolib.cpp
OBJECTS = $(patsubst src/%.cpp,bin/%.o,$(SOURCES))
so you only need to keep the list of files in one place.
You can make a rule that builds anything conforming to a specific pattern like this:
bin/%.o : src/%.cpp
$(CC) -c -o $# $<
That will compile any bin/%.o dependency from the corresponding source src/%.cpp.
Also it is standard when compiling C++ to use CXX rather than CC (which is for C code).
I keep getting an error saying...
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [FuelGauge] Error 1
My project is below as well as my code and makefile. Also if you see any other coding errors feel free to point them out =]
Simulator Class
#include <iostream>
#include <iomanip>
#include "FuelGauge.h"
#include "Odometer.h"
using namespace std;
int main(){
FuelGauge fuel(0); return 0;
}
FuelGauge class
#include "FuelGauge.h"
#include <iostream>
#include <cstdlib>
using namespace std;
void FuelGauge::incrementGas(int gas){
if(currentFuel < maxGallon) {
currentFuel++;
}
}
int FuelGauge::getGas(){
return currentFuel;
}
FuelGauge.h
class FuelGauge {
private:
int currentFuel;
int maxGallon;
public:
void incrementGas(int);
int getGas();
};
Odometer class
#include "FuelGauge.h"
#include "Odometer.h"
#include <iostream>
#include <cstdlib>
using namespace std;
private: int currentMileage;
Odometer::Odometer(){
mileage = 0;
Fuelgauge g;
}
int Odometer::getMileage(){
return mileage;
}
void Odometer::incrementMileage(){
if(mileage <= 999999){
mileage++;
}
else{
mileage = 0;
}
void Odometer::decreaseMileage(){
if(g.currentFuel > 24){
g.currentFuel--;
}
}
}
Odometer.h
class Odometer{
private:
int mileage;
int gallons;
}
Makefile
FLAGS = -Wall
CC = g++
SYMBOLS = -g
all: FuelGauge Odometer CarSimulatorDemo
FuelGauge: FuelGauge.cpp FuelGauge.h
$(CC) $(FLAGS) $(SYMBOLS) -o $# FuelGauge.cpp
Odometer: Odometer.cpp Odometer.h
$(CC) $(FLAGS) $(SYMBOLS) -o $# Odometer.cpp
CarSimulatorDemo: CarSimulatorDemo.cpp
$(CC) $(FLAGS) $(SYMBOLS) -o $# CarSimulatorDemocpp
clean:
rm FuelGauge Odometer CarSimulatorDemo
The problem you're getting is probably not because of your c++ code but rather your Makefile. You want to compile each of your cpp files rather to a object file than the separate application and then link them together into single app. To compile cpp to the .o file use -c option.
To sum up your Makefile should be as follows:
FLAGS = -Wall
CC = g++
SYMBOLS = -g
all: app
app: FuelGauge.o Odometer.o CarSimulatorDemo.o
$(CC) $(FLAGS) $(SYMBOLS) *.o -o app
FuelGauge.o: FuelGauge.cpp FuelGauge.h
$(CC) $(FLAGS) $(SYMBOLS) -c -o FuelGauge.o FuelGauge.cpp
Odometer.o: Odometer.cpp Odometer.h
$(CC) $(FLAGS) $(SYMBOLS) -c -o Odometer.o Odometer.cpp
CarSimulatorDemo.o: CarSimulatorDemo.cpp
$(CC) $(FLAGS) $(SYMBOLS) -c -o CarSimulatorDemo.o CarSimulatorDemo.cpp
clean:
rm FuelGauge.o Odometer.o CarSimulatorDemo.o app
Remember to change spaces in your Makefile to tabulators!
PS. #ifndef should always imply using #endif and in header files always use them!
Your Odometer.h does not end in #endif. Since it has already been included through FuelGauge.h, ODOMETER_H is defined and everything after #ifndef is not compiled (preprocessor expands it to whitespace). Including the function main.
I am attempting to write a makefile for the Cell Broadband Engine (PS3), which will link an external library.
The Makefile is as follows:
PROJ=apple_sort_ppu
PCC=ppu-g++
CFLAGS=-Wall
LIBS= -lX11 -lspe2 -lpthread
objects = apple_sort_ppu.o lodepng.o ThreadPool.o SPUTask.o
#Imports is for linking the extern spu program library to SPUTask.o. Currently not linking correctly
IMPORTS := spu/lib_process_spu_a.a $(LIBS)
all: $(PROJ)
apple_sort_ppu: $(objects)
$(PCC) $(objects) -o $(LIBS)
apple_sort_ppu.o: apple_sort_ppu.cpp
$(PCC) $(CFLAGS) -c apple_sort_ppu.cpp $(LIBS)
lodepng.o: lodepng.cpp lodepng.h
$(PCC) $(CFLAGS) -c lodepng.cpp
SPUTask.o: SPUTask.cpp SPUTask.h $(IMPORTS) ThreadPool.o
$(PCC) $(CFLAGS) -c SPUTask.cpp
ThreadPool.o: ThreadPool.cpp ThreadPool.h
$(PCC) $(CFLAGS) -c ThreadPool.cpp $(LIBS)
clean:
rm $(objects) *.d
include $(CELL_TOP)/buildutils/make.footer
When I run make on this file, I get :
No rule to make spu/lib_process_spu_a.a, needed by SPUTask.o. STOP
I have confirmed that the library exists in the correct directory. My experience of Makefiles is extremely limited, so I don't really understand what is going on here.
The file causing the problem in the makefile is SPUTask.h, with the header code:
#pragma once
#include "ThreadPool.h"
#include <libspe2.h>
extern spe_program_handle_t process_spu_a;//Program handle
class SPUTask : public Task
{
public:
SPUTask(int i_id = 0);
virtual ~SPUTask(){;}
virtual void execute();
virtual bool hasReturnData(){return false;}
virtual int getTaskID(){return m_id;}
void setData(unsigned char* pData, int pSize);
void setContext(spe_context_ptr_t pContext){mContext = pContext;}
private:
unsigned char* mData __attribute__((aligned(128)));
int m_id;
int mDataSize;
spe_context_ptr_t mContext;
};
process_spu_a has already been compiled into lib_process_spu_a.a in the /spu subdirectory.
Any help would be greatly appreciated.
I'm having issues when compiling/Linking with LTO enabled with GCC 4.8.1. I get undefined references to symbols in a DLL even though they seem to be present. The strange thing is, without LTO enabled it compiles and links successfully. LTO seems to struggle when there is a virtual destructor that hasn't been defined in the derived class.
Removing the DECLSPEC makes it compile and work with LTO enabled.
Dependency walker shows the symbols are there. The link time optimizer just can't seem to find them.
Declaring any type of destructor in derived class Test makes it work.
Removing LTO optimization also makes it work successfully, I'm wondering why this is an issue.
Test is a shared library, Main links to the shared library.
Test.h
#include <string>
#ifdef SOURCE
#define DECL __declspec(dllexport)
#warning Exporting!
#else
#define DECL __declspec(dllimport)
#warning Importing!
#endif
class DECL TestBase
{
public:
TestBase(const std::string testing);
virtual ~TestBase();
std::string getTesting();
private:
std::string _testing;
};
class DECL Test : public TestBase
{
public:
Test(const std::string testing);
//~Test(); //removing causes a linker error with LTO! Fine without LTO.
};
Test.cpp
#include "Test.h"
TestBase::TestBase(const std::string testing)
{
_testing = testing;
}
TestBase::~TestBase()
{
}
std::string TestBase::getTesting()
{
return _testing;
}
Test::Test(const std::string testing) :
TestBase(testing)
{
}
/*Test::~Test() //removing causes a linker error with LTO! Fine without LTO.
{
}*/
Main.cpp
#include "Test.h"
#include <iostream>
int main()
{
Test test("testing!");
std::cout << test.getTesting() << std::endl;
return 0;
}
Excuse my messy makefile..
CC=g++
LD=g++
LIBCFLAGS= -O3 -march=pentium4 -mfpmath=sse -flto -fuse-linker-plugin
LIBEXTRA= -c -DSOURCE
LIBLDFLAGS= ${LIBCFLAGS} -shared
LIBSOURCES=Test.cpp
LIBRARY=Test.dll
EXECFLAGS= -O3 -march=pentium4 -mfpmath=sse -flto -fuse-linker-plugin
EXTRA= -c
EXELDFLAGS= ${EXECFLAGS} -L. -lTest
SOURCES=Main.cpp
EXECUTABLE=main
LIBOBJECTS=$(LIBSOURCES:.cpp=.o)
OBJECTS=$(SOURCES:.cpp=.o)
all: $(SOURCES) $(LIBRARY) $(EXECUTABLE)
$(LIBRARY): $(LIBOBJECTS)
$(LD) $(LIBLDFLAGS) $(LIBOBJECTS) -o $#
$(EXECUTABLE): $(OBJECTS)
$(LD) $(EXELDFLAGS) $(OBJECTS) -o $#
$(OBJECTS): CFLAGS := $(EXECFLAGS) $(EXTRA)
$(LIBOBJECTS): CFLAGS := $(LIBCFLAGS) $(LIBEXTRA)
.cpp.o:
#echo "... Making: $#"
$(CC) $(CFLAGS) $< -o $#
clean:
- del /f /q *.o
- del /f /q *.dll
- del /f /q *.exe
I'm trying to compile a multi file bit of code which up until now has been working fine.
But now I am getting some linker errors. I have a class definition 'njPhaseSpace' which is reported as being:
ld: duplicate symbol njPhaseSpace::njPhaseSpace(int)in Source/Currents.o and
/var/folders/p8/0bwv51kn2w5cx4jnsg6xm7340000gn/T//ccb0Psoz.o for architecture x86_64
I have no idea what the /var/folder/.../ccb0Psoz.o file is about and it isnt (intentionally) begin used in my project.
if I change the name to something different - but similar - such as njPhaseSpaceX it will compile and link up fine. But then I clean the project using 'make clean' and when I try to remake I get the same link error again! (but with a different /var/.../XXXXXX.o file)
Any suggestions?
Cheers
UPDATE: More strange things: When I look in the /var/folder/... directory to see which file is causing the duplication no such file exists!
UPDATE: The njPhaseSpace source file is:
// Standard header files
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <stdio.h>
#include <math.h>
#include <complex>
#include <iomanip>
#include "LoadBar.h"
// CLHEP header files
#include <CLHEP/Vector/LorentzVector.h>
#include <CLHEP/Random/RanluxEngine.h>
// More convenient label for four-vectors
typedef CLHEP::HepLorentzVector HLV;
// Definition of structure to hold the phase-space point
struct ParticleStruct {
HLV pa;
HLV pb;
HLV pep;
HLV pem;
HLV p1;
HLV p2;
HLV p3;
double xa;
double xb;
} ;
// A class for the n-jet phase space
class njPhaseSpace {
private:
// Incoming Particle Momenta
HLV pa;
HLV pb;
// Emitted leptons
HLV pep;
HLV pem;
// Outgoing parton momenta
std::vector <HLV> OutgoingPartons;
// Kinematic factors
double xa;
double xb;
public:
// Constructor for class
njPhaseSpace(int n);
// Returns a vector of the outgoing parton momenta
std::vector <HLV> ReturnOutgoingPartons() {
return OutgoingPartons;
}
// HLV IncomingForward
} ;
// Class constructor - adds n vectors to the Outgoing array
njPhaseSpace::njPhaseSpace(int n) {
// Add n final states to the OutgoingPartons vector
for (int i = 0; i < n; i++) {
HLV temp;
OutgoingPartons.push_back(temp);
}
}
UPDATE: This problem goes away when the class constructor is included in the body of the class definition. Whilst its good I can avoid this it doesnt really help because now to develop my class everything will have to sit inside the definition.
UPDATE: The makefile used to compile (Analysis is something seperate I am currently running make Explorer -j8):
#/bin/bash
# CXX Compiler
CXX = g++
# Directories For Compilation
INCDIR = MadGraph
LIBDIR = MadGraph
SRCDIR = Source
# Compilation Flags
CXXFLAGS = -O3 -lm
LIBFLAGS = $(shell clhep-config --libs) $(shell fastjet-config --libs) $(shell clhep-config --libs) $(shell root-config --libs)
INCFLAGS = $(shell clhep-config --include) -I/$(INCDIR) -I$(SRCDIR) -I. $(shell fastjet-config --cxxflags --plugins) $(shell clhep-config --libs) $(shell root-config --cflags)
FLAGS = $(CXXFLAGS) $(LIBFLAGS) $(INCFLAGS)
# Object Files
Objects = $(addprefix $(SRCDIR)/, Currents.o mstwpdf.o LoadBar.o)
MadObjects = $(addprefix $(LIBDIR)/, HelAmps_sm.o Parameters_sm.o read_slha.o CPPProcess2j.o CPPProcess3j.o)
# Main targets
all: Analysis Explorer
Analysis: $(SRCDIR)/Analysis2jepem.cxx $(Objects) $(SRCDIR)/CGenerator2jepem.o
$(CXX) $(SRCDIR)/Analysis2jepem.cxx -o $# $(FLAGS) $(Objects) $(SRCDIR)/CGenerator2jepem.o
Explorer: $(SRCDIR)/qQepemqQ_Explorer.cxx $(Objects) $(MadObjects) $(LIBDIR)/libmodel_sm.a
$(CXX) $(SRCDIR)/qQepemqQ_Explorer.cxx -o $# $(FLAGS) $(Objects) -lmodel_sm -L$(LIBDIR)
# Build object files
$(Objects):
$(CXX) -c $(#:.o=.cxx) -o $#
# Build the MG5 object code
$(MadObjects):
$(CXX) -c $(#:.o=.cxx) -o $# -I../
$(SRCDIR)/CGenerator2jepem.o:
$(CXX) -c $(#:.o=.cxx) -o $#
# Build the Standard Model library
$(LIBDIR)/libmodel_sm.a: $(MadObjects)
$(AR) cru $# $^
ranlib $#
# Debugging flags
debug: CXX += -g -Wall -pendantic
debug: all
# Create a clean build
.PHONY: clean
clean:
rm -f $(Objects) $(MadObjects) $(LIBDIR)/2j/libmodel_sm.a $(LIBDIR)/3j/libmodel_sm.a $(TARGET) $(SRCDIR)/CGenerator2jepem.o Analysis Explorer
The problem is that the class constructor is defined in the header file as:
njPhaseSpace::njPhaseSpace(int n) {
// Add n final states to the OutgoingPartons vector
for (int i = 0; i < n; i++) {
HLV temp;
OutgoingPartons.push_back(temp);
}
Either put it in the class declaration, or into it's own separate .cpp file that is compiled and linked separately.
This is no different from creating a non-inline/non-static/non anonymous namespaced function in a .h file and #including it in multiple .cpp files.
This error is sometimes prompted if you include the files like this:
File a included in file b;
Filb and file a included in file c.
Can you try to put the "static" keyword in front of the class constructor that gives you problems?