Thanks a lot for the comments. In this case actually VPATH is not used.
I write some makefiles to recursively build my project.
Part of the makefile in the root directory looks like this,
VPATH += $(shell find -type d)
export VPATH
#Codes to generate $(ARXIVS), i.e. the list of all local archives,
#is omitted here to save spaces
all : main.o $(ARXIVS)
$(ARXIVS) :
$(MAKE) --directory $(#D)
.PHONY : $(ARXIVS) all
As you can see, I pass the variable VPATH to sub-makes, in order to save some computational cost. And the whole system works.
But the searching paths in a sub-directory is different from the ones in the root directory.
I have print the values of VAPTH in sub-makes, the paths are indeed the ones with respect to the root directory. So VPATH in the sub-makes should be wrong.
But the whole system works. How did this happen?Any one give the suggestion to me. Thanks in advance
Related
I'm trying to make a rule that will generate files regarding their names but regardless of the directory.
I'm starting from this makefile (see a previous question of mine):
TARGETS:=$(patsubst %_tpl,%,$(wildcard *_tpl))
.PHONY: all
all: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): %: $$(wildcard %*_tpl)
./generate $#_tpl > $#
With this, I can do, for instance, make foo.xml. It looks if a set of foo.xml*_tpl files are there, consider them as prerequisites and call the generate script to generate the target.
What I would like to do is, for example, make ../ressources/foo.xml and have make use the rule to create foo.xml but creating it in the ../ressources/ directory, without having to explicitely specify this directory in the makefile.
What I have tried for the moment is adding this to the Makefile:
../ressources/%: $(notdir %)
mv $< $#
Which works, but I would like to avoid creating the file in the current directory before moving it to the destination folder. I would also like not having to specify the possible destination folders in the makefile (but this is less important).
But first of all, does this make any sense? Or is what I want to do just conceptually wrong?
EDIT: Some precisions regarding the _tpl files and the generate script to avoid confusions:
Each target has a main template ($#_tpl) that includes others ($#-part1_tpl, $#-part2_tpl...) and the generate script only takes the main template as argument. The templates are written with Jinja2 (the subparts included with the {% include %} jinja directive).
If you always want the targets in another directory, just say so.
TARGETS:=$(patsubst %_tpl,../resources/%,$(wildcard *_tpl))
.PHONY: all
all: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): ../resources/%: $$(wildcard %*_tpl)
./generate $#_tpl > $#
I'm not sure if you should have generate $^ >$# instead; superficially, this would make more sense.
If there are multiple *_tpl files for each target (i.e. there are more tpl files than xml files), the TARGETS definition isn't really correct; but we don't have enough information to actually fix it.
On the other hand, if the target directory can change a lot, the sane way forward might be to cd into the target directory and use make -f ../path/to/Makefile -- just make sure your VPATH is set up so that the source files can be found.
I have bunch of C files, each with differnt path, so I have something like
SRC=/path1/path2/file1.c file2.c /usr/joe/files/file3.c
I want to build object file from each C file in build directory, so I did:
SRCBASE=$(notdir $(SRC))
OBJS= $(addprefix $(OBJDIR)/,$(SRCBASE:.c=.o))
This works fine, and I got the OBJS is build/file1.o build/file2.o build/file3.o
My question is how to write the implicit rule to build the object file, I tried to do:
build/%.o : %.c
gcc ....
But that seems now to work, since this rule did not catch the files with the full path.
I've tried to look at the gnu make, but did not find the answer there.
Many thanks.
You can use VPATH to locate files in other directories. Note that this does implicit searches, though, rather than using explicit paths. That is, you specify that you need file1.o through file3.o and that make should look first in ., then in /path1/path2, then in /usr/joe/files; so if . contains a file3.c you will get that one rather than the one in /usr/joe/files (or if not, but if there is one in /path1/path2, you will get that one).
It turns out that path searching is more often useful than explicit location anyway, so usually that's what you want. If you need to override something you just copy or symlink the "desired version" to the first place to be searched.
I have a variable with a list of prerequisites in varying directories, each specified by a relative path. For example:
HTML_FILES := ../foo1/bar1.html ../foo1/bar2.html ../foo2/bar3.html foo3/bar4.html
(Note that this variable is actually generated, so the full list of folders isn't known in advance.)
For each of these, I want to generate a target file in the current directory, e.g. bar1.xml, bar2.xml, bar3.xml, bar4.xml.
How can I write a rule which will match for this? This is as close as I've come. It seems like something magic in the place of ?????? might do the trick.
build: $(XML_FILES)
$(XML_FILES): %.xml : ??????/%.html
perl $(HTML_TO_XML) $<
Use vpath.
vpath %.html $(dir $(HTML_FILES))
Now one can use simple pattern rule as follows:
$(XML_FILES): %.xml : %.html
perl $(HTML_TO_XML) $<
This should be enough to get things work, but I'm not sure how it would behave if there are some files with the same name in different directories, like ../foo1/bar.html and ../foo2/bar.html.
I have a situation where I need to compile some source files from a library into my own program. The directories the source files are in are not writeable by me. Instead I have a local "build" directory where all the work is done.
The problem I am having the the translation of the paths. The source files are named, say xxxx.cpp and yyyy.cpp, and they are in /path/to/source/xxxx/xxxx.cpp and /path/to/source/yyyy/yyyy.cpp.
Using $(patsubst ...) I can happily convert those paths to build/xxxx/xxxx.cpp etc, but I can't get it to strip the first xxxx off.
I could do with crafting a target that would match something like this:
build/%.o: /path/to/source/%/%.cpp
$(CXX) ...
...but I can't get that to work at all. I guess it doesn't like the double wildcard in the latter part of the target.
The "source" for the names is a single variable with just the "xxxx" and "yyyy" in:
SYS_LIBS = xxxx yyyy
Any suggestions on how to get something like this to work?
Oh, I need it to be a "generic" solution - this will be an included makefile in many projects that use this library of files, so hand-crafting a target per file is not an option. I cannot predict what files will be in the library.
One easy way is to use vpath to let make find the files itself. You just define
vpath %.cpp /path/to/source
vpath %.cpp /path/to/source2
vpath %.cpp /path/to/source3
build/%.o : %.cpp
$(CXX)
You can define more than one path to source that way, but be careful if you have the same file in more than one folder (e.g. a.cpp in both path_to_source1 and path_to_source2)
Personally I'd use vpath, as Bruce suggests. If there are many directories under /path/to/source/ you can use
SRCS = $(wildcard /path/to/source/*)
vpath %.cpp $(SRCS)
(This works as long as the directories go only one level down from there. If there are things like /path/to/source/foo/bar/zzzz/zzzz.cpp, then you'll have to fall back on something like find.)
If you really want to do path translation, this will do it:
X := $(patsubst %.cpp,build/%.o,$(notdir $(X)))
Or (I don't know why you'd want to do it this way, but you could):
X := $(shell echo $(X) | sed 's|.*/\(.*\)\.cpp|build/\1\.o|')
I'm looking to modify a makefile to include a local directory of headers. However, most of the makefile compilation happens outside my current makefile limiting what I can do. Here's the current makefile:
TARGET = final
LIBS = -lsimple -lcheck -lsuif -luseful
OBJS = doproc.o main.o
all: $(TARGET)
install-bin: install-prog
include $(SUIFHOME)/Makefile.std
The directory of headers (boost) I wish to use of is in the same directory as this makefile and doproc.cc/main.cc. I tried modifying the makefile to this
TARGET = final
INC= -I/boost
LIBS = -lsimple -lcheck -lsuif -luseful
OBJS = doproc.o main.o
all: $(TARGET) $(INC)
install-bin: install-prog
include $(SUIFHOME)/Makefile.std
but to no effect. I have an account on this machine but no root access and I can't change Makefile.std. If this is trivial, I apologize. I'm not used to using makefiles.
Thanks in advance
EDIT:
The suggestions so far are helpful for getting me the right directory. But It's still not making the directory be included in the compilation
Okay, it's really hard to discern all details without knowing the internals of Makefile.std. However, let's assume that $(INC) is not somehow magically consumed inside Makefile.std (it's at least not one of the default macros, see make -p for those), in this case you would have to append your include folders to CXXFLAGS (for C++) or CFLAGS (for C) like so:
CXXFLAGS+=$(CXXFLAGS) -I$(MAKEDIR)/boost
Side-note: There are variations on this, but from where I stand
all: $(TARGET) $(INC)
doesn't make too much sense for a value of -I/boost or even the corrected -I$(MAKEDIR)/boost. The reason is that it is no variable assignment (which is possible instead of dependencies) and thus would be considered as a file dependency (unless declared .PHONY).
I should add that I'm assuming the usual default rules that come with GNU make. Otherwise you'd have to show us the actual rules %.o: %.cpp etc ...
Use this - Your current INC specifies /boost not ./boost:
INC= -I$(PWD)/boost
/ is filesystem root; ./ is current directory.
Did you mean -I./boost? -Iboost works too.
Remove the leading / in front of boost. You're telling the compiler to look in /boost under the root folder.