I have a folder called UnitTest. I have several .c files in it. All files contain function 'main'.
Using makefile, I want to compile all .c files of that folder together.
But these files have dependency on other C files which are in different folder.
How can I write make file for this?
eg.
Common\*.c - generate object file
App\*.c - generate object file. - refers to .o files of Common directory
UnitTest\.c - these files should be compiled as executables. Refer *.o from directory App and Common.
Update:
Header files are in seperate directory called \Include
I need a single makefile for this. Please help.
As per the standards every directory will contain one Makefile. So you can have three Makefiles for this job done if you have three directories.
(d) common
|
|---(f) common.h
|---(f) common.c
|---(f) Makefile --- MAkefile for the common folder.
(d) app
|
|---(f) app.h
|---(f) app.c
|---(f) Makefile
(d) unittest
|
|---(f) unittest.h
|---(f) unittest.c
|---(f) Makefile
(f) Makefile --- invoke all makefiles in the mentioned order.
If you want one Makefile to happen all these done, you can do in that way also. Here you have to compile the files by providing paths of the files. order is most impotent.
This is complicated, so we will take it in stages. First, building the object files:
CFLAGS += -I/include
vpath %.h /include
This should be enough to build any object file in Common/, Apps/ or UnitTest/. Test this before going further.
Now to build all of the objects in Common/:
COMMONSOURCES := $(wildcard Common/*.c)
COMMONOBJECTS := $(COMMONSOURCES:.c=.o)
all: $(COMMONOBJECTS)
Test this before going further.
Remove that all rule, and put in a rule for the Common library. (We'll use a static library for now, since it's a little simpler.)
Common/libCommon.a: $(COMMONOBJECTS)
ar -cvq $# $^
Test that much, tell us in the comments how it worked, then we'll build Apps library and the UnitTest executables.
Related
I have a .c file that is dependent on a generated include file named control.po but when it is included in the dependencies, make thinks it needs to build it.
make[1]: *** No rule to make target `control.po', needed by `proccmd.o'. Stop.
proccmd.o: ddemsgid.do ddelen.do control.po tprecs.ro tlktp.h comtrac.h basmsg.fo \
tiop.h
If I copy control.po to control.fo and change the dependency control.po, it compiles.
I have tried changing .SUFFIXES
this way
.SUFFIXES:
.SUFFIXES: .c .o .h .po
and this
.SUFFIXES:
.SUFFIXES: .c .o .h
with the same result.
I am ASSUMING there is some implied rule about .po files.
I am converting a large project from a proprietary build to gnu make, so I cannot easily change the file extensions of the generated files.
I am ASSUMING there is some implied rule about .po files.
Wrong assumption. The builtin rules are obtained with make -p and they don't mention .po
As I told in comments:
when building a large project, ninja is more suitable (it runs by default in parallel, like make -j and it runs faster). If you are migrating from a proprietary build system, it probably would be better. You'll need to write or find your build.ninja generator (e.g. with your Python script generating it, with meson, etc...).
If you stay with GNU make, you should add your own recipes and rules for your .po suffix (assuming that your foo.po is generated from some foo.src). So read the documentation of GNU make and you may want some rule like
%.po: %.src
# how to build a .po from some .src fle
You could find useful to use remake with -x for debugging your Makefile
the generated include files are in a different directory and I failed to add an vpath entry for .po files..
VPATH_INCLUDE_LIST = ../include:../../include:../../../include:../../../../include
vpath %h $(VPATH_INCLUDE_LIST)
vpath %.do $(VPATH_INCLUDE_LIST)
vpath %.fo $(VPATH_INCLUDE_LIST)
vpath %.to $(VPATH_INCLUDE_LIST)
vpath %.ro $(VPATH_INCLUDE_LIST)
vpath %.go $(VPATH_INCLUDE_LIST)
vpath %.po $(VPATH_INCLUDE_LIST)
We can add pattern rules such as %.c or %.o which mimics *.c or *.o in bash (it searches for all files that have extension .c or .o. This is very useful if you have several targets, so you don't have to write all rules. I would like to know how to use this trick if your target files (.c or .o) are in the previous directory. In bash, one can write ../*.c, but ../%.c does not work in makefile as I tested. How do you do such thing in makefile?
My second question: sometimes one would like to add header dependencies like this:
HEADER=factorial.h
%.o: %.c $(HEADERS)
gcc -o program $%
It is a good idea to add a header dependency because sometimes you don't know whether or not the included libraries have some change.
Here we have to manually type the file names for HEADER.
How do I make it so it can scan the target file's included headers?
For example: my main.c has #include "dog.h"
How do I make it so it detects main.c has included dog.h.
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.
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'm a C Newb
I write lots of code in dynamic languages (javascript, python, haskell, etc.), but I'm now learning C for graduate school and I have no idea what I'm doing.
The Problem
Originally I was building all my source in one directory using a makefile, which has worked rather well. However, my project is growing and I would like to split the source into multiple directories (unit tests, utils, core, etc.). For example, my directory tree might look like the following:
.
|-- src
| |-- foo.c
| |-- foo.h
| `-- main.c
`-- test
`-- test_foo.c
test/test_foo.c uses both src/foo.c and src/foo.h. Using makefiles, what is the best/standard way to build this? Preferably, there would be one rule for building the project and one for building the tests.
Note
I know that there are other ways of doing this, including autoconf and other automatic solutions. However, I would like to understand what is happening and be able to write the makefiles from scratch despite its possible impracticality.
Any guidance or tips would be appreciated. Thanks!
[Edit]
So the three solutions given so far are as follows:
Place globally used header files in a parallel include directory
use the path in the #include satement as in #include "../src/foo.h"
use the -I switch to inform the compiler of include locations
So far I like the -I switch solution because it doesn't involve changing source code when directory structure changes.
For test_foo.c you simply need to tell the compiler where the header files can be found. E.g.
gcc -I../src -c test_foo.c
Then the compiler will also look into this directory to find the header files. In test_foo.c you write then:
#include "foo.h"
EDIT:
To link against foo.c, actually against foo.o, you need to mention it in the object file list. I assume you have already the object files, then do after that:
gcc test_foo.o ../src/foo.o -o test
I also rarely use the GNU autotools. Instead, I'll put a single hand-crafted makefile in the root directory.
To get all headers in the source directory, use something like this:
get_headers = $(wildcard $(1)/*.h)
headers := $(call get_headers,src)
Then, you can use the following to make the object-files in the test directory depend on these headers:
test/%.o : test/%.c $(headers)
gcc -std=c99 -pedantic -Wall -Wextra -Werror $(flags) -Isrc -g -c -o $# $<
As you can see, I'm no fan of built-in directives. Also note the -I switch.
Getting a list of object-files for a directory is slightly more complicated:
get_objects = $(patsubst %.c,%.o,$(wildcard $(1)/*.c))
test_objects = $(call get_objects,test)
The following rule would make the objects for your tests:
test : $(test_objects)
The test rule shouldn't just make the object files, but the executables. How to write the rule depends on the structure of your tests: Eg you could create an executable for each .c file or just a single one which tests all.
A common way of doing this is for header files used by a single C file to be named the same as that C file and in the same directory, and for header files used by many C files (especially those used by the whole project) to be in a directory include that is parallel to the C source directory.
Your test file should just include the header files directly using relative paths, like this:
#include "../src/foo.h"