I have source code in one directory and have a makefile in a different directory. I am able to compile the code using the make system's vpath mechanism. The .o files are being created in the same folder where the makefile is. But I want to move those .o files to a different directory called obj. I tried the following:
vpath %.o obj
However, they are still being created in the same folder as the makefile. Can anyone help me to solve this issue?
Here are some highlighted lines of the makefile:
PATH_TO_OBJ:- ../obj
SRC :- .c files
OBJS :- $(SRC:.c = .o)
.c.o = $(CC) $(CFLAGS) -c
exe: cc $(LFLAGS) -o $(PATH_TO_OBJ) $(SRC).
After this also, .o file is creating in same folder of Makefile. Not moving to obj
-o option defines where to save the output file, produced by a gcc compiler.
gcc main.c -c -o path/to/object/files/main.o
Make's VPATH is only for finding source files. The placement of object files is up to the thing that is building them. There's a nice description at http://mad-scientist.net/make/vpath.html (I see someone beat me to posting this in a comment).
The *BSD build systems use variants of make that can place object files (and other generated files, including C sources from lex and yacc variants) in /usr/obj automatically. If you have access to that version of make, that will likely be a good way to deal with whatever underlying problem you are trying to solve.
Related
Till now, I was using the following makefile that I have generated somehow for my school projects:
my makefile
But now I have a different situation: I am supposed to compile 4 programs for one project, while part of the code is supposed to be compiled as .so, for use for the 4 programs.
like described here:
1 - all the parts that are supposed to be compiled together as one .so file, using for example:
gcc -shared -fPIC src/file1.c src/file2.c src/file3.c -o libutils.so
3,4,5 should be compiled and linked together with this .so file, using for example:
gcc src/file4.c -L'pwd' lutils -o file4.out
the same way for all the 3 projects, and one more simple compilation of project 2.
I wandered across the net, google, your site, etc.
tried to find a solution for this situation,
without any luck.
already seen solutions like this one:
solution example
where you supply makefile with the details of the entire project structure.
I thought about dividing all the files into 4 folders, below the main folder, and creating a loop inside makefile that will compile each program in each cycle, with "if" statements to make a different compilation, according to the index. but I had no luck, it seems very complicated (maybe someone can show me a solution like that one...).
I am wondering if there is a way of making this whole compilation process generic and automatic like the current file (maybe little less),
if there is a way, I would like to study and discover it.
thank you in advance!!!
Arie
Since you have a nicely drawn tree of dependencies, you "just" need to translate this into a Makefile.
You might like to start with this:
.PHONY: all
all: reloader.exe block_finder.exe formatter.exe printdb.exe
MODULES = reloader block_finder formatter printdb linked_list bitcoin file_handler
SRCS = $(MODULES:%=%.c)
reloader.exe block_finder.exe formatter.exe printdb.exe: libbitcoin_manager.so
reloader.exe: reloader.o
block_finder.exe: block_finder.o
formatter.exe: formatter.o
printdb.exe: printdb.o
libbitcoin_manager.so: linked_list.o bitcoin.o file_handler.o
gcc -shared -fPIC $^ -o $#
%.exe: %.o
gcc $< -L. -lbitcoin_manager -o $#
%.o: %.c
gcc -c $< -o $#
%.d: %.c
gcc -MM -MT $# -MT $*.o -MF $# $<
include $(SRCS:%.c=%.d)
Because you don't have a loop in the diagram, you don't need a loop in the Makefile. Instead you put all dependent files on the left of a colon and the file they depend on on the right.
You might like to collect more "objects" in variables, for example the programs to build, the modules in the library, and so on.
I have also used a common pattern to generate the dependencies from the header files. The way shown is just one way to do it. It uses files with a ".d" extension, for "dependency." GCC has options to build these files, it scans the source and collects all included headers even if "stacked."
For example, "bitcoin.d" looks like this:
bitcoin.d bitcoin.o: bitcoin.c bitcoin.h linked_list.h definitions.h \
file_handler.h
The re-generate the dependency file on changes in the sources it is also a target, not only the object file.
EDIT:
First, using directories makes Makefiles more difficult. I don't like such structures not only for that reason, but also because they separate header files and implementation files that clearly belong to each other.
Anyway, here is an enhanced Makefile:
.PHONY: all
SRCDIR = src
INCDIR = include
BLDDIR = build
APPS = reloader block_finder formatter printdb
MODULES = reloader block_finder formatter printdb linked_list bitcoin file_handler
LIBNAME = bitcoin_manager
LIBMODULES = linked_list bitcoin file_handler
VPATH = $(SRCDIR)
SRCS = $(MODULES:%=%.c)
LIB = $(LIBNAME:%=lib%.so)
#win LIB = $(LIBNAME:%=%.lib)
EXES = $(APPS:%=%.exe)
all: $(BLDDIR) $(EXES)
$(BLDDIR):
mkdir $#
$(LIB): $(LIBMODULES:%=$(BLDDIR)/%.o)
gcc -shared -fPIC $^ -o $#
$(EXES): $(LIB)
$(EXES): %.exe: $(BLDDIR)/%.o
gcc $< -L. -l$(LIBNAME) -o $#
$(BLDDIR)/%.o: %.c
gcc -I$(INCDIR) -c $< -o $#
$(SRCDIR)/%.d: %.c
gcc -I$(INCDIR) -MM -MT $# -MT $(BLDDIR)/$*.o -MF $# $<
include $(SRCS:%.c=$(SRCDIR)/%.d)
It uses a lot more variables to simplify renaming and managing a growing library and application.
One important issue is the use of VPATH. This makes make search for sources in the list of paths assigned to it. Make sure you understand it thoroughly, search for articles and documentation. It is easy to use it wrong.
The pattern $(EXES): %.exe: $(BLDDIR)/%.o is a nice one. It consists of three parts, first a list of targets, second a generic pattern with a single target and its source. Here is means that for all executables each of them is built from its object file.
Now to your questions:
Is answered by the new proposal. I didn't add the directory but use VPATH.
Make stopped not because the exe-from-o pattern was wrong, but because it didn't find a way to build the object file needed. This is solved by the new proposal, too. To find out what happens if you delete these 4 recipes in the old proposal: you can experiment, so do it!
The dot is, like user3629249 tried to say, the present working directory. You had it in your Makefile with 'pwd' and I replaced it. This is not special to make, it is common in all major operating systems, including Windows. You might know .. which designates the parent directory.
When make starts it reads the Makefile or any given file. If this file contains include directives the files listed are checked if they need to be rebuild. make does this even if you call it with -n! After (re-)building all files to be included they are included finally. Now make has all recipes and continues with its "normal" work.
So here is a Makefile I have been given, with comment I have added.
MF= Makefile_c #name of the makefile
CC= cc #compiler to use
CFLAGS= -g #flags to use
LFLAGS= -lm #flags to use after the thingy
EXE= hello #name to give the executable
INC= \ # ??? What's this for ???
# No user-defined include files at present - list here if required.
# name of the source file
SRC= \
hello.c
#delete default suffix
.SUFFIXES:
#define the suffixes we are interested in
.SUFFIXES: .c .o
OBJ= $(SRC:.c=.o) # names to give the object files
#The .o files depend on the .c files. Compile the object files.
.c.o:
$(CC) $(CFLAGS) -c $<
all: $(EXE) #The output is the executable
$(OBJ): $(INC) #The objects depend on whatever INC is
# The executable depends on the object files. build it from the object files.
$(EXE): $(OBJ)
$(CC) $(CFLAGS) -o $# $(OBJ) $(LFLAGS)
# ??? the object files depend on the makefile???
$(OBJ): $(MF)
# remove any old executables or object files.
clean:
rm -f $(OBJ) $(EXE) core
I am still learning about makefiles so please correct me if I have misidentified anything. The makefile works fine But I want to adapt it to work with my program that has multiple files and header files. I suspect that the variable $INC will somehow make this possible, but so far my attempts to use it have not worked.
For now I would like to understand what this makefile is trying to do, cn you tell me what $INC is for?
The makefile works fine But I want to adapt it to work with my program that has multiple files and header files. I suspect that the variable $INC will somehow make this possible
Unfortunately, no. The \ is just a line continuation, so you can write content for the variable in the next line. It's empty here. This is just a very simple (and ancient!) approach for dependencies: List them yourself. The intention is to list all files your C source file #includes there, so make will rebuild when any of these included files change.
There are much advanced patterns, gcc (and other compilers) allow to do automatic dependency information for make, but this is out of scope for this question. (*)
As for building with multiple source files, this Makefile already supports it, again using an "ancient" way, a suffix rule. It automatically considers all .c files in your directory part of your final program.
(*) As mentioned by Tormund Giantsbane in the comments, this document has nice information on the topic auf automatic dependencies
So I have a make file, stored in a directory called "temp" the following directory has a src folder, with 2 .c files "file1.c" and "file2.c". The temp directory also holds a include folder (which is empty), and a bin folder (which is empty until the make command is so posed to be run). I'm currently to trying get a single .c file to compile (get it working),but a single file doesn't even seem to work here.
This is how the directories look:
temp
cd into temp..
bin include Makefile src
Here is my makefile:
all:
gcc -Wall -pedantic -std=c99 src/file1.c -Iinclude -o bin/runMe -lncurses
And yes, there is a tab before the gcc. Any help on this frustrating issue, would be much appreciated. Also, if possible any input on compiling the second .c file, would also be very helpful!
Nothing to be done for TARGET means that a target has no commands which, in this case, almost certainly means that you do not have a tab on that gcc line.
That being said that's only the immediate problem. This makefile is also not following good practices and will unnecessarily recompile your program (as well as ceasing to work entirely should an all file be created).
DrC had, in a currently deleted answer, very good suggestions for how to improve your makefile to avoid both of those latter issues.
Specically, your makefile should look more like this:
.PHONY: all
all: bin/runMe
bin/runMe: src/file1.c
gcc -Wall -pedantic -std=c99 $^ -Iinclude -o $# -lncurses
Which marks the all target as a .PHONY so that an all file or directory getting created won't confuse make as well as setting up a prerequisite on the source file for your built binary so that make can tell when it does (and doesn't) need to rebuild the binary.
I am having a 1.c 2.c....n.c files and having its dependencies .h file also... i know to create make file for multiple c files.But i don't how to create make file for which the c files are linking to .h files. If i try the makefile which i know it will give error like
make: *** No rule to make target '2.h', needed by '2.o' .Stop.
and I don't need this type of makefile also.
program: main.o dbAdapter.o
gcc -o program main.o dbAdapter.o
main.o: main.c dbAdapter.h
gcc -c main.c
dbAdapter.o dbAdapter.c dbAdapter.h
gcc -c dbAdapter.c
This will be good for 4 or 5 files. But if I have a large number of files, what is the best solution?
You can link all your .h in the Makefile by this way :
Put all the .h in a same file (that we called "Include" for the exemple)
Add this in your Makefile : gcc *.c -I/path/Include -iInclude
Ps: Your way to compile your .c file is a bit strange.
Usually we use this:
SRC = 1.c
2.c
n.c
OBJ = $(SRC:.c=.o)
all: $(OBJ)
gcc $(SRC) -I/path/Include -iInclude (where path is the location of your file called "Include")
As long as I'm working with C, I never wrote make files that includes header files (.h) the header files are here to expose some of the data structure and methods, constants that are needed in other C modules.
You don't need to create rules for header files, all you have to do is build the .o objects then the liker will do the magic for you when you create the executable file.
If you need some help crating a make file you can explain here what you wanna build and I'll send you a hint.
Cheers.
If your header files are not in current directory and you included it in Makefile, Make starts looking for header files in default location but it is not able to find them in your case.
you should put 2.h header files in current directory to avoid this search.
I am working on a C project which contains around 200 .c files and some .h files. Not all of these 200 files are required in the final product. Currently around 180 files needs to be compiled. We have a file "compile_only_these.c" which includes these 180 *.c files required for the project. Our makefile compiles only this file instead of individual .c files.
/* file: compile_only_these.c*/
#include "file1.c"
#include "file2.c"
.
.
.
#include "file180.c"
But I think including .c files is a bad idea. Because every time I modify any of these files, all files are compiled again.
Can you suggest a better way to compile these files.
More info:
All .c files are in same folder "../project/src"
I keep adding new .c files which are required to be compiled. I dont want to modify Makefile every-time I add a new file.
I still want to keep those 20 .c files which I am not compiling right now. I may use it in future. Deleting these files are moving them to other directory is not a solution
What you need is a variable in the makefile, a list of required object files, like this:
OBJS := file1.o file2.o ... file180.o
You can have Make construct it from the compile_only_these.c file like this:
OBJS := $(shell sed -e '/\#include/!d' -e 's/\#include "\(.*\)\.c"/\1.o/' compile_only_these.c)
Do you also need a hand with the rule that uses these objects to construct the final product?
As already mentioned, it's sort of a weird way to manage a project, but given what you have to work with, you might try something along this approach...
CC = gcc
OBJFILE = myprog
# Tweak to match whatever you compile with normally
CFLAGS = -O2 -Wall -std=c89 -pedantic
LDFLAGS= # Extra flags here, for example -lm -pthread
RM = rm -f
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
$(OBJFILE):$(OBJS)
$(CC) -o $# $^ $(LDFLAGS)
clean:
$(RM) core *~ $(OBJS) $(OBJFILE)
You will obviously need to adjust the path(s) for the specifics of your build hierarchy if you want to do more in your make than just compile this list of files, but this is a general approach for grabbing all files with wildcard substitution.