Makefile link issue - c

I can't figure out how link static libraries in Makefiles. I use ubuntu 20.04 LTS. I even tried to use direct path to these libraries, and the issue remains unchanged. Here's my Makefile code.
LIB = libgeoms.a
SRC = mlx_pxl_put.c \
std_arc.c \
std_crcl.c \
std_line.c \
std_poly.c \
std_rect.c \
CC = clang
WARNS = -Wall -Wextra -Werror
OBJ = $(SRC:.c=.o)
SRCP = /usr/local/wealdboar/src/
INCLUDEP = /usr/local/wealdboar/include/
LIBP = /usr/local/wealdboar/lib/
HEADER = geoms.h
LX11P = /usr/lib/x86_64-linux-gnu/libX11.a
LXEXTP = /usr/lib/x86_64-linux-gnu/libXext.a
LMLX = /usr/local/lib/libmlx.a
$(LIB): $(OBJ)
#echo "Every funtion is compile proved ..."
#ar rcs $(LIB) $(OBJ)
#echo "All functions added to static lib ..."
$(OBJ): %.o :%.c
#echo "check $< to be right"
#$(CC) $(WARNS) -c $(LX11P) $(LMLX) $(LXEXTP) $< -o $#
all: $(LIB)
clean:
#echo "removing all binaries ..."
#rm -rf $(OBJ)
fclean: clean
#echo "removing static library ..."
#rm -rf $(LIB)
re: fclean all
install: re clean
#echo "coping $(LIB) to $(LIBP)"
#sudo cp $(LIB) $(LIBP)
#echo "coping sources to $(SRCP)"
#sudo cp $(SRC) $(SRCP)
#echo "coping header to $(INCLUDEP)"
#sudo cp $(HEADER) $(INCLUDEP)
Issue image

You haven't specified the -l or -L flags to tell clang to link against choosen libraries.

First please don't paste image links in StackOverflow. They aren't searchable, they aren't quotable, and many people are not willing to click a on links to other sites. Please cut and paste the actual messages.
Second, when working with makefiles you should not use the # option which hides the most important information about the commands being run. It's much harder to debug a makefile when the command lines are not visible. If you really want to hide the actual commands you should either add in the # after everything is already working and not before, or else use tricks like this to allow for a debug mode.
Finally your error is as I suggested in my comment above. You are trying to add static libraries to a compile command (a command that compiles source files into object files). Libraries can only be added into link commands (commands that convert object files and libraries into executables).
You are not actually creating an executable anywhere in your makefile that I can see, so there's nowhere that you can add libraries here. But, you need to remove them from the compile rule:
$(OBJ): %.o :%.c
#echo "check $< to be right"
#$(CC) $(WARNS) -c $< -o $#

Related

How to stop Make from recompiling the whole project if one include file changes? [duplicate]

