How to Compile Object files into an Archive using Make - c

Problem
I'm writing a B-tree in c and it's getting pretty big. I have a struct for the tree, one for the nodes, and one for the items (key/value). I'd like to compile the object files from all three header files into an archive (.a) using make. Whenever I try to compile using make it uses the archive without every building the objects. Any idea why?
include/
btree.h
item.h
node.h
src/
btree_attach.c
btree_create.c
btree_destructor.c
btree_disk.c
btree_find.c
btree_get_node.c
btree_insert.c
btree_key_size.c
item_compare_item.c
item_compare_item_qsort.c
item_print_item.c
node_create_.c
node_destructor.c
node_find.c
node_flush_node.c
node_insert.c
node_print_node.c
node_split_node.c
# Generic makefile
# VAriables:
src := $(wildcard *.c)
obj := $(obj:.c=.o)
dep := $(dep:.o=.d)
CFLAGS := -g
INCLUDE = -Iinclude
all: lib/btree.a\
clean:
rm -f a.out obj/* bin/*
# ---------------
# Object files
$(obj): $(src) $(dep)
$(CC) $(CFLAGS) $(INCLUDE) $# $^
#Archive file
.PHONY: lib/btree.a
lib/btree.a: $(obj) $(dep)
ar -rv $# $^
Update
I changed the make file to the following:
# VAriables:
src := $(wildcard src/*.c)
obj := $(src:.c=.o)
dep := $(obj:.o=.d)
CFLAGS := -g
INCLUDE = -include
print:
$(src)\
$(obj)\
$(dep)
all: lib/btree.a
# ---------------
# Object files
$(obj): $(src)
$(CC) $(CFLAGS) $(INCLUDE) $# $^
#Archive file
lib/btree.a: $(obj)
ar -rv $# $^
The printout has the following
src/b_util.c src/item_compare_item.c src/b_tree.c src/item_print_item.c src/random_tester_2.c src/node_attach.c src/node_find.c src/node_create_.c src/btree_disk.c src/node_insert.c src/tnode.c src/btree_create.c src/node_unattach.c src/b_tree_test.c src/node_split_node.c src/node_print_node.c src/random_tester_1.c src/node_destructor.c src/btree_insert.c src/item.c src/btree_attach.c src/item_compare_item_qsort.c src/node_flush_node.c src/jdisk.c src/btree_find.c src/btree_destructor.c src/btree_get_node.c src/jdisk_test.c src/btree_key_size.c\
src/b_util.o src/item_compare_item.o src/b_tree.o src/item_print_item.o src/random_tester_2.o src/node_attach.o src/node_find.o src/node_create_.o src/btree_disk.o src/node_insert.o src/tnode.o src/btree_create.o src/node_unattach.o src/b_tree_test.o src/node_split_node.o src/node_print_node.o src/random_tester_1.o src/node_destructor.o src/btree_insert.o src/item.o src/btree_attach.o src/item_compare_item_qsort.o src/node_flush_node.o src/jdisk.o src/btree_find.o src/btree_destructor.o src/btree_get_node.o src/jdisk_test.o src/btree_key_size.o\
src/b_util.d src/item_compare_item.d src/b_tree.d src/item_print_item.d src/random_tester_2.d src/node_attach.d src/node_find.d src/node_create_.d src/btree_disk.d src/node_insert.d src/tnode.d src/btree_create.d src/node_unattach.d src/b_tree_test.d src/node_split_node.d src/node_print_node.d src/random_tester_1.d src/node_destructor.d src/btree_insert.d src/item.d src/btree_attach.d src/item_compare_item_qsort.d src/node_flush_node.d src/jdisk.d src/btree_find.d src/btree_destructor.d src/btree_get_node.d src/jdisk_test.d src/btree_key_size.d
Essentially they all went to the src dir but I'd like them to be seperated into (see below). Why is it putting everything in src?
obj/*.o
dep/*.d
src/*.c

Most likely because your sources variable src is empty. Which means your objects list variable obj is empty. Which means that your library lib/btree.a doesn't depend on anything, so make doesn't build anything.
This is most likely because this:
src := $(wildcard *.c)
obj := $(obj:.c=.o)
dep := $(dep:.o=.d)
should instead be:
src := $(wildcard src/*.c)
obj := $(src:.c=.o)
dep := $(obj:.o=.d)
It would be more clear if you showed us where your makefile was, and what directory you invoking make from.
You have a lot of other issues as well; for example this:
$(obj): $(src) $(dep)
$(CC) $(CFLAGS) $(INCLUDE) $# $^
is quite wrong. This says "each object file depends on ALL the source files and ALL the dependency files", and "to build a single object file, you compile ALL the source files".

Related

Compiling lot of .c files to .o files using makefile

I want to compile all .c files to .o files except some of them. Any help?
Currently my commands are looking like this:
%.o: %.c
$(CC) -C -o $(CFLAGS) $# $^
but I made a
EXCEPTIONS2 = testadmin.c testclient.c testserver.c server_comm.c client_comm.c
TO_COMPILE = $(filter-out $(EXCEPTIONS2), $(wildcard *.c))
But i dont know how to put them together, any idea?
You need to add a target that depends on those files. You can, for example, get all files in a directory like
SOURCEDIR := Some/Directory/You/Like
SOURCES := $(shell find $(SOURCEDIR) -name '*.c')
EXCEPTIONS2 = testadmin.c testclient.c testserver.c server_comm.c client_comm.c
TO_COMPILE = $(filter-out $(EXCEPTIONS2), $(SOURCES))
and then do something like:
%.o: %.c
$(CC) -C -o $(CFLAGS) $# $^
all: $(TO_COMPILE:%.c=%.o)
Just add a target that depends on the object files you want to be created:
.PHONY: all
all: $(TO_COMPILE:%.c=%.o)
and that's all.

How to generate object files in the build directory?

I am currently working on a C project to implement a Linux userspace application.
I wrote this Makefile, which allows me to compile :
PROJ_DIR := ../
SRC_DIR := $(PROJ_DIR)/src
BUILD_DIR := $(PROJ_DIR)/build
# define the executable file
TARGET := tcp_proxy
# include paths list
INC_DIRS := $(SRC_DIR)
INC_DIRS += $(SRC_DIR)/rpmsg
INC_DIRS += $(SRC_DIR)/rpmsg/rx
INC_DIRS += $(SRC_DIR)/rpmsg/tx
INC_DIRS += $(SRC_DIR)/tcp
INC_DIRS += $(SRC_DIR)/tcp/rx
INC_DIRS += $(SRC_DIR)/tcp/tx
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# source file list
SRCS := $(shell find $(SRC_DIR) -name *.c)
# object file list
OBJS := $(SRCS:.c=.o)
LDFLAGS := -pthread
all: tcp_proxy
tcp_proxy: $(OBJS)
$(CC) $(CFLAGS) $(INC_FLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)
%.o: %.c
$(CC) $(CFLAGS) $(INC_FLAGS) -c $< -o $#
.PHONY: clean
clean:
$(RM) *.o *~ $(TARGET)
However, the object files are generated in the same place as the source files.
So I would like to know how to duplicate the folders under "src" in a "build" directory and generate inside this directory the object files and the executable.
I would also like, when I do a make clean, to be able to delete all the object files and the executable.
My project :
Searching would definitely find you a lot of examples and information on this.
First tell make what objects you want to build; change your setting of OBJS to this:
# object file list
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
Then tell make how to build it; change your pattern rule for building objects to this:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) $(INC_FLAGS) -c $< -o $#

Makefile error when including dependency files generated from another Makefile

I have the current structures of directories:
./myFolder/
Makefile
main.c
./common/
Makefile
error.c
error.h
./build/
/common/
/myFolder/
/build/common contains the object and dependency files obtained from the compilation of the folder common and the equivalent for build/myFolder.
Basically /myFolder/ contains a programme that requires some function contained in common. Thus, the /myFolder/Makefile calls also the /common/Makefile to compile.
./common/Makefile is the following:
CC = gcc
CURRENT_DIR := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := ../build/$(CURRENT_DIR)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
all: $(OBJECTS)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
-include $(DEPENDS)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $< -o $#
$(OBJDIR):
mkdir -p $(OBJDIR)
and ./myFolder/Makefile is the following:
CC = gcc
INC_PATH := -I../common/
BUILD_DIR_NAME := build
BUILDDIR := ../$(BUILD_DIR_NAME)
CURR_DIR_NAME := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := $(BUILDDIR)/$(CURR_DIR_NAME)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR_NAME := common
COMMONDIR := ../$(COMMONDIR_NAME)
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(BUILDDIR)/$(COMMONDIR_NAME)
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
EXECUTABLE := ../out_file
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
+$(MAKE) -C $(COMMONDIR) clean
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTS) $(OBJECTSCOMMON)
$(CC) $(WARNING) $^ -o $#
-include $(DEPENDS) $(DEPENDSCOMMON)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $#
$(OBJDIRCOMMON):
mkdir -p $(OBJDIRCOMMON)
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c $(COMMONDIR)/Makefile| $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
If I step into the folder myFolder and compile with make for the first time, everything is ok.
If then I try again I get the following error:
make: *** No rule to make target `error.c', needed by `../build/common/error.o'. Stop.
If I do make clean and then make it works.
The line causing the problem is the following:
-include $(DEPENDS) $(DEPENDSCOMMON)
particularly $(DEPENDSCOMMON). With -include $(DEPENDS) instead of it, it works perfectly.
Now, - tells the Makefile not to complain if the files do not exist. If they exist they will be included and recompile your sources properly according to the dependencies. For this reason I would expect not to compile at the first attempt, but if it compiles at the first attempt, also to not generate such error (since all files exist).
Can someone please tell me what I am missing?
For completeness here are the other files which are just examples:
main.c
#include "../common/error.h"
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc<1) err_sys("some error");
printf("Hello world\n");
return 0;
}
error.c
#include <stdio.h>
void err_sys(const char *fmt, ...)
{
printf("some err\n");
}
error.h
#ifndef _ERROR_H_
#define _ERROR_H_
#endif
/*Fatal error related to a system cal1.
* Print a message and terminate*/
void err_sys(const char *fmt,...);
The error is related to your Makefile structure.
The main problem is that you generate the dependencies in common/Makefile and use it in myFolder/Makefile. The dependencies are generated for $(SOURCEDIR)/%.c, e.g. ./somefile.c which is valid only in common, not in myFolder
A related problem is that you duplicate many parts from common/Makefile in myFolder/Makefile. It doesn't make much sense to have a separate Makefile in this situation.
One way to solve this would be to build a library from the files in common and reference only the library from myFolder/Makefile. This avoids duplicating information from common/Makefile to myFolder/Makefile.
I changed your Makefiles to work this way. (There might be room for improvement, I only wanted to make it work.)
common/Makefile:
CC = gcc
CURRENT_DIR := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := ../build/$(CURRENT_DIR)
LIBNAME=libcommon.a
COMMONLIB = $(OBJDIR)/$(LIBNAME)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
.PHONY: all clean
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
all: $(COMMONLIB)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(COMMONLIB)
-include $(DEPENDS)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $< -o $#
$(OBJDIR):
mkdir -p $(OBJDIR)
$(COMMONLIB): $(OBJECTS)
$(AR) $(ARFLAGS) $# $^
myFolder/Makefile:
CC = gcc
INC_PATH := -I../common/
BUILD_DIR_NAME := build
BUILDDIR := ../$(BUILD_DIR_NAME)
CURR_DIR_NAME := $(shell basename $(CURDIR))
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR := $(BUILDDIR)/$(CURR_DIR_NAME)
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR_NAME := common
COMMONDIR := ../$(COMMONDIR_NAME)
OBJDIRCOMMON := $(BUILDDIR)/$(COMMONDIR_NAME)
LIBNAME=libcommon.a
COMMONLIB = $(OBJDIRCOMMON)/$(LIBNAME)
.PHONY: buildlib clean all
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
EXECUTABLE := ../out_file
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
+$(MAKE) -C $(COMMONDIR) clean
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTS) $(COMMONLIB)
$(CC) $(WARNING) $^ -o $#
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $#
$(COMMONLIB): FORCE
+$(MAKE) -C $(COMMONDIR)
FORCE:
Note: I used the target FORCE with no rule as a dependency instead of declaring $(COMMONLIB) as .PHONY to force running the recursive make. When I tried with .PHONY, the executable was re-built every time without checking the time stamp of the library file.
Another option would be to throw away the Makefile in common and replace the recursive make call in myFolder/Makefile with the corresponding compile command.
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c Makefile| $(OBJDIRCOMMON)
$(CC) $(WARNING) -MMD -MP -c $< -o $#
Notes
You don't need to use the relative path ../common in the #include directive when you specify this as an include directory with option -I.
I added .PHONY to declare your phony targets as such.
For automatic dependency generation and general recommendations about Makefiles I recommend to read the papers at http://make.mad-scientist.net/papers/.
You might also consider using a Makefile generator like cmake.
If you copy&paste the Makefile code from here, make sure to replace the spaces at the beginning of the lines with a tab.

