How to execute a make target on file change automatically? - go

How do I write a make target that will watch for any file changes in specific folders and execute some other make target to compile files? I am looking for a way that can do this with minimal dependency on tools in addition to make itself to keep things simple.

For the watching you can use fswatch. (There's also a go version of this program which may be easier to install: fswatch) For example:
fswatch -ext cpp,c,h make -f Makefile
Anytime you change a cpp, c or h file it will run make again.
Make can be a bit slow for this, so I tend to use ninja instead, but that really depends on the size of your project.
Another option is tup, which has watching built-in:
tup monitor
But, sadly, only for linux.

You can use entr and adjust your Makefile similar to this one
.DEFAULT_GOAL := run
SHELL := /bin/bash
run:
clear && \
cp one.txt two.txt && \
rm -f _* *.l2m *.o2m && \
Ganlib < testgan2.x2m
watch:
while sleep 1 ; do find . -name '*.x2m' -o -name '*.c2m' \
| entr -d make -f ./Makefile ; done
.PHONY: run watch
followed by
$ make watch

Related

Make: Can we have directories as a target in GNUmakefile

I am working on GNUmake to create symlink to specific file by parsing whole directory which has a folder which needs to be linked.
Here is my makefile snippet.
TGT_LINK = /lan/test/workspace/build/tools
all_target: release_buid complete_test $(TGT_LINK)
$(TGT_LINK):
if [ ! -d $# ]; then mkdir -p $#; fi
cd $#; \
tar_ln=`\ls -d synopsystcl* | sed 's/synopsys//'`; \
sour_dir=`\ls -d synopsystcl*`; \
if ! [ -e $tar_ln ]; then \
ln -s $sour_dir $tar_ln; \
fi
Directory : /lan/test/workspace/build/tools Contains following content in it
polaris.so link.a dynamic.so kbuild.so README.txt license.txt synopsystcl5.5 build.json
Here i am trying to create symlink with name tcl5.5 pointing to synopsystcl5.5 with my above target $(TGT_LINK) code.
tcl5.5 -> synopsystcl5.5
After successful completion of two targets : release_buid complete_test , build is not proceeding to go for next target $(TGT_LINK) to create symlink. Could you please help whats wrong in code?
I would let make itself to check and recreate symlink as needed, i.e.:
TGT_LINK = /lan/test/workspace/build/tools
all_target: release_buid complete_test symlink
.PHONY: symlink
symlink: $(patsubst $(TGT_LINK)/tcl%, $(TGT_LINK)/synopsystcl%, $(wildcard $(TGT_LINK)/tcl*))
$(TGT_LINK)/synopsystcl%: $(TGT_LINK)/tcl%
set -e; \
cd $(#D); \
rm -f $(#F); \
ln -s $(<F) $(#F)
I would also consider reordering targets if there are dependencies indeed. One should never assume that dependency list is processed left to right; it will also lead to errors when parallel build (-j) is involved. If you have dependencies that something should happen before something else, it should be explicitly stated, e.g.:
all_target: symlink
symlink: complete_test
complete_test: release_buid

How does "make dist" command work? I'm stuck on a script which I need to update to add new file and folder

I've to add a file and a folder to the zip that is created when I run make dist command. This is an open-source project.
After research, I understood I've to modify the Makefile.am but examples online don't work or match with my current Makefile.am
Makefile.am
SUBDIRS = bin data po src extensions docs
DISTCLEANFILES = \
intltool-extract \
intltool-merge \
intltool-update
EXTRA_DIST = \
$(bin_SCRIPTS) \
intltool-merge.in \
intltool-update.in \
intltool-extract.in
DISTCHECK_CONFIGURE_FLAGS = --disable-update-mimedb
check-po:
#for i in $(top_srcdir)/po/*.po ; do \
if ! grep -q ^`basename $$i | \
sed 's,.po,,'`$$ $(top_srcdir)/po/LINGUAS ; then \
echo '***' `basename $$i | \
sed 's,.po,,'` missing from po/LINGUAS '***' ; \
exit 1; \
fi; \
done;
lint:
flake8 --ignore E402 $(top_srcdir)/src $(top_srcdir)/extensions
test: lint check-po
PYTHONPATH=$(pkgdatadir)/extensions:$(PYTHONPATH) \
python -m sugar3.test.discover $(top_srcdir)/tests
configure.ac
AC_INIT([Sugar],[0.114],[],[sugar])
AC_PREREQ([2.59])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([configure.ac])
SUCROSE_VERSION="0.114"
AC_SUBST(SUCROSE_VERSION)
AM_INIT_AUTOMAKE([1.9 foreign dist-xz no-dist-gzip])
AM_MAINTAINER_MODE
PYTHON=python2
AM_PATH_PYTHON
AC_PATH_PROG([EMPY], [empy])
if test -z "$EMPY"; then
AC_MSG_ERROR([python-empy is required])
fi
PKG_CHECK_MODULES(SHELL, gtk+-3.0)
IT_PROG_INTLTOOL([0.35.0])
GETTEXT_PACKAGE=sugar
AC_SUBST([GETTEXT_PACKAGE])
AM_GLIB_GNU_GETTEXT
AC_ARG_ENABLE(update-mimedb,
AC_HELP_STRING([--disable-update-mimedb],
[disable the update-mime-database after install [default=no]]),,
enable_update_mimedb=yes)
AM_CONDITIONAL(ENABLE_UPDATE_MIMEDB, test x$enable_update_mimedb = xyes)
GLIB_GSETTINGS
AC_CONFIG_FILES([
bin/Makefile
bin/sugar
data/icons/Makefile
data/Makefile
extensions/cpsection/aboutcomputer/Makefile
extensions/cpsection/aboutme/Makefile
extensions/cpsection/background/Makefile
extensions/cpsection/backup/Makefile
extensions/cpsection/backup/backends/Makefile
extensions/cpsection/datetime/Makefile
extensions/cpsection/frame/Makefile
extensions/cpsection/keyboard/Makefile
extensions/cpsection/language/Makefile
extensions/cpsection/modemconfiguration/Makefile
extensions/cpsection/Makefile
extensions/cpsection/network/Makefile
extensions/cpsection/power/Makefile
extensions/cpsection/updater/Makefile
extensions/cpsection/webaccount/services/Makefile
extensions/cpsection/webaccount/Makefile
extensions/deviceicon/Makefile
extensions/globalkey/Makefile
extensions/webservice/Makefile
extensions/Makefile
Makefile
po/Makefile.in
src/jarabe/config.py
src/jarabe/controlpanel/Makefile
src/jarabe/desktop/Makefile
src/jarabe/frame/Makefile
src/jarabe/intro/Makefile
src/jarabe/journal/Makefile
src/jarabe/Makefile
src/jarabe/model/Makefile
src/jarabe/model/update/Makefile
src/jarabe/util/Makefile
src/jarabe/util/telepathy/Makefile
src/jarabe/view/Makefile
src/jarabe/webservice/Makefile
src/Makefile
])
AC_OUTPUT
When I run the command make dist, the output zip doesn't include a file and folder which I now need to add. I'm not able to understand where in the code(Makefile.am or configure.ac) should I make changes.
I've to add a file and a folder to the zip that is created when I run make dist command.
I take it that these are not already included in the distribution. If you're not sure, then check -- Automake-based build systems such as yours identify a lot of files automatically for inclusion in distribution packages.
Supposing that these files are not already included, there are several ways to cause them to be. Easiest would be to add them to the EXTRA_DIST variable, yielding
EXTRA_DIST = \
$(bin_SCRIPTS) \
intltool-merge.in \
intltool-update.in \
intltool-extract.in \
a_directory \
some_file.ext
Don't forget the trailing backslashes if you continue with the multiline form (which I like, as I find it much easier to read). You can specify a path to the file, the directory, or both. Do note that in the case of the directory, it will be not just the directory itself but all its contents, recursively, that are included in the distribution. This is all documented in the manual.
If you need finer control, then there is also an extension point for managing the contents of the distribution in the form of the "dist hook". This comprises a make target named dist-hook. Like any other literal make rule in your Makefile.am, any rule you provide for building that target is copied to the final generated Makefile, and if such a rule is present then its recipe is run as part of building the distribution, after the distribution directory is otherwise populated but before the archive file is built from that. You can write more or less arbitrary shell code in that target's recipe to tweak the distribution. Follow the above link to the documentation for the gory details.
EXTRA_DIST variable sounds like the thing.

Why command "go clean -n -r -i github.com/ethereum/go-ethereum..." does not work?

What I did were as follows step by step:
Git clone go-ethereum project to my local PC. It is located in
D:\GOPATH\src\github.com\ethereum\go-ethereum. It is the source code
of go-ethereum
Note: The OS is windows 7. Go has already been installed. And GOPATH env has already been set to "D:\GOPATH"
cd /d D:\GOPATH\src\github.com\ethereum\go-ethereum. Then execute
"go install". Some exe files were genereated under D:\GOPATH\bin
directory, and many pkg file with suffix .a were generated under
D:\GOPATH\pkg directory. Everything seems no problem.
Execute "go clean -n -r -i github.com/ethereum/go-ethereum..." to
remove all the generated exe files and .a files. But something very
interesting happened:
In the command's log, it showed that some files are deleted, but actually they are not deleted from disk.
For example, event.a exists under D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum, but the log of "git clean" shows:"rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\event.a"
The detailed information is in the attached images.
It is very strange. The log does not match with the actual result:
A small segment of go clean command is as follows(since there are more than 1300 lines in log, I can not paste all of it):
cd D:\GOPATH\src\github.com\ethereum\go-ethereum\event
rm -f event.test event.test.exe
rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\event.a
cd D:\GOPATH\src\github.com\ethereum\go-ethereum\common\mclock
rm -f mclock.test mclock.test.exe
rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\common\mclock.a
cd D:\GOPATH\src\github.com\ethereum\go-ethereum\vendor\github.com\aristanetworks\goarista\monotime
rm -f monotime.test monotime.test.exe
rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\vendor\github.com\aristanetworks\goarista\monotime.a
cd D:\GOPATH\src\github.com\ethereum\go-ethereum\accounts\abi
rm -f abi.test abi.test.exe
rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\accounts\abi.a
cd D:\GOPATH\src\github.com\ethereum\go-ethereum\accounts\abi\bind
rm -f bind.test bind.test.exe
rm -f D:\GOPATH\pkg\windows_amd64\github.com\ethereum\go-ethereum\accounts\abi\bind.a
But some of the files remain:
The correct answer is actually provided by #Peter in comment. As Peter said "The -n flag causes clean to print the remove commands it would execute, but not run them."
I tried "-x" instead of "-n", and it works well. Thanks Peter. But you posted your answer in comment section, so I have to post your answer here and close this question.

Why does following makefile rebuilt target "build" everytime

I have the following code to untar all the files in a directory and move it to build directory. If I call make multiple times, it tries to execute "build" target everytime even if build directory already exists. Has anyone comes across this?
I found this question but it is not the same.
Makefile always running target
OS: Ubuntu 12.04
Program: GNU Make 3.81
build: mkBuildDir untar
chmod 700 build
.PHONY: mkBuildDir untar
mkBuildDir:
mkdir build
untar: *.tar.gz
for prefix in *.tar.gz; do \
tar xvf $$prefix --directory=build; \
done
clean:
rm -Rf build
This is pretty much the same as the question you've linked. You never create a file called mkBuildDir, so it's always out-of-date, so build is always out of date.
Your mkBuildDir target isn't doing anything useful (though I presume this is a cut-down makefile). If instead you did
# it'd be better to list the TARFILES explicitly, though this will probably work
TARFILES=`ls *.tar.gz`
all: build untar
build: $(TARFILES)
test -d build || mkdir build
chmod 700 build
for prefix in $(TARFILES); do \
tar xvf $$prefix --directory=build; \
done
clean:
rm -Rf build
that would probably accomplish what you're looking for.
Having too many phony targets in a Makefile is usually a makefile 'code smell'. They are rarely the best/idiomatic way of doing things.

Make install causes recompiles

I am writing a master makefile to compile and install multiple autoconf based libraries, which depend on each other. All works well for the first go. The issue is: if I am working on one of these libraries individually and do "make && make install" header files in the prefix folder are overwritten (even if they are untouched). This causes all dependent libraries to compile from scratch.
Is there a way to avoid the unnecessary recompiles without hacking into the makefiles?
Maybe the solution is a little late, but
./configure INSTALL="install -p"
fixes the recompilation problem. This flag makes GNU install set the timestamps of the installed files to the timestamps of the built files.
You could use sentinel files that exist only to establish your dependency graph. For eg.
prefix := /usr/local
.PHONY: all
all: libx-built
libx-built \
: libx.tar.gz \
; tar xzvf $# \
&& cd libx \
&& ./configure --prefix=$(prefix) \
&& make && make install \
&& touch $#
Then, you'd make a dependent liby build only when libx-built is new.
liby-built \
: liby.tar.gz libx-built \
; ...

Resources