Problem Creating a Static Lib in Linux - c

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.

Related

No rule to make target 'main.o', needed by 'out'. Stop

I keep getting this error and I can't figure out what I am doing wrong. I am using an template so I can get in the dir bin the executable. The dir include the header files. The dir obj for the object files created and the src for the .c files.
My makefile
OBJ_dir = obj
INC_DIR = include
OBJECTS = main.o client.o private.o memory.o process.o proxy.o server.o
main.o = main.h memory-private.h stdio.h stdlib.h string.h syscall.h unistd.h wait.h sysexits.h memory.h
client.o = client.h
private.o = private.h
memory.o = memory.h memory_private.h
process.o = process.h
proxy.o = proxy.h
server.o = server.h
CC = gcc
CFLAGS = -Wall –I $(INC_DIR)
LIBS = -lm
out: $(OBJECTS)
$(CC) $(addprefix $(OBJ_dir)/,$(OBJECTS)) -o bin/out $(LIBS)
%.o: src/%.c $($#)
$(CC) $(CFLAGS) -o $(OBJ_dir)/$# -c $<
clean:
rm –f *.o out
rm –f out
There are many issues here. It's probably a good idea to read at least the first few chapters of the GNU make manual to understand how make and makefiles work.
Take this rule:
out: $(OBJECTS)
$(CC) $(addprefix $(OBJ_dir)/,$(OBJECTS)) -o bin/out $(LIBS)
First, it's not right to list a different target than the file you actually build. Here you told make you'd build a target named out, but your recipe actually builds a target named bin/out. That's wrong.
Second, but similarly, it's not right to have your target depend on one set of prerequisites (the files defined by $(OBJECTS)) but then have the recipe of your rule use a completely different set of prerequisites (by adding a $(OBJ_dir)/ prefix to all the files).
This tells make "please build files main.o, client.o, etc., but what my command will actually use is files obj/main.o, obj/client.o, etc.". It doesn't make sense to tell make to build targets that you aren't going to actually use.
This should be:
bin/out: $(addprefix $(OBJ_dir)/,$(OBJECTS))
$(CC) $^ -o $# $(LIBS)
In general if you ever find yourself writing a recipe where you are modifying the automatic variables like $# or $^ instead of using them as-is, you're almost certainly doing something wrong.
Next your pattern rule has other issues:
%.o: src/%.c $($#)
$(CC) $(CFLAGS) -o $(OBJ_dir)/$# -c $<
First, you cannot use automatic variables like $# in a prerequisite list. Those values are only set when expanding the recipe of a rule. They are not set (empty) when evaluating the prerequisite list. So $($#) expands to the empty string here and does nothing.
Second you have the same problem as above where you are not creating $# you are creating $(OBJ_dir)/$# which is wrong. You should write your rule like this:
$(OBJ_dir)/%.o: src/%.c
$(CC) $(CFLAGS) -o $# -c $<
so that the target lists the file you want to build, and the recipe uses $# without modification.
As for your prerequisites, you should just create them directly rather than trying to use fancy variables (which can't work). As the comment above suggests, just change:
proxy.o = proxy.h
to:
proxy.o : proxy.h
(and all the rest) and it will work. Note, though, that make always builds the first explicit target it sees by default so you may have to re-arrange your makefile a little bit if you want bin/out to be the default target.

'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).

Make does not run ar and make new libraries after object changes

Iam trying to start project with couple of static libraries that are built on their own makefiles, like this:
LIBDIR= ../../lib/
SRC= mgui.c
-include $(SRC:%.c=%.d)
INC=-I../../inc \
-Iinc \
-I../../shared
EXEC= libmgui.lib
CFLAGS= -Wall -static -D$(DEBUG) -MMD -MP
ARFLAGS= rcs
AR = ar
all: $(SRC:%.c=%.o)
$(AR) $(ARFLAGS) $(LIBDIR)$(EXEC) $<
%.o: %.c
$(CC) -c $< -o $# $(INC) $(CFLAGS)
That makefile is run from higher level makefile.
I have globals.h file in ../../shared/ folder, which is included from mgui.c and if I make modifications to that file, this makefile does not work. It just makes new .o file, but ar and new .lib is never made , why ? Using win8 with mingw.
Generated dependency file looks like this:
mgui.o: mgui.c inc/mgui.h ../../shared/globals.h
inc/mgui.h:
../../shared/globals.h:
You need to move the -include down to the end of your makefile. Make takes the first target defined (even if it's in an included file) and uses it as the default target. Since the include comes first, it defines the mgui.o as the first target and that's the only target that will be built, unless you explicitly run make all.
Also, you shouldn't put the recipe to build the library in the all target rule. If you do, then that library will always be rebuilt even if nothing has changed.
You should write it as:
all: $(LIBDIR)$(EXEC)
$(LIBDIR)$(EXEC): $(SRC:%.c=%.o)
$(AR) $(ARFLAGS) $# $<

Makefiles - ar: *.a: No such file or directory.... but there is... it's right there

Trying to compile a friend's code - but he has included no Makefile, I build my own and am perplexed by an issue I've run into.
I think it's best I post the full contents of the Makefile below... I tried to keep it short!
CFLAGS = -Wall -pedantic
LFLAGS =
CC = gcc
RM = /bin/rm -rf
AR = ar rc
RANLIB = ranlib
LIBRARY = const.a read.a descr.a
LIB_SRC = read.c futex.c testy.c
LIB_OBJ = $(patsubst %.c,%.o,$(LIB_SRC))
# pattern rule for object files
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
all: $(LIBRARY)
$(LIBRARY): $(LIB_OBJ)
$(AR) $(LIBRARY) $(LIB_OBJ)
$(RANLIB) $(LIBRARY)
clean:
$(RM) $(LIBRARY) $(LIB_OBJ)
.PHONY: depend
depend:
$(CFLAGS) -- $(LIB_SRC) 2>/dev/null
All of the files, const.h, read.h, and descr.h are in the directory in which I call make. Likewise for read.c, futex.c, and testy.c.
The files are entangled in various ways - if I need to show exactly the nature of these entanglements, I will do so.
I 'make' and the compiler alledges:
ar: read.a: No such file or directory
Is it not the case that read.a is supposed to be being produced? Of course it isn't there yet.
I've stared a while now and I feel like this must be something simple I am missing.
This command:
$(AR) $(LIBRARY) $(LIB_OBJ)
expands to this:
ar rc const.a read.a descr.a read.o futex.o testy.o
So when Make tries to build const.a, it tells ar to combine several files into const.a, starting with read.a, and ar complains that there's no such file. (Whether ar could do anything useful with read.a if it did exist is immaterial.)
It's not clear how you want Make to build those libraries, but this might be a step in the right direction:
$(LIBRARY): $(LIB_OBJ)
$(AR) $# $(LIB_OBJ)
$(RANLIB) $#
The automatic variable $# expands to the name of the target. You can use another one for the list of prerequisites ($(LIB_OBJ)), but let's try one new thing at a time.

Make recursive all C files

I really can't get into makefiles. In previous projects, I hardcoded all compile tasks in the Makefile:
all: compile_a compile_b compile_c
compile_a:
${CC} ${CFLAGS} ${A_SRC} -o ${A_OUT}
and so on.
But as the latest project has more files than every project before, I want to write better make tasks and of course LESS characters as make is not really friendly to my eyes (it makes them suffer)! :-P
What I want:
One task to rule them all (just make projectname or make all, you know?)
One task for every C file to compile (I read something about this %.o: %.c syntax, but didn't really get it)
One task for linking (how to get all .o files and link them without hardcoding each?)
One task for cleaning (oh, i can do this!)
The project structure is:
bin (binary goes here!)
src
some
directories
are
here
I don't know if I need a directory for object files, I put them in ./bin, I think that's good enough, isn't it?
Maybe I just need someone who can explain it with easy words!
EDIT:
As someone pointed out, there's no real question, so here it goes:
how to recursively compile all C files to bin/(filename).o
how to link all .o files in 'bin/' without knowing their names
maybe this helps.
Try this:
CC = gcc
CFLAGS = -c -Wall -g -Os
LD = $(CC)
LDFLAGS = -lfoo
TARGET = MyProject
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LD) -o $# $^ $(LDFLAGS)
# You don't even need to be explicit here,
# compiling C files is handled automagically by Make.
%.o: %.c
$(CC) $(CFLAGS) $^ -o $#
clean:
rm $(TARGET) $(OBJECTS)
I frequently use the wildcard function in combination with the foreach function for something like you want to achieve.
If your sources are in src/ and you want to put the binaries into bin/ the basic construction of my Makefile would look like follows:
SOURCES=$(shell find src -type f -iname '*.c')
OBJECTS=$(foreach x, $(basename $(SOURCES)), $(x).o)
TARGET=bin/MyProject
$(TARGET): $(OBJECTS)
$(CC) $^ -o $#
clean:
rm -f $(TARGET) $(OBJECTS)
I usually take advantage of make's built in implicit rules and predefined variables (Make manual, Chap 10).
without going into specifics of makefiles, use the * to your advantage.
i.e.
compileAll: gcc -c *.c
linkAll: gcc *.o -o output.exe

Resources