I am writing a PHP extension. config.m4 generates the Makefile, but I want to include, at the begin of this Makefile another Makefile. (e.g.: "-include Makefile.local").
I don't want to do it in the Makefile itself, since configure will recreate it and erase my changes when invoked.
How can I do it from config.m4?
Try this in config.m4:
AC_CONFIG_COMMANDS_PRE([cat >Makefile.tmp <<EOF
-include MyInclude1
-include MyInclude2
EOF
cat Makefile >> Makefile.tmp
mv -f Makefile.tmp Makefile])
Your Makefile should now look like:
-include MyInclude1
-include MyInclude2
srcdir = /path/to/source/dir
...
...after running configure.
Related
I have a large project I'm working on, in which I want to perform include to some .mak file, but only after I make change to this file content via a command inside the original makefile. Since it's a large project it will be hard to write code, so I will give this ridiculous example instead:
I have some small C project that all it's C and header files are in the same directory, and I need to write a makefile. I'm not allowed to use clean rule in the makefile I write, but I have a file named file.mak that I can include in my makefile. Content of file.mak:
.PHONY: clean
cleam:
$(RM) $(objs) test
The problem here is that the rule is cleam and not clean. I'm also not allowed to change manually file.mak , but I'm allowed to do this with a command inside the original makefile. This can be done easily by:
sed -i 's/cleam/clean/g' file.mak
So I thought of writing the makefile like this:
CC = gcc
srcs = $(wildcard ./*.c)
objs = $(srcs:.c=.o)
test: $(objs) change_file include_file
$(CC) $^ -o $#
%.o: %.c
$(CC) -c $< -o $#
change_file:
$(shell sed -i 's/cleam/clean/g' file.mak)
include_file: change_file
include file.mak
But I get the following error:
include: Command not found
So I understand that there is a problem of using include inside a rule, so is there a way to achieve what I want?
(GNU) make has a feature Remaking Makefiles that can be used for scenarios like this, but your approach is wrong. include is a directive and can't be used in a recipe.
Instead, when you include a file, make first checks for rules creating this exact file and executes them. As in your case, the file you want to include already exists, you have to make this rule .PHONY to force its execution. It would look like this:
.PHONY: file.mak
file.mak:
sed -i 's/cleam/clean/g' file.mak
include file.mak
As a more robust alternative (without the need for a phony rule), consider creating a fixed version (copy) and include this:
file_fixed.mak: file.mak
sed -e 's/cleam/clean/g' <file.mak >file_fixed.mak
include file_fixed.mak
Hopefully this is a very simple question. I have a makefile pattern rule that looks like this:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
I want the makefile to build a number of .so files, so I tried to get it to build two files (radgrd_py.so and lodiso_py.so) by doing this:
radgrd_py.so lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
and then tried this:
radgrd_py.so:
lodiso_py.so:
%.so : %.f %.pyf
f2py -c -L${LAPACK_DIR} ${GRASPLIBS} -m $* $^ ${SOURCES} --opt='-02' --f77flags='-fcray-pointer' >> silent.txt
But in each case, it only builds the first target that I specify. If I run 'make radgrd_py.so' it works fine, I'm just not sure how to specify a list of files that need to be built so I can just run 'make'.
The usual trick is to add a 'dummy' target as the first that depends on all targets you want to build when running a plain make:
all: radgrd_py.so lodiso_py.so
It is a convention to call this target 'all' or 'default'. For extra correctness, let make know that this is not a real file by adding this line to your Makefile:
.PHONY: all
Best way is to add:
.PHONY: all
.DEFAULT: all
all: radgrd_py.so lodiso_py.so
Explanations:
make uses the first target appearing when no .DEFAULT is specified.
.PHONY informs make that the targets (a coma-separated list, in fact) don't create any file or folder.
all: as proposed by schot
My command get the dependencies of a file passed in parameter and now, I want use it like dependencies into Makefile. I do somethink like :
%.dep: %.txt
./mycommand filedepend ${<} > $#
#Tex compilation
$(OUTPUTDIRECTORY)/%.tex.json: %.txt %.dep $(eval $(shell cat %.dep))
./mycommand export --to="latex" --path="${<}" $<
rm $*.dep
It doesn't work, the result of the rule should be like :
$(OUTPUTDIRECTORY)/%.tex.json: %.txt %.dep foo.txt bar.txt
./mycommand export --to="latex" --path="${<}" $<
rm $*.dep
but for independant file (I want one rule for all files)
You could generate your dependency files in such a way they contain:
$(OUTPUTDIRECTORY)/%.tex.json: foo.txt bar.txt
instead of only
foo.txt bar.txt
and then include the dependency files with:
-include %.dep
The minus is for ignoring the initial include error when the dependency file not yet exists. You can try what happens when you omit it, it shall also work.
Complete example, not tested, maybe i'm missing something, but basically this should work:
-include %.dep
%.dep: %.txt
./mycommand filedepend ${<} > $# # <-- this must generate the dep file in the correct format
#Tex compilation
$(OUTPUTDIRECTORY)/%.tex.json: %.txt %.dep
./mycommand export --to="latex" --path="${<}" $<
rm $*.dep
This is a good source explaining auto dependency generation using gcc, just replace gcc by your custom dependency generator: http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
I would like to change the working directory of a makefile.
(Extraneous info: I have a legacy makefile that I mostly want to reuse, though many targets and generated deps files make assume that the working directory will not be different. My idea is to create a makefile for my newer project, which is in a different directory, and include the old one, and set the working directory to the old directory.)
I easily can do this from the command line with
make -f /path/to/new/makefile -C /path/to/old/makefile
The users of this makefile would like not to type that out every time.
Attempt 1
Use MAKEFLAGS in the makefile itself. But neither of these seem to have any effect. (I understand why -f couldn't have an effect; I'm really wondering about -C.)
I've looked at http://www.gnu.org/software/make/manual/html_node/Options-Summary.html, but I can't find anything about what is allowed in MAKEFLAGS and what isn't.
Attempt 2
Create a makefile2 with the new targets
include path/to/old/makefile
foo: bar
and then makefile passes everything through
%:
$(MAKE) -f $(abspath makefile2) -C path/to/old/makfele /$*
I don't get nice autocompletion, parallel jobs don't work, and debug options (dry run) doesn't work.
So
(1) Why doesn't -C work MAKEFLAGS (it does work, but I made a mistake; it doesn't work, and it is documented; it doesn't work, and it is not documented but it is intentional; it doesn't work, and it is a bug)?
(2) Is there a better way of change a makefile's working directory?
Some things are wrong here :
make -f /path/to/new/makefile -C /path/to/old/makefile
The -f options specifies the name of the Makefile to be found when searched in the directory specified with -C (or the current directory if not provided). So it is more :
make -C /path/to/old/Makefile -f name_of_old_makefile
If the name is simply Makefile or makefile, there is no need to provide the -foption.
The MAKEFLAGS variable does not contains -f or -C in the called sub-Makefile.
To be able to pass multiple targets to another makefile, you need the MAKECMDGOALS variable.
Ultimately, all you have to do in your new Makefile is to have someting like this :
all:
$(MAKE) $(MAKEFLAGS) -C /path/to/old/Makefile -f old_Makefile_name $#
%:
$(MAKE) $(MAKEFLAGS) -C /path/to/old/Makefile -f old_Makefile_name $(MAKECMDGOALS)
The project I work on is organised in one folder with a root Makefile, and a lot of sub-project each one being a subfolder containing its own makefile.
The root Makefile invokes make into each subdirectory (make -C command). Object files are generated at the same level as the source files.
I would like to order the root make command to redirect object file generation(and retrieving) into a specified build_dir. Is there a simple way of doing this ? (Instead of modifiying every Makefiles in every sub-project).
It's kind of a hack, but you can do this with a combination of a compiler wrapper and vpath.
Suppose we have foo.c:
#include <stdio.h>
int main() {
printf("hi there\n");
return 0;
}
and bar.c:
int bar() {
return 1;
}
Putting vpath %.o obj inside the Makefile will tell make to look inside the obj/ directory for object files. But we need to tell the compiler to write object files into the obj/ directory. gcc has no such option—but we don’t have to use gcc, we can write our own compiler wrapper that calls gcc with a modified command line.
cc-wrapper:
#!/bin/bash
OUTDIR=obj
#
function push() {
# usage: push ARRAYNAME ARG
# adds ARG to the end of ARRAY
eval $1[\${#$1[#]}]="\$2"
}
ARGS=()
change_dir=false
mkdir -p "${OUTDIR}"
for (( i = 1; i <= $#; i++)); do
eval arg="\${$i}"
if $change_dir; then
arg="${OUTDIR}/${arg}"
change_dir=false
fi
if [ -e "${OUTDIR}/${arg}" ]; then
arg="${OUTDIR}/${arg}"
fi
if [ "${arg}" = "-o" ]; then
change_dir=true
fi
push ARGS "${arg}"
done
echo gcc "${ARGS[#]}"
exec gcc "${ARGS[#]}"
It’s an ugly shell script, but all it's doing is modifying some arguments:
if the previous argument was -o, add obj/ to the start of this one
if the current argument is a file in obj/, add obj/ to the start
and then calling gcc.
Then the Makefile is:
CC=./cc-wrapper
vpath foo obj
vpath %.o obj
foo: foo.o bar.o
clean::
rm -rf foo.o bar.o foo obj
Now, all your objects go in obj/ and make tracks dependencies correctly.
It'll take some tuning to make this ready for production—you'll probably want to rewrite the script in a comprehensible language like Python—but this should help you get started.
No solution that would prevent you from modifying every Makefile.
Makefiles and make are no magic. The Makefile contains the command line that is used to compile each source file. Therefore, to be able to generate all the object files in a specified directory, you'd have to modify every Makefile to change this command line adding options telling where to place the object files.
Do you mean something like a fallback target akin to
%:
make -C $(dir $#) $(notdir $#)
so that you can
make somedir/sometarget
?