Make and VPATH. Why are my source files being placed where I don't want them? - makefile

I am trying to compile with make. I have source in two directories, src and altsrc. I want make to look in altsrc for source files first, and then in src. I want the objects to go into directory obs. The relevant parts of my Makefile looks like:
VPATH=altsrc:src:obj
$(A_OUT): $(OBS)
$(FORTRAN) -o $(A_OUT) $(OBS) $(LFLAGS)
obs/%.o: %.f
$(FORTRAN) $(FFLAGS) $< -o $#
This Makefile actually compiles the code OK, but it has one really obnoxious side effect: It finds each source file (and there are alot) and copies them out of altsrc or src into the directory where I am running make. This is really annoying and leads to a bunch of confusion later on. I haven't found any documentation anywhere that says this should be an effect of the VPATH macro. Can anyone tell me how to solve this? Thanks.

The trouble is that Make is RCS-savvy, and will check to see if a source file (e.g. td.f) can and should be updated from RCS. Yes, Make knows how to use co. If the source file isn't in such an archive (such as the source files in altsrc), then Make shrugs and gets on with the work.
The quickest, dirtiest solution is to use make -r. This will disable the built-in rules, which should solve the problem nicely... unless you rely on the built-in rules elsewhere.
If that won't do, you can override that particular rule with a do-nothing rule of your own, or with a rule that actually updates the sources in place, or you can touch the sources so that Make won't consider them out of date, or put the RCS files someplace where Make can't see them, or maybe two or three other options.

Related

How to trigger the rebuild of a Makefile prerequisite file ONLY when a specific target is called?

I haven't found an answer so far, so I think this is not a repeat question.
I have some Makefile along the lines of:
include prerequisite_2
all: prerequisite_1 prerequisite_2
clean:
rm *.mod
prerequisite_1:
mkdir somedir
prerequisite_2:
re-write existing file
The issue is that I want the prerequisite_2 to rebuild whenever the default goal is called (all) or when prerequisite_2 is called from the command line, and I know I can use touch prerequisite_2, FORCE or .PHONY to achieve this. However, I DO NOT want it to run every time (the written file contains dependency information for the Fortran files involved) as it doesn't make sense to also rebuild this when calling: make clean
Is it possible to emulate the effects of FORCE or .PHONY only when the depending targets are called?
You can see what the goal targets are by looking at the MAKECMDGOALS variable.
So you can do something like:
ifeq (,$(if $(MAKECMDGOALS),$(filter-out all prerequisite-2,$(MAKECMDGOALS))))
include prerequisite-2
endif
The if condition will be true if MAKECMDGOALS is the empty string, or if it contains only all and/or prerequisite-2 but not if it contains any other target.
Usually, this is not what you want though. Usually you want to disable the include only if certain targets (clean is the classic example) are used.
This exact situation is even discussed in the GNU make manual.

Makefile pattern rules not working

