implement subdirectory in makefile - c

WARNFLAGS = -W -Wall -Werror
OPTFLAGS = -O3
CFLAGS += $(WARNFLAGS) $(OPTFLAGS)
CC = gcc
DOBJS = /Desktop/Sysprog/Uebungsblatt6/a4/awesome2/awesome.h /Desktop/Sysprog/Uebungsblatt6/a4/awesome3/awesome.h
#MODULES = awesome2 awesome3
$(OBJS): /Desktop/Sysprog/Uebungsblatt6/a4/awesome2/awesome.h /Desktop/Sysprog/Uebungsblatt6/a4/awesome3/awesome.h
awesome:
$(CC) $(CFLAGS) awesome.c -o $#
clean:
rm -f *~ *.o awesome
I have tried everything, but don´t know how to include a headerfile from a subdirectory, into makefile.
My awesome.c is in directory a4, awesome.h is in directory awesome2 and awesome3, and I want to compile awesome.c, but if I compile it does do not find awesome.h. How can I make it work.

You need to include the .h file in your .c file.
There are two forms of the include directive you can put in your C source file:
#include "path/filename.h"
This version, with the file to include between quotes, includes a file relative to the directory of the .c file. You could of course put an absolute path there, but that is not recommended as you have to adapt it whenever you move the code/.h-file to another machine or place.
#include <path/filename.h>
With the file to include between < and >, the file will be searched relative to an include path you provide the compiler. In your case:
INC= /Desktop/Sysprog/Uebungsblatt6/a4/
$(CC) $(CFLAGS) awesome.c -o -I$(INC) $#
The -I switch is used by many compilers to provide it with a standard include path. It may be different for your compiler (and a guru may provide some adjustment, as my Make is rusty).

Related

C actualize files through makefile all at once

