How to compile two C programs? - c

This is my makefile:
all: prgrm1 prgrm2
prgrm1: prgrm1.c
gcc -o prgrm1 prgrm1.c -lrt
prgrm2: prgrm2.c
gcc -o prgrm2 prgrm2.c -lrt
When I try to compile I get the message "Nothing to be done for 'all'."
I made sure that I used tabs not spaces so that is not it. What am I doing wrong?

Related

How to build CS50 programs with make

I am trying to study cs50 on linux , I downloaded everything I found on github, but now I can not compile my first program with make, but I can use clang instead clang hello.c -lcs50 -o hello which works just fine, but when I try to compile with make hello I get
:~/cs50/pset1# make hello
cc hello.c -o hello
/usr/bin/ld: /tmp/cczILfhu.o: in function 'main':
hello.c:(.text+0x1a): undefined reference to 'get_string'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: hello] Error 1
I even moved the libcs50 folder that I downloaded to /usr/include/
but I still get the same results.
after I compile with clang , and then excute make hello it says
make: 'hello' is up to date.
I know it sounds dump but I am still newbie and looking for help.
thanks in advance.
For linking in the cs50 library (which you should have installed from https://github.com/cs50/libcs50 according to the instructions there), your linking command should specify the -lcs50 argument.
make usually needs a Makefile to control the build. In its absence it can use some implicit rules to guess the build process, like that hello.o could be built from hello.c and hello could be linked from hello.o and so forth, but it certainly cannot guess that libcs50 should be linked in.
Fortunately, the implicit linking rules include the contents of the variable LDLIBS in the correct, so you can fix this by writing a simple Makefile in the same directory, containing just
LDLIBS += -lcs50
I.e. "append the string -lcs50 to the current value of LDLIBS".
After that make hello will use the implicit rules and the new value of LDLIBS to execute
cc hello.c -lcs50 -o hello
Also do note that the cc command usually is GCC, not Clang, not that it should matter in CS50. It can be configured with the CC variable in Makefile:
CC := clang
Finally, it does make sense to enable warnings and pedantry in the compilation flags, for example:
CFLAGS += -Wall -Wextra -Werror -pedantic -std=c11
With all these 3 present, make hello will actually execute
clang -Wall -Wextra -Werror -pedantic -std=c11 hello.c -lcs50 -o hello
which means we did save quite a lot typing and get more useful diagnostics!
Of course for a more complicated build process you'd need to write a more complicated Makefile with dependency rules - say if your helloworld program consisted of hello.c and world.c linked together you could get by the implicit rules and just state that helloworld depends on both hello.o and world.o and should be linked together from these:
helloworld: hello.o world.o
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS)
# the command *must* be indented by a *single* tab character, not spaces!
# unfortunately SO editor does not make it easy to write tabs.
Just make new Makefile in the dir where is your *.c file:
$ touch Makefile
Then just add this strings to your Makefile:
CC=clang
CFLAGS=-fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow
LDLIBS=-lcrypt -lcs50 -lm
Than you can compile *.c file just typing:
$ make hello.c

gcc makefile won't compile

My final executable (this is in unix though) will be proj07.
proj07: /user/cse320/Projects/project07.driver.o proj07.support.o
gcc -Wall /user/cse320/Projects/project07.driver.o proj07.support.o
proj07.support.o: proj07.support.c
gcc -c proj07.support.c
This creates proj07.support.o but no proj07 exists after compilation. I don't get an error so my mistake must be simple but I can't seem to figure it out.
Here's the output:
gcc -c proj07.support.c
gcc -Wall /user/cse320/Projects/project07.driver.o proj07.support.o
Also I am to use a static driver to test my file which is why the path is like that
You probably do have an a.out executable. Add -o $# to your first gcc occurrence and you should be fine.

linking pthread library issue

