(Sorry if duplicate. Post appeared to be accepted but cannot find.)
I am using Windows 10 and gnuWin\GetGnuWin32\gnuwin32\bin\make.exe using SHELL = cmd.exe
The two lines…
copyFiles = $(wildcard $(configDir)\*.txt)
$(info ?TXT? $(copyFiles))
…only print “?TXT?”.
But all the documentation I understand says I should see my two .txt files. And that includes many stack exchange files. Clearly, something is missing. Once I get it right I’m onto trying to get these files copied into my build directory. (I can get the files with VAR=$(shell dir …) but I would rather have them located using VPATH but one thing at a time.)
Related
We are using make utility in windows to build our project. The version of make is "GNU Make 3.81". I need to understand how our project is built and so have added additional log lines like below which is working as expected --
$(warning Entering componentsWin32.mak )
Additionally I need to find the current directory and the list of files in that directory, for the first one, this is working--
$(warning Entering componentsWin32.make $(CURDIR))
To print the list of files in a directory I tried this but it did-not work --
$(warning Entering componentsWin32.make $(DIR))
Is it possible using $(SHELL...some command) or any other way? Any pointers to this would be helpful.
The function $(wildcard [path string]) will evaluate to a list of files which are desginated by path string: the path string may be written as a glob, so e.g.
$(wildcard $(CURDIR)/src/*.c)
will evaluate to a list of all C files, given that there is a subdirectory src under your current directory with *.c files in it.
You can even pass an arbitrary number of such path expressions:
$(wildcard $(CURDIR)/src/*.c $(MY_INCLUDE_DIR)/*.h)
Obviously, spaces in path names are not allowed.
In my project, I have a set of sub-directories that contain package.yaml files, for e.g.:
A/package.yaml
B/package.yaml
C/package.yaml
If I run hpack A/package.yaml, the file A/A.cabal is (re-)generated. The list of such directories can change over time, so I want to use GNU make to find all immediate sub-directories containing package.yaml files and generate the corresponding .cabal files using hpack.
I tried this based on another question, but it didn't work:
HPACK_FILES := $(wildcard */package.yaml)
PKG_DIRS := $(subst /,,$(dir $(HPACK_FILES)))
CABAL_FILES := $(addsuffix .cabal,$(join $(dir $(HPACK_FILES)),$(PKG_DIRS)))
test:
#echo $(CABAL_FILES)
update-cabal: $(CABAL_FILES)
%.cabal: package.yaml
hpack $<
However, make update-cabal says there's nothing to be done. make test however does output the right cabal files. How can I fix this?
Cheers!
The problem is this:
%.cabal: package.yaml
There is no file package.yaml. The files are named things like A/package.yaml. That is not the same thing.
Because the prerequisite doesn't exist, make decides that this pattern rule cannot match and so it goes looking for another rule that might be able to build the target. It doesn't find any rule that can build the target, so make says there's nothing to do because all the output files already exist.
Unfortunately what you want to do is not at all easy with make, because make is most comfortable with input and output files that are tied together by the filename with extensions, or similar. And in particular, it has a really hard time with relationships where the variable part is repeated more than once (as in, A/A.cabal where the A is repeated). There's no easy way to do that in make.
You'll have to use an advanced feature such as eval to do this. Something like:
# How to build a cabal file
%.cabal:
hpack $<
# Declare the prerequisites
$(foreach D,$(dir $(HPACK_FILES)),$(eval $D/$D.cabal: $D/package.yml))
Is there a way to let make determine the number of files to be recompiled before actually compiling? The problem is this: Consider having a quite big project with hundreds of source files. It would very convenient to have a rough idea of how long compilation will take, but to know that, one needs to know the number of files to be compiled.
The general answer is no, because your build could generate files which themselves are inputs to other rules which generate more files. And so on. However if a rough answer is good enough you can try the --dry-run flag. From the GNU make documentation...
“No-op”. Causes make to print the recipes that are needed to make the targets up to date, but not actually execute them. Note that some recipes are still executed, even with this flag (see How the MAKE Variable Works). Also any recipes needed to update included makefiles are still executed (see How Makefiles Are Remade).
As you can see, despite its name even the --dry-run flag will change the state of your build.
"make -n" will do the dry run. But you can't get the list of files to be rebuilt. May be you can write shell script to store the last modified time of files and get the list of files.
I think a found a decent solution for unix. Here SRC are your source files, HDR your headers and DEP the dependency files (something like DEP:=$(OBJ:.o=.d) )
isInDepFile+=$(shell grep -q $(modifiedFile) $(depFile) 1>&2 2> /dev/null && echo $(depFile))
COMPFILES=
checkDepFiles=$(foreach depFile,$(DEP), $(eval filesToCompile+=$(isInDepFile))) $(thinOutDepFiles)
thinOutDepFiles=$(foreach fileToCompile,$(filesToCompile),$(eval DEP=$(filter-out $(fileToCompile),$(DEP))))
countFilesToCompile: $(SRC) $(HDR)
$(eval modifiedFiles=$?)
$(foreach modifiedFile,$(modifiedFiles), $(call checkDepFiles))
$(eval numOfFilesToCompile = $(words $(filesToCompile)))
$(eval numDepFiles = $(words $(DEP)))
$(eval NumSRCFiles = $(words $(SRC)))
#echo $(NumSRCFiles) sources
#echo $(numDepFiles) files to leave
#echo $(numOfFilesToCompile) files to compile
#touch $#
This first generates a list of modified files within your source and header files lists. Then for each modified file it checks all dependency files for its filename. If a dependency file contains the current file we are looking at, it is added to the list of filesToCompile. It is also removed from the list of dependency files to avoid duplication.
This can be invoked in the main building rule of your project. The advantage of that over the dry run is that it gives you a simple number to work with.
I have a simple makefile that I use to build some latex files. The syntax looks like this:
pdf: thesis.tex chapters/a.tex chapters/b.tex chapters/c.tex
latexmk -pdf -pdflatex="pdflatex thesis.tex
open:
open thesis.pdf
The files inside chapters folder can increase further with d.tex, e.tex and may even contain subfolders f\section1.tex, f\section2.tex etc.
I manually add all the requried tex files inside my thesis.tex like this which is not a problem.
\input{chapters/a.tex}
\input{chapters/b.tex}
\input{chapters/c.tex}
\input{chapters/d.tex}
\input{chapters/e.tex}
How can I get make target pdf to depend upon any file changes inside chapters and its subdirectories?
How do I write inter task dependency in makefile. If target open depends upon target pdf, how do I write it?
open: pdf will sort-of do what you want for your second question.
Though it would be better to not use the phony pdf target for this.
Instead have a thesis.pdf: target which depends on the right prerequisites and have both pdf: thesis.pdf and open: thesis.pdf targets.
For the first question you can either use something like:
SRCS := $(shell find chapters -name '*.tex')
or use from here:
rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
SRCS := $(call rwildcard,chapters,*.tex)
and then:
thesis.pdf: thesis.tex $(SRCS)
to use that variable as the prereq.
If you wanted to get even fancier you could write a script to pull out the actual filenames from the \input{} directives in thesis.tex and use that as your SRCS variable (but that's probably not worth the effort unless you know you will have other, unrelated, .tex files).
Here is my problem: I have been using Java for many years and enjoy having many directories separating different areas of the code. For my current project I am writing Fortran code, which should compile under Windows and Unix/Linux. For Windows, I am using Eclipse/Photran with MinGW/gfortran tools to set up Makefiles.
Here is the desired project structure (deep nesting tree-like Java-like would be even nicer)
dir1/src/*.f95
dir1/make/Makefile_lib1.any
dir1/make/Makefile_lib1.win
dir1/make/Makefile_lib1.unix
dir2/src/*.f
dir2/make/Makefile_lib2.any
dir2/make/Makefile_lib2.win
dir2/make/Makefile_lib2.unix
...
dir_main/src/*.f or *.f95
dir_main/make/Makefile_main.any
dir_main/make/Makefile_main.win
dir_main/make/Makefile_main.unix
I would like to call make Makefile_main.unix, which would set up any Unix-specific variables and then include Makefile_main.any, Makefile_lib1.any, ...
(similar for making on Windows)
I got to the stage where I can see all source files in a given directory, e.g.
SRCS := $(wildcard $(SRC_DIR)/*.$(SRC_EXT))
Now I am struggling with how to make all dependencies as in Fortran 95 each source generates *.o and *.mod.
Is there a way to switch between directories when compiling so that all targets/dependencies do not have dir-path in their names? Note that I am calling make from some other service directory where the Eclipse project lives. Any suggestions how to proceed?
I really do not want to do the usual Fortran style of having just one directory with
all the mess together with the code.
There are two major strategies you can take.
You can place a makefile in each subdirectory and have it support targets like all, clean etc, then use recursive make invocations from the top-level makefile to make the same target (e.g. all) in every subdirectory.
Alternatively, you can handle it all in one make invocation, without recursing, but then you'll have to work with relative paths containing subdirectory names. Personally I don't see a problem with it, and I've maintained a system of makefiles based on this approach.
Here is what you can do in your case, assuming that SRC is set correctly to the list of relative paths to every source you need to compile.
# This replaces the SRC_EXT suffix with .o in each filename
OBJ = $(SRC:%.$(SRC_EXT)=%.o)
$(BINARY_NAME): $(OBJ)
...link command...
%.o: %.$(SRC_EXT)
...compile command...