There are two observations which make this possible: (1) virt-sparsify
contains at least one C unit, so automake thinks it is compiling a C
program. (2) Automake lets us add a *_LINK rule to override linking.
We list the C sources of virt-sparsify as virt_sparsify_SOURCES, so
automake thinks it is building a C program as normal.
We override virt_sparsify_LINK to make it actually link an OCaml
program.
We add virt_sparsify_DEPENDENCIES listing the OCaml objects so that
they get built before linking.
We need a small linker script (link.sh) which adds some options at the
end of the linker command line which are impossible to add using pure
automake.
Inspired by the same idea in supermin:
https://github.com/libguestfs/supermin/blob/master/src/Makefile.am
---
.gitignore | 1 +
configure.ac | 2 +
sparsify/Makefile.am | 104 ++++++++++++++++++++++-----------------------------
sparsify/link.sh.in | 22 +++++++++++
4 files changed, 69 insertions(+), 60 deletions(-)
create mode 100644 sparsify/link.sh.in
diff --git a/.gitignore b/.gitignore
index dc8aaf8..3e6a084 100644
--- a/.gitignore
+++ b/.gitignore
@@ -414,6 +414,7 @@ Makefile.in
/ruby/Rakefile
/run
/sparsify/.depend
+/sparsify/link.sh
/sparsify/stamp-virt-sparsify.pod
/sparsify/virt-sparsify
/sparsify/virt-sparsify.1
diff --git a/configure.ac b/configure.ac
index 8abdc90..f48a8d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1607,6 +1607,8 @@ AC_CONFIG_FILES([podwrapper.pl],
[chmod +x,-w podwrapper.pl])
AC_CONFIG_FILES([run],
[chmod +x,-w run])
+AC_CONFIG_FILES([sparsify/link.sh],
+ [chmod +x,-w sparsify/link.sh])
AC_CONFIG_FILES([Makefile
align/Makefile
diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am
index 5e1b382..bcb95a2 100644
--- a/sparsify/Makefile.am
+++ b/sparsify/Makefile.am
@@ -1,5 +1,5 @@
# libguestfs virt-sparsify tool
-# Copyright (C) 2011 Red Hat Inc.
+# Copyright (C) 2011-2014 Red Hat Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,52 +18,50 @@
include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
- $(SOURCES) \
+ $(SOURCES_ML) $(SOURCES_C) \
virt-sparsify.pod \
test-virt-sparsify.sh \
test-virt-sparsify-in-place.sh
CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-sparsify
-# Alphabetical order.
-SOURCES = \
+SOURCES_ML = \
cmdline.ml \
copying.ml \
in_place.ml \
- sparsify.ml \
+ sparsify.ml
+
+SOURCES_C = \
+ $(top_builddir)/fish/progress.c \
+ $(top_builddir)/mllib/tty-c.c \
+ $(top_builddir)/mllib/progress-c.c \
statvfs-c.c
if HAVE_OCAML
-# Note this list must be in dependency order.
-deps = \
- $(top_builddir)/fish/guestfish-progress.o \
- $(top_builddir)/mllib/tty-c.o \
- $(top_builddir)/mllib/progress-c.o \
- $(top_builddir)/mllib/common_gettext.cmx \
- $(top_builddir)/mllib/common_utils.cmx \
- $(top_builddir)/mllib/tTY.cmx \
- $(top_builddir)/mllib/progress.cmx \
- $(top_builddir)/mllib/config.cmx \
- statvfs-c.o \
- cmdline.cmx \
- copying.cmx \
- in_place.cmx \
- sparsify.cmx
+bin_PROGRAMS = virt-sparsify
-if HAVE_OCAMLOPT
-OBJECTS = $(deps)
-else
-OBJECTS = $(patsubst %.cmx,%.cmo,$(deps))
-endif
+virt_sparsify_SOURCES = $(SOURCES_C)
+virt_sparsify_CFLAGS = \
+ -I. \
+ -I$(top_builddir) \
+ -I$(shell $(OCAMLC) -where) \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/fish
-bin_SCRIPTS = virt-sparsify
+BOBJECTS = \
+ $(top_builddir)/mllib/common_gettext.cmo \
+ $(top_builddir)/mllib/common_utils.cmo \
+ $(top_builddir)/mllib/tTY.cmo \
+ $(top_builddir)/mllib/progress.cmo \
+ $(top_builddir)/mllib/config.cmo \
+ $(SOURCES_ML:.ml=.cmo)
+XOBJECTS = $(BOBJECTS:.cmo=.cmx)
# -I $(top_builddir)/src/.libs is a hack which forces corresponding -L
# option to be passed to gcc, so we don't try linking against an
# installed copy of libguestfs.
-OCAMLPACKAGES = \
- -package str,unix \
+OCAMLPACKAGES = -package str,unix \
-I $(top_builddir)/src/.libs \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/mllib
@@ -71,45 +69,31 @@ if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
endif
-OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES)
-OCAMLOPTFLAGS = $(OCAMLCFLAGS)
+OCAMLFLAGS = -g -warn-error CDEFLMPSUVYZX
-if HAVE_OCAMLOPT
-virt-sparsify: $(OBJECTS)
- $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
- mlguestfs.cmxa -linkpkg $^ \
- -cclib -lncurses \
- $(OCAML_GCOV_LDFLAGS) \
- -o $@
+if !HAVE_OCAMLOPT
+OBJECTS = $(BOBJECTS)
+BEST = c
+OCAMLFLAGS += -custom
+OCAMLPACKAGES += mlguestfs.cma
else
-virt-sparsify: $(OBJECTS)
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) \
- mlguestfs.cma -linkpkg $^ \
- -cclib -lncurses \
- -custom \
- $(OCAML_GCOV_LDFLAGS) \
- -o $@
+OBJECTS = $(XOBJECTS)
+BEST = opt
+OCAMLPACKAGES += mlguestfs.cmxa
endif
+virt_sparsify_DEPENDENCIES = $(OBJECTS)
+
+virt_sparsify_LINK = \
+ ./link.sh \
+ $(OCAMLFIND) $(BEST) $(OCAMLFLAGS) $(OCAMLPACKAGES) $(OBJECTS) -o $@
+
.mli.cmi:
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmo:
- $(OCAMLFIND) ocamlc $(OCAMLCFLAGS) -c $< -o $@
+ $(OCAMLFIND) ocamlc $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
.ml.cmx:
- $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
-
-# automake will decide we don't need C support in this file. Really
-# we do, so we have to provide it ourselves.
-
-DEFAULT_INCLUDES = \
- -I. \
- -I$(top_builddir) \
- -I$(shell $(OCAMLC) -where) \
- -I$(top_srcdir)/src \
- -I$(top_srcdir)/fish
-
-.c.o:
- $(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+ $(OCAMLFIND) ocamlopt $(OCAMLFLAGS) $(OCAMLPACKAGES) -c $< -o $@
# Manual pages and HTML files for the website.
diff --git a/sparsify/link.sh.in b/sparsify/link.sh.in
new file mode 100644
index 0000000..50bcc1f
--- /dev/null
+++ b/sparsify/link.sh.in
@@ -0,0 +1,22 @@
+# libguestfs Makefile.am
+# @configure_input@
+# (C) Copyright 2014 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Hack automake to link binary properly. There is no other way to add
+# the -cclib parameter to the end of the command line.
+
+exec "$@" -linkpkg -cclib '-lncurses'
--
1.8.5.3