I am working on project, where i use couple of .c and .h files.
I created Makefile where i actualize executable program based on changes in all of these files.
Problem is, when i use make, program is compiled, but when i execute program, it runs without any change. I need to save ( working in vim so :w ) all included files, even when i changed only one.
If i don't save all these files, program is compiled, but executes the same thing as it did before change.
Could someone explain me why is that ?
Makefile code :
CC=gcc
CFLAGS=-WALL
execFile: execFile.o functions.h newDataTypes.h
Thank you.
The reason you are not getting execFile updated is because you're NOT updating it. Or at least you don't seem to be in this particular case.
There are many ways to get about doing this. However since you are using gcc and I assume you're using gnu make the following is probably the best solution you can execute1.
Given the files:
-rw-r--r-- 1 user sudo 73 Nov 4 22:54 exeFile.c
-rw-r--r-- 1 user sudo 74 Nov 4 22:54 exeFile.h
-rw-r--r-- 1 user sudo 90 Nov 4 22:55 hello_world.c
-rw-r--r-- 1 user sudo 888 Nov 4 23:03 Makefile
cat exeFile.c
#include <stdio.h>
#include "exeFile.h"
int main()
{
hello_world();
}
exeFile.h
#ifndef _EXEFILE_H
#define _EXEFILE_H
extern void hello_world();
#endif
hello_world.c
#include <stdio.h>
#include "exeFile.h"
void hello_world()
{
printf("Hello World\n");
}
you can set up a make file that generates dependencies and ensures that the program will always be compiled correctly:
CC=gcc
CFLAGS=-Wall
SOURCES=exeFile.c hello_world.c
EXE=exeFile
OBJ=$(SOURCES:%.c=%.o)
DEPDIR := .deps
$(shell mkdir -p $(DEPDIR) >/dev/null)
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.Td
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
POSTCOMPILE = #mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $#
%.o: %.c
%.o: %.c $(DEPDIR)/%.d
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cc
%.o : %.cc $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
%.o : %.cxx
%.o : %.cxx $(DEPDIR)/%.d
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(POSTCOMPILE)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
$(EXE): $(OBJ)
$(CC) -o $# $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) $(EXE)
dev-clean: clean
$(RM) -r $(DEPDIR)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SOURCES))))
Let's go over the relevant parts about dependencies
DEPDIR =
This implementation places dependency files into a subdirectory named .deps .
$(shell mkdir -p $(DEPDIR) 2>/dev/null)
GCC does not create subdirectories for output, this line ensures that the DEPDIR directory always exists.
DEPFLAGS = ...
These are GCC-specific flags which tell the compiler to generate dependency info.
-MT $#
Set the name of the target in the generated dependency file.
-MMD
Generate dependency information in addition to compiling. -MMD omits system headers from the generated dependencies: if you prefer to preserve system headers as prerequisites, use -MD instead.
-MP
Adds a make target for each prerequisite in the list, this avoids errors when deleting files.
-MF $(DEPDIR)/$*.Td
Write the generated dependency file to a temporary file $(DEPDIR)/$*.Td e.g. hello_world.c will generate hello_world.Td as temp dependency content for use in Makefile.
POSTCOMPILE = ...
First rename the generated temporary dependency file to the real dependency file. We do this in a separate step to side-step compile errors. Next we explicitly touch the files to avoid a gcc bug.
%.o : %.c
Delete the built-in rules for building object files from .c files, so that our rule is used instead. Do the same for the other built-in rules.
... $(DEPDIR)/%.d
Declare the generated dependency file as a prerequisite of the target, so that if it’s missing the target will be rebuilt.
$(DEPDIR)/%.d: ;
Create a pattern rule with an empty recipe, so that make won’t fail if the dependency file doesn’t exist.
.PRECIOUS: $(DEPDIR)/%.d
Mark the dependency files precious to make, so they won’t be automatically deleted as intermediate files.
include ...
Include the dependency files that exist: translate each file listed in SOURCES into its dependency file. Use wildcard to avoid failing on non-existent files.
1 See Auto-Dependencies Generation for details.
Fix:
Tell make that the executable depends only on the object file and the object file depends on the header files:
execFile: execFile.o
execFile.o: functions.h newDataTypes.h
Explanation:
In order to build your executable two steps are needed:
compilation of C source files (that include header files) to produce object files,
linking of the object files to produce the executable.
So, when changing your header files you must re-compile, that is re-built the object files, not just re-link that would produce the same executable from the same object files.
In your Makefile the dependencies are not properly defined. You did not tell make that the object file (execFile.o) shall be rebuilt when your header files change. Instead, you told it that the executable (execFile) shall be rebuilt.
First of all, your dependencies are mistaken. Your executable does not depend on the .h header files, as they are using only at compilation time. The dependencies are normally between .o files and .h files, as when you modify one .h file, the including .c file must be compiled to generate the .o file. so in case you have execFile.o (which, on lack of complete information, I'll suppose it depends on execFile.c, which #includes functions.h and newDataTypes.h, the rule should be:
execFile.o: execFile.c functions.h newDataTypes.h
As it has been pointed out in other responses, there's no need to write the command to build the .o file, as there is a default rule like this:
.c.o:
$(CC) $(CFLAGS) -o $# -c $<
(observe there's a -c option to the compiler indicating to compile only and don't link, we'll return here below) which means that once you detect the .o is outdated (as the dependencies on .c and .hs mark) it will be compiled with the above command, which result in:
gcc -Wall -o execFile.o -c execFile.c
making the appropiate compilation.
Other thing is the dependencies of the executable file. These have to be included, as make(1) doesn't know which object files form your final executable. In this case, assuming you have your program execFile depend on execFile.o and a.o, b.o and c.o, I normally use to write:
execFile_objs = execFile.o a.o b.o c.o
execFile: $(execFile_objs)
$(CC) $(LDFLAGS) -o $# $(execFile_objs)
so any of the .os is changed (because an indirect change in a source file) the whole program is linked again (but only the touched files are compiled)
NOTE
In the case (not normal) that you have a Makefile to create a program that has only one source file and several include files you can compile each time the whole thing each time you modify one source file, in this way:
execFile: execFile.c functions.h newDataTypes.h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# execFile.c
This will execute
gcc -Wall -o execFile execFile.c
Observe that there is no -c (compile only, don't link) option in this command.
There's no mention of the include files (they are included because of the #include directives in the code... and you only state here that the executable depends also (and have to be built) in case any of the .h files are modified.
Automatic dependency rules are a little confusing at first, as they induce you to think there are such rules to make any kind of file from any other kind of file (well, there are for .c -> .o files, and .c -> <nothing> to compile directly to an executable) normally you have to include dependencies in such cases when your target depends on more files than the automatic rule states. In such cases, it is very important not to include any command, so the compiler selects the automatic rule (when you don't include a command to generate the target, the make(1) program tries to use a default rule for it, or nothing at all if you have not included commands, it only assumes your dependencies are indirect through this fake target --- and, as this fake target is not built in the process, it will fail always and be followed)

Makefile: "ld: can't link with a main executable file" in C

I am trying to compile two c files, calutil.c and calutil.h into one executable. Here is my makefile:
CC = gcc
CFLAGS = -Wall -std=c11 -DNDEBUG
all: caltool
caltool: calutil.o caltool.o
$(CC) $(CFLAGS) calutil.o caltool.o
caltool.o: caltool.c
$(CC) $(CFLAGS) caltool.c -o caltool.o
calutil.o: calutil.c
$(CC) $(CFLAGS) -c calutil.c -o calutil.o
clean:
rm -rf *.o *.out
calutil.c has no main, while caltool.c has a main. I get the error
ld: can't link with a main executable file when I make. What is the cause of this?
The main problem is that some your recipe for linkage is missing the output file, and that your compilation is missing -c.
In case you're using GNU make, the following Makefile would be sufficient to do what you want to do:
CFLAGS:=-Wall -std=c11
CPPFLAGS:=-DNDEBUG
.PHONY: all
all: caltool
caltool: caltool.o calutil.o
.PHONY: clean
clean::
$(RM) *.o
Explanation:
When you're not using target-specific variables, you should use := instead of = to assign variables so that they're expanded at assignment and not at evaluation.
When your Makefile grows and you split it, you might want to have multiple targets called clean which all would be executed. In that case use clean:: instead of clean:.
There's a predefined variable to call rm, it is $(RM) and it includes the -f flag to prevent the Makefile from failing in case one or more of the files to be removed do not exist in the first place.
The pattern for clean should be *.[adios] (that's really easy to remember, adios is Spanish for goodbye) so that it removes intermediate archives (.a when you build your own static libraries), dependency files (.d), preprocessor output (.i) and assembler files (.s) in case you use -save-temps to see what the compiler is doing.
GNU make has built-in rules to compile and link, see http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=3.81
The built-in rule for compilation calls $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $# $< so you don't need to write your own rule.
The built-in rule for linkage calls $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $#
Targets which are not files themselves should be declared .PHONY to prevent confusion when a user creates a file with the same name, like all or clean.
I do not see how any of your commands would create a file matching the glob pattern *.out, so I removed that part of the clean rule.
Flags for the preprocessor should go into CPPFLAGS instead of CFLAGS. Preprocessor flags typically are all those -D and -I flags and would also be passed to other tools that use a C preprocessor in the same project, like splint or PC-Lint.
When the Makefile is run, it is looking how to make all, and it finds that for all it has to make caltool. For caltool it finds that it has to first make calutil.o and caltool.o. When it tries to make calutil.o and caltool.o, it finds that it can make them from calutil.c and caltool.c and will do so. Then it will link caltool.o and calutil.o into caltool.
From your naming I guessed that it's caltool.c that contains the main() function. It is helpful to place the object which contains main() first once you use static link libraries.
Edit: Here's some more magic for you. I assume that you have a header file calutil.h which is included by caltool.c to access extern symbols provided by calutil.c. You want to rebuild all objects that depend on these header files. In this case, add the following lines to your Makefile:
CPPFLAGS+=-MMD
-include caltool.d calutil.d
In order to not have the list of objects multiple times, you could add a variable objects like this:
objects:=caltool.o calutil.o
You would then build the application with this rule:
caltool: $(objects)
And include the dependency files like this:
-include $(objects:.o=.d)
In case you keep your working tree "clean", i.e. do not "pollute" it with "alien" code, i.e. you always want to include all .c files in your project, you can change the definition of objects as follows:
sources:=$(wildcard *.c)
objects:=$(sources:.c=.o)
In case you wonder why it is CPPFLAGS (uppercase) but objects (lowercase): it is common to use uppercase for all variables which configure the recipes of rules and control the built-in behavior of make, tools built on top of it, and classic environment variables, and lowercase variables for everything else.
I just removed the .o files from the directory, and edited my makefile to add -c to the caltool.o line.

What is wrong with this Makefile? (header files not found)

I am modifying an old makefile in order to build a C extension for postgreSQL. The Makefile currently looks like this:
PGLIB = /usr/lib/postgresql/8.4/lib
PQINC = /usr/include/postgresql/8.4/server
CC=gcc
override CFLAGS+= $(CFLAGS_SL) -DPG_AGGREGATE
SHLIB = pg_myextlib
SRC = foo.c \
foobar.c
OBJS = foo.o \
foobar.o
all: $(OBJS)
$(CC) -shared -o $(SHLIB)$(DLSUFFIX) $(OBJS) -I$(PQINC)
cp *.so $(PGLIB)
clean:
rm -f $(SHLIB) $(OBJS)
The error I get when I run make is:
common.h:58:22: error: postgres.h: No such file or directory
Which suggests that the include path is not being added (the file exists in $PQINC).
Its a long time since I wrote the Makefile - and I haven't written many since. As an aside, I am pretty sure that 'shared' is not the gcc flag to build shared libs on Ubuntu (my current dev box) - I think the flag should be 'fPIC' - can someone confirm this?
I am runing gcc v4.4.3 on Ubuntu 10.0.4 and compiling for use with PG 8.4
Try moving the -I$(PQINC) from target all to the end of line that starts with override CFLAGS.
Placing -Isomething on the compiler line which turns object files, like those in $(OBJS), into executable will have no effect whatsoever.
You need to do it when you compile the source files.
Since your makefile doesn't explicitly show the rule for processing source files, it may well be using a default one, which is incredibly unlikely to know about PQINC.
You seem to be using the default rules to build foo.o from foo.c, which doesn't have your -I. Try adding the following rule to your Makefile:
.c.o:
$(CC) $(CFLAGS) -c $< -o $# -I$(PQINC)

Makefile Subdirectories

I'm attempting to organize my project directory as follows
shell
|inc/[header files]
|obj/[object files]
|src/[source files]
|Makefile
|Executable
Everything compiles without error with everything in the root folder, but I'm running into difficulty modifying my makefile to accommodate having everything in different directories.
Here's how my makefile looked without directories
OBJS = shutil.o parser.o sshell.o
HEADER_FILES = shell.h parser.h
EXECUTABLE = sshell
CFLAGS = -Wall
CC = gcc
#Create main executable
$(EXECUTABLE): $(OBJS)
$(CC) -o $(EXECUTABLE) $(OBJS)
#Create object files
%.o: %.c
$(CC) $(CFLAGS) -I. -c -o $# $<
$(OBJS) : $(HEADER_FILES)
I've tried adding the directories into the definitions (for the obj/ and inc/ directories)
OBJS = obj/shutil.o obj/parser.o obj/sshell.o
And modified every instance of %.o and %.c to obj/%.o and src/%.c
Everything should be okay as far as I can tell, but I get this error when I go to make from the root directory
gcc -Wall -Iinc -c -o obj/shutil.o src/shutil.c
src/shutil.c:8:23: fatal error: inc/shell.h: No such file or directory
compilation terminated.
Can anyone find what I'm doing wrong here? I've been struggling with this for days.
Change -I. to -I${CURDIR}. The former adds the directory of the source being compiled to the include path list, which would be shell/src. The latter adds shell, this is probably what you want.
You may also take a look at Building multiple executables with similar rules for a micro non-recursive make framework.
Your compiler is looking for inc/shell.h, which it shouldn't. Generally, no build system dependent path should be in the source file, but the details of the build system should rather be defined via compiler flags.
That is, your source file src/shutil.c should look like:
#include "shell.h"
and your compiler invocation be the same, with the -Iinc passing the include path.
By keeping the paths out of the source files, implementation and installation of header files is much simpler.
Okay, it took some thorough frustration, but I got it now.
I changed my definitions at the top to include the file paths, as so:
OBJS = obj/shutil.o obj/parser.o obj/sshell.o
HEADER_FILES = inc/shell.h inc/parser.h
And it seems the key was -I./inc, instead of -Iinc as I expected.
obj/%.o: src/%.c
$(CC) $(CFLAGS) -I./inc -c -o $# $<

Why does this makefile not apply includes to all objects?

This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.

Resources