Question

I have many functions in different files.

eg: OBJ_SRC=sum.c sub.c mul.c div.c remainder.c

When I am creating a library I do like this:

libarithmatic.a: $(OBJ_SRC)
     gcc -c $(OBJ_SRC)  # creates sum.o sub.o.. 
     ar rcs libarithmatic.a $(OBJS) #<--- problem @OBJS

How to store the output of gcc -c $(OBJ_SRC): add.o sub.o mul.o.. (newly created/updated file names) into OBJS variable?

Was it helpful?

Solution

The usual way is with patsubst

OBJS=$(patsubst %.c,%.o,$(OBJ-SRC))

Now calling gcc as part of the target to build the library is a bad idea. It misses the main point of using make at all as you are asking gcc to blindly recompile all the objects instead of having make find which have changed. The usual rule is:

libarithmatic.a: $(OBJS)
        ar rcs libarithmatic.a $(OBJS)

You can put in the pattern rule for compiling the .c files, but if you'd just put in

%.o: %.c
        gcc -c $<

you don't have to bother as that is implicit. Well, the default implicit rule is really

%.o: %.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<

where CC defaults to suitable compiler and you can override it and CPPFLAGS and CFLAGS default to empty and you can set them to whatever flags you want to use for compilation. CPPFLAGS is for both C and C++, CFLAGS is for C only, CXXFLAGS is for C++ only (C++ compiler is CXX).


On a side-note, I'd suggest looking at CMake, which supports generating build files for various platforms, IDEs and the new ultra-fast ninja. The corresponding CMakeLists.txt would be as trivial as

project(arithmatic)
add_library(arithmatic sum.c sub.c mul.c div.c remainder.c)

and making it a shared library as trivial as adding SHARED keyword when you want to.


Note, that the % placeholder does not have to be at the beginning. If you want to put the objects in different directory from the sources, you can write things like

OBJS=$(patsubst src/%.c,obj/%.o,$(SOURCES))

(the sources have to be listed with the directory prefix in this case) or perhaps

OBJS=$(patsubst %.c,.objs/%.o,$(SOURCES))

And you can similarly use the pattern in the rules, so

obj/%.o: src/%.c
        mkdir -p obj
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<

or

.objs/%.o: %.c
        mkdir -p .objs
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $<

You have to make sure the output directory exists as the compiler won't create it (so I include the mkdir in the rules) and you have to explicitly specify compiler output, because it would create it in current directory otherwise.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top