Why are these static functions working outside their file? - c

I defined the next two static functions in a file named Grafico.h.
static inline interface_t * obtener_intf_por_nombre(nodo_t *nodo, char *nombre_if) {
for (int i = 0; i < MAX_INTF_POR_NODO; ++i)
{
if(!nodo->intf[i]) return NULL;
if(strncmp(nodo->intf[i]->nombre_if, nombre_if, TAM_NOMBRE_IF) == 0) {
return nodo->intf[i];
}
}
return NULL;
}
static inline nodo_t * obtener_nodo_por_nombre(grafico_t *topologia, char *nombre_nodo) {
return obtener_elemento(topologia->lista_nodos, nombre_nodo);
}
In my main file I called these functions without remembering they were static, and I didn't get any warning or error from the compiler related to it.
#include <stdio.h>
#include "Net.h"
#include "Grafico.h"
#include "Topologias.h"
#include "CommandParser/libcli.h"
#include "clired.c"
extern grafico_t *const_primera_topo();
grafico_t *topo = NULL;
int main(void) {
inic_cli_red();
topo = const_primera_topo();
sleep(2);
nodo_t *nodo_trans = obtener_nodo_por_nombre(topo, "R0");
interface_t *interface_trans = obtener_intf_por_nombre(nodo_trans, "ethR0/0");
char *mensaje = "Este es un mensaje de prueba\0";
printf("Llegamos hasta aquí señores. Fue un honor.\n");
enviar_paquete(mensaje, strlen(mensaje), interface_trans);
start_shell();
return 0;
}
In case it's useful, here is my makefile.
TARGET = $(BIN_DIR)/sim_tcp_ip
LIBS = -lpthread -L ./CommandParser -lcli -lrt
OBJS = $(OBJ_DIR)/prueba.o \
$(OBJ_DIR)/ListaEnlazadaGenerica.o \
$(OBJ_DIR)/Grafico.o \
$(OBJ_DIR)/Net.o \
$(OBJ_DIR)/Topologias.o \
$(OBJ_DIR)/Com.o \
$(OBJ_DIR)/Utiles.o \
$(OBJ_DIR)/Capa2.o
BIN_DIR = ./bin
OBJ_DIR = ./obj
INC_DIR = ./inc
SRC_DIR = ./src
CFLAGS = -g -lpthread -Wall -I$(INC_DIR)
$(TARGET): $(OBJS) CommandParser/libcli.a
mkdir -p $(BIN_DIR)
gcc $(CFLAGS) $(OBJS) -o $(TARGET) $(LIBS)
$(OBJ_DIR)/%.o : %.c
mkdir -p $(OBJ_DIR)
gcc -c -MD $(CFLAGS) $< -o $#
CommandParser/libcli.a:
(cd CommandParser; make)
-include $(OBJ_DIR)/*.d
.PHONY: clean
clean:
rm -rf $(OBJ_DIR) $(BIN_DIR)
(cd CommandParser; make clean)
all:
make
Is there something wrong with the definition of these static functions?

When you #include a file, it is equivalent to copypasting the contents of that file in place of that line. So the static functions are in the same compilation unit, and hence just as usable as any other static thing you define in the .c file itself.

The problem is that you have declared them in your header file, Graphico.h!
The static keyword just means that if you compile a source C file prog.c into an object file prog.o, then any static functions in prog.c will be hard coded as memory addresses in prog.o. That is to say, whereas a normal function has an entry defined in the symbol table of prog.o, that is used when prog.o is linked with another object file, a static function does not.

Related

Why i must to include my own lib archive when i´m compiling

I have a problem including my own library.
I have created some functions in a few archives .c,
after that i have created the header file .h,
but when i try to compile a main.c that call a function that was in my own lib
i must to type gcc ownlib.a main.c -o prog.out and include the lib ownlib.a archive
as a parameter of gcc.
In this case i was trying to call my own strlen() called ft_strlen() function that is in my own lib.
I know when i compile any program using a function that is in a compiler library i only must
include the header in the code for example: #include <string.h>,
but when i call my own function i add #include "ownlib.h".
If i compile the main.c calling system function strlen() i have to compile only the main.c
archive and it works.
When i create a lib with my own ft_strlen() and in the main.c i include my own lib
#include "ownlib.h" it doesn´t work if i do this gcc main.c -o program.out
but it works if i add my lib archive like this gcc main.c ownlib.a -o program.out
I want to know why when i use a system library function i don´t need to compile with the library archive,
for example gcc main.c string.c -o program.out,
only whith the #include <string.h> it works,
and why i must to include my ownlib.a in the compiation gcc libft.a main.c -o program.out.
I don't know if I explained myself well
LIBNAME = ownlib.a
HEADERNAME = ownlib.h
SRCS = ft_strlen.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
AR = ar
ARFLAGS = -rcs
$(LIBNAME): $(OBJS) $(HEADERNAME)
#$(AR) $(ARFLAGS) $(LIBNAME) $(OBJS)
all: $(LIBNAME)
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(LIBNAME)
re: fclean all
%.o: %.c $(HEADERNAME)
#${CC} ${CFLAGS} -c $< -o ${<:.c=.o}
.PHONY: all clean fclean re
one of the functions is like this:
#include "ownlib.h"
size_t ft_strlen(const char *str)
{
int i;
i = 0;
while (str[i] != '\0')
i++;
return (i);
}
Th main function is:
#include <stdio.h>
#include "ownlib.h"
int main(void)
{
char *str;
str = "How many characters";
printf("%i", ft_strlen(str);
return (0);
}
If i compile gcc main.c -o program.out don´t know what is ft_strlen()
Thanks so much

Undefined reference to function that is already defined in my header file

I have three files, posl.h, state.c and main.c. What I plan on doing is adding functions that are used throughout the project in posl.h, and then I call it to test the function with main.c, and then make the function in state.c. The problem I am having is that I keep getting an error of undefined reference to init_poslState() even though I have it defined in posl.h
main.c
#include <posl.h>
int main(int argc, char * argv[]) {
pState poslState = init_poslState();
return 0;
}
posl.h
#ifndef POSL_LANGUAGE_H
#define POSL_LANGUAGE_H
#define POSL_MAJOR_VERSION 1
#define POSL_MINOR_VERSION 0
#define POSL_RELEASE_VERSION 0
// State
typedef struct POSL_STATE {
// ...
} pState;
pState init_poslState();
void free_poslState(pState poslState);
#endif
state.c
#include "state.h"
#include <posl.h>
pState init_poslState() {
pState newState;
return newState;
}
Makefile
CFLAGS=-g -Wall -Wextra -I./include
CC=gcc $(CFLAGS)
CORE_O_FILES=./src/Core/lexer.o ./src/Core/parser.o ./src/Core/state.o
CLI_O_FILES=
O_FILES=$(CORE_O_FILES)
# Making CLI Tool
posl: $(CLI_O_FILES) libposl.a ./src/CLI/main.c
$(CC) -o posl -L./ -lposl ./src/CLI/main.c $(CLI_O_FILES)
# Making Library
libposl.a: $(O_FILES) ./include/posl.h
ar rcs libposl.a $^
# Core Files
./src/Core/lexer.o: ./src/Core/lexer.c ./src/Core/lexer.h
$(CC) -o $# -c ./src/Core/lexer.c
./src/Core/parser.o: ./src/Core/parser.c ./src/Core/parser.h
$(CC) -o $# -c ./src/Core/parser.c
./src/Core/state.o: ./src/Core/state.c ./src/Core/state.h
$(CC) -o $# -c ./src/Core/state.c
# PHONY List
.PHONY: all
all:
make update-libs
make libposl.a
make posl
make pcc
# Post-Compile Clean
.PHONY: pcc
pcc:
rm -rf ./src/Core/*.o
rm -rf ./src/CLI/*.o
.PHONY: clean
clean:
make pcc
rm -rf ./libposl.a ./posl*
The order of compiler and (especially) linker options is significant. With this command ...
$(CC) -o posl -L./ -lposl ./src/CLI/main.c $(CLI_O_FILES)
... the linker will not attempt to resolve any function references from main.c against functions in libposl.a. It will look only to objects and libraries appearing after main.c on the command line.
Therefore, rewrite that recipe to
$(CC) -o posl -L. ./src/CLI/main.c $(CLI_O_FILES) -lposl
Welp, #user17732522 answered my question. I had the -l flag messed up, and it wasn't after my source files. ~Thank you guys!~

Forcing Orders in Makefile Dependencies

I need some help writing a GNU makefile. I have a C program "main.c", which is dependent on the value of "CONSTANT" defined in the file "constants.h".
"main.c"
#include <stdio.h>
#include "constants.h"
void work(void)
{
int array[CONSTANT];
for (int i = 0; i < CONSTANT; i++) {
printf("%d\n", i);
}
}
int main(int argc, char const* argv[])
{
printf("constant=%d\n", CONSTANT);
work();
return 0;
}
"constant.h"
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define CONSTANT 4
#endif
What I'm trying to do here is to compile the program with different values for "CONSTANT". For example, "out1" is compiled with "CONSTANT=1" and with "make all", I should be able to produce all the variants ("out1", "out2" and "out4").
The problem is that "a.o" required by "main.c" also depends on the value of "CONSTANT". So "a.o" must be compiled after "sed%". However, as far as I understand, there is no way in "make" to force orders in dependencies (I guess this is the whole point of using makefiles).
What is the recommended way to address this situation?
"Makefile"
CC= gcc
CFLAGS = -std=c99 -Wall
CONSTANTS = 1 2 4
targets = $(addprefix out, $(CONSTANTS))
seds = $(addprefix sed, $(CONSTANTS))
.PHONY: $(seds)
$(seds): sed%:
sed -i 's/define CONSTANT [0-9]*/define CONSTANT $*/g' constants.h
$(targets): out%: main.c sed% a.o
$(CC) $(CFLAGS) $< a.o -o $#
a.o: a.c constant.h
$(CC) $(CFLAGS) $< a.o -o $#
.PHONY: all
all : $(targets)
Note that I'm aware that I can rewrite "main.c" so that it takes a parameter from the comman line. In practice, many other files other than "main.c" depend on "CONSTANT", so I want to avoid rewriting all these files. I'm also aware that I can do something like "gcc -DCONSTANT=n main.c", but every file dependent on "CONSTANT" must be recompiled as well.
Related Questions
How to specify Makefile target building order without put any physical dependencies?
Force order of dependencies in a Makefile
I'm ... aware that I can do something like "gcc -DCONSTANT=n main.c",
but every file dependent on "CONSTANT" must be recompiled as well.
This needn't be a hindrance if you have your makefile generate
the correct -DCONSTANT=n and distinct object file in every compilation recipe.
Here's an illustration:
constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
#ifndef CONSTANT
#define CONSTANT 4
#endif
#endif
foo.c
#include "constants.h"
int foo = CONSTANT;
main.c
#include <stdio.h>
#include "constants.h"
extern int foo;
int main()
{
printf("%d\n",CONSTANT + foo);
return 0;
}
Makefile
CC := gcc
CFLAGS := -std=c99 -Wall
CONSTANTS = 1 2 4
TARGETS = $(addprefix out, $(CONSTANTS))
SRCS := main.c foo.c
define compile =
$(basename $(1))$(2).o: $(1) constants.h
$$(CC) -c -DCONSTANT=$(2) $$(CFLAGS) $$< -o $$#
endef
.PHONY: all clean
all : $(TARGETS)
$(foreach src,$(SRCS),\
$(foreach const,$(CONSTANTS),$(eval $(call compile,$(src),$(const)))))
out%: main%.o foo%.o
$(CC) $^ -o $#
clean:
rm -f $(TARGETS) *.o
This runs like:
$ make
gcc -c -DCONSTANT=1 -std=c99 -Wall main.c -o main1.o
gcc -c -DCONSTANT=1 -std=c99 -Wall foo.c -o foo1.o
gcc main1.o foo1.o -o out1
gcc -c -DCONSTANT=2 -std=c99 -Wall main.c -o main2.o
gcc -c -DCONSTANT=2 -std=c99 -Wall foo.c -o foo2.o
gcc main2.o foo2.o -o out2
gcc -c -DCONSTANT=4 -std=c99 -Wall main.c -o main4.o
gcc -c -DCONSTANT=4 -std=c99 -Wall foo.c -o foo4.o
gcc main4.o foo4.o -o out4
And the resulting programs run like:
$ for i in 1 2 4; do ./out$i; done
2
4
8

