MakeFile: Implicit file declaration warnings in C - c

i am new to creating Make File and im running into some error caused by dependencies, basically in each "*.c" file i only include it self for example: Main will only include Main.h. As a result of this, i am trying to create the dependencies on MakeFile, the dependencies are:
-Main.c uses functions/structs that are declared in memory.h, synchronization.h, client.h, server.h proxy.h and process.h
-memory.c uses functions/structs that are declared in synchronization.h
-process.c uses functions/structs that are declared in client.h, proxy.h and server.h
Some other dependencies are made by #include in the header files.
Some of the errors i have got so far are:
gcc -c process.c
process.c: In function ‘launch_process’:
process.c:25:46: warning: implicit declaration of function ‘execute_client’ [-Wimplicit-function-declaration]
data->client_stats[process_id] = execute_client(process_id, buffers, data, sems);
process.c:30:45: warning: implicit declaration of function ‘execute_proxy’ [-Wimplicit-function-declaration]
data->proxy_stats[process_id] = execute_proxy(process_id, buffers, data, sems);
process.c:33:46: warning: implicit declaration of function ‘execute_server’ [-Wimplicit-function-declaration]
data->server_stats[process_id] = execute_server(process_id, buffers, data, sems);
gcc -c main.c
main.c: In function ‘launch_processes’:
main.c:159:32: warning: implicit declaration of function ‘launch_process’; did you mean ‘launch_processes’? [-Wimplicit-function-declaration]
data->client_pids[i] = launch_process(i, 0, buffers, data, sems);
main.c: In function ‘wait_processes’:
main.c:243:33: warning: implicit declaration of function ‘wait_process’; did you mean ‘wait_processes’? [-Wimplicit-function-declaration]
data->client_stats[i] = wait_process(data->client_pids[i]); //o retorno dos processos client_pids etc ira returnar o return do execute_client sendo que sera o "exit" do processo
PS:I am not allowed to change header files and sorry for the long question by have spent more then 24 hours straight around this and this is not allowing me to test my finished project, Thank you.
Here is the makefile that i have created.
sovaccines: client.o proxy.o server.o process.o main.o memory.o synchronization.o
gcc client.o proxy.o server.o process.o main.o memory.o synchronization.o -o sovaccines -lrt -pthread -g
main.o: main.c ../include/memory.h ../include/synchronization.h ../include/client.h ../include/proxy.h ../include/server.h ../include/process.h
gcc -c main.c
client.o: client.c
gcc -c client.c
memory.o: memory.c ../include/synchronization.h
gcc -c memory.c
process.o: process.c ../include/client.h ../include/proxy.h ../include/server.h
gcc -c process.c
proxy.o: proxy.c
gcc -c proxy.c
server.o: server.c
gcc -c server.c
synchronization.o: synchronization.c
gcc -c synchronization.c

Your warnings simply tell you that you forgot to include the correct header files in your C source files, or that you did not tell the compiler where to find these header files. Example: if in main.c you have something like:
#include "memory.h"
#include "synchronization.h"
#include "client.h"
#include "server.h"
#include "proxy.h"
#include "process.h"
you should pass the -I../include option to gcc. As you are using GNU make your Makefile could then look like this:
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
INCLUDE := ../include
CFLAGS := -g -I$(INCLUDE)
LDLIBS := -lrt -pthread
VPATH := $(INCLUDE)
sovaccines: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
main.o: memory.h synchronization.h client.h proxy.h server.h process.h
memory.o: synchronization.h
process.o: client.h proxy.h server.h
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
wildcard and patsubst are make functions
CC, CFLAGS, LDLIBS... are Variables Used by Implicit Rules
VPATH defines a Search Path for All Prerequisites
$#, $^, $<... are Automatic Variables
%.o: %.c is a Pattern Rule
Note that there are ways to automatically generate the dependencies of source files on header files. If you are interested, have a look, for example, at this excellent guide: Auto-Dependency Generation.
Note also that make knows already how to compile and link C projects. It has Implicit Rules. This is another way to further simplify your Makefile. In the proposed Makefile above you could, for instance, omit the pattern rule completely and also the recipe of the sovaccines: $(OBJ) rule.

