How to link multiple .c files - c

I know that you have to create a header file and #include it in your main. I have done that and when I compile my code for some reason it is unable to figure out where one of my functions are.
The layout of my project is a: threads.c makeCityFromInput.h and makeCityFromInput.c
I have the threads.c #including the makeCityFromInput.h
This is what happens when I try to compile:
make
gcc -ggdb -std=c99 -Wall -Wextra -pthread -c threads.c
gcc -ggdb -std=c99 -Wall -Wextra -pthread -o threads threads.o -lm -lncursesw -pthread
threads.o: In function `main':
/home/project3/threads.c:183: undefined reference to `readConfig'
collect2: error: ld returned 1 exit status
Makefile:71: recipe for target 'threads' failed
make: *** [threads] Error 1
It is unable to find my readconfig file even though it is in my header file
my threads.c file
#define _DEFAULT_SOURCE
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <ncurses.h> //displays the cars
#include <pthread.h> //threading
#include <unistd.h>
#include "makeCityFromInput.h"
#define MAX 2048
int main(int argc, char *argv[]){
//Expected input: Name of config file
// If the config file is not given; or too many config files are given
if (argc != 2){
endwin();
fprintf(stderr, "Usage: Enter a configuration file");
exit( EXIT_FAILURE );
}
FILE *fp = NULL;
fp = fopen(argv[1], "r");
assert( fp );
readConfig(fp);
fclose( fp );
return 0;
}
my makeCityFromInput.h file:
#ifndef _MAKECITYFROMINPUT_H
#define _MAKECITYFROMINPUT_H
void readConfig(FILE *fp);
int *parse_line(char *line, int *numInts);
void create_skyline(int *ground, int size, int maxMissiles);
#endif
my makeCityFromInput.c file:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <ncurses.h> //displays the cars
#include <pthread.h> //threading
#include <unistd.h>
void readConfig(FILE *fp){
...
}
My make file
#
# Created by gmakemake (Ubuntu Jul 25 2014) on Wed Nov 14 20:05:05 2018
#
#
# Definitions
#
.SUFFIXES:
.SUFFIXES: .a .o .c .C .cpp .s .S
.c.o:
$(COMPILE.c) $<
.C.o:
$(COMPILE.cc) $<
.cpp.o:
$(COMPILE.cc) $<
.S.s:
$(CPP) -o $*.s $<
.s.o:
$(COMPILE.cc) $<
.c.a:
$(COMPILE.c) -o $% $<
$(AR) $(ARFLAGS) $# $%
$(RM) $%
.C.a:
$(COMPILE.cc) -o $% $<
$(AR) $(ARFLAGS) $# $%
$(RM) $%
.cpp.a:
$(COMPILE.cc) -o $% $<
$(AR) $(ARFLAGS) $# $%
$(RM) $%
CC = gcc
CXX = g++
RM = rm -f
AR = ar
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
CPP = $(CPP) $(CPPFLAGS)
########## Flags from header.mak
CFLAGS = -ggdb -Wall -Wextra -pedantic -std=c99 -pthread
# program uses pthreads and curses libraries
CLIBFLAGS = -lncursesw -lpthread -lrt
########## End of flags from header.mak
CPP_FILES =
C_FILES = pt-cruisers.c racer.c
PS_FILES =
S_FILES =
H_FILES = racer.h
SOURCEFILES = $(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)
.PRECIOUS: $(SOURCEFILES)
OBJFILES = racer.o
#
# Main targets
#
all: pt-cruisers
pt-cruisers: pt-cruisers.o $(OBJFILES)
$(CC) $(CFLAGS) -o pt-cruisers pt-cruisers.o $(OBJFILES) $(CLIBFLAGS)
#
# Dependencies
#
pt-cruisers.o: racer.h
racer.o: racer.h
#
# Housekeeping
#
Archive: archive.tgz
archive.tgz: $(SOURCEFILES) Makefile
tar cf - $(SOURCEFILES) Makefile | gzip > archive.tgz
clean:
-/bin/rm -f $(OBJFILES) pt-cruisers.o core
realclean: clean
-/bin/rm -f pt-cruisers

It looks like this
gcc -ggdb -std=c99 -Wall -Wextra -pthread -c threads.c
gcc -ggdb -std=c99 -Wall -Wextra -pthread -c makeCityFromInput.c
gcc -ggdb -std=c99 -Wall -Wextra -pthread -o threads threads.o makeCityFromInput.o -lm -lncursesw -pthread
If you show your make file we can also help with that...