Am facing a problem that may be slightly complicated to explain and understand as giving the entire picture would be too big and difficult.
Please excuse me for it.
Consider the following Makefile:
all: clients.so simulator backup
LD_PRELOAD=/home/Juggler/client/clients.so ./simulator
backup: backup.c libclient.a
gcc backup.c -o backup -L /home/Juggler/client -L. -lclient -ldl
simulator: simulator.c libclient.a
gcc -g simulator.c -o simulator -L /home/Juggler/client -L. -lclient -ldl -pthread
libclient.a: libclient.o client.o
ar rcs libclient.a libclient.o client.o
libclient.o:libclient.c
gcc -c libclient.c -o libclient.o -pthread
clients.so: client.o client_invoke.o
ld -shared -o clients.so client_invoke.o client.o -ldl
client_invoke.o: client_invoke.c
gcc -Wall -fPIC -DPIC -c -g client_invoke.c
client.o: client.c
gcc -Wall -fPIC -DPIC -c -g client.c -ldl -pthread
We call function written in client.c from libclient.c and these functions in client.c make call to pthread_key_create(), pthread_setspecific..etc.
Threads are created by simulator.c and theses threads access functions written in he other files.
On doing make...Errors like the following appear.
/home/Juggler/client/libclient.a(client.o):In function 'setup_connection':
/home/Juggler/client/client.c:35: undefined reference to 'pthread_setspecific'
pthread.h has been included in both client.c and libclient.c
Would be grateful for anypointers . I understand information is very less...
Thanks
On linux, pthread functions live in the libpthread library. So you have to link to that.
The proper way, when using pthreads, is to compile and link using the -pthread , which, among other things, will link in the pthread library. You have the -pthread flag for some of your executables, but not for others, and not for your clients.so library, so add the flag where required.
Also, remember, when you are creating a shared library, you should compile the source files with the -fPIC flag.
(And, seems you are calling ld directly to produce the client.so library, you really should use gcc to do the linking.)

make is automatically attempting to link even when I pass -c in my makefile

I'm new to makefiles, so I apologize in advance if this is a silly question. Also I removed most variables from my makefile because they weren't working properly (gnu make tells me that $(myvar) should be completely replaces by the value of myvar, however the output of make was showing me that this was not happening), so I apologize for the ugliness and the more than 80 character lines.
acolibobj = acoLibInit acoGlobalDefs
acolibinterface: $(acolibobj).o
acoLibInit.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
acoGlobalDefs.o:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoGlobalDefs.o acoCommands/acoLibInterface/acoGlobalDefs.c
When I run this makefile I get:
gcc -fPIC -g -c -Wall -I/usr/include/dc1394 -o acoLibinit.o acoCommands/acoLibInterface/acoLibInit.c
cc acoLibInit.o -o acoLibInit
gcc: acoLibInit.o: No such file or directory
gcc: no input files
make: *** [acoLibInit] Error 1
So far as I can tell, what's happening is that make is trying to compile AND link, even though I explicitly added the -c flag. When I run "gcc -fPIC -g -c..." myself (from bash), I do not get any problems at all. Why does make go on to try "cc acoLibInit.o -o acolibInit"?
make is trying to build acoLibInit. It probably has built-in rule that specifies "whatever" can be produced by linking "whatever.o", which is why you get that cc line.
This line:
acolibinterface: $(acolibobj).o
expands to:
acolibinterface: acoLibInit acoGlobalDefs.o
(note the absence of .o on the first dependency). This is why it's trying to link acoLibInit.
Try this:
acolibinterface: $(addsuffix .o,$(acolibobj))
if you want only the .o files as dependencies for that target.
$(acolibobj).o expands to acoLibInit acoGlobalDefs.o. Thus, you're really saying:
acolibinterface: acoLibInit acoGlobalDefs.o
Simply define acolibobj = acoLibInit.o acoGlobalDefs.o and use acolibinterface: $(acolibobj).

Have my makefile show me compile errors?

exedarken: darken.c
gcc -o exedarken darken.c
exeimagestats: imagestats.c
gcc -o exeimagestats imagestats.c
exelighten: lighten.c
gcc -o exelighten lighten.c
exerotate: rotate.c
gcc -o exerotate rotate.c
exeflip: flip.c
gcc -o exeflip flip.c
exematte: matte.c
gcc -o exematte matte.c
Theres my makefile. Is there a way for when I execute this makefile, I get to see the compile errors I get?
By default, make prints the output of any command it executes, ie if there are compilation errors, they should be shown.
On an unrelated note: repeating yourself is bad; your makefile can be simplified to
executables := exedarken exeimagestats exelighten exerotate exeflip exematte
$(executables) : exe% : %.c
gcc -o $# $<
Write in console:
make VERBOSE=1

Resources