Makefile : Automatically compile all c files, keeping .o files in separate folder

What I have is a directory with 3 sub-directories. src/ for .c and .h files, bin/ where the compiled executable is supposed to go and obj/ where I want the .obj files to go.
Now I want the makefile to compile every .c file from src (without me having to list them all in the makefile) and put the .o files in obj and the executable built from foo.c saved as bin/foo.
Can someone help me out? Whenever I use wildcards, make complains about rules not being there and when I use implicit rules, it doesn't put the object files in a separate folder.
To build foo.o from foo.c, locally:
foo.o: foo.c
$(CC) -c $< -o $#
To do the same, but with any needed header files in src/:
SRC := src
foo.o: foo.c
$(CC) -I$(SRC) -c $< -o $#
To do the same, but with the source file in src/:
SRC := src
foo.o: $(SRC)/foo.c
$(CC) -I$(SRC) -c $< -o $#
To do that, but put the object file in obj/:
SRC := src
OBJ := obj
$(OBJ)/foo.o: $(SRC)/foo.c
$(CC) -I$(SRC) -c $< -o $#
A pattern rule that will do that for any such object file (obj/foo.o, obj/bar.o, ...):
SRC := src
OBJ := obj
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -I$(SRC) -c $< -o $#
To create the list of desired objects:
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
And a rule to cover them all:
all: $(OBJECTS)
Putting it all together:
SRC := src
OBJ := obj
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
all: $(OBJECTS)
$(CC) $^ -o $#
$(OBJ)/%.o: $(SRC)/%.c
$(CC) -I$(SRC) -c $< -o $#
Note that this has one big shortcoming: is does not track dependencies on header files. This can be done automatically, but it's a subtle trick; it can wait until you've mastered this much.

