I've looked at several posts of the same questions on here and as far as I've figured I've done what they said to do. However, I still get a "undefined reference to `cmb::functionA()'" warning.
I have the header:
//combine.h
#ifndef COMBINE_H
#define COMBINE_H
namespace cmb
{
void functionA();
}
#endif
Function source file:
// combine.cc
#include <iostream>
#include "combine.h"
using namespace std;
namespace cmb
{
void functionA()
{
cout << "print something\n";
}
}
And main:
//main.cc
#include "combine.h"
using namespace std;
using namespace cmd;
int main(int argc, char *argv[])
{
functionA();
}
It is now working when compiling manually (g++ -o Test *.cc -Wall --std=c++17) but using make still gives me the same error. I really don't understand make files so any help would be appreciated.
makefile:
CXX := g++
CXXFLAGS += -Wall -std=c++17
LIBSRCS = $(filter-out main.cc,$(shell find -name \*.cc))
LIBOBJS = $(patsubst %.cc,%.o,$(LIBSRCS))
main: main.o combine.o libproject.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $# $<
$(LIBOBJS): %.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
libproject.a: $(LIBOBJS)
ar rcs $# $^
clean:
rm -f libproject.a $(LIBOBJS)
.PHONY: clean
I just use make main in terminal.
You must add combine.o after main: in the makefile.
Since you use a library, you need to tell the linker to use it (LDFLAGS), and it should be after the main in g++ command. As in previous comments, the using namespace cmd needed to be changed to cmb
This one worked for me:
CXX := g++
CXXFLAGS += -Wall -std=c++17
LIBSRCS = $(filter-out ./main.cc,$(shell find -name \*.cc))
LIBOBJS = $(patsubst %.cc,%.o,$(LIBSRCS))
LDFLAGS += -L. -lproject
main: main.o libproject.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# $< $(LDFLAGS)
libproject.a: $(LIBOBJS)
ar rcs $# $^
.PHONY: clean
clean:
rm -f libproject.a $(LIBOBJS) main main.o
I also needed to add ./ in filtering out main.cc
Example run:
jontte#jontte-Latitude-E5420:~/Temp/maketest$ make
g++ -Wall -std=c++17 -c -o main.o main.cc
g++ -Wall -std=c++17 -c -o combine.o combine.cc
ar rcs libproject.a combine.o
g++ -Wall -std=c++17 -o main main.o -L. -lproject
jontte#jontte-Latitude-E5420:~/Temp/maketest$ ./main
print something
jontte#jontte-Latitude-E5420:~/Temp/maketest$ make clean
rm -f libproject.a ./combine.o main main.o
jontte#jontte-Latitude-E5420:~/Temp/maketest$
Related
I am having trouble compiling using a makefile and including gflags. I have not done Makefiles in a while. The compile error I am getting is related to gflags
This is my makefile:
CXX = g++
CPPFlags = -g -Wall -std=c++11
LDLIBS = -lgflags
pa1: Main.cpp PA1.o Node.o
$(CXX) $(CPPFlags) $(LDFLAGS) Main.cpp Node.o PA1.o -o PA1
PA1.o:PA1.h PA1.cpp
$(CXX) $(CPPFlags) -c PA1.cpp -o PA1.o
Node.o:Node.h Node.cpp
$(CXX) $(CPPFlags) -c Node.cpp -o Node.o
This is my main.cpp
#include "PA1.h"
#include <string>
#include <iostream>
#include <fstream>
#include <string>
#include <gflags/gflags.h>
DEFINE_string(root, "0,0", "Root");
int main(int argc, char *argv[])
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
PA1 run= PA1(argv[2]);
std::string rc=FLAGS_root;
int r= rc[0];
int c= rc[2];
if(run.ReadMaze()==-1)
{
return -1;
}
run.SolveMaze(r,c);
return 0;
}
edit:
This is the error message
g++ -g -Wall -std=c++11 Main.cpp Node.o PA1.o -o PA1
/tmp/ccIdQf46.o: In function `main':
/home/peteryan/Documents/Main.cpp:10: undefined reference to
`google::ParseCommandLineFlags(int*, char***, bool)'
/tmp/ccIdQf46.o: In function `__static_initialization_and_destruction_0(int,
int)':
/home/peteryan/Documents/Main.cpp:7: undefined reference to
`google::FlagRegisterer::FlagRegisterer(char const*, char const*, char
const*, char const*, void*, void*)'
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'pa1' failed
make: *** [pa1] Error 1
The linker does not appear to be linking with with -lgflags and your Makefile is likely the cause. You should put your LDLIBS at the end of your build arguments. This generic Makefile will compile all the .cpp sources and link all the object files in the same directory. It also should track your header file dependencies. Notice the LDLIBS at the end of the build directive. Give it a try for your program.
program_name := PA1
CXX := g++
CXXFLAGS := —g -Wall std=c++11
LDLIBS := -lgflags
source_files := $(wildcard *.cpp)
objects := ${source_files:.cpp=.o}
all: $(program_name)
$(program_name): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(program_name) $(objects) $(LDLIBS)
depend: .depend
.depend: $(source_files)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
distclean: clean
rm -f *~ .depend
include .depend
I am sure this is stupid but i get this linker error
undefined reference to insert_record ,which is a function declared in Operations.hpp,implemented in Operations.cpp and used in main, and i can't find what is wrong in this makefile.
Maybe a pair of rested eyes can spot the problem.
It seems that operations isn't linked although the object is being created.
OBJS = main.o Operations.o CDR.o TBucketList.o RBucketList.o DateTime.o HashTable.o
CC = g++
CXXFLAGS = -W -Wall -Wno-unused -pedantic -c -g
LDFLAGS = -W -Wall -Wno-unused -pedantic -g
werhaus: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o werhaus
main.o : CDR.hpp Operations.hpp HashTable.hpp
$(CC) $(CXXFLAGS) main.cpp
Operations.o : Operations.hpp HashTable.hpp
$(CC) $(CXXFLAGS) Operations.cpp
TBucketList.o : TBucketList.hpp RBucketList.hpp
$(CC) $(CXXFLAGS) TBucketList.cpp
RBucketList.o : RBucketList.hpp
$(CC) $(CXXFLAGS) RBucketList.cpp
HashTable.o : HashTable.hpp TBucketList.hpp
$(CC) $(CXXFLAGS) HashTable.cpp
CDR.o : CDR.hpp DateTime.hpp
$(CC) $(CXXFLAGS) CDR.cpp
DateTime.o : DateTime.hpp
$(CC) $(CXXFLAGS) DateTime.cpp
clean:
\rm *.o werhaus
Update:
main.cpp :
insert_record(originator_number, aCDR, destination_number, hashtable1, hashtable2, BucketSize);
Operations.hpp:
void insert_record(const char*, CDR*, const char*, const Hashtable*, const Hashtable*, int);
Operations.cpp:
void insert_record(const char* originator_number, CDR* aCDR, const char* destination_number, Hashtable* hashtable1, Hashtable* hashtable2, int Bsize)
All seem fine in main..
There does not seem to be an error in your Makefile. As #G.M. noted, the dependencies of .o to corresponding .cpp are missing, these need to be added.
It can be that insert_record declaration in Operations.hpp does not match the definition in Operations.cpp and you end up with two functions insert_record. Check that the function declaration and definitions match: same return type and argument types, both in the same namespace.
I think you should better use something like this:
NAME= werhaus
CXX= g++ # Use CXX for C++
CXXFLAGS= -W -Wall -Wno-unused -pedantic -g
LDFLAGS= -g # No need for warning flags at linking
SRC= main.cpp \
Operations.cpp \
CDR.cpp \
TBucketList.cpp \
RBucketList.cpp \
DateTime.cpp \
HashTable.cpp
OBJS= $(SRC:.cpp=.o)
$(NAME): $(OBJS)
$(CXX) $(LDFLAGS) $(OBJS) -o $(NAME)
all: $(NAME)
%.o: %.cpp
$(CXX) -o $# -c $< $(CXXFLAGS)
clean:
rm -f $(OBJ)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
This type of makefile will avoid you a lot of errors.
Also, you don't need to put hpp files as dependencies.
Good luck.
In Operations.hpp you have a declaration with signature:
void insert_record(
const char*, CDR*,
const char*,
const Hashtable*,
const Hashtable*,
int)
In Operations.cpp you define a function with the different signature:
void insert_record(
const char* CDR*,
const char*,
Hashtable*,
Hashtable*,
int)
So the declaration in Operations.hpp is not in fact implemented in Operations.cpp
and is undefined.
I'm new to C++, and I'm having some trouble setting up a simple class reference.
Class: Test.hh
#ifndef _TEST_HH_
#define _TEST_HH_
class Test {
public:
Test (double x);
};
#endif
Class Test.cc
#include "Test.hh"
#include <stdio.h>
Test::Test(double x) {
printf("%f",x);
}
Now I want to access this class from another class:
Class: DriverClass.hh
#ifndef _DRIVERCLASS_HH_
#define _DRIVERCLASS_HH_
#include "Test.hh"
class DriverClass {
public:
DriverClass(double y);
Test *t;
}
#endif
Class DriverClass.cc
#include "DriverClass.hh"
DriverClass::DriverClass(double y) {
t = new Test(y);
}
However, I get an error: "undefined reference to 'Test::Test(double)?
Does anyone know what might be wrong? Please assume that DriverClass is being called directly from a main method (not shown).
There is still an error in your post - a missing ; after the DriverClass
declaration. The rest is correct.
You should compile and link all the sources. The following is a sample Makefile and a
sample test code.
Makefile
all: t
t: t.cc DriverClass.cc Test.cc
g++ -Wall -g -o $# $^
clean:
rm -f *.o t
However, note that it's generally recommended to compile the sources into objects separately in order to compile only the sources changed after the last compilation. For example:
CFLAGS=-Wall -g
all: t
t: t.o DriverClass.o Test.o
g++ -o $# $^
t.o: t.cc DriverClass.o Test.o
g++ $(CFLAGS) -c $< -o $#
DriverClass.o: DriverClass.cc
g++ $(CFLAGS) -c $< -o $#
Test.o: Test.cc
g++ $(CFLAGS) -c $^ -o $#
clean:
rm -f *.o t
I've used the GNU compiler. For the meaning of $# and $^ variables refer to the official documentation.
t.cc
#include "Test.hh"
#include "DriverClass.hh"
int main(int argc, char const* argv[])
{
DriverClass d(10.4);
return 0;
}
Testing
$ make
g++ -Wall -g -o t t.cc DriverClass.cc Test.cc
$ ./t
10.400000
P.S.: don't forget to delete the allocated object.
I have a C/C++ mixed project and for each source code, I want to generate an assembly file (.S) and then an object file (.o) from the assembly. I thought the following Makefile should work:
all: a.o b.o main.o
g++ $^ -o main
%.o: %.S
gcc -o $# $<
%.S: %.c
gcc -S -o $# $<
%.S: %.cc
g++ -S -o $# $<
clean:
rm -rf *.o main
Ideally, in order to generate X.o, X.S needs to be generated by using one of the rules depending on whether X.c or X.cpp is available.
However, make apparently doesn't work the way I imagined. It resorts to the default rule for X.o and neither %.S: %.c nor %.S: %.cpp was applied... make -n gives
cc -c -o a.o a.c
g++ -c -o b.o b.cc
g++ -c -o main.o main.cc
g++ a.o b.o main.o -o main
The following example code can reproduce this:
// a.c
int a() { return 0;}
// b.cc
int b() { return 0;}
// main.cc
extern "C" int a();
extern int b();
int main() { a(); b(); return 0; }
I must have some misunderstanding of how a target is resolved. Any idea?
Use .SUFFIXES: at the top of your Makefile to flush predefined suffixes. Working example:
$tail -n +1 a.c b.cc main.cc Makefile; make clean; make; ./main
==> a.c <==
#include <stdio.h>
void a(void) {
printf("a\n");
}
==> b.cc <==
#include <stdio.h>
void b(void) {
printf("b\n");
}
==> main.cc <==
extern "C" {
void a(void);
}
void b(void);
int main(void) {
a();
b();
}
==> Makefile <==
.SUFFIXES:
all: main.o a.o b.o
g++ $^ -o main # all
%.o: %.S
gcc -c -o $# $< #o
%.S: %.c
gcc -S -o $# $< #Sc
%.S: %.cc
g++ -S -o $# $< #Scc
clean:
rm -rf *.o main
rm -rf *.o main
g++ -S -o main.S main.cc #Scc
gcc -c -o main.o main.S #o
gcc -S -o a.S a.c #Sc
gcc -c -o a.o a.S #o
g++ -S -o b.S b.cc #Scc
gcc -c -o b.o b.S #o
g++ main.o a.o b.o -o main # all
rm b.S main.S a.S
a
b
You need to cancel the implicit rules as they are a better match, add the following lines
%.o: %.cc
%.o: %.c
Note that your rule for all is broken as it doesn't create a file called all, make already knows how to assemble object files from assembly, and it also already knows how to link object files into a program if one of the object files matches the target
assembly := a.s b.s main.s
objects := $(assembly:.s=.o)
.SECONDARY: $(assembly)
main: CC := $(CXX)
main: $(objects)
%.s: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -S -o $# $<
%.s: %.cc
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -S -o $# $<
%.o: %.cc
%.o: %.c
clean: ; $(RM) $(objects) $(assembly) main
In my test.cpp I have:
#include <iostream>
#include "first.h"
using namespace std;
int main ()
{
auto dliste = d::data_preparation::prepare_d(100);
cout << "Hello World!\n";
return 0;
}
In my first.h I have:
namespace d {
namespace data_preparation {
something;
std::vector<row<mdata::dliste>> prepare_d(int f);
something;
}
}
In my first.cpp I have:
#include "first.h"
something;
namespace d {
namespace data_preparation {
vector<row<mdata::dliste>> prepare_d(int f) {
vector<row<mdata::dliste>> dliste;
cout << f << '\n';
return dliste;
}
}
}
When I compile this I get:
undefined reference to
`d::data_preparation::prepare_d(int)'
EDITED
In my Makefile I have:
test: test.o
$(CXX) -o $# $(LDFLAGS) $^ $(LDLIBS)
Should I modify it somehow?
You have most likely forgot to link first.cpp to your executable.
Just run this commands (if you are using gcc):
g++ -c first.cpp -o first.o
g++ -c test.cpp -o test.o
g++ test.o first.o
Or just use the compact version:
g++ first.cpp test.cpp -o app
You should edit your Makefile along the lines of:
app: test.o first.o
$(CXX) $^ -o $# $(LDFLAGS) $(LDLIBS)
test.o: test.cpp
$(CXX) -c test.cpp -o first.o
first.o: first.cpp
$(CXX) -c first.cpp -o first.o
Notice: I'm forced to use 4 spaces for indentation but Makefile may require tabs instead.