I have 4 .c files hello.c,here.c,bye.c and main.c.
One header file mylib.h
The contents are as follows
hello.c
#include<stdio.h>
void hello()
{
printf("Hello!\n");
}
here.c
#include<stdio.h>
void here()
{
printf("I am here \n");
}
bye.c
#include<stdio.h>
void bye()
{
printf("Bye,Bye");
}
main.c
#include<stdio.h>
#include "mylib.h"
int main()
{
hello();
here();
bye();
return 1;
}
mylib.h
#ifndef _mylib_
#define _mylib_
void hello();
void here();
void bye();
#endif
The makefile for creating a static lib is :
Makefile
#Which Compiler
CC = gcc
#Compiler Flags
CFLAGS = - Wall -c -fPIC
DYNLINKFLAGS = -shared -W1,-soname,$#.0
PROG = main
PROG_OBJS = main.c
LIB = mylib
LIB_FILES = libmylib.so
LIB_MINOR = $(LIB_FILES).0.1
LIB_RELEASE = $(LIB_MINOR).0
LIB_OBJS = hello.o here.o bye.o
PATH = /home/srinivasa/cspp51081/labs/srinivasa.lab2.1
all: $(LIB_FILES) $(PROG)
#Create Lib with this file
$(LIB_FILES): $(LIB_OBJS)
$(CC) $(DYNLINKFLAGS) $^
ln -sf $(LIB_RELEASE) $(LIB_MINOR)
ln -sf $(LIB_MINOR) $#
ln -sf $# $#.0
#Compiling main program and link with shared library
$(PROG): $(PROG_OBJS)
$(CC) -o $(PROG) $(PORG_OBJS) -l$(LIB) -L$(PATH)
main.o: main.c
hello.o: hello.c
here.o: here.c
bye.o: bye.c
#clean files
clean:
rm -rf $(LIB_OBJS) $(LIB_FILES) $(LIB_RELEASE) $(LIB_MINOR) libmylib.so.0
Problem: When I execute the command
make -f Makefile all
I get the error:
gcc -Wall -fPIC -c -o hello.o hello.c
make: gcc: Command not found
make: * [hello.o] Error 127
Questions : How do I resolve this?
+++++
OK. Lets revert to your original code, but with a small difference.
Change DYNLINKFLAGS back to:
DYNLINKFLAGS = -shared -Wl,-soname,$#.0
Then change the library link to:
$(CC) $(DYNLINKFLAGS) -o $(LIB_RELEASE) $^
ln -sf $(LIB_RELEASE) $(LIB_MINOR)
ln -sf $(LIB_MINOR) $#
ln -sf $# $#.0
Do "rm -f lib*", build and then post make output.
There are a few bugs (just typos) I can see is:
space between - and Wall:
CFLAGS = - Wall -c -fPIC
^
PORG_OBJS should be PROG_OBJS
$(CC) -o $(PROG) $(PORG_OBJS) -L$(PATH)
^^^^
You are doing an absolute assignment to PATH. Now every executable called in makefile will be search in that directory. Since gcc is not found in that directory you get this error. To fix this you can either use a different variable name or add your directory to current path as:
PATH := $(PATH):/home/srinivasa/cspp51081/labs/srinivasa.lab2.1
^ ^^^^^^^^
Try changing this line from:
$(CC) -o $(PROG) $(PORG_OBJS) -l$(LIB) -L$(LIBPATH)
to:
$(CC) -o $(PROG) $(PORG_OBJS) -L$(LIBPATH) -l$(LIB)
The -L flag needs to precede the -l flags.
OK. First change:
DYNLINKFLAGS = -shared -W1,-soname,$#.0
to
DYNLINKFLAGS = -shared -W1,-soname,$#
Then change:
ln -sf $(LIB_RELEASE) $(LIB_MINOR)
ln -sf $(LIB_MINOR) $#
ln -sf $# $#.0
To:
ln -sf $# $(LIB_RELEASE)
ln -sf $# $(LIB_MINOR)
ln -sf $# $#.0
Then post the library links and the final executable link.
Related
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!~
This simple program (two .c files and one .h) compiles and links properly from the command line. However, my Makefile is throwing an error during the linking stage. Proper tab usage is in effect.
CC = gcc
BINDIR = bin/
OBJDIR = obj/
SRCDIR = src/
MKDIR = mkdir -p
RM = rm -rf
SRC = $(wildcard $(SRCDIR)*.c)
_OBJS = $(patsubst $(SRCDIR)%.c, %.o, $(SRC))
OBJS = $(addprefix $(OBJDIR), $(_OBJS))
CFLAGS = -Wall -g -Iinclude
.PHONY: all
all: $(BIN)
_BIN = a.out
BIN = $(addprefix $(BINDIR), $(_BIN))
$(BIN): $(OBJS) $(BINDIR)
$(CC) -o $# $(CFLAGS) $<
$(BINDIR):
$(MKDIR) $(BINDIR)
$(OBJS): $(SRC) $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR):
$(MKDIR) $(OBJDIR)
.PHONY: clean
clean:
#echo "Cleaning things up..."
$(RM) $(OBJDIR) $(BINDIR)
The program's files:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "hellomake.h"
int main(void) {
myPrintHelloMake();
return EXIT_SUCCESS;
}
hellomake.c
#include <stdio.h>
#include "hellomake.h"
void myPrintHelloMake(void) {
puts("Hello makefiles!");
}
hellomake.h
#ifndef __HELLO_H__
#define __HELLO_H__
void myPrintHelloMake(void);
#endif
The .c files are in the src/ directory and the .h file is in the include/ directory. Makefile compiles the code, creates the obj/ directory, and places and main.o and hellomake.o therein. However, that is where things break down. Here is gcc's complaint:
$ make
mkdir -p obj/
gcc -Wall -g -Iinclude -c src/hellomake.c -o obj/hellomake.o gcc -Wall -g -Iinclude -c src/hellomake.c -o obj/main.o mkdir -p bin/ gcc -o bin/a.out -Wall -g -Iinclude
obj/hellomake.o /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o: in function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status make: *** [Makefile:34: bin/a.out] Error 1
There were a number of issues.
I'd leave off / from (e.g.) BINDIR et. al.
The patsubst was incorrect. It needed $(OBJDIR) in the the TO
Using _OBJS was unnecessary/harmful.
The rule for $(OBJS) was incorrect. It created the two .o files using the first prereq source, so [the function] main was defined twice. It needs a pattern rule instead.
Using $(BINDIR) as a prereq for $(BIN) added bin/ at the end of the gcc line [and it complained]
As M.Oehm mentioned, $< only gets the first prereq.
The all: was indented so it was not recognized properly
Anyway, here's the corrected Makefile:
CC = gcc
BINDIR = bin
OBJDIR = obj
SRCDIR = src
MKDIR = mkdir -p
RM = rm -rf
SRC = $(wildcard $(SRCDIR)/*.c)
###_OBJS = $(patsubst $(SRCDIR)%.c, %.o, $(SRC))
###OBJS = $(addprefix $(OBJDIR), $(_OBJS))
OBJS = $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRC))
CFLAGS = -Wall -g -Iinclude
_BIN = a.out
BIN = $(addprefix $(BINDIR)/, $(_BIN))
.PHONY: all
all: $(BINDIR) $(OBJDIR) $(BIN)
####$(BIN): $(OBJS) $(BINDIR)
$(BIN): $(OBJS) $(BINDIR)
###$(CC) -o $# $(CFLAGS) $<
$(CC) -o $# $(CFLAGS) $(OBJS)
$(BINDIR):
$(MKDIR) $(BINDIR)
###$(OBJS): $(SRC) $(OBJDIR)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR):
$(MKDIR) $(OBJDIR)
.PHONY: clean
clean:
#echo "Cleaning things up..."
$(RM) $(OBJDIR) $(BINDIR)
I´m trying to create a Makefile that build a lib and compile the file. My problem is that depending on the %.c file I need to compile with different lib.
The SRC_MLX need the $(LFLAGS) and the SRC don´t. So the gcc compiler don´t allow me to compile the SRC with the LFLAGS. That´s the reason I need to separate.
I´ve tried this way:
SRCS = $(DIR_SRC)/ft_utils.c \
$(DIR_SRC)/ft_adt.c \
$(DIR_SRC)/ft_circle.c \
$(DIR_SRC)/ft_line.c \
$(DIR_SRC)/ft_trgb.c \
$(DIR_SRC)/ft_quadrilateral.c \
$(DIR_SRC)/ft_player.c \
$(DIR_SRC)/ft_color.c
SRCS_MLX = $(DIR_SRC)/win_update.c \
$(DIR_SRC)/ft_vars.c \
$(DIR_SRC)/ft_image.c \
$(DIR_SRC)/ft_map.c
$(NAME): $(LIB_NAME)
$(CC) $(CFLAGS) main.c -I. -I$(DIR_MLX) -L$(DIR_MLX) -L. $(LFLAGS) $(LIB_FLAG) -o $# -g
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -o $#
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -L$(DIR_MLX) $(LFLAGS) -o $#
$(LIB_NAME): $(OBJ_MLX) LIB_OBJ
$(AR) $(LIB_NAME) $(OBJ)
ranlib $(LIB_NAME)
LIB_OBJ: $(OBJ)
$(AR) $(LIB_NAME) $(OBJ)
In the example above I´ve tried to create a lib with one kind of files and after that create a lib with the first lib with the others files. But I keep getting this error:
Makefile:41: warning: overriding recipe for target '.objs/'
Makefile:37: warning: ignoring old recipe for target '.objs/'
make: Warning: File 'Makefile' has modification time 454 s in the future
rm -f .objs/ft_utils.o .objs/ft_adt.o .objs/ft_circle.o .objs/ft_line.o .objs/ft_trgb.o .objs/ft_quadrilateral.o .objs/ft_player.o .objs/ft_color.o
rm -f libcub3d.a
rm -f main
make: *** No rule to make target 'src/src/win_update.c', needed by '.objs/win_update.o'. Stop.
How can I compile this objects with different lib?
P.S. Those are my variables:
DIR_OBJ = .objs
DIR_SRC = src
DIR_LIB = lib
DIR_MLX = ./minilibx-linux
NAME = main
LIB_NAME = libcub3d.a
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
CC = clang
CFLAGS = -Wall -Werror -Wextra
LFLAGS = -lmlx -lm -lX11 -lXext -lbsd
LIB_FLAG = -lcub3d
AR = ar -rc
RM = rm -f
These lines are definitely not right:
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
...
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
along with the way you've defined SRCS and SRCS_MLX and these:
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
Just expand the variables in the rule in your head, or else ask make to expand it for you with the info function, and you'll see it's definitely not right:
$(info output is '$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c')
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
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"