Make: *.h no such file or directory

My project has the following directory structure:
main.cu
FA_kernels/*.cu
FD_kernels/*.cu
MEM_kernels/*.cu
MOD_kernels/*.cu
headers/*.h
Where *.extension means a bunch of files with that extension. I can't seem to get the makefile to work correctly. The error I'm getting is:
FA_kernels/FA_SFD.cu:2:20: fatal error: FA_SFD.h: No such file or directory
#include "FA_SFD.h"
^
My intent was for -I headers to be specified to the compiler, thereby making the headers directory available for searching. Clearly this has not worked. Here is the makefile:
CC := nvcc
LD := nvcc
MODULES := FA_kernels FD_kernels MEM_kernels MOD_kernels .
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix build/,$(MODULES))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cu))
OBJ := $(patsubst src/%.cu,build/%.o,$(SRC))
INCLUDES := $(addprefix -I,headers)
vpath %.cu $(SRC_DIR)
define make-goal
$1/%.o: %.cu
$(CC) $(INCLUDES) -c $$< -o $$#
endef
.PHONY: all checkdirs clean
all: checkdirs build/lem
build/lem: $(OBJ)
$(LD) $^ -o $#
checkdirs: $(BUILD_DIR)
$(BUILD_DIR):
#mkdir -p $#
clean:
#rm -rf build
$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))
Any ideas?
UPDATE: Here is the full console output from running make
nvcc FA_kernels/FA_SFD.cu FA_kernels/partition.cu FA_kernels/contribA.cu FA_kernels/parallel-SFD-List.cu FD_kernels/SFD.cu FD_kernels/flow_routines.cu FD_kernels/floodingDriver.cu FD_kernels/watershed.cu MEM_kernels/memory_dev.cu MEM_kernels/Data.cu MEM_kernels/MapInfo.cu MEM_kernels/memory.cu MOD_kernels/erosion.cu MOD_kernels/eroincidep.cu MOD_kernels/updates.cu MOD_kernels/runoffweight.cu MOD_kernels/depo-List.cu lem.cu -o build/lem
FA_kernels/FA_SFD.cu:2:20: fatal error: FA_SFD.h: No such file or directory
#include "FA_SFD.h"
^
compilation terminated.
Makefile:24: recipe for target 'build/lem' failed
make: *** [build/lem] Error 1
From your output, apparently patsubst in OBJ was not successful at all. From the way you define SRC, I assume makefile is directly under src/, then you should change src/%.cu to %.cu in the definition of OBJ as such:
OBJ := $(patsubst %.cu,build/%.o,$(SRC))
Also, if I understand you correctly, you were trying to create a folder structure under build/ that is identical to the folder structure under src/. So, for instance, /src/abc.cu will generate /src/build/abc.o, then you don't need to define functions to get these rules, simply do:
build/%.o: %.cu
$(CC) $(INCLUDES) -c $< -o $#
and you are good to go.
If instead you wish to create build/ on the same level as src/. i.e. XXX/src/abc.cu -> XXX/build/abc.o. Then simply replace all occurrences of build in your makefile with ../build.
If you would rather put makefile at the same level as src/, then you should edit SRC to reflect that:
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard src/$(sdir)/*.cpp))
and change the target to:
build/%.o: src/%.cpp
$(CC) $(INCLUDES) -c $< -o $#
Now you can safely remove vapth ... and the last line $foreach in your makefile.
EDIT: This is what your makefile will look like. I can't test it right now so there may be some mistakes in it, but hopefully it makes you understand the general idea.
CC := nvcc
LD := nvcc
MODULES := FA_kernels FD_kernels MEM_kernels MOD_kernels .
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix build/,$(MODULES))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cu))
OBJ := $(patsubst %.cu,build/%.o,$(SRC))
INCLUDES := $(addprefix -I,headers)
# vpath %.cu $(SRC_DIR)
#define make-goal
build/%.o: %.cu
$(CC) $(INCLUDES) -c $< -o $#
#endef
.PHONY: all checkdirs clean
all: checkdirs build/lem
build/lem: $(OBJ)
$(LD) $^ -o $#
checkdirs: $(BUILD_DIR)
$(BUILD_DIR):
#mkdir -p $#
clean:
#rm -rf build
#$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))

Resources