Undefined reference from C++ to variables/functions defined in C file - c++

I've been given a package of files (one .cpp, and some .c and .h) and want to make some modifications. But right now I'm just trying to get the original version to compile (in Linux).
Here's a (really) minimal working example:
mainfile.cpp
extern "C"{
#include "auxfile.h"
}
int main(int argc, char * argv[]){
getfoo(temperature);
return 0;}
auxfile.h
#define PUBLIC
#define PRIVATE static
extern int temperature;
int getfoo( int inputint);
auxfile.c
#include "auxfile.h"
int temperature = 37;
PUBLIC int getfoo( int inputint){
return 7;
}
When I type
g++ mainfile.cpp
I get
mainfile.cpp(.text+0x11): undefined reference to `temperature'
mainfile.cpp(.text+0x18): undefined reference to `getfoo'
collect2: ld returned 1 exit status
For what it's worth, I've looked through numerous "undefined reference" questions and spent dozens of hours working on my own. The above code presents the essence of the problem. Any help would be massively appreciated. Thanks.

At the time of linking, all symbols (except those for dynamic linking, aka shared libraries) have to be defined. To create an object file with possibly unresolved symbols for later linking, there is the -c flag, that means just compile, do not link.
So, the following would work:
g++ -c -omainfile.o mainfile.cpp
gcc -c -oauxfile.o auxfile.c
g++ -o mainfile mainfile.o auxfile.o
Only the last line actually invokes the linker and as you have both object files, all symbols are found.
Just for completeness, in a real-world scenario you'd handle compiling and linking using make. Create a Makefile with the following contents:
OBJS:= mainfile.o auxfile.o
all: mainfile
# $# means what to build (in this case "mainfile"), $^ is replaced by all
# dependencies (here the contents of the variable OBJS)
mainfile: $(OBJS)
g++ -o$# $^
# pattern for *.cpp -> create a *.o file with same name using g++
%.o: %.cpp
g++ -c -o$# $<
# the same for *.c, but using gcc here
%.o: %.c
gcc -c -o$# $<
clean:
rm -f $(OBJS)
# "PHONY" are targets, that are not actually the names of output files
.PHONY: all clean
Then just type make and see the "magic" happening. Of course this is just for starters, no dependencies are tracked etc...

Related

Makefile/C++ Classes: Makefile error for C++? Or maybe class definition error?