I have the following makefile that I use to build a program (a kernel, actually) that I'm working on. Its from scratch and I'm learning about the process, so its not perfect, but I think its powerful enough at this point for my level of experience writing makefiles.
AS = nasm
CC = gcc
LD = ld
TARGET = core
BUILD = build
SOURCES = source
INCLUDE = include
ASM = assembly
VPATH = $(SOURCES)
CFLAGS = -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I $(INCLUDE)
ASFLAGS = -f elf
#CFILES = core.c consoleio.c system.c
CFILES = $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES = assembly/start.asm
SOBJS = $(SFILES:.asm=.o)
COBJS = $(CFILES:.c=.o)
OBJS = $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).elf
c:/python26/python.exe concat.py stage1 stage2 pad.bin core.elf floppy.img
$(TARGET).elf : $(OBJS)
$(LD) -T link.ld -o $# $^
$(SOBJS) : $(SFILES)
$(AS) $(ASFLAGS) $< -o $#
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
#Clean Script - Should clear out all .o files everywhere and all that.
clean:
-del *.img
-del *.o
-del assembly\*.o
-del core.elf
My main issue with this makefile is that when I modify a header file that one or more C files include, the C files aren't rebuilt. I can fix this quite easily by having all of my header files be dependencies for all of my C files, but that would effectively cause a complete rebuild of the project any time I changed/added a header file, which would not be very graceful.
What I want is for only the C files that include the header file I change to be rebuilt, and for the entire project to be linked again. I can do the linking by causing all header files to be dependencies of the target, but I cannot figure out how to make the C files be invalidated when their included header files are newer.
I've heard that GCC has some commands to make this possible (so the makefile can somehow figure out which files need to be rebuilt) but I can't for the life of me find an actual implementation example to look at. Can someone post a solution that will enable this behavior in a makefile?
EDIT: I should clarify, I'm familiar with the concept of putting the individual targets in and having each target.o require the header files. That requires me to be editing the makefile every time I include a header file somewhere, which is a bit of a pain. I'm looking for a solution that can derive the header file dependencies on its own, which I'm fairly certain I've seen in other projects.
As already pointed out elsewhere on this site, see this page:
Auto-Dependency Generation
In short, gcc can automatically create .d dependency files for you, which are mini makefile fragments containing the dependencies of the .c file you compiled.
Every time you change the .c file and compile it, the .d file will be updated.
Besides adding the -M flag to gcc, you'll need to include the .d files in the makefile (like Chris wrote above).
There are some more complicated issues in the page which are solved using sed, but you can ignore them and do a "make clean" to clear away the .d files whenever make complains about not being able to build a header file that no longer exists.
You could add a 'make depend' command as others have stated but why not get gcc to create dependencies and compile at the same time:
DEPS := $(COBJS:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) -c $(CFLAGS) -MM -MF $(patsubst %.o,%.d,$#) -o $# $<
The '-MF' parameter specifies a file to store the dependencies in.
The dash at the start of '-include' tells Make to continue when the .d file doesn't exist (e.g. on first compilation).
Note there seems to be a bug in gcc regarding the -o option. If you set the object filename to say obj/_file__c.o then the generated _file_.d will still contain _file_.o, not obj/_file_c.o.
This is equivalent to Chris Dodd's answer, but uses a different naming convention (and coincidentally doesn't require the sed magic. Copied from a later duplicate.
If you are using a GNU compiler, the compiler can assemble a list of dependencies for you. Makefile fragment:
depend: .depend
.depend: $(SOURCES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^>>./.depend;
include .depend
There is also the tool makedepend, but I never liked it as much as gcc -MM
You'll have to make individual targets for each C file, and then list the header file as a dependency. You can still use your generic targets, and just place the .h dependencies afterwards, like so:
%.o: %.c
#echo Compiling $<...
$(CC) $(CFLAGS) -c -o $# $<
foo.c: bar.h
# And so on...
Basically, you need to dynamically create the makefile rules to rebuild the object files when the header files change. If you use gcc and gnumake, this is fairly easy; just put something like:
$(OBJDIR)/%.d: %.c
$(CC) -MM -MG $(CPPFLAGS) $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(#D)/\1.o $(#D)/\1.d:,' >$#
ifneq ($(MAKECMDGOALS),clean)
include $(SRCS:%.c=$(OBJDIR)/%.d)
endif
in your makefile.
Over and above what #mipadi said, you can also explore the use of the '-M' option to generate a record of the dependencies. You might even generate those into a separate file (perhaps 'depend.mk') which you then include in the makefile. Or you can find a 'make depend' rule which edits the makefile with the correct dependencies (Google terms: "do not remove this line" and depend).
Simpler solution: Just use the Makefile to have the .c to .o compilation rule be dependent on the header file(s) and whatever else is relevant in your project as a dependency.
E.g., in the Makefile somewhere:
DEPENDENCIES=mydefs.h yourdefs.h Makefile GameOfThrones.S07E01.mkv
::: (your other Makefile statements like rules
::: for constructing executables or libraries)
# Compile any .c to the corresponding .o file:
%.o: %.c $(DEPENDENCIES)
$(CC) $(CFLAGS) -c -o $# $<
None of the answers worked for me. E.g. Martin Fido's answer suggests gcc can create dependency file, but when I tried that it was generating empty (zero bytes) object files for me without any warnings or errors. It might be a gcc bug. I am on
$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
So here's my complete Makefile that works for me; it's a combination of solutions + something that wasn't mentioned by anyone else (e.g. "suffix replacement rule" specified as .cc.o:):
CC = g++
CFLAGS = -Wall -g -std=c++0x
INCLUDES = -I./includes/
# LFLAGS = -L../lib
# LIBS = -lmylib -lm
# List of all source files
SRCS = main.cc cache.cc
# Object files defined from source files
OBJS = $(SRCS:.cc=.o)
# # define the executable file
MAIN = cache_test
#List of non-file based targets:
.PHONY: depend clean all
## .DEFAULT_GOAL := all
# List of dependencies defined from list of object files
DEPS := $(OBJS:.o=.d)
all: $(MAIN)
-include $(DEPS)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
#suffix replacement rule for building .o's from .cc's
#build dependency files first, second line actually compiles into .o
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
clean:
$(RM) *.o *~ $(MAIN) *.d
Notice I used .cc .. The above Makefile is easy to adjust for .c files.
Also notice importance of these two lines :
$(CC) $(CFLAGS) $(INCLUDES) -c -MM -MF $(patsubst %.o,%.d,$#) $<
$(CC) $(CFLAGS) $(INCLUDES) -c -o $# $<
so gcc is called once to build a dependency file first, and then actually compiles a .cc file. And so on for each source file.
I believe the mkdep command is what you want. It actually scans .c files for #include lines and creates a dependency tree for them. I believe Automake/Autoconf projects use this by default.

Makefile not generating debugging information with -g flag

I recently moved from working in the terminal to VScode and am needing to generate debugging information to use with the debugger in vscode.
My makefile is:
SRCS = src/ft_argcheck.c \
src/ft_operations.c \
src/ft_stcutils.c \
src/push_swap.c
NAME = push_swap
INCS = inc/push_swap.h
OBJS = $(SRCS:c=o)
CC = gcc
CFLAGS = -g -Wall -Wextra -Werror
RM = rm -f
LIBFT = libft/libft.a
LIBFT_DIR = libft
.PHONY: all bonus clean fclean re
all: $(NAME)
$(NAME): $(OBJS)
#make -C $(LIBFT_DIR) --silent
#$(CC) $(CFLAGS) -I$(INCS) -o $(NAME) $(OBJS) -L $(LIBFT_DIR) -lft
clean:
#$(RM) $(OBJS)
#make -s clean -C $(LIBFT_DIR)
fclean: clean
#$(RM) $(NAME)
#make -s fclean -C $(LIBFT_DIR)
re: fclean all
But despite adding the -g flag, no debugging information is generated. on which I can run lldb.
A good proposal is to remove the #s in front of the command names to see what commands make is executing.... To make a program debuggable, you need to check that all the compilation steps are done using the -g flag and that the linking step has also included the -g flag. Also a good option is to specify no optimization so you will not get to problems with breakpoints you cannot fix because the compiler has eliminated or changed the final code, and has broken the correspondence between source lines and points in the code.
If you take off all the #s there, you will see the commands as make is executing them, think you don't see now. I think there's a command (berkeley make has it) to make make to print the commands even though the #s remain in place.
By the way, as you are telling you are using vscode it should be fine if you execute make on the command line alone, to see the output of the commands, and try to see if it is some problem with make or with vscode itself.
As you have not provided your complete project, I'm sorry to say that I can only test it with dumb/fake files and no program can be made to test it with gdb.
I guess that the problem is that you have put your project sources in a different directory than where the program is built, and the sources cannot be found by gdb and so, no source debugging can be done because gdb cannot find the source files. Gdb has some way to specify the path to the source files... You should look at gdb documentation.
Thanks for all your answers (Removing # didn't really give me much more information, as it did show the -g flag and I already tried remaking everything with fclean). I seem to have figured out an easy fix with the help of a friend:
add a rule "debug"
debug:
$(CC) -g $(CFLAGS) -I$(INCS) $(LIBFT) $(SRCS) -o $(NAME)
which we can run just when we want to generate the debugging information and run this directly with $(SRCS) instead of running it on the $(OBJS) as in the normal command.

'linker input file unused because linking not done' error when running make

I'm compiling C programs I made for a project.
Goals
Compiling get_next_line.c and get_next_line_utils.c.
Structure
I have 3 files, get_next_line.c, get_next_line_utils.c and get_next_line.h in my folder (excluding Makefile). Nothing more, nothing less.
Code
NAME = get_next_line
SRCS = get_next_line.c get_next_line_utils.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
LIB_CRT = ar rcs
all: $(NAME)
$(NAME) : $(OBJS)
#$(LIB_CRT) $(NAME) $(OBJS)
%.o: %.c $(INCLUDE)
#$(CC) -c $(CFLAGS) -o $# $<
clean:
#rm -f $(OBJS) a.out
fclean: clean
#rm -f $(NAME)
re : fclean all
Error Message
linker input file unused because linking not done. I get this error several times.
I keep on running on this error when I run make. I followed another Makefile I had for another project, to no avail. I also read this article and that one too but they aren't relevant to my issue.
Any input appreciated.
Your makefile appears to be aimed at building a program named "get_next_line", but this is not altogether clear because what you are actually building is a static archive file with that (unconventional for an archive) name. That's what the ar utility does. With the gcc toolchain and many others, one would normally use the same front end (gcc in this case) for both compiling and linking. That is,
$(NAME) : $(OBJS)
$(CC) -o $(NAME) $(OBJS)
... or, a bit DRYer ...
$(NAME) : $(OBJS)
$(CC) -o $# $^
It is not clear why you are getting the specific message you report. It looks like a message from the linker, ld, but I see no reason in the makefile presented to think that the linker would ever run. As such, I am inclined to suppose that the message is associated with something altogether different. Possibly you are running make in a different working directory, and therefore using a different makefile. Or perhaps it is associated with some other command than make itself. Or maybe you have an influential variable set in your environment that alters the meaning of your makefile. Maybe you get that message when you try to run the archive as if it were a program (though that's not what I would expect to happen in that case).

gmake (Gnu) to make (Cygwin) - verification of my implementation [only 3 statements]

I need to convert a makefile built for gmake into a makefile that could be executed via cygwin "make" command.
The GMAKE code is below:
OBJ := ${SOURCES:%.c=%.o}
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS) $(DEFINES)
$(LIBNAME).lib: $(OBJ)
$(AR) rcs $# $(OBJ)
clean:
del $(OBJ)
del *.out
I've used the statements below in the Cygwin makefile. Could you please confirm, if it replicates the gmake statements above or am I missing something. Any inputs would be helpful.
Cygwin "make":
OBJ := ${SOURCES:%.c=%.o}
%.obj: %.c
$(CC) -c -o `cygpath -w $#` `cygpath -w $<` $(CFLAGS) $(DEFINES)
.DEFAULT_GOAL := ${LIBNAME}.lib
${LIBNAME}.lib: $(OBJS)
$(SILENCE)echo -e "Archive: ${LIBNAME}.lib\n"
$(SILENCE)$(AR) $(ARFLAGS) `cygpath -w $#` ${OBJS}}
clean:
rm $(OBJ)
rm *.out
Thanks much in advance.
As pointed out by #matzeri, cygwin make is gnu make.
That's why I use it.
The first makefile looks fine to me.
If all your files use relative paths, everything should be fine.
Even the Microsoft compiler can build subdir/file.cpp and stick the object into objdir/file.o (cl subdir/file.cpp -o objdir/file.o).
Hint: Strive manfully to use forward slashes in your filenames. Always.
The only difficulty you might have is with absolute paths,
as typically appear in include paths say.
/usr/local/include only makes sense to cygwin programs.
cl.exe would like this translated to C:/cygwin64/usr/local/include.
Don't use backslashes unless the command really really requires it.
One issue then is that bash interprets backslashes,
so you will have to quote the filename in some way to prevent this.
objdir/1.o: /usr/local/src/1.cpp
some-odd-compiler "$$(cygpath -wa $<)" -o "$$(cygpath -w $#)"
Quoting not required if you use forward slashes (cygpath -ma).
Why prefer $(…) over `…`? Because then the double quotes nest.
Useful if the path in question expands to something with a space in it ("$$(cygpath -wa "$<")")

Problem Creating a Static Lib in Linux

I am making a simple lib to use in my apps to save me the trouble of defining some functions over and over...
Here's my makefile:
CC=gcc
CFLAGS=-Wall -g -Wextra
OBJS=getline.o debug.o
LIB=libjimi.a
.PHONY: clean purge
libjimi.so : $(OBJS)
ar rcs $(LIB) $(OBJS)
#echo done!
%.o : %.c
$(CC) $(CFLAGS) -c $^
clean :
#rm *.o
purge : clean
#rm $(LIB)
Now I get a segfault if I link the library, but if I link the object files that I link to create the library, it works...advice?
Your target say libjimi.so which is the extension for a shared library, it should just be libjimi.a for a static lib.
And note that when you use a static lib you just link it in like any other object file, but with a shared lib you use the -l syntax.
Static libraries on Linux (Unix) normally end with '.a'; shared objects end with '.so'. Your library rule is currently:
libjimi.so : $(OBJS)
ar rcs $(LIB) $(OBJS)
#echo done!
It should be:
$(LIB): $(OBJS)
ar rcs $(LIB) $(OBJS)
#echo done!
Personally, I tend to use
AR = ar
ARFLAGS = rv
Leading to:
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) $(LIB) $(OBJS)
Now all aspects of the build can be tuned by setting macros - if necessary.
Without knowing where the crash is occurring, it is hard to know what might be causing it.
One possibility is that because of the makefile confusion, you are linking with an old version of the library and not with the current working version.
Incidentally, it is not nice to conceal what a clean or purge target is doing; it is much better to let make echo the commands (no # in front). The # is entirely appropriate for the echo though; its absence would lead to the same information being presented twice.

Resources