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

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!~

Related

Trouble Writing My First Makefile

So here is my Makefile:
# My First Makefile
HEADERS = stdio.h
all: main.o input.o output.o
cc -o all main.o input.o output.o
main.o: main.c $(HEADERS)
cc -c main.c -o main.o
input.o: input.c $(HEADERS)
cc -c input.c -o input.o
output.o: output.c $(HEADERS)
cc -c output.c -o output.o
clean:
-rm -f *.o
-rm -f all
And below is input.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
void getChar()
{
getchar();
}
#endif
Below is output.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
void putChar(char c)
{
putchar(c);
}
#endif
Below is main.c:
#ifndef __STDIO_H__
#define __STDIO_H__
#include <stdio.h>
int main()
{
char c;
while ((c = etChar()) != '\n')
{
putChar(c);
}
}
#endif
Yet whenever I press "make" command in Terminal,
I get:
make: *** No rule to make target `stdio.h', needed by `main.o'. Stop.
cc refers to clang
What is it that I am doing wrong here?
I was trying to get used to $(ARGS) by using $(HEADERS)
but it seems that the clang compiler does not accept this.
Do you think I should use gcc instead?
It is unnecessary to write stdio.h in your Makefile. GCC will automatically search it in DEFAULT PATH (/usr/include, ....). Write header files as targes in Makefile only if you use your own header files.
# Makefile
# define CC
CC := gcc
# define final targets
TARGETS := main
# just trigger $(TARGETS)
all: $(TARGETS)
# build main from main.o, input.o, output.o
main: main.o input.o output.o
$(CC) -o $# $^
# build main.o/input.o/output.c from main.c/input.c/output.c
%.o: %.c
$(CC) -c -o $# $<
# trigger $(TARGETS), then run ./main
run: $(TARGETS)
./main
clean:
-rm $(TARGETS)
-rm *.o
# define targets which are not bound to file
.PHONY: all clean run
In your case:
"make" will look for stdio.h in the current directory, and is complaining that the header is not found.
Just to fix this, you should mention the full path where stdio.h is located, for example:
HEADERS = /usr/include/stdio.h
Ideally, if you want to check for the presence of standard headers like stdio.h, you should use tools like automake and autoconf, which generate the Makefile automatically. Here's a link which points to the autoconf documentation:
https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html

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"

Makefile for static library with self-test capability

I want to have Makefile for my static library where I can conditionally build it as program to perform simple self-test. My current Makefille looks like follows:
OBJECTS = sm3.o ./core/sm3_internal.o
INCLUDES = -I. -I./core
CFLAGS = -g -Wall -O3
CC = c99
OUT = libsm3.a
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS) $(INCLUDES)
$(OUT): $(OBJECTS)
ar rcs $(OUT) $(OBJECTS)
At my main library file I have:
#ifdef TEST
main(int argc, int* argv[])
{
//my self-test logic here
}
#endif
Where should I add -DTEST flag? If I add it to CFLAGS and then add line:
test: $(OBJECTS)
library also would be build with main, which obviously is not something I want.
I would suggest that you compile main.c conditionally instead:
$(TESTOUT): $(OBJECTS) $(TESTOBJ)
$(CC) -o $# $<

SHA1 library link not found using makefile

I'm having trouble linking the sha library with my makefile while compiling.
Here is my makefile:
CFLAGS= -g -Wall -Werror -std=c99 -pedantic
LDFLAGS=-lssl -lcrypto
CC = gcc
LD = gcc
OBJS = dhtnode.o
PROG = dhtnode
.c.o:
gcc $< -o $# $(CFLAGS)
all: $(PROG)
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
dhtnode.o: dhtnode.c dhtpackettypes.h
$(CC) $(CFLAGS) $(LDFLAGS) dhtnode.c
clean:
/bin/rm -f *.o dhtnode
My function using the lcrypto library is here:
#include <openssl/sha.h>
#include <stdlib.h>
#include <stdin.h>
//there are other includes but not concerning this part of the code
char sha() {
char *ibuf = malloc(sizeof(char));
ibuf ="172.0.0.1:11112";
char *obuf = malloc(SHA_DIGEST_LENGTH);
SHA1((unsigned char*)ibuf, strlen(ibuf), (unsigned char*)obuf);
int i;
for (i = 0; i < 20; i++) {
printf("%x" , (unsigned char)obuf[i]);
}
printf("\n");
return *ibuf;
}
Here is the error I get when building with Eclipse:
C/p2p/dhtnode.c:107: undefined reference to `SHA1'
Can anybody tell my what is wrong with my makefile or possible eclipse settings?
Thx in advance!
When compiling the object file, you don't need the LDFLAGS. You'll also need the -c compiler flag to produce an object file instead of linking a binary:
dhtnode.o: dhtnode.c dhtpackettypes.h
$(CC) $(CFLAGS) -c dhtnode.c
After making this change, the program compiles and links successfully for me.

Resources