Difference between revisions of "Writing Makefiles"

From Apertium
Jump to navigation Jump to search
Line 44: Line 44:
   
 
(The <code>PRECIOUS</code> line prevents the .d file from being cleaned up and removed automatically.)
 
(The <code>PRECIOUS</code> line prevents the .d file from being cleaned up and removed automatically.)
  +
  +
==Removing directories on make clean==
  +
Say you want to remove .deps and modes on "make clean". Don't do </code>CLEANFILES=-rf .deps modes file1 file2 …</code>, it doesn't work everywhere.
  +
  +
A more portable solution is this:
  +
<pre>
  +
CLEANFILES = $(TARGETS_COMMON)
  +
clean-local:
  +
-rm -rf .deps modes
  +
</pre>

Revision as of 06:33, 24 October 2013

Some tips for writing clean Makefile.am's in Apertium:

Avoid ending up with root-owned modes files

When you do "sudo make install", some Makefiles.am still have a bug where they'll leave around root-owned modes files. Then on the next "make", you see a "Permission denied" error, since it tries to create the same filenames again as non-root. (The installable mode files have paths pointing to e.g. /usr/local, while the non-install mode files have paths that point to your source development directory. You want the latter to hang around so you can do apertium -d . fie-bar.)

A workaround is this: when doing make install, first stash away any already existing development modes directory, the generate the install modes, then clean up the root-owned stuff and unstash the old modes directory:

install-data-local:
	mv modes modes.bak
	apertium-gen-modes modes.xml $(BASENAME)
	rm -rf modes
	mv modes.bak modes
	test -d $(DESTDIR)$(apertium_modesdir) || mkdir $(DESTDIR)$(apertium_modesdir)
	$(INSTALL_DATA) $(PREFIX1).mode $(DESTDIR)$(apertium_modesdir)
	$(INSTALL_DATA) $(PREFIX2).mode $(DESTDIR)$(apertium_modesdir)
	rm $(PREFIX1).mode $(PREFIX2).mode

This method leaves no root-owned files hanging around.

(It might look odd that we "rm -rf modes" there after gen-modes, but "apertium-gen-modes somedir" creates both apertium-foo-bar/foo-bar.mode and non-installable debug modes in apertium-foo-bar/modes/ – perhaps tihs could be fixed in apertium-gen-modes so we can avoid this makefile workaround.)

Use .deps/.d to say that the .deps directory must be created

Say you have several goals that put temporary files in .deps/, e.g.

.deps/apertium-wat-lol.lol.dix: apertium-wat-lol.lol.dix
	test -d .deps || mkdir .deps
	xsltproc lexchoicebil.xsl $< >$@

and so on. The .deps directory has to be created for the file in .deps to be created. If you put mkdir .deps in each such goal, you can get a race condition where two goals try to make .deps at the same time.

The solution is this: if a goal needs the .deps directory to be created, let it depend on the file .deps/.d. First put this in Makefile.am:

.deps/.d:
	test -d .deps || mkdir .deps
	touch $@

.PRECIOUS: .deps/.d

And then, instead of creating the dir in each goal, just depend on .deps/.d for those goals:

.deps/apertium-wat-lol.lol.dix: apertium-wat-lol.lol.dix .deps/.d
	xsltproc lexchoicebil.xsl $< >$@

(The PRECIOUS line prevents the .d file from being cleaned up and removed automatically.)

Removing directories on make clean

Say you want to remove .deps and modes on "make clean". Don't do CLEANFILES=-rf .deps modes file1 file2 …, it doesn't work everywhere.

A more portable solution is this:

CLEANFILES = $(TARGETS_COMMON)
clean-local: 
	-rm -rf .deps modes