I tried executing the following (found on a website)
.PHONY: coat shoes mobile sweater socks trousers shirt pants undershirt
# target prerequisite command
# ------------------------------------------------
coat: shoes mobile sweater; #echo put on $#
shoes: socks trousers; #echo put on $#
mobile: trousers; #echo put on $#
sweater: shirt; #echo put on $#
socks: ; #echo put on $#
trousers: pants shirt; #echo put on $#
shirt: undershirt; #echo put on $#
pants: ; #echo put on $#
undershirt: ; #echo put on $#
But I am getting Circular dependency error when executed on cygwin.
Here is the output
1 MAKE Version 5.2 Copyright (c) 1987, 2000 Borland
2 Error: Circular dependency exists in makefile
3 socks -> socks
4 Error: Circular dependency exists in makefile
5 shoes -> socks
6 Error: Circular dependency exists in makefile
7 mobile -> mobile
8 Error: Circular dependency exists in makefile
9 coat -> shoes
10 Fatal: ';' does not exist - don't know how to make it
Need help...
Use GNU make. Here's the evidence:
You are using a make copyrighted to Borland, which indicates that the make you are using is not GNU make.
I've found the example here. The author provides a link to GNU make, suggesting that his examples expect GNU make.
The make you are running interprets ; as a dependency. Clearly it is not interpreting your Makefile correctly.
If I use GNU make with your example, here's what I get:
$ make
put on socks
put on pants
put on undershirt
put on shirt
put on trousers
put on shoes
put on mobile
put on sweater
put on coat
Related
I am working on a writing project and would like to use make for running pandoc on files. So far I've tried to pass arguments to make like I do with a bash script.
For example:
$ make chapter 2
In the make file chapter is the target and 2 would be the argument.
I don't know if makefiles have the facility to take cli arguments. I haven't been able to find what I'm looking for in the documentation.
So far I have tried to run make with this recipe.
chapter:
#pandoc -s -o "$1.epub" "$1.md"
I get this error back
pandoc: .md: openBinaryFile: does not exist (No such file or directory)
make: *** [Makefile:2: chapter] Error 1
This is for turning sections of a book I'm working on into epubs. I'm open to other ways to do this with make seeing as tokens don't to work.
In the make file chapter is the target and 2 would be the argument
$ make chapter num=2
The assignment to variables on the make command-line overrides any definition inside the makefile
(yep, such variables effectively become read-only).
This suggests a makefile something like:
num = $(error You must set $$num to the chapter number you want (make chapter num=4))
.PHONY: chapter
chapter:
pandoc -s -o "${num}.epub" "${num}.md"
What's going on here?
Well, if you forget to set num,
when make expands the recipe for chapter the
$(error) will cause make to stop.
$ make
Makefile:5: *** You must set $num to the chapter number you want (make chapter num=4). Stop.
And your original example?
$ make chapter num=2
pandoc -s -o "2.epub" "2.md"
Tips
I rarely recommend using the # prefix — Users can use make's -s if they don't want to see the shell commands
Don't lie to make — In particular, your rule does not produce a file called chapter, so please tell make that by marking the target .PHONY
The natural way to say this in Make is to enumerate all the chapters as targets, typically as dependencies for make all.
So basically
src := $(wildcard *.md)
epubs := $(patsubst %.md,%.epub,$(src))
.PHONY: all
all: $(epubs)
%.epub: %.md
pandoc -s -o $# $<
You can say make ch4.epub if you have a chapter whose source is ch4.md. You can't really pass in an argument which isn't a file name or a target name, and these cannot contain spaces.
I suppose you could add a phony like
.PHONY: 2
2: ch2.epub
to be able to say make 2 and have it mean make ch2.epub. If file names are systematically named like this, you could generalize to
short := $(patsubst ch%.md,%,$(src))
.PHONY: $(short)
$(short): %: ch%.epub
Don't use # in front, it just makes things harder. You can use make -s if you don't want to see the output and not wreck your Makefile.
I’ve the following makefile, with two rules.
Is there a way to run these two rules in parallel, I mean to maximize
the core’s capabilities? I see this section but not sure that I got how to use it for my purpose, since I want to handle it within the makefile and not from the command line.
I.e. run module1 & 2 targets in parallel.
This is the makefile:
all: module1 module2
.PHONY: module1
module1:
#echo "run module 1"
DIR=$(PWD)
#echo $(DIR)
.PHONY: module2
module2:
#echo "run module2”
cleanup:
fzr clean $(DIR)
You can set make options that you usually pass to make via its command line invokation in the makefile itself. Add this line to your makefile
MAKEFLAGS += -j2
and you can invoke make without the -j flag, it will still spawn two processes to build targets in parallel, when they aren't dependent on each other. To automatically determine the number of jobs to spawn, you can use this on linux
NPROCS = $(shell grep -c 'processor' /proc/cpuinfo)
MAKEFLAGS += -j$(NPROCS)
and on MacOS
NPROCS = $(shell sysctl hw.ncpu | grep -o '[0-9]\+')
MAKEFLAGS += -j$(NPROCS)
Even a MAKEFLAGS += -j$(NPROCS) would not work if you have '::' instead of ':' for your rule, as illustrated by that recent fix in Git 2.25.2 (March 2020)
See commit 2607d39 (18 Feb 2020) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 29b09c5, 02 Mar 2020)
doc-diff: use single-colon rule in rendering Makefile
Signed-off-by: Jeff King
When rendering the troff manpages to text via "man", we create an ad-hoc Makefile and feed it to "make".
The purpose here is two-fold:
reuse results from a prior interrupted render of the same tree
use make's -j option to build in parallel
But the second part doesn't seem to work (at least with my version of GNU make, 4.2.1). It just runs one render at a time.
We use a double-colon "all" rule for each file, like:
all:: foo
foo:
...actual render recipe...
all:: bar
bar:
...actual render recipe...
...and so on...
And it's this double-colon that seems to inhibit the parallelism.
We can just switch to a regular single-colon rule.
Even though we do have multiple rules for "all" here, we don't have any recipe to execute for "all" (we only care about triggering its dependencies), so the distinction is irrelevant.
When I tried my makefile, I got error saying that No such file or directory, but my directory is right there, what do I do wrong? Thanks.
my project structure :
dev |--- ev
|--- display
|--- install ( makefile is here, try to call makefiles in ev and display folder)
My makefile :
MODULES :=ev display
SRC_DIR :=$(addprefix ../, $(MODULES))
BUILD_DIR:=$(addsuffix /build, $(SRC_DIR))
x:=../ev ------> add temporarily just for test,
------> the same error if x:=$(HOME)/dev/ev
INSTALL_DIR:=EX Frameworks Add-ons
INSTALL_DIR:=$(addprefix $(HOME)/EX/, $(INSTALL_DIR))
vpath %.cpp %.java $(SRC_DIR)
.PHONY: all clean
checkdirs: $(INSTALL_DIR)
$(INSTALL_DIR):
#echo "INSTALL DIR"
#mkdir -p $#
define make-goal
$1:
#echo "start building each part"
cd $# && make -f Makefile_new.osx clean
cd $# && make -f Makefile_new.osx package
endef
clean:
#echo "clean up"
#echo "BUILD_DIR IS $(BUILD_DIR)"
#rm -rf $(BUILD_DIR)
all:
#echo "start build subdirectory"
#echo "SRC_DIR IS $(SRC_DIR)"
#echo "x is $(x)"
$(call make-goal, $(x))) ----> when it comes to here, I got error message
The error messages:
x is ../ev
../x:
make: ../ev:: No such file or directory.
I guess it is about relative path, because I call this makefile from Install folder, then $(x) can't be found from Install folder, but when I tried to make a folder named ev (Install/ev), I still got the same error.
I think it must be something basic I missed here, but what it is.
Thanks.
Update:
I am trying to build a project which includes several sub-projects. the structure is:
dev |---- ev
|---- edf
|----- dt
|------af
|------Install
Inside of Install, I have a makefile, which is at the top level. The makefile in Install folder will call makefiles in other folders to build different subjects,
Ideally, I want to build every sub projects without touching sources. My sources include c++ and java code.
It's not clear what you're trying to do. Also due to some indentation hiccups I can't be sure, but you appear to be defining a variable make-goal that contains a template for a make rule, then using it with $(call ...) inside the recipe for the all target. That cannot work: you cannot create a make rule inside the recipe for another make rule!
The reason this fails is that the $(call ...) is expanding to content which is added to the recipe of the all target, so instead of creating a new make rule it's treating the result as a shell script. The first line is $1:, and you passed in ../ev, so make is trying to run the command ../ev: just as the error shows you.
If you describe what you want to do at a higher level we can give you some ideas on how to do it.
ETA:
If you just want your all target to also build a subdirectory, there's no need for all this complex GNU make advanced capabilities. That stuff is only needed when you get to guru-level makefile creation. Simple "build a target after another target is finished" is the exact thing make was designed to do: nothing special is needed to do that.
For example:
.PHONY: all $(SRC_DIR)
all: $(SRC_DIR)
$(SRC_DIR):
#echo "start building $#"
cd $# && $(MAKE) -f Makefile_new.osx clean
cd $# && $(MAKE) -f Makefile_new.osx package
This is still a pretty non-standard setup but I think it will work the way you want. Remember you'll have to either move the all target up to be the first one in the makefile, or you'll have to run make all explicitly: make only builds the first target in the makefile unless you give it specific targets on the command line.
Following is the directory structure of my project:
expt-main
---------
Makefile_main
/ \
subdir-1 subdir-2
-------- --------
Makefile_1 Makefile_2
mod_codeA.f90 mod_code1.f90
mod_codeB.f90 mod_code2.f90
mod_codeC.f90 mod_code3.f90
Makefile_main:
export
SHELL = /bin/sh
F90 = mpxlf95
SRCDIRS = $(subdir-1) $(subdir-2)
all:
#for DIR in ${SRCDIRS} ;
do \
back=`pwd`; \
cd $$DIR ;\
$(MAKE) ; status=$$? ; \
if [ $$status != 0 ] ; then \
echo "Exit status fro make was $$status" ; exit $$status ; \
fi ; \
cd $$back ; \
done
-------------------------------------------------------------------------------
Makefile-1:
%.o: %.f90
$(F90) $(F90FLAGS) -I$(subdir-2) -c $<
mod_codeA.o: mod_codeC.o $(subdir-2)/mod_code2.o
-------------------------------------------------------------------------------
Makefile-2:
PROG = $(exec)
subdir-1_objs = $(subdir-1)/mod_codeA.o mod_codeB.o mod_codeC.o
all: $(PROG)
$(PROG): $(subdir-2_objs) $(subdir-1_objs) -o $# $(subdir-2_objs) $(subdir-1_objs)
---------------------------------------------------------------------------------
-
I've written the Makefile_main such that it compiles the codes (modules) in subdir-1 first and then the ones in subdir-2 and finally makes the executable. The issue: modules in subdir-1 uses modules from subdir-2 and in similar fashion, modules in subdir-2 uses those in subdir-1. My make is getting failed because the modules being used is in other directory. How to write a makefile which will take care of this issue that is, while compiling modules in subdir-1, whenever it encounters the need for an object file from subdir-2, it should switch to subdir-2 compile the necessary modules and return back to subdir-1 for further action?
If modules in different subdirectories need each other as you say, then this is not a good use of recursive Make.
Do away with Makefile-1 and Makefile-2, and let Makefile_main do all the work. (I can't tell you specifically how to change Makefile-main, since I don't do Fortran, I don't understand Makefile-2, and I don't see any dependency of modules in subdir-2 upon those in subdir-1).
If you want to stick to this directory layout and still keep three separated Makefiles, then you can use compiler flags to instruct the FORTRAN compiler to put module files into a common directory of your choice.
For instance using:
$ gfortran --version
GNU Fortran (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
you can use -I and -J flags to instruct the compiler on:
where to search for module files (.mod)
where to put generated module files
That said I think that the suggestion given by Beta to join the Makefiles makes a lot of sense. To know some of the reasons why you should do that you can read this paper.
Finally, as your project seems not to be very large at this stage, I also suggest to take into consideration CMake as a build system, as it possibly provides a more convenient way of specifying dependencies between targets (as well as many other things).
I want the rules of a target to be executed but all dependent targets shall regard this target as satisfied.
How can I achieve this?
Example:
$(NETWORK_SHARE)/foo.log:
#echo Warning: server offline, still continue ...
#exit 0
foo.csv: $(NETWORK_SHARE)/foo.log
#echo Long export from a (different) server
#echo sleep 20
#echo foo > $#
If $(NETWORK_SHARE)/foo.log exists: foo.csv shall be rebuilt if $(NETWORK_SHARE)/foo.log is newer than foo.csv; otherwise nothing should happen (default)
If $(NETWORK_SHARE)/foo.log does not exist (e.g., server offline, failure, ...) only a message indicating a problem should be printed but foo.csv shall only be built if foo.csv does not exist.
I played around with .PHONY and returning different return values but for case 2, the expensive "export" happens as soon as I execute something on $(NETWORK_SHARE)/foo.log ...
Regards
divB
Looks like instead of using some old file (that someone can accidentally touch), you can use an order-only prerequisite. Here's a quote from the GNU makefile manual (chapter 4.3)
Occasionally, however, you have a situation where you want to impose a
specific ordering on the rules to be invoked without forcing the
target to be updated if one of those rules is executed. In that case,
you want to define order-only prerequisites. Order-only prerequisites
can be specified by placing a pipe symbol (|) in the prerequisites
list: any prerequisites to the left of the pipe symbol are normal; any
prerequisites to the right are order-only:
targets : normal-prerequisites | order-only-prerequisites
Great, thanks to Thiton's answer in my related question (Force make to find out-of-date condition from file) I can now provide a hack to solve this:
.PHONY: always-remake
NETWORK_SHARE = //server/dfs/common/logs
.PHONY: all
all: foo.csv
# file does not exist ...
ifeq "$(wildcard $(NETWORK_SHARE)/foo.log)" ""
old_file: always-remake
#echo Warning: network is not available ....
foo.csv: old_file
#echo Expensive export
#sleep 10
#echo $# > $#
else
foo.csv: $(NETWORK_SHARE)/foo.log
#echo Doing expensive export since log file changed ...
#sleep 10
#echo $# > $#
endif
"old_file" is a dummy file which must exist and should never be newer than any other file (e.g. 1/1/1971, 00:00)
Regards
divB