Link .h files and .c files from different directory using makefile - c++

I'm trying to compile a program called um from a current folder with um.c
and include some external implementations. The .h files are in one directory but the .c files implementing these .h files are in a different directory. Below is my makefile. It seems that the compiler knows where to look for the .h file. However, the linker fails and produces the error:
ld: symbol(s) not found for architecture x86_64
clang: fatal error: linker command failed with exit code 1
Makefile:
# define the C compiler to use
CC = gcc
# define any compile-time flags
CFLAGS = -g -O -Wall -Wextra -Werror -Wfatal-errors -std=c99 -pedantic
# define any directories containing header files other than /usr/include
INCLUDES = -I/Users/nguyenmanhduc/Documents/C\ library/cii/include
# define library paths in addition to /usr/lib
LFLAGS = -L/Users/nguyenmanhduc/Documents/C\ library/cii/src
# define any libraries to link into executable:
LIBS = -lm
# define the C source files
SRCS = um.c
# define the C object files
OBJS = $(SRCS:.c=.o)
# define the executable file
MAIN = um
.PHONY: depend clean
all: $(MAIN)
#echo Simple compiler named um has been compiled
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
clean:
$(RM) *.o *~ $(MAIN)
depend: $(SRCS)
makedepend $(INCLUDES) $^
This question might seem weird because I have little experience with makefile but is there a way that I can link .h and .c files in different folders using makefile.
Thanks!

The problem here is not that your additional .c files are in different directories: it's that you didn't tell your Makefile that they exist at all!
Here's where you list the source inputs (I guess you didn't see the comment?):
# define the C source files
SRCS = um.c
Add the other .c files whose compiled .os are what you want to link.
For example:
# define the C source files
SRCS = um.c ../wot.c ../hah/lol.c
There is no hard and fast rule but, the way you've constructed this Makefile, those relative paths should resolve just fine.

You don't link .c files, you link .o files.
You appear to be stating is that some of your .c files are in a different directory.
No matter, you have to explicitly list those .c files, in your makefile, just like you are listing the .c files in the directory with the makefile. You have to compile the .c files in a different directory, and then link them, just like you're compiling and linking the .c files in the same directory as the makefile. They're not going to compile themselves.
Another approach would be to have a separate makefile in that other directory, that compiles and builds an archive library, and then in this directory link with that archive library.

Related