I am learning makefiles, and can't just wrap my head around this problem i am having, and would like to understand how/why this fail.
I have half a dozen erlang files in a src directory. I want to compile these into a ebin directory, without having to define a rule for each and every one of them. According to the Gnu make documentation, pattern rules should be right up my alley.
However, with the following makefile, all I get from make is make: *** No targets. Stop. Why is that?
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
Edit: Based on this answer, I now understand that i would have to explicitly declare the targets, for instance by using make ebin/cmplx.beam. However, i still do not understand how i should write my makefile to get my desired behaviour - since I have half a dozen targets (and in other projects even more), this seems like an unnecessary hassle. Is there not a way to define targets based on the source file names?
The target rule tells make that whenever it needs to produce a beam file in the ebin directory, and there exists a corresponding erl file in the src directory, it can use erlc.
However, this doesn't tell make that this is what it needs to do. You could explicitly tell make what it needs to do by giving it a target on the command line:
make ebin/foo.beam
If you don't give a target on the command line, make will pick the first non-pattern rule in the makefile as its target. However, your makefile doesn't have any non-pattern rules, so there is no target.
What you probably want is that for each existing erl file in src, make should consider the corresponding beam file in ebin to be a target. You can achieve that by calling wildcard and patsubst:
erl_files=$(wildcard src/*.erl)
beam_files=$(patsubst src/%.erl,ebin/%.beam,$(erl_files))
ebin/%.beam: src/%.erl
mkdir -p ebin
erlc -o ebin $<
all: $(beam_files)
(The indented lines need to be actual physical tabs, not spaces.)
That way, running make will rebuild all beam files that are out of date. all gets chosen as the default target, and it in turn depends on all beam existing or potential, each of which in turn depends on the corresponding erl file.
This trick is described in the GNU make manual.

GNU make with VPATH: target which appears circular, but really shouldn't be

I have a rule in my Makefile which is intended to create a symlink to a file in a different directory:
VPATH = ../source
foo: foo
ln -s $< $#
Even though I intend for the target to resolve to ./foo and the dependency to resolve to ../source/foo, I understand why make sees it as circular. Is there a way to express this rule in a way that is not circular?
Note that the link does not depend on the changes of the link target; it only needs to exist. Therefore, there is no ordinary prerequisite needed at all, and the simplest fragment to do what you want would be
foo:
ln -sf ../source/$#
However, this won't work correctly if you still need your VPATH for other purposes. If that is so, then it seems to me the simplest way would be to ignore VPATH for this rule by using absolute path:
VPATH := ../source
$(CURDIR)/foo:
ln -sf ../source/$(#F)
Finally, if the file ../source/foo is also a target which is generated by Make, then maybe the best way would be:
VPATH := ../source
.SECONDEXPANSION:
$(CURDIR)/foo: | ../source/$$(#F)
ln -sf $|
Note that we are not depending on the changes of the prerequisite here, only on the existence of it.
By the way, the reason why I am using -f option is because, Make should support -B option. That option will not work unless you use -f here.
I think what you're trying here falls under the category of "VPATH abuse".
My experience is repeatedly pointing me toward the mantra "explicit is better than implicit" and this is one of the reasons why. Contrary to the assertions in the GNU make Manual, my experience has led me to believe that in larger, more complex projects, you need to be more explicity, not less, because the size makes it more difficult to locate files, unless their path is explicit.
I also believe that a lot of the need to use VPATH stems from the use of recursive make, where you're not building complete dependency trees; write your build system properly and you just don't need VPATH at all.
On a related subject, I'm a firm believer in only specifying one or two -I directories: your top-level src/ and include/ directories and make all inclussions relative to these paths. Again, on larger, more complex projects, seing #include "my/really/cool/thing.h" is soooo much informative than simply #include "thing.h".
That said, I am open to the idea of using VPATH for libraries, especially system libraries, because you can use the -lfoo syntax, but I wouldn't want to use it as a general rule, because it could threaten build reproducibility.

How to write rule to build object file when C files have different paths

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.

moving from make to cmake: how to use build target with wildcards

I'm trying to convert an makefile-build to cmake (to avoid the current state of being forced to take care for the windows-build env based on make/msdev and the linux based on make/gcc).
In this project, I've found a directory full of sourcecode files that get, based on a naming convention, compiled to libraries. (e.g. c1223.c => c1223.dll (or .sl) )
The current makefile consists of some directives using wildcards, e.g.:
LIB_NO = $(basename $(subst s,,$#))
OBJ = $(OBJ_PATH)/s$(LIB_NO).o $(OBJ_PATH)/c$(LIB_NO).o\
$(OBJ_PATH)/b$(LIB_NO).o
$(OBJ_PATH)/%.o : %.c
-$(CC) $(CFLAGS) -I$(PWD) -c $< -o $#
-(chmod a+w $#;true)
I've searched for a while but can't find anything that seems to work. Is it even possible with cmake to let it generate a wildcard based build?
Any comments, hints and suggestions are very welcome :)
cheers
Markus
You can use fairly primitive globbing (there's no regular expression syntax that I can see).
file(GLOB TESTSRCS "test/src/*.cpp")
# Compile the test sources.
add_executable(Tests ${TESTSRCS})
target_link_libraries(Tests ${LIB} gtest gtest_main)
The actual makefiles do not seem to contain wildcard searches inside them. If you add new files you will need to re-run cmake.
What I don't know is how you would manage to wrap up the library creation in a single macro if you have many different library files to generate.
You might be able to do something like this if there's only one c file per library:
file(GLOB libfiles "path/to/libs/c*.c")
foreach(libfile ${libfiles})
GET_FILENAME_COMPONENT(libname ${libfile} NAME) # remove the '.c' part (untested, hopefully this will work)
add_library(${libname} ${libfile})
endforeach(libfile)
If anybody else has a better solution, I would also like to learn it.
CMake does not generate makefiles that have wildcard-based rules in them. It generates specific rules for the files that it knows about.
In your example, you are explicitly listing the .o files that comprise your library. In CMake, you would instead explicitly list the source files that contribute to your library, and then let CMake take care of the rest.
Do you need makefiles that have wildcard-based rules in them for some reason?
Couldn't you simply construct a list of the source files, and then, for each element in the list, do an "add_library" call with the source file and a library name constructed from the source file name?

Resources