How to not rebuild the project without changes in the directory? - makefile

I'm trying to write Makefile which would rebuild the file "./target/js/bundle.js" after changing any file in a directory "./ts" or its subdirectories. "make" should not rebuild "./target/js/bundle.js" without changing any file in a directory "./ts" or its subdirectories.
The structure of the project:
/ts - directory with typescript's sources
/ts/tsconfig.json - config for the tsc (TypeScript compiler), this filename is known by tsc
/target/js/bundle.js - target file
/Makefile
/ts/tsconfig.json:
{
"compilerOptions": {
"outFile": "../target/js/build.js"
}
}
My Makefile:
target/js/bundle.js: ts/*
cd ts && tsc
clean:
rm -r target
Now "make" run "cd ts && tsc" every time.

This rule:
target/js/bundle.js: ts/*
cd ts && tsc
says that if the file target/js/bundle.js does not exist, or it does exist but some file matching the glob pattern ts/* has a newer modification time, then re-run the recipe.
So, if you're seeing the recipe re-run every time then one of those two things is always true.
You can run make -d to have make generate a lot of information about how it's making its decision; that will tell you why it decides to rebuild the target.
I don't know how tsc works: are you sure that running tsc from the ts directory will understand that it needs to build the file ../target/js/bundle.js?

The problem in naming of files:
In /ts/tsconfig.json the name of the target file is build.js, but in Makefile the name of the file is bundle.js. So the GNU make is looking that bundle.js does not exist and rebuild project.

Related

change prerequisites in makefile at runtime

I am relatively new to make and don't know how to do one specific thing:
The overall process should look something like this:
the source files are java sources in a directory like src/org/path/to/packages/*.java
I want only to translate a specific java file, but the translation process will automatically translate all dependencies (I say 'translate' because I use j2objc to translate the java files to obj-c files - but that should be of no concern for this question)
The translated files will be put into the build/ directory with a folder structure reflecting the source folder structure (so build/org/path/to/packages/.m+.h)
These *.m and *.h files will then be compiled with j2objcc (a clang wrapper) into *.o files -> this step has to be done per file so every file is compiled with a command like j2objcc -c build/org/path/to/packages/file1.m -o build/org/path/to/package/file1.o
these shall be combined into a static library using ar
My problem is that I know which (one) java file I am starting with, but after step 2 I don't know which *.m and *.h files are generated/translated into the build directory. I'd like to read the contents of the build dir after step 2 with a command like find ./build -name '*.m' at make runtime but I don't know how to use this as a prerequisite in the make target.

how to compile from src directory to bin directory?

I have a src directory that contains main.ml and compose.ml files, and i need to compile from that directory and store the binary result in bin directory.
How can i make it?
I am assuming here that main.ml is the main program and compose.ml a module it uses. Then the compilation process will produce files compose.cmo (or compose.cmx), compose.cmi, and the final binary.
It is not quite clear, where you want the intermediate files (compose.cmo and compose.cmi) to go.
If you are fine with them being in src, you can use the -o command line option in the final compilation step.
If you want to keep the source directory clean but are fine with extra stuff going to bin, I suggest symlinking your source files to bin and compile there.
If you want to keep both src and bin clean, you can use a third directory like build, where you symlink the sources, compile, and copy the final binary to bin.
The easiest solution is probably to use ocamlbuild:
ocamlbuild -I src -no-links main.native
ln -f _build/src/main.native bin/main
This will leave the temporary files in the _build directory, which you can later remove with ocamlbuild -clean or rm -r _build.
Use main.byte instead of main.native instead if you want to build the bytecode version.

Using automake with files that may not be present in the source tree

I am transitioning to git-annex for storing data files in my git repo. With git-annex you can clone a repository and exclude the files in the annex until you specifically request them. So, Im trying to create a system in which users can build the src tree without the git-annexed data files being present during the make stage. Currently, we assume the files are present on the users filesystem, so the following snippet of the Makefile.am is sufficient:
foo_DATA=datafile1 datafile2 datafile3
EXTRA_DIST=$(foo_DATA)
However, when using the _DATA primary, an error is generated when the user attempts to make and any of the files in the list are not present. So my question is, is there a way to define the data files so that no error is generated when the data file is not present during make, but behaves exactly as the above code if the files are present during the make install step?
I have tried avoiding the _DATA primary altogether, doing something simple like the follow:
data_files=datafile1 datafile2 datafile3
install:
test -z $(foodir) || mkdir -p $(foodir)
install -c -m 644 $(data_files) $(foodir)
But that is rather hackey. Im hardcoding the "install" binary and the permission flags instead of getting them from the configure script. Ide rather just have automake not fail during the make step if the files were not present, but behave as expected in all other circumstances.
TLDR: Can I define a set of files using the _DATA primary that will not error out during make if the file is not present? But also installs exactly as the _DATA primary would if it were present?
Your current approach seems reasonable. I'd write it as an install-data-local hook, though:
data_files=datafile1 datafile2 datafile3
install-data-local:
test -z $(foodir) || $(MKDIR_P) $(foodir)
$(INSTALL_DATA) $(data_files) $(foodir)
MKDIR_P and INSTALL_DATA should be set up for you by automake.
If you'd rather not do this, the following may work in combination with your first Makefile.am snippet. I've not used git-annex before, so this may be wrong:
$(foo_DATA) :
if test ! -e $#; then git annex get $#; fi

Automake: Remove configure script checks with make dist

I'm wondering if there is a way to remove dependency checks from a configure script when make dist is run. The purpose is that the version of the package in the repository uses emacs to execute lisp files and generate .c files, whereas those generated source files are included in the tarball when make dist is run. Automake supports including built files in the output tarball simply by setting EXTRA_DIST in the Makefile. I would like to be able to check for emacs only when someone tries to compile from the repository, but not when someone compiles from the tarball.
More concretely, in configure.ac I have:
AM_PATH_LISPDIR
AS_IF([test "$EMACS" = no], [AC_MSG_ERROR([cannot find emacs])])
but I would like that check not to occur after make dist is run. Any way to do this? If not, how is this case normally handled?
The best method I've come up with is to check for the presence of the Bootstrap file. Bootstrap is removed from the tarball after make dist is run.
AC_CHECK_FILE([Bootstrap])
if test "$ac_cv_file_Bootstrap" == yes ; then
<check for emacs>
fi
I'd normally set a conditional if I find the tool in configure.ac:
AM_PATH_LISPDIR
AM_CONDITIONAL([HAVE_EMACS_IN_REPOSITORY], [test "x$EMACS" != xno -a -d ".git"])
AS_IF([test "$EMACS" = no -a -d ".git"], [AC_MSG_ERROR([cannot find emacs])])
Then in Makefile.am
if HAVE_EMACS_IN_REPOSITORY
Execute lisp files...
Generate .c files...
endif
Usually configure ends up in the same location as .git. If not, the path can be adjusted.

Make - autogenerated file issue

Here is the context :
I am working on a makefile to create a .h at every build, including another makefile that will use this header. I can't edit the second one.
Using a target all depending on my file, it compiles the first time, creating the missing MyHeader.h. The problem is, when I recompile, the header is not regenerated...
My makefile looks like this :
all: myHeader.h
myHeader.h:
scriptToBuildMyHeader.sh
include obscureAndPrivateMakefile.make
I also tried with a .phony target at the beginning. Same result : once created, it won't be regenerated at every build.
PS : I can't call a script before make.
Do some makfile-Masters have any ideas how to deal with that ?
Thanks!
Because myHeader.h has no dependencies, it will never be rebuilt once it exists. You can work around this by creating a dependency from myHeader.h to a phony target, eg:
forcebuild:
# dummy; do nothing and don't create this file
.PHONY: forcebuild
myHeader.h: forcebuild
scriptToBuildMyHeader.sh
This will however slow down your build considerably, as the header (and any source files including it) will need to be rebuilt every time.
The trouble is that because myHeader.h does not depend on anything, it exists and is therefore up to date on the second build. To make sure it is built each time, it has to depend on a non-existent file:
myHeader.h: .FORCE
scriptToBuildMyHeader.sh
.FORCE:
The name '.FORCE' (or, sometimes, FORCE) is used classically.
If you use GNU Make, you could make the 'non-existent' file into a phony target:
.PHONY: .FORCE
The advantage of this is that (GNU) make does not create the file .FORCE even if you run make -t - which would break the automatic rebuild of the header because that rule depends on there not being a file .FORCE that actually exists.
Here's another possible approach:
all: clean foo.txt
clean:
rm foo.txt
foo.txt:
echo > foo.txt
where I'm using echo > foo.txt to simulate creation of your header.

Resources