Related

Easy gnu make makefile rule to build of GCC executable from multiple source files

I'm trying to make a simple as possible make file that uses the math library (fmax below, the rest is C cruft for this examlpe):
easy.c:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, const char *argv[]) {
double x=atof(argv[1]);
double y=atof(argv[2]);
double z=fmax(x,y);
printf("max(%f,%f)=%f\n",x,y,z);
return 0;
}
Makefile:
CFLAGS=-g
LDFLAGS=-lm
easy : easy.c
However this creates a link error (missing fmax). This is because make places the LDFLAGS first in the compile line:
> make easy
cc -g -lm easy.c -o easy
/usr/bin/ld: /tmp/ccmN5G9c.o: in function `main':
/home/user/projects/easy/easy.c:8: undefined reference to `fmax'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: easy] Error 1
Of course, if I explicitly put the LDFLAGS at the end using an explicit rule, it works:
CFLAGS=-g
LDFLAGS=-lm
easy : easy.c
$(CC) $(CFLAGS) -o $# $^ $(LDFLAGS)
Of course, understanding the Makefile is not nearly so easy now. Does anyone have a reason why the default rule does not put the link line at the end? Or is there an "easy" make that does allow a newcomer to link a number of source files into one executable (no lingering .o files)?
You should be using LDLIBS not LDFLAGS. LDFLAGS is for linker flags (such as -L). LDLIBS is for linker libraries (such as -lm).
If you investigate the default rules (make -pf/dev/null) you'll find this one:
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
(Ignore LOADLIBES as that's a deprecated name). Also see the documentation for LDLIBS and LDFLAGS.

How do you construct a C makefile so that it compiles the source.c file?

I have three files. main.c, graph.c, and graph.h.
I know the code works without a makefile because I tested it on the onlinegbd compiler. Everything runs smoothly.
When I try to run my makefile in terminal, I get an error of:
undefined reference to "function"
Where "function" is every function I call in main that is in graph.c.
So this leads me to think I'm not compiling graph.c in my makefile.
edit
I have confirmed it is the makefile. I compiled it using:
gcc -o xGraph main.c graph.c
And it ran without issue.
Here is the makefile:
CC = gcc
VPATH = SRC INCLUDE
TARGET = XGraph
CFLAGS = -g -Wall
all: $(TARGET)
$(TARGET): main.o graph.o
$(CC) main.o graph.o -o $(TARGET)
main.o: main.c graph.h
$(CC) $(CFLAGS) main.c
graph.o: graph.c graph.h
$(CC) $(CFLAGS) graph.c
clean:
rm *.o *~ $(TARGET)
When compiling C code the first stage is to generate .o files. Pass the -c flag to gcc to do this.
main.o: main.c graph.h
$(CC) $(CFLAGS) -c main.c
graph.o: graph.c graph.h
$(CC) $(CFLAGS) -c graph.c
In C, there are two types of undefined reference errors. The first results in an implicit declaration of function error, while the second gives your undefined reference. The first says gcc cannot find a definitition of your function. but the second means gcc sees nothing wrong with your code, then tries to link object files using ld and that crashes the code. Make sure that your source files are included in compilation and they have declarations, not just definitions. Also, providing a minimum reproducible example of your code might be helpful here.
Your simplest Makefile can be:
CFLAGS = -g -Wall
xGraph_objs = main.o graph.o
xGraph: $(xGraph_objs)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $(xGraph_objs)
main.o graph.o: graph.h
as there are implicit rules (that use the $CFLAGS variable, so you don't need to add rules to do the compilation, just to specify the extra dependencies between the objects and the header file)
The structure I use frequently for small projects is very similar to yours:
targets = xGraph
toclean = $(targets)
xGraph_deps = # no dependencies to link the executable. (E.g. creating a library needed to link this)
xGraph_objs = main.o graph.o
xGraph_libs = # no libs to specify at link time. (E.g. -lm -lX11)
xGraph_ldfl = # no flags for the linker. (E.g. -L/usr/local/lib)
toclean += $(xGraph_objs)
all: $(targets)
clean:
$(RM) $(toclean)
xGraph: $(xGraph_deps) $(xGraph_objs)
$(CC) $(LDFLAGS) $(xGraph_ldfl) $(xGraph_objs) -o $# $(xGraph_libs)

Compiling multiple .c and .h files

My program is divided into 6 files:
list.h (Containing basic list struct info and function prototypes)
list.c (Containg the implementation of the above)
search_tree.h (Containing basic tree struct info and function prototypes)
search_tree.c (Containing the implementation of the above, and includes list.h)
search.h ( again, prototypes of functions )
search.c (implementation of the aobve functions)
main.c ( Requires all of the above in order to run )
I cant seem to figure out what the makefile should be, i've tried the one below but it doesnt work and i get errors of structs and functions not implemented.
myprog: list.o search_tree.o search.o main.o
gcc -o myprog list.o search_tree.o search.o main.o
list.o: list.c list.h
gcc -c list.c
search_tree.o: search_tree.c search_tree.h
gcc -c search_tree.c
search.o: search.c search.h
gcc -c search.c
main.o: search.h search_tree.h list.h hash_table.h
gcc -c main.c
You do not need to explicitly create a rule for each file - make has a number of implicit rules that already do 90% of what you need. Your makefile can be as simple as
CC=gcc
CFLAGS=-std=c11 -pedantic -Wall -Werror # my usual compiler flags
LDFLAGS= # specify additional libraries and library search paths here
myprog: main.o search.o search_table.o list.o
$(CC) -o $# $(LDFLAGS) $?
clean:
rm -rf myprog *.o
There's already an implicit rule to build .o files from .c files, so you don't need to create your own unless you want to override the default, which is
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
You do need the explicit myprog rule to link the object files into the executable since the executable name doesn't match any of the source or object file names. $# expands to the target name, myprog, and $? expands to the list of prerequisites for the target (i.e., the object files). $< expands to the first name in the list of prerequisites.
This doesn't cover header file dependencies, but your project is small enough for that to not be too much of an issue. However, give this article a read for one way to handle that.
Similar to John's proposal with a small bug fixed ($^ automatic variable instead of $?), a bit more automation (wildcard to search for the C source files) and with dependencies added for the header files ($(OBJS): %.o: %.h static pattern rule):
EXEC := myprog
OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
$(EXEC): $(OBJS)
$(CC) -o $# $(LDFLAGS) $^
$(OBJS): %.o: %.h
clean:
rm -f $(EXEC) $(OBJS)

New to c, linking error when using a method declared in a header that's included

I'm new to c and I'm trying to use a method from tester in my main.c class.
So here is main.c:
#include <stdbool.h>
#include <stdio.h>
#include "tester.h"
int main(void) {
bool is_valid = isTrue();
}
Here is tester.h:
#include <stdbool.h>
bool isTrue();
Here is tester.c:
#include "tester.h"
bool isTrue() {
return true;
}
And here is what happens when I try to compile:
$ make main tester
gcc -g -O0 -Wall --std=c99 -pedantic -g -O0 main.c -o main
main.c: In function ‘main’:
main.c:7:10: warning: unused variable ‘is_valid’ [-Wunused-variable]
bool is_valid = isTrue();
^
/tmp/ccwIzgJQ.o: In function `main':
/home/paul/CS261/p1-check/mess/main.c:7: undefined reference to `isTrue'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
My Makefile was provided by my professor. I can post the contents here, but I'm confident it's correct. I know there's a linking error happening here, but why? I included the tester.h file in my main.c, so shouldn't isTrue be defined? Assistance would be greatly appreciated.
Edit: Here is the Makefile:
# Simple Makefile
#
#
# This makefile builds a simple application that contains a main module
# (specified by the EXE variable) and a predefined list of additional modules
# (specified by the MODS variable). If there are any external library
# dependencies (e.g., the math library, "-lm"), list them in the LIBS variable.
# If there are any precompiled object files, list them in the OBJS variable.
#
# By default, this makefile will build the project with debugging symbols and
# without optimization. To change this, edit or remove the "-g" and "-O0"
# options in CFLAGS and LDFLAGS accordingly.
#
# By default, this makefile build the application using the GNU C compiler,
# adhering to the C99 standard with all warnings enabled.
# application-specific settings and run target
EXE=y86
MODS=p1-check.o
OBJS=
LIBS=
default: $(EXE)
test: $(EXE)
make -C tests test
# compiler/linker settings
CC=gcc
CFLAGS=-g -O0 -Wall --std=c99 -pedantic
LDFLAGS=-g -O0
# build targets
$(EXE): main.o $(MODS) $(OBJS)
$(CC) $(LDFLAGS) -o $(EXE) $^ $(LIBS)
%.o: %.c
$(CC) -c $(CFLAGS) $<
clean:
rm -f $(EXE) main.o $(MODS)
make -C tests clean
.PHONY: default clean
Am I missing a part of the command when I try to use the Makefile for linking? It's probably something on my end, but I'm not sure what.
I figured out what I was doing wrong. I should have been saying make main.o when I wanted to link files with it. I wasn't paying enough attention to the build commands in Makefile, it seems. Thanks to kaylum for the clarification between declarations and definitions.

libgcrypt-config --libs: no such file or directory

I'm using gcrypt, but my compiler seems to unable to find it. Here is my makefile. function.c is a function source file containing functions I defined; I also wrote a header file miao.h with function declaration, and gcrypt.h is included in it. main.c is a source file including miao.h. When I do make: .Could anyone help me? This bothers me so long.
CC = gcc
CFLAGS = 'libgcrypt-config --cflags'
LIBS = 'libgcrypt-config --libs'
OBJS = function.o main.o main
all: $(OBJS)
function.o: function.c
$(CC) -c function.c $(CFLAGS)
main.o: main.c
$(CC) -c main.c $(CFLAGS)
main: main.o function.o
$(CC) -o main main.o function.o $(LIBS)
clean:
rm $(OBJS)
the makefile should be written more like the following:
caveat: I was unable to test the makefile as I do not have libgcrypt-config available.
Per the web site: https://gnupg.org/documentation/manuals/gcrypt/Building-sources.html the libgcrypt-config is an executable so should be surrounded by back-ticks, not single quotes so it will be executed in the current shell.
(back ticks on stackoverflow will result in emphasised text but should still be visible as to where they should be placed.)
Note: where I have placed <tab> your actual makefile needs to have a tab character
Note: targets, like all and clean do not produce a file with the same name, so early in the file there needs to be the statement: .PHONY: all clean
when defining a macro, use := rather than = so the macro is only evaluated once.
Any calls to shell functions should be incorporated via a macro, so it is easy to make a change. In general it is best to include the path to the shell function: I wrote this on Linux, your path may be different. Specifying the actual path becomes very important when cross compiling or there are duplicate names visible via the $PATH statement (as can easily be the case with gcc)
Note: the actual libgcrypt-config executable must be in visible via your $PATH environment variable.
Note: all the individual compile statements could be reduced to the following two lines: (and nothing else needed for the compiles)
%.o: %.c
<tab>$(CC) -c $< -o $# -I. $(CFLAGS)
Note: do not place the contents of a rule where the dependencies is expected. This error was noted in the clean: target
the proposed makefile follows:
CC := /usr/bin/gcc
RM := /usr/bin/rm
CFLAGS := `libgcrypt-config --cflags`
LIBS := `libgcrypt-config --libs`
OBJS := function.o main.o main
TARGET := main
.PHONY: all clean
all: $(TARGET)
function.o: function.c
<tab>$(CC) -c function.c $(CFLAGS) -o function.o -I.
main.o: main.c
<tab>$(CC) -c main.c $(CFLAGS) -o main.o -I.
$(TARGET): $(OBJS)
<tab>$(CC) -o $(TARGET) $(OBJS) $(LIBS)
clean:
<tab>$(RM) -f $(OBJS)

Resources