Makefile with multiple files always builds everything

I am writing a Makefile which compiles a number of C files, some in the same directory as the Makefile and others in parent directories (must be there for historic reasons). I want to put all *.o files in a single directory (objdir in my case). This seems to work, but for some reason, this Makefile always builds everything, even if nothing has changed. Where am I going wrong in my rules/dependecies?
UPDATE: I've distilled my Makefile and sources down to the bare minimum (see below for source file contents. To be clear, this does compile and link. The problem is that it does the compilation and linking every time I run make, even if nothing has changed. This is not typical make behavior.
Makefile contents:
CC = gcc
CFLAGS = -g -Wall -Werror -I..
SRCS = main.c ../a.c
OBJS = $(patsubst %.c, objdir/%.o, $(SRCS))
LN_OBJS = $(patsubst %.c, objdir/%.o, $(notdir $(SRCS)))
MAIN = foo
.PHONY: clean
default: objdir $(MAIN)
#echo Done
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) -o $(MAIN) $(LN_OBJS )
objdir/%.o: %.c
$(CC) $(CFLAGS) -c $< -o objdir/$(notdir $#)
objdir:
#mkdir -p objdir
clean:
#$(RM) -rf objdir $(FDP) $(DK)
main.c contents
#include "stdlib.h"
#include "stdio.h"
#include "a.h"
int main(int argc, char**argv)
{
printf("Hello\n");
a();
}
../a.c contents
#include <stdio.h>
void a()
{
printf("Hi from a\n");
}
../a.h contents
#ifndef __a__
#define __a__
void a();
#endif
Your rule for objdir/%.o: is expanded to objdir/../a.o: ../a.c, but you then go and create objdir/$(notdir $#), violating rule 2 of the Rules of Makefiles.
One way to fix this is with vpath (also note that objdir should be a (order-only) dependency of the objects):
SRCS = main.c a.c
vpath %.c ../
# [...]
objdir/%.o: %.c | objdir
$(CC) $(CFLAGS) -c $< -o $#

`multiple definition of` lots of variables error - is my make file incorrect?

I am getting an error when I compile multiple definition of lots of variables. For example:
/tmp/ccwHwJ7t.o:(.data+0x0): multiple definition of `serial_number'
/tmp/ccmT1XNI.o:(.data+0x0): first defined here
All the variables are located in ftdi.h, which is included by main.c. Is there something wrong with my make file that is causing this to be included twice? or am I looking in the wrong directio.
SSHELL = /bin/sh
CC = gcc
APP = npi_usb_ftdi
INC = include
INCDIRS +=-I${INC}
CFLAGS= ${INCDIRS} -Wall -Wextra
LIBS = libftd2xx.a -ldl -lpthread -lrt
all: ${APP}
${APP}: src/main.c src/ftdi.c src/vt100.c src/monitor.c
${CC} ${CFLAGS} src/main.c src/ftdi.c src/vt100.c src/monitor.c -o ${APP} ${LIBS}
ftdi.o:
${CC} -c -o src/ftdi.o src/ftdi.c
vt100.o:
${CC} -c -o src/vt100.o src/vt100.c
monitor.o:
${CC} -c -o src/monitor.o src/monitor.c
clean:
rm -f src/*.o ; rm -f src/*~ ; rm -f *~ ; rm -f ${APP}
You probably include the .h file in other source files too. No problem, but only in one source file should the variables be declared and in the others just defined. I use:
// ftdi.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int examplevar;
// main.c
#define EXTERN
#include "ftdi.h"
// ftdi.c
#include "ftdi.h"

Resources