Filepath as Makefile target - makefile

I'm trying to write a Makefile. I have two targets in the Makefile.
$(var1)_target : a.txt b.txt
<recipes>
$(var2) : c.txt d.txt
<recipes>
Here var1 and var2 both are file paths of the form (./dir1/dir2/file)
When I'm trying to run this, although the first target gets created/updated as expected, the second target doesn't gets created.
But if I add "_target" to the second target as well, it functions as expected (i.e. file2 gets created)
I've been scratching my head around this, but I'm unable to understand this behavior.
It'll be helpful if someone takes this up and help me in understanding what's actually happening here.
Thanks in advance.

Related

Makefile:1: *** missing separator. Stop error when using Make with a config file with no tabs or spaces

I have seen this question and has read its many answers. I understand that this problem usually (always??) appears because of a mistake in using tabs vs spaces in Makefiles. So far that is the general case.
In my case, I have found the error in the title but not when doing make with a Makefile I suspect.
I do:
make a_configuration_file
and I get
Makefile:1: *** missing separator. Stop.
I suppose this "1" means that the error is occurring in the first line of the file, right?
This a_configuration_file is actually a generated file and the first lines are copied here :
#
# Automatically generated file; DO NOT EDIT.
# Ambarella SDK Configuration
#
CONFIG_THREADX=y
CONFIG_BOOT_CORE_SRTOS=0
So my questions for my particular case are:
The "1" refers to the comment line "#"? or the CONFIG_THREADX line?
This configuration file is not using Tabs. So what could be the problem?
EDIT:
Robert tells me that the problem could be the end-of-line. I checked with cat -A a_configuration_file and it seems there are no \r characters (I ve had problems with this before so I learned how to check for end-of-line chars)
Wander Nauta tells me the problem is in the Makefile. Which Makefile should I check? Right now there is a Makefile in the directory from where I call make and it is like this
build/Makefile
no tabs or spaces
I also did cat -A Makefile and I got
build/Makefileroot#themachine.....
If you are wondering what is that, is just that it seems that the Makefile does not have an end of the line at the end, so the cat command prints the contents and the rest (root#themachine...) is just the normal line in the command line
EDIT2:
I think I am close to finding the error.
Originally the "Makefile" was a link as in
ls ./ -l
lrwxrwxrwx 1 1133 543 13 Mar 18 Makefile -> build/Makefile
However now it is just a plain text file
ls ./ -l
-rw------- 1 11250 10513 14 Jul 6 Makefile
Somehow in the linux-windows-linux transference the link condition got lost
In my case, I have found the error in the title but not when doing make with a Makefile I suspect.
The error in the title specifies the name of the file in which the error is encountered: Makefile. Thus, your suspicion about "not when doing so with a Makefile" is unfounded. Although it is possible to run make without a makefile, and doing so can even be advantageous, make will always read a makefile if it can find one by one of the default names it looks for.
Moreover, though it may not be obvious in this case, the name given in the message is not just a base name but a (relative) path to the file. It is therefore complaining about a file named Makefile in make's working directory.
Right now there is a Makefile in the directory from where I call make
and it is like this
build/Makefile
no tabs or spaces I also did cat -A Makefile and I got
build/Makefileroot#themachine.....
Those two claims do not appear to be consistent with each other. In any case, however, neither one attributes valid makefile content to the makefile in question. This is likely the cause of the error message, which would then be a bit misleading.
It looks like you may be trying to have one makefile specify that another make be run in the build/ directory -- a so-called "recursive make". There are a couple of variations on how that is done, and they differ slightly in effect, but here's a guess at what you might be after for that top-level Makefile:
all:
$(MAKE) -C build
Of course, that second line needs to be indented with a leading tab, not spaces.
That will cause the top-level make run to trigger a second make run with the build/ directory as the second's working directory.

Makefile: change in dependencies fail to trigger rebuild

I have a Makefile target that depends on a dynamic list of source files. This list is parsed on make invocations so it could potentially change. It looks like this:
target: $(shell cat foo.txt)
#echo "build target"
foo.txt changes from time to time. What I'm seeing is that target will be rebuilt the first time foo.txt changes content to X. Say that foo.txt changes content to Y then changes back to X then target won't be built. I know I can include foo.txt as a dependency itself but for reasons difficult to explain that's not an option.
As a more concrete example, foo.txt looks like this:
google.golang.org/grpc#v1.29.0/dialoptions.go
but could change to something like:
google.golang.org/grpc#v1.28.0/dialoptions.go
What's going on? Is Makefile caching something?
EDIT
I guess Makefile is caching the timestamp of the dependencies and thus if the dependency files didn't change at all then the target won't be rebuilt? Is there a way to fix this?
Make caches nothing. It has no preserved data whatsoever about any previous build. Make uses the filesystem as its "cache".
Because you're using $(shell cat foo.txt), make knows absolutely nothing about the file foo.txt. All it knows about is the set of files inside the foo.txt files. It treats all of those as prerequisites.
Then it merely compares the time last modified of the target file (target) with the time last modified of the prerequisite file that is contained in foo.txt.
So if foo.txt contains google.golang.org/grpc#v1.29.0/dialoptions.go then it's as if your makefile was written to be:
target: google.golang.org/grpc#v1.29.0/dialoptions.go
and if the time last modified of target is older than google.golang.org/grpc#v1.29.0/dialoptions.go (use ls -l to see these values) then make decides target is out of date and must be rebuilt. If it's newer, then make decides target is up to date and doesn't have to be rebuilt.
If you change the contents of foo.txt to be google.golang.org/grpc#v1.28.0/dialoptions.go then it compares the time last modified between target and google.golang.org/grpc#v1.28.0/dialoptions.go, the same way.
That's all make does, at its root.
I don't really understand your requirements so I can't give any suggestions for solutions. If you need to have target rebuilt if either the contents of foo.txt changes or the modification time on the prerequisite listed in foo.txt changes, then the only way to do that is list foo.txt as a prerequisite so make can detect when it was changed. You say you can't do that so... I don't have any good solutions for you.

How to create a makefile to call a buildscript?

Hi I have a build script called "buildMyJava" that builds a bunch of Java source code. Assuming those source code are in differnet directories such as "folder1" and "folder2", the output goes to some folder called "classes". How do I create a makefile so it KNOWS to build only when the source code meaning the *.java in those two directories have changed as well as the output classes is missing?
I have something like the following but it ALWAYS builds, dependencies are not working.
all: task
task: folder1/*.java folder2/*.java classes/
buildMyJava
First of all, the build script produces the .java files, thus the .java files should be targets, not prerequisites. So you should have something like this:
folder1/%.java folder2/%.java:
buildMyJava
The only problem with this is that if you do a make -j2, buildMyJava will run multiple times (once for folder1, and once for folder2). In fact, this is a limitation to makefiles -- you cannot have multiple targets invoke the same recipe only once. There is a good discussion on this here: http://www.cmcrossroads.com/article/rules-multiple-outputs-gnu-make
Notice though that a 'pattern' target counts as a single target though -- which means, if you can get a pattern to match all targets, you can invoke the recipe only once. A small caveat to that -- the % symbol cannot represent /'s. Thus you cannot do folder%.java, as that would not match folder1/file1.java... If you can split your script to output only to one directory at a time though, you may be able to do the following:
folder1/%.java:
buildMyJava folder1
folder2/%.java:
buildMyJava folder2
John

what is the correct way of using `include` to avoid recursive makefile?

I am not sure if i understand include statement in makefile well enough. I have recently started to use makefile for making my analysis reproducible, and thought i was in the right track until the complexity grew, and seems like include statement is the answer as I am also trying to avoid recursive makefile problem while trying to keep my makefile sane.
To test what include did i ran a dumb test basically created the following.
test_folder-|-makefile
|-test_folder2-|
|-test2.mk
In the makefile i added include test_folder2/test2.mk, which according to my understanding would add the code from the test2.mk, so when i run make, it will also run target:dependencies listed in test2.mk, but it only ran the target:dependencies from makefile.
It would be great if someone can explain or point me to another blog/stack answer that might explain the right way to avoid recursive makefiles by using include statement.
PS: My analysis mostly includes python and R scripts and some command line tools.
makefile
test.txt:
echo "test.txt" > test.txt
include test_folder2/test2.mk
test2.mk
test_folder2/test1.txt:
echo "this is a test" > test1.txt
First, there is no directory called test1, so I will modify the makefiles accordingly.
Second, notice that the test_folder2/test1.txt rule builds test1.txt locally, despite its name. there is more than one way to so what I think you want; one way is to modify test_folder2/test2.mk:
test_folder2/test1.txt:
echo "this is a test" > test_folder2/test1.txt
In order to execute this rule by running make in test_folder/, you must modify makefile.
To execute only the test_folder2/test1.txt rule, do this:
test_folder2/test1.txt:
test.txt:
echo "test.txt" > test.txt
include test_folder2/test2.mk
To execute both rules, do this:
all: test.txt test_folder2/test1.txt
test.txt:
echo "test.txt" > test.txt
include test_folder2/test2.mk
(Note that "all" is the conventional name for a phony target that comes first in the makefile -- and is therefore the default -- and requires other rules to be executed. You can use another name if you like.)
To execute test_folder2/test1.txt dirst, then test.txt, do this:
test.txt: test_folder2/test1.txt
echo "test.txt" > test.txt
include test_folder2/test2.mk
(It is possible to execute them in the opposite order, but it gets ugly.)
Further refinements are possible, but this is a start.

Makefile: how to find out dependencies are no longer used in other rules

I have a somewhat complicated Makefile which runs perl scripts and other tools and generates some 1000 files. I would like to edit/modify some of those generated files after all files are generated. So I thought I can simply add a new rule to do so like this:
(phony new rule): $LIST_OF_FILES_TO_EDIT
file_modifier ...
however, the point here is some of those generated files which I'd like to edit ($LIST_OF_FILES_TO_EDIT) are used in the same make process to generate a long list of files. So I have to wait to make sure those files are no longer needed in the make process before I can go ahead and edit them. But I don't know how to do that. Not to mention that it is really hard to find out what files are generated by the help of $LIST_OF_FILES_TO_EDIT.
If it was possible to mention in the Makefile that this rule should be only run as the last rule, then my problem would be solved. but as far as I know this is not possible. So anyone has an idea?
Some points:
List of files to edit ($LIST_OF_FILES_TO_EDIT) is determined dynamically (not known before make process)
I am not sure I have picked a good title for this question. :)
1) If you're going to modify the files like that, it might behoove you to give the targets different names, like foo_unmodified and foo_modified, so that the Make's dependency handling will take care of this.
2) If your phony new rule is the one you invoke on the command line ("make phonyNewRule"), then Make will build whatever else it's going to build before executing the file_modifier command. If you want to build targets not on that list, you could do it this way:
(phony new rule): $(LIST_OF_FILES_TO_EDIT) $(OTHER_TARGETS)
file_modifier ...
3) If your dependencies are set up correctly, you can find out which targets depend on $(LIST_OF_FILES_TO_EDIT), but it's not very tidy. You could just touch one of the files, run make, see which targets it built, repeat for all files. You could save a little time by using Make arguments: "make -n -W foo1 -W foo2 -W foo3 ... -W foo99 all". This will print the commands Make would run-- I don't know of any way to get it to tell you which targets it would rebuild.

Resources