C makefile undefined-reference error - c

I am having slight problems with using makefile in C. Ive been following a tutorial in a textbook, but it doesnt seem to want to work. I have three files, message_hider.c, encrypt.h and encrypt.c. When I create a makefile for these files it returns an error, but when I run each command individually it works just fine. Here are my files.
encrypt.c
#include "encrypt.h"
void encrypt(char *message) {
char c;
while (*message) {
*message = *message ^ 31;
message++;
}
}
message_hider.c
#include <stdio.h>
#include "encrypt.h"
int main() {
char msg[80];
while (fgets(msg, 80, stdin)) {
encrypt(msg);
printf("%s", msg);
}
}
encrypt.h
void encrypt(char *message);
Makefile
message_hider: message_hider.o encrypt.o
gcc message_hider.o encrypt.o -o message_hider
message_hider.o: message_hider.c encrypt.h
gcc -c message_hider.c
encrypt.o: encrypt.c encrypt.h
gcc -c encrypt.c
Error message
$ make message_hider
cc message_hider.o -o message_hider
message_hider.o:message_hider.c:(.text+0x17): undefined reference to `encrypt'
message_hider.o:message_hider.c:(.text+0x17): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `encrypt'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../x86_64-pc-cygwin/bin/ld: message_hider.o: bad reloc address 0x0 in section `.pdata'
/usr/lib/gcc/x86_64-pc-cygwin/4.8.2/../../../../x86_64-pc-cygwin/bin/ld: final link failed: Invalid operation
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'message_hider' failed
make: *** [message_hider] Error 1

$ make message_hider
cc message_hider.o -o message_hider
That is not the rule you've specified in your makefile. First off, it appears to be using cc rather than gcc. Second, there's no mention of encrypt.o in there which is why your link is failing.
Try to explicitly use the makefile, such as with:
make -f Makefile message_hider
It may be that it's picking up a different makefile, one that either has different rules or one that simply relies on the default rules like .c.o.
And, based on your update that:
make -f Makefile message_hider
gives you:
$ make -f Makefile message_hider
make: Makefile: No such file or directory
make: *** No rule to make target 'Makefile'. Stop.
that's the error you get when Makefile does not actually exist.
So you need to check that it's in the current directory, and named exactly as you expect.
That would explain the use of default rules as mentioned earlier, since your makefile isn't actually being picked up.
Another thing to check, though it's probably moot now that we've seen the error above, is that you're actually running the correct make program. Use which make to find out where it is (should be /usr/bin/make on CygWin) and make --version to check the version.

Related

How to fix 'undefined reference' when compiling in C?

I'm trying to compile a C program linking two previously created object files but keep getting an 'undefined reference' error.
I'm using Visual Code to write the code and Ubuntu on Windows to compile using a makefile. The two C files, task5.c and reverse.c which have been made into object files both contain #include reverse.h statements which contains the prototypes for the functions in reverse.c.
task5.c
#include <stdio.h>
#include "ctap.h"
#include "reverse.h"
TESTS {
const char *a = "Family";
char *b = reverse(a);
//test 1
ok(string_length(a) == string_length(b), "Strings are the same size");
//test 2
is("ylimaF", b, "Strings match");
}
reverse.c
#include <stdio.h>
#include <stdlib.h>
#include "reverse.h"
char *reverse(const char *str) {
//code
}
int string_length(const char *str) {
//code
}
reverse.h
char *reverse(const char *str);
int string_length(const char *str);
makefile
linked:
gcc -o linked task5.o reverse.o
task5.o
gcc -c -o task5.o task5.c
reverse.o
gcc -c -o reverse.o reverse.c
When I run the command make linked I expect it to be made and return nothing.
But when I run that command I get this error:
cc task5.o -o linked
task5.o: In function `ctap_tests':
task5.c:(.text+0x1abe): undefined reference to `reverse'
task5.c:(.text+0x1ace): undefined reference to `string_length'
task5.c:(.text+0x1adc): undefined reference to `string_length'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'linked' failed
make: *** [task5] Error 1
According to this GNU make documentation, the GNU make program will try to use GNUMakefile, makefile or Makefile.
The make program will not try makefile.mk, which means that e.g. make linked will use no makefile and only the default rules.
You can solve this by either renaming your makefile as Makefile (the most common) or makefile; Or by using the -f option to specify the makefile
$ make -f makefile.mk linked

