How to tell GNU MAKE to treat .po files like .h files? - c

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)

Related

Compile each file from file list in Make

The problem is the following. I have a list of .c files in several directories that I wish to compile, one by one, into a .o file, located at BUILD_DIR folder, to be later linked. They are appended to the SOURCE_FILES_FREERTOS variable. The Makefile code section that attempts to perform this is:
OBJ_FILES_FREERTOS = $(SOURCE_FILES_FREERTOS:%.c=$(BUILD_DIR)/%.o)
# Build the Operating System Library
freertos: ${OBJ_FILES_FREERTOS}
${BUILD_DIR}/%.o : $(dir ${SOURCE_FILES_FREERTOS})/%.c
-mkdir -p ${BUILD_DIR}
$(CC) $(CFLAGS) ${INCLUDE_DIRS} -MMD -c $< -o $#
However, it does not work, saying there is no rule fore the first target file:
make: *** No rule to make target 'build/../../../FreeRTOS/Source/stream_buffer.o', needed by 'freertos'. Stop.
What seems to be the problem?
From a top-down perspective we first declare the objects to be part of the library:
OBJECT_FILES_FREERTOS := $(patsubst ...)
libfreertos.a: $(OBJECT_FILES_FREERTOS)
I cannot create OBJECT_FILES_FREERTOS from the variables in the question. You'd have to add more to it or figure it out yourself. Below I assume that all object files have $(BUILD_DIR)/-prefix and the same directory structure as the source it is derived from (which is a pain since Make does not create necessary directory hierarchy for you, but that's just how Make rolls).
Make now tries build object files from source files. By default searching for source files in the same directory as where the object files are expected to be. This is where it becomes tricky, since the source files (from looking at your error) is not in the source tree, making a relative path to god knows where. You need a different source-to-object map, here using static rules:
$(OBJECT_FILES_FREERTOS): $(BUILD_DIR)/%.o: $(FREERTOS_SRC_DIR)/%.c
No rule to make target means it cannot find a rule to build the file, most often because the source file is missing and Make does not know how to build it from nothing.
freertos has a dependency on build/../../../FreeRTOS/Source/stream_buffer.o but you don't have any rules that cover that file. This is your root cause for the build failure.
The pattern rule suggest you are putting the object files in $(BUILD_DIR) and not 3 levels up from it. This means that the pattern rule doesn't apply in this case.

How do you indicate relative (or absolute) path for pattern rule in makefile? and How do you detect included headers from a source file?

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.

make file multiple executables

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.

Makefile to move .o files to Different Directory

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.

Updating source files to different folder using makefile in Linux

I have a Linux GNU C project that requires building output for two different hardware devices, using a common C source code base, but different makefiles. Presently I have two makefiles in the same folder, one for each device, and when I make a change to the code, I have to first do "make clean" to make the first model, then "make clean" to make the second model. This is because they use different compilers and processors. Even if a code file didn't change, I have to recompile it for the other device.
What I would like to do is use a different folder for the second model, so it stores a separate copy of *.d and *.o files. I would not have to "make clean", only recompile the changed sources. I have looked at makefile syntax, and being new to Linux, can only scratch my head at the cryptic nature of this stuff.
One method I'm considering would update the .c & .h files from model_1 folder into model_2 folder. Can someone provide me with a simple makefile that will copy only newer *.c and *.h files from one folder to another?
Alternatively, there must be a way to have a common source folder, and separate output folders, so duplicated source files are not required. Any help to achieve that is appreciated. I can provide the makefiles if you want to look at them.
You want to generated files (object and dependencies) put into a separate folder for each build type as it compiles. Here's what I had do that may work for you:
$(PRODUCT1_OBJDIR)/%.o $(PRODUCT1_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT1_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT1_OBJDIR)/$*.o
$(PRODUCT2_OBJDIR)/%.o $(PRODUCT2_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT2_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT2_OBJDIR)/$*.o
$PRODUCT1_OBJDIR and $PRODUCT2_OBJDIR are variables names for the directory where you wish to have the generated files stored. This will check for changes to dependencies and recompile if needed.
If you still have problems, get back with feedback, will try and sort you out.
You could compile your source files to object files in different directories ("folder" is not really the appropriate word on Unix). You just have to set appropriate make rules. And you might use other builders like omake, scons, ...
You could use remake to debug your GNU Makefile-s. You could have inside a rule like
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -c $^ -o $#
And you could set (earlier in your Makefile) variables with e.g.
OBJDIR:=obj-$(shell uname -m)
or something better
I do suggest to read GNU make's manual; it has an introduction to makefiles.
This can be easily achieved with makepp's repository mechanism. If you call makepp -R../src ARCH=whatever then it will symbolically link all parts of ../src under the current directory and compile here.
You can even create a file .makepprc and put in any options specific to this architecture, so you'll never get confused which command to call where.
If your different architectures have identically produced files (like generated sources), you can even build in ../src and the other architecture will pick up everything that doesn't depend on your current compile options.
There is much more to makepp. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.

Resources