After a certain attempt to write a simple program with a main and one function,
I ask for your help to find the bug. I include the 3 files that are in action:
the main function in base.c
the function in fun.c
the makefile
The compiler says that the function is called in a bad way in the main:
undefined reference to `fun'
base.c
#include <stdio.h>
int fun(char c);
main()
{
printf("please enter a single char\n");
char c=getchar();
fun(c);
return 0;
}
fun.c
#include <stdio.h>
int fun(char c)
{
printf("%d3 is the value of your char!\n", 'c');
return 0;
}
makefile
charprint: base.o fun.o
gcc -g -Wall -ansi base.o fun.o -o charprint
base.o: base.c
gcc -g -Wall -ansi base.c -o base.o
fun.o: fun.c
gcc -g -Wall -ansi fun.c -o fun.o
The compilation problem is that you forgot the -c flags in the compiler line for base.o and fun.o. One obvious simple (but not very good) way to fix that is:
charprint: base.o fun.o
gcc -g -Wall -ansi base.o fun.o -o charprint
base.o: base.c
gcc -c -g -Wall -ansi base.c -o base.o
fun.o: fun.c
gcc -c -g -Wall -ansi fun.c -o fun.o
Interestingly, the simplest fix would be to delete the two compiler command for the two object files — make knows how to compile C files to object files. You could set CFLAGS += -Wall (or CFLAGS = -Wall) to get the (very important) -Wall flag included. Adding -Werror too would be good.
CFLAGS += -Wall -Werror -g -std=c11
charprint: base.o fun.o
${CC} ${CFLAGS} base.o fun.o -o $#
base.o: base.c
fun.o: fun.c
In the code for fun(), your argument to printf() should be just c and not 'c'. You probably also mean %3d rather than %d3 though that 'works'; it just doesn't do what you expect. Note that you should use an explicit int main(void) { … }. And you should probably create a header fun.h containing:
extern int fun(char c);
and #include "fun.h" in both source files, and add fun.h after the source file name in the dependency lines in the makefile:
CFLAGS += -Wall -Werror -g -std=c11
charprint: base.o fun.o
${CC} ${CFLAGS} base.o fun.o -o $#
base.o: base.c fun.h
fun.o: fun.c fun.h
In fact, you don't need to list the source files as dependencies for the object files; make will infer that dependency automatically. But you do need to specify the header file dependency.
Related
I have a github repo representing my exercise folder. Upon running make all the compiler throws error messages saying (Ubuntu):
cc -g -O2 -Wall -Wextra -Isrc -DNDEBUG -fPIC -c -o src/libex29.o src/libex29.c
src/libex29.c: In function ‘fail_on_purpose’:
src/libex29.c:36:33: warning: unused parameter ‘msg’ [-Wunused-parameter]
int fail_on_purpose(const char* msg)
^~~
ar rcs build/libex29.a src/libex29.o
ranlib build/libex29.a
cc -shared -o build/libex29.so src/libex29.o
cc -g -Wall -Wextra -Isrc test/ex29_test.c -o test/ex29_test
/tmp/cc7dbqDt.o: In function `main':
/home/givi/Desktop/lcthw_dir/29/test/ex29_test.c:21: undefined reference to `dlopen'
/home/givi/Desktop/lcthw_dir/29/test/ex29_test.c:22: undefined reference to `dlerror'
/home/givi/Desktop/lcthw_dir/29/test/ex29_test.c:25: undefined reference to `dlsym'
/home/givi/Desktop/lcthw_dir/29/test/ex29_test.c:26: undefined reference to `dlerror'
/home/givi/Desktop/lcthw_dir/29/test/ex29_test.c:33: undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'test/ex29_test' failed
make: *** [test/ex29_test] Error 1
i spent quite a lot trying to figure out how to fix undefined references. dlfcn.h is included, everything seems to be ok. Am i missing something? Please help
You must add following option when linking code using dlopen(3) :
-ldl
Here is a demo for Ubuntu 18:
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.4 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ cat dl.c
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
void *r;
r = dlopen("", RTLD_LAZY);
if (r != NULL)
printf("r is not null \n");
return 0;
}
$ gcc -o dl -Wall -pedantic -std=c11 dl.c -ldl
$ echo $?
0
Here is a very simple Makefile(note position of -ldl) and related make commands:
$ cat Makefile
CFLAGS=-g -O2 -Wall -Wextra -Isrc -DNDEBUG $(OPTFLAGS) $(OPTLIBS)
dl.o :dl.c
$(CC) -c $< $(CFLAGS)
dl :dl.o
$(CC) -o $# $^ $(CFLAGS) -ldl
clean :
rm -f dl dl.o
$ make clean
rm -f dl dl.o
$ make dl
cc -c dl.c -g -O2 -Wall -Wextra -Isrc -DNDEBUG
dl.c: In function ‘main’:
dl.c:5:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
int main(int argc, char **argv)
^~~~
dl.c:5:27: warning: unused parameter ‘argv’ [-Wunused-parameter]
int main(int argc, char **argv)
^~~~
cc -o dl dl.o -g -O2 -Wall -Wextra -Isrc -DNDEBUG -ldl
$ ./dl
r is not null
Usually the references you're missing can be resolved by adding linker flag -ldl.
You didn't mention which operating system you're using.
In case you're on Windows you'll need this library: https://github.com/dlfcn-win32/dlfcn-win32
I am trying to compile the following source file using gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm.
source.h
void simple_sum(void)
source.c
#include "source.h"
#include <stdio.h>
void simple_sum(void)
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d + %d = %d\n",a, b, a + b);
}
main.c
#include "source.h"
#include <stdio.h>
int main(void)
{
printf("\n");
simple_sum();
return 0;
}
I get following error:
gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function _start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1
Could someone please suggest how to fix this?
Edit
I get the following error when I run using gcc -g -Wall main.c -o main
/tmp/ccEAL4iG.o: In functionmain':
/home/a/aalto_university/functions/calculation/main.c:7: undefined reference to simple_sum'
collect2: error: ld returned 1 exit status
Compile with
gcc -g -Wall -Wextra -pedantic -std=c99 source.c main.c -o myprog -lm
(actually, -lm is not needed, you don't use <math.h> functions; but keeping -lm should not harm)
Later, learn to write your Makefile to do these things in several steps:
First, get the source.o object file with
gcc -g -Wall -Wextra -pedantic -std=c99 -c source.c
then get the main.o object file with
gcc -g -Wall -Wextra -pedantic -std=c99 -c main.c
At last, link both of them
gcc -g source.o main.o -lm -o myprog
Here
gcc -g -Wall -Wextra -pedantic -std=c99 -o main -lm
you are not providing source file name to linker, hence it throw error like
undefined reference to `main'
While compiling provide source file main.c and source.c. For e.g first run this
gcc -g -Wall -Wextra -pedantic -std=c99 -c main.c source.c -lm
to create the object.o files & then create the executable by running
gcc source.o main.o -o my_exe
And finally run the executable. Also declaration of simple_sum() missing ; it should be
void simple_sum(void); /* you miss ;*/
Also learn how to use Makefile for compilation as #Basile pointed, there you don't have to create .o file manually, your Makefile will create .o file & compile if it's written correctly.
Hello to the good people of Stack Overflow, I am back at it again with the questions! haha
So I have a couple of files that I am trying to compile and link together. The library I have created is a DLL. Using a RTLD_LAZY method. I have the library in the same directory as the application. I'm having a tough time completing this task. I'm trying to link it using -ldl.
My files that I have are:
lab3.c //Which has my main
myLibrary.c //which is my library
sdv.h //which is my header file
testDynamic.c //which is my handle file for the RTLD_LAZY
Here is what I have done so far, but I'm clearly screwing something up..
dynamic: lab3.o myLibrary.o test
gcc -o dynamic lab3.o myLibrary.o -lm
lab3.o: lab3.c
gcc -fPIC -c -o lab3.o lab3.c -lm
myLibrary.o: myLibrary.c
gcc -fPIC -c myLibrary.c -o myLibrary.o -lm
libmyLibrary.so: myLibrary.o
gcc -shared -o libmyLibrary.so myLibrary.o -lm
testDynamic.o:
gcc testDynamic.c -L. -lmyLibrary -o test -ldl
export LD_LIBRARY_PATH=./
Any advice will be greatly appreciated! Thanks in advance!
Here comes an example close to your own makefile.
makefile:
CC=gcc
CFLAGS=-Wall -Wextra -Werror -std=gnu99
.PHONY:all mrproper clean
all:libmyLibrary.so dynamic testDynamic
dynamic:lab3.o
$(CC) $(CFLAGS) -o dynamic lab3.o -L. -lmyLibrary -lm
lab3.o:lab3.c
$(CC) $(CFLAGS) -c -o lab3.o lab3.c
myLibrary.o:myLibrary.c
$(CC) $(CFLAGS) -fPIC -c myLibrary.c -o myLibrary.o
libmyLibrary.so:myLibrary.o
$(CC) $(CFLAGS) -shared -o libmyLibrary.so myLibrary.o -lm
testDynamic.o:testDynamic.c
$(CC) $(CFLAGS) -o testDynamic.o -c testDynamic.c
testDynamic:testDynamic.o
$(CC) $(CFLAGS) -o testDynamic testDynamic.o -ldl
mrproper:clean
rm -f dynamic libmyLibrary.so testDynamic
clean:
rm -f lab3.o myLibrary.o testDynamic.o
Use -lm only when linking. -fPic is only necessary when linking dynamic library. -lmyLibrary is only necessary when linking program with dynamic library. So generating testDynamic does not need it as it will load library dynamically, it does not require being linked to it.
sdv.h:
#ifndef SDV_H
#define SDV_H
extern void sdv_print_version();
#endif
myLibrary.c:
#include <stdio.h>
#include <stdlib.h>
void sdv_print_version()
{
printf("v1.0\n");
}
testDynamic.c:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define MY_LIB "libmyLibrary.so"
#define PRINT_VERSION "sdv_print_version"
int main()
{
void *handle = dlopen(MY_LIB, RTLD_LAZY);
if (handle == NULL)
{
fprintf(stderr, "%s\n", dlerror());
return 1;
}
void (*p_print_version)() = NULL;
p_print_version = dlsym(handle, PRINT_VERSION);
if (p_print_version == NULL)
{
printf("No version available.\n");
fprintf(stderr, "%s\n", dlerror());
}
else
{
(*p_print_version)();
}
if (dlclose(handle) != 0)
{
fprintf(stderr, "%s\n", dlerror());
}
return 0;
}
Now building:
>make
gcc -Wall -Wextra -Werror -std=gnu99 -fPIC -c myLibrary.c -o myLibrary.o
gcc -Wall -Wextra -Werror -std=gnu99 -shared -o libmyLibrary.so myLibrary.o -lm
gcc -Wall -Wextra -Werror -std=gnu99 -c -o lab3.o lab3.c
gcc -Wall -Wextra -Werror -std=gnu99 -o dynamic lab3.o -L. -lmyLibrary -lm
gcc -Wall -Wextra -Werror -std=gnu99 -o testDynamic.o -c testDynamic.c
gcc -Wall -Wextra -Werror -std=gnu99 -o testDynamic testDynamic.o -ldl
Let's keep a first version of dynamic library:
>mkdir v1.0
>mv libmylibrary.so v1.0/
Now update myLibrary.c:
#include <stdio.h>
#include <stdlib.h>
void sdv_print_version()
{
printf("v2.0\n");
}
Build again:
>make
gcc -Wall -Wextra -Werror -std=gnu99 -fPIC -c myLibrary.c -o myLibrary.o
gcc -Wall -Wextra -Werror -std=gnu99 -shared -o libmyLibrary.so myLibrary.o -lm
Let's move this new dynamic library to another directory:
>mkdir v2.0
>mv libmylibrary.so v2.0/
Now testing with no dynamic library available:
>export LD_LIBRARY_PATH=./
>PATH=$PATH:.
>dynamic
dynamic: error while loading shared libraries: libmyLibrary.so: cannot open shared object file: No such file or directory
>testDynamic
libmyLibrary.so: cannot open shared object file: No such file or directory
What's the difference? In "testDynamic.c" we could, instead of showing a message error, do an alternative algorithm not requiring "libmyLibrary.so".
Now checking we can use "libmyLibrary.so":
>cd v1.0
>../dynamic
v1.0
>../testDynamic
v1.0
>cd ../v2.0
>../dynamic
v2.0
>../testDynamic
v2.0
Here is my console output:
Tylers-MacBook-Pro:laser_finder_c tylerjw$ make
gcc -g -Wall -c -o dots_img.o dots_img.c
gcc -g -Wall -c -o no_dots_img.o no_dots_img.c
gcc -g -Wall -c -o point.o point.c
gcc -g -Wall -c -o images.o images.c
gcc -g -Wall -c -o laser_finder_c.o laser_finder_c.c
gcc dots_img.o no_dots_img.o point.o images.o laser_finder_c.o -g -Wall -o laser_finder_c
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [laser_finder_c] Error 1
This doesn't seem to make any sense as the main function is defined in laser_finder_c.c. Below is my makefile. I'm real confused as to why this is happening.
TARGET = laser_finder_c
OBJECTS = dots_img.o no_dots_img.o point.o images.o laser_finder_c.o
#######################################################################################
CFLAGS = -g -Wall
ASFLAGS = -Wall
LDFLAGS = -g -Wall
CC = gcc
AS = gcc
########################################################################################
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $(TARGET)
point.o: point.h
images.o: images.h
laser_finder_c.o: images.h point.h
dots_img.o: images.h
no_dots_img.o: images.h
clean:
rm -f $(OBJECTS) $(TARGET)
Here is the definition of main in laser_finder_c.c
// laser_finder.c - finds the location of laser points comparing two images
#include "point.h"
#include <stdio.h>
#include <stdlib.h>
// #defines ... removed
int main()
{
// ... code removed
return 0;
}
For context the output of gcc -v is:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
I'm pretty new to c coding and I've checked the standard references on makefiles but I seem to be misunderstanding something because I'm getting an error. If anybody can help me it would be greatly appreciated.
Here it is:
#makefile
all: runme dontrunme
runme: runme.o
clang runme.o -o runme
dontrunme: dontrunme.o library.o fun.o
clang dontrunme.o -o dontrunme
runme.o: library.o runme.c
clang -c runme.c -o runme.o
dontrunme.o: dontrunme.c
clang -c dontrunme.c -o dontrunme.o
library.o: library.c library.h
clang -c library.c -o library.o
fun.o: fun.c fun.h
clang -c fun.c -o fun.o
clean:
rm -f *.o runme dontrunme
The error I get when I type make is:
runme.o:runme.c:function main: error: undefined reference to 'reverse'
reverse is a function whose protoype is in library.h and is defined in library.c
Any help in understanding where I went wrong is greatly appreciated.
Edit: Here is the code for runme.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "library.h"
int main(int argc, char * argv[]){
char s[] = "Hello World!";
printf("%s\n", s);
reverse(s);
printf("%s\n", s);
}
Change this:
runme: runme.o
clang runme.o -o runme
to this:
runme: runme.o library.o
clang runme.o library.o -o runme
And do the same for dontrunme
dontrunme: dontrunme.o library.o fun.o
clang dontrunme.o library.o fun.o -o dontrunme
In both cases you're not including all the object code files in your final links.
please change order in makefile as follows. you first need library.o for build runme.o
so please build library.o first then runme.o
library.o: library.c library.h
clang -c library.c -o library.o
runme.o: library.o runme.c
clang -c runme.c -o runme.o