I've included a header file but I still get undefined when trying to run make

I am trying to implement bcrypt into an open source project I've found, more of a learning thing. I've git cloned https://github.com/rg3/bcrypt and moved the bcrypt.h bcrypt.c and crypto_blowfish into my projects file, then in my file database.c I've
include "bcrypt.h"
Then when I run make I get:
database.c:2084: undefined reference to `bcrypt_checkpw'
This is how I'm using it
int ret;
ret = bcrypt_checkpw(pass, row[0]);
assert(ret != -1);
if (ret == 0) {
return 1;
} else {
return 2;
}
I have a Makefile I'm not sure if I did this right but I added bcrypt.h to the makefile
.obj/database.o: database.c bcrypt.h server.h log.h create.h player.h sleep.h tool.h drdata.h drvlib.h timer.h direction.h map.h mem.h database.h misc_ppd.h badip.h
All compile
gcc -O -g -m32 -rdynamic -L/usr/lib/mysql -o server .obj/server.o .obj/io.o .obj/libload.o .obj/tool.o .obj/sleep.o .obj/log.o .obj/create.o .obj/notify.o .obj/skill.o .obj/do.o .obj/act.o .obj/player.o .obj/rdtsc.o .obj/los.o .obj/light.o .obj/map.o .obj/path.o .obj/error.o .obj/talk.o .obj/drdata.o .obj/death.o .obj/database.o .obj/see.o .obj/drvlib.o .obj/timer.o .obj/expire.o .obj/effect.o .obj/command.o .obj/date.o .obj/container.o .obj/store.o .obj/mem.o .obj/sector.o .obj/chat.o .obj/statistics.o .obj/mail.o .obj/player_driver.o .obj/clan.o .obj/lookup.o .obj/area.o .obj/task.o .obj/punish.o .obj/depot.o .obj/prof.o .obj/motd.o .obj/ignore.o .obj/tell.o .obj/clanlog.o .obj/respawn.o .obj/poison.o .obj/swear.o .obj/lab.o .obj/consistency.o .obj/btrace.o .obj/club.o .obj/teufel_pk.o .obj/questlog.o .obj/badip.o -lmysqlclient -lm -lz -ldl -lpthread
.obj/database.o: In function `load_char_pwd':
/home/ec2-user/astonia3_server/database.c:2084: undefined reference to `bcrypt_checkpw'
collect2: error: ld returned 1 exit status
make: *** [server] Error 1
The bcrypt_checkpw in .h file is put on extern Cso it has C linkage
The bcrypt_checkpw in .c file has C++ linkage
They are different symbols so you will get linking error.

error on using libblkid

when i compile and link this code to get disk uuid:
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <blkid/blkid.h>
int main (int argc, char *argv[]) {
blkid_probe pr;
const char *uuid;
if (argc != 2) {
fprintf(stderr, "Usage: %s devname\n", argv[0]);
exit(1);
}
pr = blkid_new_probe_from_filename(argv[1]);
if (!pr) {
err(2, "Failed to open %s", argv[1]);
}
blkid_do_probe(pr);
blkid_probe_lookup_value(pr, "UUID", &uuid, NULL);
printf("UUID=%s\n", uuid);
blkid_free_probe(pr);
return 0;
}
it errors out:
/home/usr/blkid/blkid.c:15: undefined reference to `blkid_new_probe_from_filename'
make[2]: Leaving directory `/home/usr/blkid'
make[1]: Leaving directory `/home/usr/blkid'
/home/usr/blkid/blkid.c:20: undefined reference to `blkid_do_probe'
/home/usr/blkid/blkid.c:21: undefined reference to `blkid_probe_lookup_value'
/home/usr/blkid/blkid.c:25: undefined reference to `blkid_free_probe'
when i compile the code by the following command, the code compiles with no error
gcc -c -g -MMD -MP -MF build/Debug/GNU-Linux-x86/blkid.o.d -o build/Debug/GNU-Linux-x86/blkid.o blkid.c
Try to put -lblkid into your gcc command so the linker will know that you need to link your code to that library. Be sure to put this option at the end of the command. The order of options somehow matters. From here:
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after
file foo.o but before bar.o. If bar.o refers to functions in ‘z’,
those functions may not be loaded.
This command should automatically both compile and link your source code:
gcc -o test -g -MMD -MP -MF build/Debug/GNU-Linux-x86/blkid.o.d blkid.c -lblkid
The error you show comes from the linker.
If you compile one single file to a .o file without linking, no external references will be tried to fulfill.
But if you want to compile into an executable, all needed requirements must be fulfilled. If the program requires the presence of a blkid_do_probe(), you should provide it somehow. Probably this will be done by linking with the appropriate library. As someone mentionned in a comment, this is to be done with -lblkid.

How do I link object files in C? Fails with "Undefined symbols for architecture x86_64"

So I'm trying trying to use a function defined in another C (file1.c) file in my file (file2.c). I'm including the header of file1 (file1.h) in order to do this.
However, I keep getting the following error whenever I try to compile my file using gcc:
Undefined symbols for architecture x86_64:
"_init_filenames", referenced from:
_run_worker in cc8hoqCM.o
"_read_list", referenced from:
_run_worker in cc8hoqCM.o
ld: symbol(s) not found for architecture x86_64
I've been told I need to "link the object files together" in order to use the functions from file1 in file2, but I have no clue what that means :(
I assume you are using gcc, to simply link object files do:
$ gcc -o output file1.o file2.o
To get the object-files simply compile using
$ gcc -c file1.c
this yields file1.o and so on.
If you want to link your files to an executable do
$ gcc -o output file1.c file2.c
The existing answers already cover the "how", but I just wanted to elaborate on the "what" and "why" for others who might be wondering.
What a compiler (gcc) does: The term "compile" is a bit of an overloaded term because it is used at a high-level to mean "convert source code to a program", but more technically means to "convert source code to object code". A compiler like gcc actually performs two related, but arguably distinct functions to turn your source code into a program: compiling (as in the latter definition of turning source to object code) and linking (the process of combining the necessary object code files together into one complete executable).
The original error that you saw is technically a "linking error", and is thrown by "ld", the linker. Unlike (strict) compile-time errors, there is no reference to source code lines, as the linker is already in object space.
By default, when gcc is given source code as input, it attempts to compile each and then link them all together. As noted in the other responses, it's possible to use flags to instruct gcc to just compile first, then use the object files later to link in a separate step. This two-step process may seem unnecessary (and probably is for very small programs) but it is very important when managing a very large program, where compiling the entire project each time you make a small change would waste a considerable amount of time.
You could compile and link in one command:
gcc file1.c file2.c -o myprogram
And run with:
./myprogram
But to answer the question as asked, simply pass the object files to gcc:
gcc file1.o file2.o -o myprogram
Add foo1.c , foo2.c , foo3.c and makefile in one folder
the type make in bash
if you do not want to use the makefile, you can run the command
gcc -c foo1.c foo2.c foo3.c
then
gcc -o output foo1.o foo2.o foo3.o
foo1.c
#include <stdio.h>
#include <string.h>
void funk1();
void funk1() {
printf ("\nfunk1\n");
}
int main(void) {
char *arg2;
size_t nbytes = 100;
while ( 1 ) {
printf ("\nargv2 = %s\n" , arg2);
printf ("\n:> ");
getline (&arg2 , &nbytes , stdin);
if( strcmp (arg2 , "1\n") == 0 ) {
funk1 ();
} else if( strcmp (arg2 , "2\n") == 0 ) {
funk2 ();
} else if( strcmp (arg2 , "3\n") == 0 ) {
funk3 ();
} else if( strcmp (arg2 , "4\n") == 0 ) {
funk4 ();
} else {
funk5 ();
}
}
}
foo2.c
#include <stdio.h>
void funk2(){
printf("\nfunk2\n");
}
void funk3(){
printf("\nfunk3\n");
}
foo3.c
#include <stdio.h>
void funk4(){
printf("\nfunk4\n");
}
void funk5(){
printf("\nfunk5\n");
}
makefile
outputTest: foo1.o foo2.o foo3.o
gcc -o output foo1.o foo2.o foo3.o
make removeO
outputTest.o: foo1.c foo2.c foo3.c
gcc -c foo1.c foo2.c foo3.c
clean:
rm -f *.o output
removeO:
rm -f *.o
Since there's no mention of how to compile a .c file together with a bunch of .o files, and this comment asks for it:
where's the main.c in this answer? :/ if file1.c is the main, how do
you link it with other already compiled .o files? – Tom Brito Oct 12
'14 at 19:45
$ gcc main.c lib_obj1.o lib_obj2.o lib_objN.o -o x0rbin
Here, main.c is the C file with the main() function and the object files (*.o) are precompiled. GCC knows how to handle these together, and invokes the linker accordingly and results in a final executable, which in our case is x0rbin.
You will be able to use functions not defined in the main.c but using an extern reference to functions defined in the object files (*.o).
You can also link with .obj or other extensions if the object files have the correct format (such as COFF).

Reading data from matlab files into C

I'm trying to learn how to use the C API to reading Matlab .mat files, but it's not working as I expected:
I'd like to just open a very simple .mat file called test.mat, read a value from the file and store it in a C variable. I've created test.mat in Matlab using the following commands:
> value = 3;
> save ("test.mat", "value")
Below is my C code, which doesn't even compile - the compiler doesn't seem to find the header files. See below the code for compiler output. What am I doing wrong here?
Code:
#include <stdlib.h>
#include <stdio.h>
#include <mat.h>
#include <matrix.h>
int main(int argc, char *argv[]) {
double value;
MATFile *datafile;
datafile = matOpen("test.mat", "r");
mxArray *mxValue;
mxValue = matGetVariable(datafile, "value");
matClose(datafile);
value = *mxGetPr(mxArray);
mxFree(mxArray);
printf("The value fetched from the .mat file was: %f", value);
return 0;
}
Compiler output:
$ make animate_shot
cc -I/usr/local/MATLAB/R2011a/extern/include/ animate_shot.c -o animate_shot
/tmp/cczrh1vT.o: In function `main':
animate_shot.c:(.text+0x1a): undefined reference to `matOpen'
animate_shot.c:(.text+0x2f): undefined reference to `matGetVariable'
animate_shot.c:(.text+0x3f): undefined reference to `matClose'
animate_shot.c:(.text+0x4b): undefined reference to `mxGetPr'
animate_shot.c:(.text+0x5e): undefined reference to `mxFree'
collect2: ld returned 1 exit status
make: *** [animate_shot] Error 1
(the -I flag is specified with the line CPPFLAGS=-I/usr/local/MATLAB/R2011a/extern/include/ in my makefile, and I've verified that the directory exists and contains the header files mat.h and matrix.h).
UPDATE:
I've found that the libraries I need to link in are libmat.so and libmx.so (according to this MathWorks help article), residing in /usr/local/MATLAB/R2011a/bin/glnxa64/ on my system. I've therefore updated my makefile to this:
CPPFLAGS =-I/usr/local/MATLAB/R2011a/extern/include/
LDFLAGS = -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx
Now, running make gives the following command:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 -l mat -l mx animate_shot.c -o animate_shot
However, I still get the same errors. Any ideas?
This is a linker failure, not a compiler failure (and is unrelated to -I compiler option). You need to specify the directory in which the matlab .so files are located using -L flag and add a -l<matlab-lib-name> option to end of the compiler command that specifies the name of the matlab library.
For example:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/lib animate_shot.c -o animate_shot -lmatlab
(I don't know the exact directory into the which .so are located or the name of the matlab library)
Based on the comment providing further information:
cc -I/usr/local/MATLAB/R2011a/extern/include/ -L/usr/local/MATLAB/R2011a/bin/glnxa64 animate_shot.c -o animate_shot -lmat -lmx

Resources