C Makefile for 2 mainfiles - makefile

It's my first question around here. I'm working on a project for my course.
I know this question might have been answer to many times but I can't really understand what's the problem in the other people's topics.
The project is a simple chat with pipes and forks and I need to make a Makefile to compile the program. Here's my makefile:
CC=cc
FLAGS=-c -Wall
LIBS=-lm
OBS=cliente.o server.o
all : cliente server
cliente.c : cliente
$(CC) $(FLAGS) cliente.c
server.c : server
$(CC) $(FLAGS) server.c
And the output is:
make: Circular cliente.c <- cliente dependency dropped.
cc -c -o cliente.o cliente.c
cc cliente.o -o cliente
make: Circular server.c <- server dependency dropped.
Thank you for the help.

First, you've got your rules backwards. The correct syntax for Makefile rules is:
target-you-are-trying-to-build: things it depends on
command to build target from things it depends on
Therefore, you want to write:
cliente : cliente.c
$(CC) $(FLAGS) cliente.c
server: server.c
$(CC) $(FLAGS) server.c
(Note the flipping of the executable and the source file in the first line of each rule.)
The reason your original Makefile works at all is because make has some built in rules, so when you type make, it tries to build all which needs cliente and server, and it generates automatic rules to build cliente from cliente.c and server from server.c. (You can tell it's using it's internal rules and not yours because it ignores your FLAGS.)
The error messages about dropped dependencies are because you've told it to build cliente, which it knows it can build from cliente.c, but your rules tell it that cliente.c should be built from cliente which makes a circular dependency, so it complains.
However, as you note in the comment, this still won't work right. That's because your rules for building cliente and server don't actually build cliente and server. The command:
cc -c -Wall cliente.c
only compiles cliente.c to an object file cliente.o because of the -c flag. It doesn't link or output an executable. The modified version in #InvicibleWolf's answer which is equivalent to:
cc -c -Wall -o cliente -c client.c
won't work either, because the (multiple) -c flags produce object files, not executables, even if you force the output to go to cliente instead of the default of cliente.o. You're getting a "permission denied" error because, by default, object files are created without execute permissions. (Giving them execute permissions wouldn't help -- object files can't be run directly, so you'd get a different error.)
There are a couple of approaches here:
Use make's built-in rules exclusively
The following Makefile will work:
CC=cc # should be "CC=", not "C="
CFLAGS=-Wall # internal rules use CFLAGS not FLAGS, don't need -c
LDLIBS=-lm # internal rules use LDLIBS not LIBS
all : cliente server
cliente: cliente.o
server: server.o
This tells makes that cliente can be built from cliente.o, and make is smart enough to generate a rule equivalent to:
cc cliente.o -lm -o cliente
using your definition of CC and LDLIBS. It will also automatically generate the rule to build cliente.o from cliente.c without any guidance, equivalent to:
cc -Wall -c -o cliente.o cliente.c
using your definition of CFLAGS. (It supplies the -c flags automatically.)
Use explicit rules that directly generate the executable from the C file
This will work, too. It's just what #InvicibleWolf has written above with a typo fixed, the -c dropped, and the LIBS value included in the rules:
CC=cc ## use CC=, not C=
FLAGS=-Wall ## no -c flag
LIBS=-lm
all : cliente server
cliente: cliente.c
$(CC) $(FLAGS) $(LIBS) -o cliente cliente.c # no -c, and use LIBS
server: server.c
$(CC) $(FLAGS) $(LIBS) -o server server.c # no -c, and use LIBS

To compile your make file should follow the rule #K. A. Buhr mentioned in the answer. Makefile in his answer will just create object files . Considering your question I think you want to make two binaries client and server, so your make file should look like this:
C=cc
FLAGS= -Wall
LIBS=-lm
# OBS=cliente.o server.o not necessary if you are clreating to different binaries
all : cliente server
cliente: cliente.c
$(CC) $(FLAGS) -o cliente cliente.c
server: server.c
$(CC) $(FLAGS) -o server server.c
This will create object file as well as binaries too. -o option is to output to server/cliente file, and -c option means compile and assemble, but do not link or other words generate object files.

Related

How to configure a dynamic library using a macro / variable in a makefile?

I'm writing a small study project in C. I need to create a dynamic library and configure its use with macros. First, I create object files with the command:
$gcc -fPIC -c ../data_module/data_process.c
$gcc -fPIC -c ../data_libs/data_stat.c
Then I create a dynamic library like this:
$gcc -shared -o data_process.so data_process.o data_stat.o
And finally I build an executable file using this library:
$gcc main_executable_module.o ../data_libs/data_io.o ../yet_another_decision_module/decision.o -L. data_process.so -o test_main
It works and the executable works correctly. But there is a task to configure the library using macros:
Make the necessary changes to the code of the main_executable_module, configuring the use of the dynamic library using macros.
That is, if I understand correctly, you need to add macros to the main_executable_module.o so that you do not use the -L flags during assembly. But I can't find information anywhere on how to do it. Can you please tell me how to implement this or where can I read about it?
UPD: John Bollinger says
It is possible that the word "macros" is intended to be interpreted as makefile macros, which many people instead call (makefile) "variables". That would make this a question about make / makefiles, not about C.
My Makefile:
CC=gcc
LDFLAGS=
CFLAGS=-c -Wall -Wextra -Werror
SOURCES=main_executable_module.c ../data_libs/data_stat.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c ../data_module/data_process.c
DYNLIB=../data_module/data_process.c
STAT=../data_libs/data_stat.c
BUILDDYN=main_executable_module.c ../data_libs/data_io.c ../yet_another_decision_module/decision.c
OBJECTS=$(SOURCES:.c=.o)
OBJBUILDDYN=$(BUILDDYN:.c=.o)
OBJDYNLIB=data_process.o
OBJDATASTAT=data_stat.o
EXECUTABLE=../../build/main
DEXECUTABLE=../../build/Quest_6
DLIBS=data_process.so
all: $(SOURCES) $(EXECUTABLE)
data_stat.a: $(OBJLIB) $(LIBS)
ar -rcs $(LIBS) $(OBJLIB)
data_process.so: $(OBJDYNLIB) $(OBJDATASTAT)
$(CC) -shared -o $(DLIBS) $(OBJDYNLIB) $(OBJDATASTAT)
$(OBJDYNLIB): $(DYNLIB)
$(CC) -fPIC -c $(DYNLIB)
$(OBJDATASTAT): $(STAT)
$(CC) -fPIC -c $(STAT)
build_with_dynamic:$(OBJECTS) $(EXECUTABLE)
$(CC) $(OBJBUILDDYN) -L. $(DLIBS) -o $(DEXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf $(EXECUTABLE) $(OBJECTS)
lclean:
rm -rf $(LEXECUTABLE) $(OBJECTS) $(LIBS) $(DEXECUTABLE)
rebuild: clean $(SOURCES) $(EXECUTABLE)
The results of the checks revealed nothing. There are two opinions about this task.
Leave everything as above. And in the file itself, add a header process.h. Then everything is assembled and working. And at the same time, if you change the code in the library, rebuild it, and do not rebuild the executable file, then the changes will be taken into account. That is, the idea of ​​a dynamic library is respected.
Implement in such a way that there is no need to include headers in the main_executable_module.c. Then a special library is used for working with dynamic libraries, which allows you to write the path to the library and take individual functions from it. More about it here.
What was meant when it was said about macros, I still did not understand ...

Make File: "Nothing to be done for 'all'" Not updating after change to source file

I am brand new to make files in linux and trying to provide a make file for a simple heap management program.
When executing the make command, it works to originally build my program, however after making changes to the source file quickfit.c, make doesnt recognize the change and says "make: Nothing to be done for 'all'."
Why is it not recompiling my software after changes? I have all my source files in a source folder and all my header files in a include folder.
CC=gcc
CFLAGS= -Wall -w -g
INCLUDE:= -Iinclude/
SOURCE:= source/quickfit.c \
source/HeapTestEngine.o
EXE=QuickFit
all: $(EXE)
$(EXE):
$(CC) $(CFLAGS) $(INCLUDE) $(SOURCE) -o $(EXE)
$(EXE) doesn't depend on anything. make does not infer this dependency for you, you have to declare it.
$(EXE): $(SOURCE)
$(CC) $(CFLAGS) $(INCLUDE) $(SOURCE) -o $(EXE)
You'll probably also want to declare dependencies on your header files as well.
Note: it's a bit odd to consider an object file as "source". source/HeapTestEngine.o should probably have its own target.
Change:
$(EXE):
Into:
$(EXE): $(SOURCE)

Order of libraries and source files from makefile

I should start by saying I'm a bit of a newbie when it comes to gcc and makefiles.
On an Ubuntu machine that I've recently started using, I find that when running gcc, the order in which I put the source files and the libraries/headers makes a difference. On another machine I could do:
gcc -I../include -L../lib myProgram.c -o myProgram
But on the new machine, this will not link the libraries, and I must do:
gcc myProgram.c -o myProgram -I../include -L../lib
Now, I have the following makefile:
SHELL = /bin/sh
CC = gcc -O3
CFLAGS = -I../include
LDFLAGS = -L../lib
PROGS = myProgram
all: $(PROGS)
$(all): $(PROGS).o
$(CC) -o $# $#.o $(LIBS) $(CFLAGS) $(LDFLAGS)
rm -f $#.o
clean:
rm -f *.o $(PROGS)
But when I do "make", the actual gcc command that it runs has the libraries and source files in the wrong order. My question is: what do I need to do in the makefile to force the "-L../libs" option to come after the source files, so that the libraries will link properly?
I've also tried including the "-Wl,--no-as-needed" option, as I thought that an --as-needed flag might be the reason that the order matters in the first place, but this didn't appear to change anything (i.e. it still fails to link the libraries unless "-L../libs" comes after the source files).
The problem was that you thought you were using that rule, but you weren't. You never defined a variable named all, so the target of the second rule actually expanded to nothing. When you commanded Make to build myProgram, Make found no suitable rule in this makefile. Make has a toolbox of implicit rules it can fall back on in such cases; it wanted to build myProgram, it saw a file named myProgram.c, and one of its rules looks something like this:
%: %.c
$(CC) $(LDFLAGS) $^ -o $#
There you have it, linker flags before sources.
You can write your own pattern rule which Make will use instead:
%: %.o
$(CC) -o $# $^ $(LIBS) $(CFLAGS) $(LDFLAGS)
(Note that this builds myProgram from myProgram.o, and lets Make figure out how to build myProgram.o.)
If your executable is to be built from several object files, add a rule like this:
myProgram: other.o yetAnother.o
If you like you can have one more rule (the first) to tell Make what you want built:
all: myProgram myOtherProgram friendsProgram
(A final note: we've all had tight work deadlines. Asking for help once can be faster than learning the tools, but learning the tools is faster than asking for help N times. Determining the value of N is up to you.)

C Makefile - recompile only changed files

Hello I have a shared library libnsd.so (made up of nsd.c,nsd.h,nd.c,nd.h) linked to main file.
My question is how to write the makefile so that it recompiles only those source files that have been changed.
I have read some topics about this but got somewhat confused, I'm a beginner programmer.
My makefile code so far:
CC=gcc
all : lib alll
alll : main.c
$(CC) main.c -o main -L. libnsd.so
lib : nsd.c nsd.h nd.c nd.h
$(CC) -c -fPIC nsd.c -o nsd.o
$(CC) -c -fPIC nd.c -o nd.o
$(CC) -shared -Wl,-soname,libnsd.so -o libnsd.so nsd.o nd.o
clean:
rm main libnsd.so nd.o nsd.o
Makefiles have the concept of build targets. The build targets are, really, all the intermediate as well as the final files and, by the way they are written, they can be made to use dependencies.
A sample solution for your makefile:
CC=gcc
all: main
main: main.c libnsd.so
$(CC) main.c -o main -L. libnsd.so
libnsd.so: nsd.o nd.o
$(CC) -shared -Wl,-soname,libnsd.so -o libnsd.so $#
%.o: %.c nsd.h nd.h
$(CC) -c -fPIC $< -o $#
A few things to note:
You should properly correct my dependencies on the object file creation (since I consider that each of the C files depends on both of the headers).
You may wish to note the wildcard construction I have used...
If there was nothing special with some of these commands I could have left default commands work. Do note that I have used $< for the first dependency and $# for the output in the wildcard rule.
I haven't copied the clean rule, since it was written correctly in the question itself.
Each of the targets (besides the "phony" target all) creates a file with the same name: The target libnsd.so creates a file with the name libnsd.so. The target main creates a file with the name main.
As a dependency of a target changes date so that the dependency is newer than the output, make will recreate the target, as well as other targets that depend on it. But if you have a target that is not mapped to any output file, that target is always called (in our code, the all target is always called but thankfully it has no commands and it depends only on actual files which may or may not need being recreated)
Do note that GNU Make doesn't need to have compiling in particular. The creation of an output file can happen by any means, and indeed I have seen a target create a .cpio.gz archive. But if that archive is older than any of the dependencies (the folder it would pack in) then it would be recreated, according to make.

Compiling SDL project on Raspberry Pi

I am trying to build a project with make (gcc on Raspbian)
Here is the makefile (I removed some unnecessary parts):
objects = 3d.o Affichage.o [...]
cflags = -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2
poly : %(objects)
gcc $(cflags) $(objects) -o poly
($objects) : types.h
[...]
When running Make, I got:
cc -c -o Affichage.o Affichage.c
fatal error: SDL.h: No such file or directory
#include <SDL.h>
I checked the folders, everything seems ok. SDL.h is indeed in /usr/local/include/SDL2. I tried to remove options one by one in cflags, no luck...
What am I missing?
Make told you exact command it tried to execute:
cc -c -o Affichage.o Affichage.c
This don't have -I path, which is the source of an error.
You have target for your resulting executable but not for object files. Make have builtin rule to compile object files from C sources, but it isn't aware of your cflags variable. So far your options are:
Define your own pattern rule
e.g:
%.o: %.c
gcc $(cflags) -c $< -o $#
However, your cflags contains -lSDL2, which is linking flag, which should be specified only on linking phase (so technically it isn't cflag). Move it to separate variable (usually LIBS, which may then be enfolded into make's semi-standard LDFLAGS).
Use variables that make is aware of
In that case, it is CFLAGS:
CC:=gcc
CFLAGS:=-I/usr/local/include/SDL2
LIBS:=-lSDL2
LDFLAGS:=-L/usr/local/lib $(LIBS)
objects:=3d.o Affichage.o
poly: $(objects)
$(CC) $^ -o $# $(LDFLAGS)
$(objects): types.h
The rest will be done by implicit rules.

Resources