make: .SECONDARY target breaks buld - makefile

My target is to generate a file (MyOut.elf) and, if this file is generated, generate other two files (MyOut.s19 and size.txt) that are dependent on the that file.
I'm quite a newbie on makefiles, but I wrote the following:
.DEFAULT_GOAL := full
full: MyOut.elf MyOut.s19 size.txt
#echo TARGET
# Tool invocations
MyOut.s19: MyOut.elf
#echo 'Building S19 : $#'
#echo 'MyOut.s19: MyOut.elf' > MyOut.s19
#echo 'Finished building target: $#'
#echo ' '
size.txt: MyOut.elf
#echo 'Building section size summary : $#'
#echo 'size.txt: MyOut.elf' > size.txt
#echo 'Finished building target: $#'
#echo ' '
all: MyOut.elf
MyOut.elf:
#echo 'Building ELF: $#'
#echo 'MyOut.elf' > MyOut.elf
#echo 'Finished building target: $#'
#echo ' '
.PHONY: full
#.SECONDARY:
Now, if I run make, everything works as expected:
> make
Building ELF: MyOut.elf
Finished building target: MyOut.elf
Building S19 : MyOut.s19
Finished building target: MyOut.s19
Building section size summary : size.txt
Finished building target: size.txt
TARGET
Instead, if I uncomment the last line .SECONDARY:, the dependency chain seems "broken", as it stops after the first target (MyOut.elf):
> del *.elf
> make
Building ELF: MyOut.elf
Finished building target: MyOut.elf
TARGET
Then, if I run make again, the dependent files MyOut.s19 and size.txt are built:
> make
Building S19 : MyOut.s19
Finished building target: MyOut.s19
Building section size summary : size.txt
Finished building target: size.txt
TARGET
So, my questions are:
Why is this happening?
How can I overcome this problem? (Note: I can't remove the .SECONDARY directive, since this is part of a makefile automatically generated by Eclipse)

I found a solution to this: I added a new "dummy" target otherTargets to the prerequisites of the target full:
full: MyOut.elf otherTargets
otherTargets: MyOut.s19 size.txt
Now, when I run make, I get
Building ELF: MyOut.elf
Finished building target: MyOut.elf
Building section size summary : size.txt
Finished building target: size.txt
Building S19 : MyOut.s19
Finished building target: MyOut.s19
And if I run it for the second time, I get
make: Nothing to be done for `full'.
Nonetheless, if I erase the .elf file, the "dependant" files are rebuilt correctly.
The explanation to this I found is related to the GNU make documentation:
If an ordinary file b does not exist, and make considers a target that depends on b, it invariably creates b and then updates the target from b. But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.
Therefore, my "intermediate files" MyOut.s19 and size.txt are not rebuilt.
My solution is then working since the target otherTargets is never generating an output file, therefore it always needs update.

Related

Run make file as all process

I've create this simple makefile and I want to run all the process witn make
while do that it run only the first section module1 and not module2,
what am I missing here ?
.PHONY: module1
module1:
#echo "run module 1"
DIR=$(PWD)
#echo $(DIR)
.PHONY: module2
module2:
#echo "run module2"
if I run make module2 the module2 is executed successfully but I want all to be run in the make command and as far as I read in the net this is how it should work, what was wrong here ?
From the documentation...
By default, the goal is the first target in the makefile (not counting
targets that start with a period). Therefore, makefiles are usually
written so that the first target is for compiling the entire program
or programs they describe. If the first rule in the makefile has
several targets, only the first target in the rule becomes the default
goal, not the whole list. You can manage the selection of the default
goal from within your makefile using the .DEFAULT_GOAL variable (see
Other Special Variables).
So you just need to provide a suitable default target -- all is `traditional'...
all: module1 module2
So the complete makefile would be...
all: module1 module2
.PHONY: module1
module1:
#echo "run module 1"
DIR=$(PWD)
#echo $(DIR)
.PHONY: module2
module2:
#echo "run module2"

make with Cygwin

I am trying to set VTK on windows (did I say it was complicated?^^).
I have successfully configured VTK with CMake and I am now trying to run make through cygwin. However when I go to the build directory and enter make all the terminal prints and does is:
make
Microsoft Windows [version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
Does anyone know what's wrong?
EDIT: when typing cygcheck
I get:
Cygwin Package Information
Package Version Status
make 4.0-2 OK
EDIT 2: Here is a screenshot of what I get (sorry it's in french)
Thanks in advance for any help you can give :)
EDIT 3: New screenshot + Makefile Content
Makefile content:
# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.2
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
SHELL = cmd.exe
# The CMake executable.
CMAKE_COMMAND = "C:\Program Files (x86)\CMake\bin\cmake.exe"
# The command to remove a file.
RM = "C:\Program Files (x86)\CMake\bin\cmake.exe" -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\Lonni\VTK\VTK-6.2.0
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\Lonni\VTK\Build1
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target edit_cache
edit_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
"C:\Program Files (x86)\CMake\bin\cmake-gui.exe" -H$(CMAKE_SOURCE_DIR) - B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
#$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
"C:\Program Files (x86)\CMake\bin\cmake.exe" -H$(CMAKE_SOURCE_DIR) - B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# The main all target
all: cmake_check_build_system
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\Lonni\VTK\Build1\CMakeFiles C:\Users\Lonni\VTK\Build1\CMakeFiles\progress.marks
$(MAKE) -f CMakeFiles\Makefile2 all
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\Lonni\VTK\Build1\CMakeFiles 0
.PHONY : all
# The main clean target
clean:
$(MAKE) -f CMakeFiles\Makefile2 clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
$(MAKE) -f CMakeFiles\Makefile2 preinstall
.PHONY : preinstall/fast
# clear depends
depend:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check- build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend
#=============================================================================
# Target rules for targets named vtk-android
# Build rule for target.
vtk-android: cmake_check_build_system
$(MAKE) -f CMakeFiles\Makefile2 vtk-android
.PHONY : vtk-android
# fast build rule for target.
vtk-android/fast:
$(MAKE) -f CMakeFiles\vtk-android.dir\build.make CMakeFiles/vtk- android.dir/build
.PHONY : vtk-android/fast
#=============================================================================
# Target rules for targets named vtk-compile-tools
# Build rule for target.
vtk-compile-tools: cmake_check_build_system
$(MAKE) -f CMakeFiles\Makefile2 vtk-compile-tools
.PHONY : vtk-compile-tools
# fast build rule for target.
vtk-compile-tools/fast:
$(MAKE) -f CMakeFiles\vtk-compile-tools.dir\build.make CMakeFiles/vtk- compile-tools.dir/build
.PHONY : vtk-compile-tools/fast
# Help Target
help:
#echo The following are some of the valid targets for this Makefile:
#echo ... all (the default if no target is provided)
#echo ... clean
#echo ... depend
#echo ... vtk-android
#echo ... edit_cache
#echo ... rebuild_cache
#echo ... vtk-compile-tools
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check- build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system
The default installation of Cygwin is quite minimal. It doesn't include GNU make, so you're getting Microsoft's make.
You need to re-run Cygwin's setup-*.exe and add make. Chances are, you probably need other things, too. I suggest opening the Devel category and giving the contents a scan while you're in there.
EDIT, after screenshots were added to the question:
Your screenshots show several confusions. I'll go through them one by one, quoting the text in each case:
Pas de cible spécifiée et aucun makefile n'a été trouvé
In English, that is "No targets specified and no makefile found." This tells you that GNU make is installed and running, but that you don't have a file called GNUmakefile, makefile, or Makefile in the current directory. It searches for those three, in order.
This is not surprising since ls shows that you are running it in an empty directory.
/cygdrive/c/MinGW/bin/make
There are two problems here:
As I said in the comments, only programs linked to cygwin1.dll can make sense of /cygdrive. Windows' cmd.exe has no idea what /cygdrive means. c:\MinGW\bin\make is the correct form under cmd.exe.
MinGW is not Cygwin. Any problems you have with MinGW are an entirely separate question, not related to the problems you're having with Cygwin's GNU make package.
/usr/bin/make
This is similar to the previous item: cmd.exe has no idea what to do with a POSIX path. Because Windows' file path parsing code sometimes treats forward slashes the same as backslashes, this gets interpreted as c:\usr\bin\make in this case, but there is almost certainly no c:\usr directory at all.
The reason this path works in the left screenshot is that Cygwin mounts your Cygwin installation directory (e.g. c:\cygwin or c:\cygwin64, by default) as the POSIX root, so that c:\cygwin\usr appears as /usr to any program linked to cygwin1.dll which uses POSIX APIs such as open(2). This includes Cygwin's version of GNU bash, as you show.
You should not require the explicit path within the Cygwin Terminal window, since /usr/bin should be ahead of anything else in the PATH. If that is not the case, you might not be using the Cygwin icon that setup.exe created, in which case you don't have a proper login shell. Either use that icon, or mimic what it does by calling mintty -, not just plain mintty.

Make implicit rule fails at first time but succeeds at second time

I encounter an error relating to implicit rule in make (3.81). The example codes are:
dongli:test02 dongli$ ls -R
Makefile a.F90 b.F90 dir
./dir:
a.t.F90
The dependencies among the codes are:
a.t.F90: a.F90
a.t.o: a.t.F90
b.o: b.F90
b: a.t.o b.o
That is a.F90 is intermediate code, and a.t.F90 will be updated when a.F90 is updated. My make process is:
Test 1 (All codes on position):
-------------------------------------------------------------
Project: >>> test <<<
-------------------------------------------------------------
Creating dependency a.t.o
-------------------------------------------------------------
-----> ./dir/a.t.F90
Creating dependency b.o
-------------------------------------------------------------
-----> b.F90
Creating target 'b'
---> b is created.
-------------------------------------------------------------
Finished
-------------------------------------------------------------
Test 2 (touch a.F90):
dongli:test02 dongli$ touch a.F90
dongli:test02 dongli$ make
-------------------------------------------------------------
Project: >>> test <<<
-------------------------------------------------------------
Processing templates in a.F90
-------------------------------------------------------------
Creating dependency a.t.o
-------------------------------------------------------------
-----> a.t.F90
gfortran: error: a.t.F90: No such file or directory
gfortran: fatal error: no input files
compilation terminated.
make: *** [a.t.o] Error 1
Test 3: (Run make again):
dongli:test02 dongli$ make
-------------------------------------------------------------
Project: >>> test <<<
-------------------------------------------------------------
Creating dependency a.t.o
-------------------------------------------------------------
-----> ./dir/a.t.F90
Creating dependency b.o
-------------------------------------------------------------
-----> b.F90
Creating target 'b'
---> b is created.
-------------------------------------------------------------
Finished
-------------------------------------------------------------
I know there is a bug in make about directory caching (see here), but in my case, dir/a.t.F90 exists all the time. Any idea? Thanks!
Update1:
I use make -d to capture the following information in test 2:
Finished prerequisites of target file `a.t.F90'.
Prerequisite `a.F90' is newer than target `a.t.F90'.
Must remake target `a.t.F90'.
Ignoring VPATH name `./dir/a.t.F90'.
...
Successfully remade target file `a.t.F90'.
Finished prerequisites of target file `a.t.o'.
Prerequisite `a.t.F90' of target `a.t.o' does not exist.
Must remake target `a.t.o'.
Why ./dir/a.t.F90 is ignored when its prerequisite a.F90 is newer than it?
Update2:
I have put the example codes on gist.
Update3:
I found the following relating information:
If a target needs to be rebuilt, GNU make discards the file name found
during the VPATH search for this target, and builds the file locally
using the file name given in the makefile. If a target does not need
to be rebuilt, GNU make uses the file name found during the VPATH
search.
You really need to show the rules that create these targets. You've provided a lot of information about many aspects of your build, but one of the most critical aspects of debugging make issues is seeing the rules.
Failures like this (where the first build fails and the second succeeds) are almost invariably due to rules that do not behave as you have described them to make. If you tell make that a rule builds a file "foo", by creating something like foo : bar, but then the recipe that you write doesn't actually create "foo" but rather "bar/foo", something like:
foo : bar ; cp bar bar/foo
then that is wrong. Another common reason for such issues is that you define a rule that builds "foo.x", but it also builds "foo.y" and you don't tell make about it but then later use "foo.y" as a prerequisite, that can't work. You have to define a rule that tells make that both those files are generated from a single invocation of the recipe, such as:
%.x %.y : %.z ; cp $< $*.x && cp $< $*.y
And finally, you mention VPATH above and it looks like you're trying to use VPATH to find generated files. That will not work. VPATH can only be used to find source files (files make doesn't know how to build and expects to always be present). Without seeing more about your makefiles and how the rules are constructed, that's about all we can say.
Edited to add:
I'm not sure it's really necessary to use so much eval and call here; often people seem to go straight to these very powerful tools when simpler ones would suffice just as well. In any event, the problem you're having is exactly as I suspected in my first comment above; you have this rule:
%.t.F90: %.$(1)
#echo " Processing templates in $$^"
#echo $$(seperator)
#cp $$< dir/$$#
Note the last line, where instead of creating $# you're creating dir/$#; this is precisely the situation I described above. Whenever you have a rule that builds something that is not exactly $#, it's almost 100% certain that rule is wrong. You need to write this as:
dir/%.t.F90: %.$(1)
#echo " Processing templates in $$^"
#echo $$(seperator)
#cp $$< $$#
and maybe more changes to match that target.
I make a workaround that I inserted some scripts in the implicit rule that add the missing directory part of the code, since VPATH has some constraints on this.
%.o: %.$(1)
#echo " Creating dependency $$#"
#echo $$(seperator)
#TEMPLATE_PATTERN='.*\.t\.$(1)'; \ <
if [[ $$$$(dirname $$<) == '.' && '$$<' =~ $$$$TEMPLATE_PATTERN ]]; then \ <
SRC=$(PROJECT_ROOT)/.codemate/processed_codes/$$<; \ <
else \ <
SRC=$$<; \ <
fi; \ <
$(FC) -c $$$$SRC $(OPTIONS) $(FFLAGS) $(INCLUDES)
labeled by <.

parallel make: two targets depend on the same prerequisite, what happens?

I need to build sources to binary file and two a static library.
Here is an example (I replaced recipes with ';' for brevity):
objects := a.o b.o ...
.PHONY: all build build_lib
all: build build_lib
build: bin/app
build_lib: bin/libapp.a
bin/app: $(objects) ;
bin/libapp.a $(objects) ;
obj/%.o: %.cpp ;
Will there be problems with parallel build? Can two make processes try to rebuild the same *.o file at once, making a broken build?
I guessed that, they can, so I rewritten the code this way:
objects := a.o b.o ...
.PHONY: all build build_lib
all: $(objects) | bin/app bin/libapp.a
build: bin/app
build_lib: bin/libapp.a
bin/app: $(objects) ;
bin/libapp.a $(objects) ;
obj/%.o: %.cpp ;
But the --debug=b output still shows:
Processing target file `all'.
File `all' does not exist.
Processing target file `bin/app'.
File `bin/app' does not exist.
Processing target file `obj/client.o'.
Need to rebuild target `obj/client.o'.
...
File `sb_all' does not exist.
File `bin/app' does not exist.
File `bin/libapp.a' does not exist.
File `sb_all' does not exist.
File `bin/app' does not exist.
File `bin/libapp.a' does not exist.
...
Need to rebuild target `bin/app'.
g++ -lgd ...
Need to rebuild target `bin/libapp.a'.
ar ...
File `all' does not exist.
Target file `all' rebuilt successfully.
So it seems that my $(objects) target does not run before order-only prerequisites, or do I incorrectly read output? And did I need this change anyway?
No, there is no problem with it. Make will not have any problem with parallelism and multiple targets (in the same instance of make) depending on the same prerequisite. If you have recursive instances of make and multiple different make instances try to build the same target you'll have problems.
Order-only doesn't have any impact on parallelism at all. Make will still invoke things in parallel if possible. The only way to impact the order in which rules are run is to declare a prerequisite relationship between those targets. Here you're just saying that both the higher-level targets must be built before the all target, so that doesn't do anything to reduce parallelism.
Luckily as I said above, you don't have to. As long as your makefile correctly defines the dependency relationship between any two targets, make will handle the bigger picture just fine.

What is the difference between "make" and "make all"?

I have a Makefile with the following structure (working example).
.PHONY: image flashcard put-files
put-files:
#echo "=== put-files"
image:
#echo "=== image"
flashcard:
#echo "=== flashcard"
all: put-files image flashcard
#echo "Done"
I expect that a simple make would build all three targets, but this is not so:
% make
=== put-files
But if I explicitly specify the target, the dependencies are built as well:
% make all
=== put-files
=== image
=== flashcard
Done
What am I doing wrong?
A simple make will build the first target in the list, which is put-files.
make all will build the target all. If you want all to be the default, then move it to the top of the list.
To understand what the .PHONY does, see http://www.gnu.org/s/hello/manual/make/Phony-Targets.html

Resources