I guess what you are actually asking is "What is wrong with my makefile?". As you have not provided it I can only take an educated guess. Here is a GNUmake snippet to build your program:
.PHONY: default
default: threads
CC := ...
LD := ...
CFLAGS := ...
LDFLAGS := ...
LIBS := ...
SRCS := threads.c makeCityFromInput.c
OBJS := $(SRCS:%.c=%.o)
$(OBJS): %.o: %.c
$(CC) $(CFLAGS) -o $# -c $<
threads: $(OBJS)
$(LD) $(LDFLAGS) -o $# $^ $(LIBS)

Related

Getting a C error that I have an undefined reference to function, but the function is defined

I am trying to take a binary to decimal function out of my main.c file and into its own file, but when I compile the files with my makefile I get the error:
undefined reference to `btod'
Here is my main.c file:
#include "btod.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n;
printf("\nEnter a binary number: ");
char c[100];
scanf("%s",c);
printf("Number converted to decimal: %d\n\n\n",btod(strlen(c),c));
return 0;
}
Here is my btod.c file:
#include <stdlib.h>
#include <string.h>
int btod(int size,char inputBin[size])
{
int i,num=0;
for(i=0;i<size;i++)
{
num=num*2+(inputBin[i]-48);
}
return num;
}
Here is my btod.h file:
int btod(int size,char inputBin[size]);
And lastly, here is my makefile:
CC = gcc
INCLUDE = -I.
CFLAGS = -g -Wall
LDFLAGS = -L. \
-L/usr/lib
LDLIBS = \
-lc -lm
.c.o:
$(CC) $(INCLUDE) $(CFLAGS) -c $<
all: main
main: main.o
$(CC) -o $# $^ $(LDFLAGS) $(LDLIBS)
btod: btod.o
$(CC) -o $# $^ $(LDFLAGS) $(LDLIBS)
clean:
rm -f *.o
rm -f main
I am thinking it might have to do with the btod.c file not being compiled properly within the makefile but I cannot figure out what is incorrect about it.
The error is because you don't link in btod.o when building main. If you use GNU Make, you can simplify your Makefile to just a few lines:
.PHONY: all clean
CFLAGS = -g -Wall
all: main
clean:
rm -f *.o main
main: btod.o main.o
In btod.c use '0' instead of 48. In main.c remove the line int n.

Undefined reference to (readline, pthread_create, pthread_detach), makefile not including libraries

This may be a simple answer but I am trying to compile code for a simple User level file system. I am running my code on a windows Ubuntu subsystem.
I have all the lpthread and lreadline libraries updated and installed and I still get the undefined reference when compiling.
gcc -Wall -g -lreadline -lcurses -lpthread userfs.c parse.c crash.c -o userfs
/tmp/ccNrZDqQ.o: In function `main':
/home/kupinah/userfs/userfs.c:75: undefined reference to `readline'
/tmp/ccwcrZEh.o: In function `init_crasher':
/home/kupinah/userfs/crash.c:10: undefined reference to `pthread_create'
/home/kupinah/userfs/crash.c:14: undefined reference to `pthread_detach'
collect2: error: ld returned 1 exit status
Makefile:12: recipe for target 'userfs' failed
make: *** [userfs] Error 1
Here is the code locations and headers included for each.
userfs.c:
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <assert.h>
#include <string.h>
#include "parse.h"
#include "userfs.h"
#include "crash.h"
...
...
...
while(1) {
cmd_line = readline(buildPrompt());
if (cmd_line == NULL) {
fprintf(stderr, "Unable to read command\n");
continue;
}
...
...
makefile
CC = gcc
COMPILER_WARNINGS = -Wall
GDB_FLAGS = -g
GCOV_FLAGS = -fprofile-arcs -ftest-coverage
GPROF_FLAGS = -pg -a
LD_LIBS = -lreadline -lcurses -lpthread
CFLAGS = $(COMPILER_WARNINGS) $(GDB_FLAGS) $(LD_LIBS)
all: userfs
userfs: userfs.c parse.c crash.c
$(CC) $(CFLAGS) userfs.c parse.c crash.c -o userfs
clean:
/bin/rm -f userfs *.o *~
Help pls.
#MadScientist Helped me out on this one.
What fixed this issue was some simple edits to the make file.
CC = gcc
COMPILER_WARNINGS = -Wall
GDB_FLAGS = -g
GCOV_FLAGS = -fprofile-arcs -ftest-coverage
GPROF_FLAGS = -pg -a
LD_LIBS = -lpthread -lreadline -lcurses
CFLAGS = $(COMPILER_WARNINGS) $(GDB_FLAGS)
all: userfs
userfs: userfs.c parse.c crash.c
$(CC) $(CFLAGS) userfs.c parse.c crash.c -o userfs $(LD_LIBS)
clean:
/bin/rm -f userfs *.o *~
Changes:
LD_LIBS = -lpthread -lreadline -lcurses---- Reordering
CFLAGS = $(COMPILER_WARNINGS) $(GDB_FLAGS)---- Removed $(LD_LIBS)
userfs: userfs.c parse.c crash.c
$(CC) $(CFLAGS) userfs.c parse.c crash.c -o userfs $(LD_LIBS)----Added $(LD_LIBS)

Strange error in makefile for C program which connect to MQ onm Linux

I have created a new makefile
CC = /usr/bin/gcc
MQM_HOME = /opt/mqm
CFLAGS = -g -Wall \
-I$(MQM_HOME)/inc \
-I/usr/include
#IBM_LIBPATH=-L/usr/vacpp/lib
IBM_LIBS= -liconv
MQ_LIBPATH=-L$(MQM_HOME)/lib64
MQLIB = $(MQ_LIBPATH) -lmqm -lmqmcs -lmqmzse
LIBS = $(IBM_LIBS) $(MQLIB) -lpthreads
#LDFLAGS = -q64 $(IBM_LIBPATH) $(MQ_LIBPATH)
SOURCE=/home/avalanche/oleg
default: ctm_mq_con_ex
ctm_mq_con_ex: ctm_mq_con_ex.o
# Compilation rules
EXE = $(SOURCE)/ctm_mq_con_ex
MAIN = $(SOURCE)/ctm_mq_con_ex.c
OBJS = $(SOURCE)/ctm_mq_con_ex.o
.c.o:
$(CC) $(CFLAGS) -c $(MAIN)
$(CC) $(CFLAGS) -o $(EXE) $(OBJS)
clean:
\rm -f $(OBJS)
\rm -f $(EXE)
Now it shows errors
make -f ./ctm_mq_con_ex.mk
/usr/bin/gcc -g -Wall -I/opt/mqm/inc -I/usr/include -c /home/avalanche/oleg/ctm_mq
/usr/bin/gcc -g -Wall -I/opt/mqm/inc -I/usr/include -o /home/avalanche/oleg/ctm_mq
/home/avalanche/oleg/ctm_mq_con_ex.o: In function `main':
/home/avalanche/oleg/ctm_mq_con_ex.c:67: undefined reference to `MQCONNX'
/home/avalanche/oleg/ctm_mq_con_ex.c:86: undefined reference to `MQOPEN'
/home/avalanche/oleg/ctm_mq_con_ex.c:114: undefined reference to `MQINQ'
/home/avalanche/oleg/ctm_mq_con_ex.c:142: undefined reference to `MQCLOSE'
/home/avalanche/oleg/ctm_mq_con_ex.c:163: undefined reference to `MQDISC'
collect2: ld returned 1 exit status
But in my C program I put header files
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/* includes for WebSphere MQ */
#include <cmqc.h> /* For regular MQI definitions */
#include <cmqxc.h> /* For MQCD definition */
Did I miss something?

Makefile for beginners

I just started learning about makefiles: i created a simple tutorial by myself but it seems I am mistaken somewhere and i don't know where; my mini-tutorial is formed by a main.c script that recalls a function named kernel.c; within this last function 2 more functions are called: add.c (which adds 2 numbers together) and mul.c (which multiplies the result of the previous sum); i then created the headers kernel.h and functions.h which contain the prototypes of the functions defined above; this two header are contained in a folder created within the same one of the main.c script: common/inc
Here are the files:
//main
#include <stdio.h>
#include <stdlib.h>
#include "kernel.h"
int main(){
int a = 5, b = 4, c = 0;
int *pa, *pb, *pc;
pa = &a; pb = &b; pc = &c;
kernel(pa, pb, pc);
printf("c = %d\n", c);
return 0;
}
here is kernel.c
#include "kernel.h"
#include "functions.h"
void kernel(int* a, int*b, int* c){
int x = add(*a,*b);
*c = mul(x);
}
here is add.c
#include "functions.h"
int add(int a, int b){
return a + b;
}
here is mul.c
#include "functions.h"
int mul(int a){
return a*2;
}
here is kernel.h
void kernel(int* a, int*b, int* c);
here is functions.h
int add(int a, int b);
int mul(int a);
The make file i wrote looks like this:
#===========================Makefile================================#
CC=gcc
IDIR = common/inc
CFLAGS=-c -Wall -I$(IDIR)
all: eseguibile
eseguibile: main.o
$(CC) $(CFLAGS) main.o -o eseguibile
main.o: main.c kernel.o
$(CC) $(CFLAGS) main.c kernel.o
kernel.o: kernel.c add.o mul.o
$(CC) $(CFLAGS) kernel.c add.o mul.o
add.o: add.c
$(CC) $(CFLAGS) add.c
mul.o: mul.c
$(CC) $(CFLAGS) mul.c
clean:
rm -rf *o eseguibile
I know the program works because if i type gcc main.c kernel.c add.c mul.c -I common/inc/ in the terminal everything works fine.
Can anyone tell me what I a doing wrong?`
The error that i get is this:
gcc -c -Wall -Icommon/inc add.c
gcc -c -Wall -Icommon/inc mul.c
gcc -c -Wall -Icommon/inc kernel.c add.o mul.o
gcc: warning: add.o: linker input file unused because linking not done
gcc: warning: mul.o: linker input file unused because linking not done
gcc -c -Wall -Icommon/inc main.c kernel.o
gcc: warning: kernel.o: linker input file unused because linking not done
gcc -c -Wall -Icommon/inc main.o -o eseguibile
gcc: warning: main.o: linker input file unused because linking not done
I prefer to build the objects separately, and then combine them all at the end. I think the problem is that you are including a -c flag on the final executable. Try this:
#===========================Makefile================================#
CC=gcc
IDIR = common/inc
CFLAGS=-Wall -I$(IDIR)
OBJS = main.o kernel.o add.o mul.o
all: eseguibile
eseguibile: $(OBJS)
$(CC) $(CFLAGS) $^ -o eseguibile
main.o: main.c kernel.h
$(CC) -c $(CFLAGS) main.c
kernel.o: kernel.c kernel.h functions.h
$(CC) -c $(CFLAGS) kernel.c
add.o: add.c functions.h
$(CC) -c $(CFLAGS) add.c
mul.o: mul.c functions.h
$(CC) -c $(CFLAGS) mul.c
clean:
rm -rf *.o eseguibile

Compiling: undefined reference to

I'm struggling with compiling multiple files into a common program. I'm getting an error:
undefined reference to 'pi'
Here's the skeleton of my code and Makefile. What am I doing wrong? Thanks!
File: calcPi.c
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <string.h>
#include "pi.h"
int main(int argc, char* argv[]) {
long iterations = 1000000;
int policy = 2;
int numChildren = 3;
pi(iterations, policy, numChildren);
return 0;
}
File: pi.h
void pi(long iterations, int policy, int numChildren);
File: pi.c
#include "pi.h"
void pi(long iterations, int policy, int numChildren) {
//lots of code here
}
I'm compiling this using a Makefile:
CC = gcc
CFLAGS = -c -g -Wall -Wextra
LFLAGS = -g -Wall -Wextra
all: calcPi pi
calcPi: calcPi.o
$(CC) $(LFLAGS) $^ -o $# -lm
pi: pi.o
$(CC) $(LFLAGS) $^ -o $# -lm
calcPi.o: calcPi.c
$(CC) $(CFLAGS) $<
pi.o: pi.c
$(CC) $(CFLAGS) $<
clean:
rm -f pi calcPi
rm -f *.o
rm -f *~
EDIT: In response to the request for the entire error message:
In function 'main'"
calcPi.c:55: undefined reference to 'pi'
collect2: error: ld returned 1 exit status
make: * [calcPi.o] error 1
First of all, is pi really supposed to be a separate application?
You're referring the pi() function from calcPi, but it's only been compiled into pi.o, so you need to add it as a dependency.
What I think you want to do, is to create calcPi using the calcPi.o and pi.o object files.
CC = gcc
CFLAGS = -c -g -Wall -Wextra
LFLAGS = -g -Wall -Wextra
all: calcPi
calcPi: calcPi.o pi.o
$(CC) $(LFLAGS) $^ -o $# -lm
calcPi.o: calcPi.c
$(CC) $(CFLAGS) $<
pi.o: pi.c
$(CC) $(CFLAGS) $<
clean:
rm -f calc
rm -f *.o
rm -f *~

Resources