I'm trying to make a Makefile, but don't quite understand how it works, and therefore can't really debug it, and add the proper things in it.
I have a total of three files. My "main" file:
valid_board.cpp
and then I have a .h and a .cpp file that define a class:
xword_puzzle.h
xword_puzzle.cpp
In xword_puzzle.cpp I wrote #include "xword_puzzle.h" , in xword_puzzle.h, I wrote #pragma once, and in valid_board.cpp I wrote #include "xword_puzzle.h". Despite this, when I run my Makefile, it doesn't seem to be properly including the class I have defined in the xword_puzzle files.
I have this as a makefile that compiles just the main file.
# the compiler: gcc for C program, define as clang++ for C++
CXX=clang++
# compiler flags:
# -g adds debugging information to the executable file
# -Wall turns on most, but not all, compiler warnings
CXXFLAGS=-g -std=c++11 -Werror -D_GLIBCXX_DEBUG
# the build target executable:
TARGET = valid_board
all: $(TARGET)
$(TARGET): $(TARGET).cpp
$(CXX) $(CXXFLAGS) -o $(TARGET) $(TARGET).cpp
clean:
$(RM) $(TARGET)
EXAMPLE OF ERROR:
In xword_puzzle.cpp I define the class
Puzzle::Puzzle(char** xword, int rows, int cols) { ...
but then in * valid_board.cpp* I attempt to type
Puzzle* asdf_puz = new Puzzle(puzzle, 15, 15);
and get the following error:
Undefined symbols for architecture x86_64:
"Puzzle::Puzzle(char**, int, int)", referenced from:
_main in valid_board-c21998.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It should be noted that currently my xword_puzzle.h contains
class Puzzle {
public:
Puzzle(char** xword, int rows, int cols);
private:
vector<string> accrosses;
vector<string> downs;
};
and when I remove public: the error changes to
valid_board.cpp:54:28: error: calling a private constructor of class 'Puzzle'
Puzzle* asdf_puz = new Puzzle(puzzle, 15, 15);
^
./xword_puzzle.h:15:3: note: implicitly declared private here
Puzzle(char** xword, int rows, int cols);\
^
which leads me to belive that the error might be elsewhere.
The error you are getting Undefined symbols for architecture means that linker - a program to 'assemble' an executable from multiple obj files - can not find 'implementation' of Puzzle::Puzzle(char**, int, int) - but this implementation is required. Not you do have implementation in xword_puzzle.cpp but you don't tell linker to use it:
$(CXX) $(CXXFLAGS) -o $(TARGET) $(TARGET).cpp
this line will be interpreted as:
clang++ -g -std=c++11 -Werror -D_GLIBCXX_DEBUG -o valid_board valid_board.cpp
which means compile 'valid_board' from valid_board.cpp.
I suggest you check http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ as it gives an example close to your use case:
CXX=clang++
# compiler flags:
# -g adds debugging information to the executable file
# -Wall turns on most, but not all, compiler warnings
CXXFLAGS=-g -std=c++11 -Werror -D_GLIBCXX_DEBUG
# the build target executable:
TARGET = valid_board
DEPS = xword_puzzle.h
OBJ = valid_board.o xword_puzzle.o
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(TARGET): $(OBJ)
$(CXX) -o $# $^ $(CXXFLAGS)

C/C++ project compiles with Xcode but not with gcc/g++

When compiling a little C or C++ project in terminal using gcc, g++ or make, I get these kind of errors:
/tmp/ccG1caGi.o: In function `main':
main.c:(.text+0xa): undefined reference to `display_menu'
main.c:(.text+0xf): undefined reference to `get_input'
collect2: ld returned 1 exit status
main.c:
#include "menu.h"
int main()
{
display_menu();
get_input();
return 0;
}
menu.h:
void display_menu();
int get_input();
However with Xcode I get no errors or warnings.
What could be the issue here? It's seems it's like this when I include files.
So, gcc is complaining that it doesn't know where display_menu and get_input are, what they are doing or how to link them in, and rightly so.
You probably have more sourcefiles, where those functions are defined (menu.c, perhaps?). If so, add them to your compile instruction:
gcc main.c menu.c
Alternatively, just compile into an object (waiting for the functions later) with the -c flag. This will not make an executable, but will make an object file that awaits final compilation with
gcc main.c -c # Make the main.o object
gcc menu.c main.o # Link the main.o object with a compiled menu.c
into a final executable.
Xcode, in all likelihood, knows all about all your source files, and is happy to put them all together in its compilation step. If you are doing it manually, you have to do a little more work yourself. Its not when you include files (h files, that is) but when you have multi-file sources.
Try with a basic Makefile:
CC=gcc
CFLAGS=-W -Wall
LDFLAGS=
SRC= $(wildcard *.c)
OBJ= $(SRC:.c=.o)
all: myexec
myexec: $(OBJ)
#$(CC) -o $# $^ $(LDFLAGS)
%.o: %.c
#$(CC) -o $# -c $< $(CFLAGS)
.PHONY: clean
clean:
#rm -rf *.o

C++ "undefined reference to" function error

I've been having some problems compiling this code for mergesort on an array of custom data types. The undefined reference is in response to
mergesort(hw1type*, int)
Here are the relevant code snips leaving out the includes, and what not, which I know all work:
Main (Where the error is propagating to):
hw1type * unsorted_array2 = new hw1type[SIZE];
unsorted_array2 = create_random_hw1type(SIZE);
mergesort(unsorted_array2, SIZE);
mergesort.h:
hw1type* mergesort(hw1type*, int);
hw1type* merge(hw1type*, int, hw1type*, int);
mergesort.cc:
hw1type mergesort(hw1type* unsorted_array, int n)
I can't see anything wrong with the way the functions are declared, or the way I'm passing the variables in main. But, it's been a while since I've used c++ so I could use a second or third pair of eyes!
Edit: Turns out it was the make file, I forgot to change. It's always something simple.
Ah, right, I was using the standard make file that came with the other classes.Anyway, here's that code:
I should probably throw mergesort.o into the list of OBJs, but anything else? The make file looks like this:
CC=gcc
CXX=c++
CFLAGS=-ggdb -O3 -I.
LDFLAGS=-L. -lcs600
OBJ=timer.o random_generator.o sort.o
cs600: libcs600.a main.o
$(CXX) $(CFLAGS) main.o -o hw1 $(LDFLAGS)
libcs600.a: $(OBJ)
ar ru libcs600.a $(OBJ)
ranlib libcs600.a
.cc.o:
$(CXX) -c $(CFLAGS) $<
clean:
#rm -f *.o
#rm -f libcs600.a
#rm -f hw1
I need to add mergesort.o to the OBJ field, but anything other than that? Considering it's been a while for C++, it's really been a while since I've messed around with make files.
"Undefined reference" is a link-time error. Make sure the object file that contains the missing function is part of your link command line. In your case, probably something like:
clang++ -o app main.o mergesort.o
Or simply:
clang++ -o app main.cc mergesort.cc
If you didn't compile each file separately first.
You're not compiling mergesort.cc into object code, and/or you're not linking in that object code.
If you're using an IDE, make sure you've added mergesort.cc to your project configuration; if you're using Makefiles or compiling on the command line, make sure you include that in the list of source files you're compiling.

C++ Linking error : the compiler can not find the definition of the function

I have a file Cache.cpp that has a corresponding header file Cache.h and another NetFunctions.cpp that has a corresponding header file NetFunction.h.
I have a makefile that looks like this
all: net cache
g++ main.cpp ../obj/NetFunctions.o ../obj/Cache.o -o ../bin/main
net: NetFunctions.cpp
g++ -c NetFunctions.cpp -o ../obj/NetFunctions.o
cache: Cache.cpp net
g++ -c Cache.cpp ../obj/NetFunctions.o -o ../obj/Cache.o
Now NetFunctions.cpp has a function getNFHTML(string) defined there, which is used in Cache.cpp. I have checked the header files and they look fine with all the functions, declared there and header files properly included.
However, when I make, I get the following linker error
../obj/Cache.o: In function `Cache::getHTML(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Cache.cpp:(.text+0x19ee): undefined reference to `getNFHTML(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
make: *** [test] Error 1***
Can someone help me with this? What is the problem?
I have also referred to this post C++ Linking error, but it was of no help to me.
Edit
Here is the code:
NetFunctions.h
#ifndef NET
#define NET 1
#include "commons.h"
bool serv_bind(struct addrinfo **servinfo, struct addrinfo **p, int *sockfd, int *yes);
void* get_in_addr(struct sockaddr *sa);
string getNFHTML(string website);
string saveHeaders(string);
//bool getNFHTML(string request, string last_modified, string *response);
extern bool useCache;
#endif
NetFunctions.cpp
#include "NetFunctions.h"
string getNFHTML(string request)
{
// a lot of code
}
Cache.cpp
#include "NetFunctions.h"
#include "Cache.h"
string Cache::getHTML(string request)
{
//some code
string response = getNFHTML(request);
//some code
}
I have stripped the files as they contained several hundred lines
This has nothing to do with the problem, but I put it in an answer so it will be better formated.
Your makefile doesn't handle dependencies very well. Try this one instead:
.PHONY: all
all: ../bin/main
../bin/main: main.cpp ../obj/NetFunctions.o ../obj/Cache.o
g++ $^ -o $#
../obj/NetFunctions.o: NetFunctions.cpp
g++ -c $< -o $#
../obj/Cache.o: Cache.cpp
g++ -c $< -o $#
For the ../bin/main target, the variable $^ means to take all prerequisites, and $# is the target of the rule. This means you can add as many object files as you like, and all will be linked.
For the compilation of the source to object files, the $< variable is the first prerequisite. This will also make it easier to copy/paste the targets if you add more files.
The rules also make sure that when you build ../bin/main all files it depends on will be built properly.
The first target, all, will be the default if you run make without specifying a target. It has been marked as a phony target, because it doesn't produce a file called all.
Note that I'm basing this on GNU make, which is standard in almost all Linux distributions, and in Cygwin/MingW. If you use BSD make the variables might change.
Change:
cache: Cache.cpp net
g++ -c Cache.cpp ../obj/NetFunctions.o -o ../obj/Cache.o
to:
cache: Cache.cpp net
g++ -c Cache.cpp -o ../obj/Cache.o
Better yet, get rid of the dummy targets and turn on compiler warnings:
../bin/main: ../obj/NetFunctions.o ../obj/Cache.o
g++ -Wall main.cpp ../obj/NetFunctions.o ../obj/Cache.o -o $#
../obj/NetFunctions.o: NetFunctions.cpp
g++ -Wall -c NetFunctions.cpp -o $#
../obj/Cache.o: Cache.cpp
g++ -Wall -c Cache.cpp -o $#
While your Makefile is pretty broken, it's pretty clear that if what you are saying:
NetFunctions.cpp has a function getNFHTML(string) defined there
was true, then it would have worked. Therefore it must be that you are lying to us. Show the code for getNFHTML in NetFunctions.cpp, or at least the output from:
nm ../obj/NetFunctions.o | grep getNFHTML
Update:
Ok, what you told us is true. However, it appears that the target that is failing to link is called test, and there is no such target in your makefile.
I am guessing that that target is being linked without the required NetFunctions.o on the link line.
In any case, please update your question with actual link line that is failing.

Undefined reference to 'main' error in crt1.o function _start

I've having problems with my Makefile.
I'm trying to create a program from 2 files - main.cpp that contains the main function, and modules.c that contains the definitions of the functions that are called in main(). modules.c only contain function definitions, no main function.
My Makefile is as follows:
CC := gcc
CXX := g++
LINK := g++ -Wall
CFLAGS := -g
CXXFLAGS := -g
TARGET = program
$(TARGET): modules.o main.o
$(LINK) -o $# $< -lpcap
clean:
rm *.o $(TARGET)
modules.o:
$(CC) $(CFLAGS) -c modules.c -o $# $<
main.o:
$(CXX) $(CXXFLAGS) -c main.cpp -o $# $<
I have included "modules.h", which contains all the function declarations, in my main.cpp. The CFLAGS and CXXFLAGS variables point to the correct paths containing
When I try to make using this Makefile, I get the error
/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../lib64/crt1.o: In function '_start':
(.text+0x20): undefined reference to 'main'
If I switch the order of modules.o and main.o in my $(TARGET) line, then I get errors that say "undefined reference to" the functions I have defined in modules.c, in main.cpp.
I don't know what is wrong.
Thank you.
Regards,
Rayne
Use $^ instead of $<. The latter contains only the first dependency (modules.o), so main.o is not linked into the executable.
Here are a couple of hints:
-o $# $< is not needed for .o files, so remove that from those targets.
-Wall makes more sense when used while compiling not linking. So I would add it to the CC and CXX line instead (or better, to the CFLAGS and CXXFLAGS).
the clean target should be a dependency of the .PHONY target, so that you can execute it always (without previous check for changed dependencies).
If you still get an error about missing references to your functions from modules.c, you are probably missing some extern "C" ... statements in main.cpp. That's because the internal name of C++ functions is calculated differently than that from C functions (i think C++ prefixes all names with the namespace, class names, etc). To tell C++ that a specific function can be found using the old internal name for linkage, use the extern "C" statement.