When do files in C++ with direct & indirect dependencies have to be recompiled and when is a new linking of the executable sufficient? [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.

Gnu Make: Strange "Multiple targets pattern" - error

I have started a SDL2-project where I have a source file containing the main function which depends on several of my own header and object files which are in other folders. My directory structure is as follows
/SDL2 // Top-Level directory of all my SDL2 projects
-> /projectX // My current project
-> main.cpp
-> /obj_sdl2_ana // Directory of all self-made object files
-> ...object files
-> ...source files of object files
-> /include_sdl2_ana // Directory of all self-made header files
-> ..header files
To compile and link main.cpp against my object and header files I have written the following Makefile
TARGET = main
FILETYPE = cpp
OBJDIR = ../obj_sdl2_ana/ # Directory with self-made object files
INCDIR = ../include_sdl2_ana/ # Directory with self-made header files
IFLAGS = -I$(INCDIR)
LFLAGS = -lSDL2 -lSDL2_image # insert all necessary libraries into it
VPATH = $(OBJDIR):$(INCDIR)
ADD_RESOURCES = common_ana
ADD_INC := $(ADD_RESOURCES:%=$(INCDIR)%.hpp) # specify header files which are prerequisites
ADD_OBJ := $(ADD_RESOURCES:%=$(OBJDIR)%.o) # specify additional object files which are prerequisites
$(TARGET): $(TARGET).o $(ADD_OBJ)
g++ $(TARGET).o $(ADD_OBJ) -g3 -o $(TARGET) $(LFLAGS)
$(TARGET).o: $(TARGET).$(FILETYPE) $(ADD_INC)
g++ -c $(TARGET).$(FILETYPE) $(IFLAGS) -g3 -o $(TARGET).o $(LFLAGS)
$(ADD_OBJ): $(OBJDIR)%.o: $(OBJDIR)%.cpp $(INCDIR)%.hpp
g++ -c $< $(IFLAGS) -g3 -o $# $(LFLAGS)
I have tested this with only one object file (common_ana.o) and the corresponding header file (common_ana.hpp) but the problem is that make is tossing a "Multiple target pattern" error at the rule
$(ADD_OBJ): $(OBJDIR)%.o: $(OBJDIR)%.cpp $(INCDIR)%.hpp
g++ -c $< $(IFLAGS) -g3 -o $# $(LFLAGS)
I have absolutely no clue, why this error appears. The Gnu make manual suggests that this error appears when there is a misuse of static pattern rules. But I have triple-checked my Makefile and couldn't find anything which would justify the error message of gnu make. While I'm aware of a workaround, I would be really glad if someone could give me a hint, what I have done wrong with respect to the above static pattern rule.
Make is including the extra space before your comments, try something the following
# Directory with self-made object files
OBJDIR = ../obj_sdl2_ana/
# Directory with self-made header files
INCDIR = ../include_sdl2_ana/
IFLAGS = -I$(INCDIR)
# insert all necessary libraries into it
LFLAGS = -lSDL2 -lSDL2_image
Same applies to the other lines, it's best to avoid inline comments.

Environment variable to configure the location of the cpp source files

I am writing a cpp library for myself and I have put the deader files in a folder <root>/include and the cpp files in <root>/src folder. To add my include path to the environment, I have appended <root>/include to CPLUS_INCLUDE_PATH. Now, the problem I am facing is that I am getting an error during the linking step because the linker is unable to find the implementation of my class. Is there any environment variable where I can mention this like the way I have done for the header files?
You cannot do that. The linker needs compiled code and cannot deal with your source files. What you can do is to write a Makefile that will compile all your source files in the /src folder and link compiled files to the target. Example of a Makefile doing this:
ROOT = YOUR_ROOT_DIRECTORY_HERE
LDFLAGS = OPTIONS_TO_LINKER_HERE
CPPFLAGS = OPTIONS_TO_COMPILER_HERE
SRC=$(wildcard $(ROOT)/src/*.cpp)
your_app: $(SRC)
g++ $(CPPFLAGS) $(LDFLAGS) -o $# $^
Compile your application using: make your_app, or make.

GNU make compiling all .cpp files to .o and include .h files

So i have folder that looks like this
OS
Makefile
/include
head.h
/src
main.cpp
head.cpp
/objects
How can i use Makefile to compile all .cpp files to objects folder then compile all .o files with include .h to my actual cpp program.I currently have:
CPP_FILES := $(wildcard src/*.cpp)
H_FILES := $(wildcard include/*.h)
OBJ :=$(wildcard objects/*.o)
LIBS := -Wall
CC := -std=c++14
What do I enter next to make all those .cpp files to .o and compile them with .h included.Thank you for your time
You can use pattern rules (previously known as "suffix rules") for that. As you use GNU make, you can write this line to compile all .cpp files in src/ to .o files in objects/, assuming the Makefile is placed in the top directory:
objects/%.o: src/%.cpp
$(CXX) -c $(CFLAGS) $< -o $#
In GNU make syntax $< denotes the dependency (a .cpp file in this case), $# denotes the target (the object file).
The .h files do not need to be compiled, just set up the correct include path as part of the string the CFLAGS variable contains:
CFLAGS += -I./include

how to use makefile to include .a static library and .h file from another directory in C?

I have created a .h header file, implemented and created .a static library file, both of them are in directory in say, /home/data/folder1.
I have another .c file which will use link the .h header file and the .a library file. However, the .c file is in directory /home/data/folder2.
What should I write in the Makefile (which is also located in /home/data/folder2)? Also, should I include myheader.h in the .c file that I want to compile? Here is what I have so far, but not working:
LIBB = -L/home/data/folder1/libmylib.a
HEADER = -L/home/data/folder2/myheader.h
main: main.o
gcc $(HEADER) $(LIBB) $< -o $#
main.o: main.c
gcc -c main.c
.PHONY: clean
clean:
rm -f *.o *.~ a.out main
Any help will be appreciated, thanks in advance!
Including header files and libraries from non-standard directories is simple.
You have the path to the directory containing the library and the one containing the header, so we store those in variables:
LIBB = /home/data/folder1
LIBINCLUDE = /home/data/folder2
Now GCC needs to know where to look for headers, so we simply include it in the CFLAGS. The linker (not the compiler) needs to know where to look for libraries, so we can add that to LDFLAGS:
CFLAGS += -I$(LIBINCLUDE)
LDFLAGS += -L$(LIBB)
It will use the CFLAGS and LDFLAGS automatically if you don't explicitly run GCC.
But for the link step, it needs to know that the library is needed, so:
LDFLAGS += -static -lmylib
The linker will look for libmylib.a in all of the directories named by the -L options in LDFLAGS.
Since your rules for main and main.o are explicit, change them like so (but be sure to use a tab, not 4 spaces):
main: main.o
gcc $(LDFLAGS) $< -o $#
main.o: main.c
gcc $(CFLAGS) $< -o $#