Commit 9b6d2d92 authored by Petr Pudlak's avatar Petr Pudlak
Browse files

Compile every Haskell object file separately



This allows parallel compilation of all targets, including the Haskell
object files. While re-starting GHC for every Haskell source almost
doubles the total CPU time, allowing it run in parallel at the end cuts
down the wall-clock time to half.

Haskell targets are split into two: main ones and testing ones.
The testing targets (starting with "test/") are build with coverage
automatically. Therefore the testing object and interface files have
different extensions (this also allows their parallel compilation).

GHC is now used to produce a separate Makefile.ghc with all
dependencies. This is then included and used for compiling each object
file separately.

Note that the inclusion + generation of Makefile.ghc is turned off when
calling clean/ganeti/distclean. For some reason, Makefile infinitely
recurses when calling "make ganeti", if it includes Makefile.ghc. But
since using ifneq/endif in Makefile.am conflicts with Automake, it was
necessary to put the snippet into an Automake variable and substitute it
into the resulting Makefile.
Signed-off-by: default avatarPetr Pudlak <pudlak@google.com>
Reviewed-by: default avatarKlaus Aehlig <aehlig@google.com>
parent 1551758e
......@@ -239,6 +239,10 @@ CLEANFILES = \
$(addsuffix /*.py[co],$(DIRS)) \
$(addsuffix /*.hi,$(HS_DIRS)) \
$(addsuffix /*.o,$(HS_DIRS)) \
$(addsuffix /*.$(HTEST_SUFFIX)_hi,$(HS_DIRS)) \
$(addsuffix /*.$(HTEST_SUFFIX)_o,$(HS_DIRS)) \
Makefile.ghc \
Makefile.ghc.bak \
$(PYTHON_BOOTSTRAP) \
$(gnt_python_sbin_SCRIPTS) \
epydoc.conf \
......@@ -614,6 +618,9 @@ HS_DEFAULT_PROGS = \
HS_ALL_PROGS = $(HS_DEFAULT_PROGS) $(HS_MYEXECLIB_PROGS)
HS_TEST_PROGS = $(filter test/%,$(HS_ALL_PROGS))
HS_SRC_PROGS = $(filter-out test/%,$(HS_ALL_PROGS))
HS_PROG_SRCS = $(patsubst %,%.hs,$(HS_DEFAULT_PROGS)) src/mon-collector.hs
HS_BUILT_TEST_HELPERS = $(HS_BIN_ROLES:%=test/hs/%) test/hs/hail
......@@ -623,6 +630,22 @@ HFLAGS = \
-fwarn-tabs \
$(GHC_BYVERSION_FLAGS)
if HPROFILE
HFLAGS += -prof -auto-all
endif
if HCOVERAGE
HFLAGS += -fhpc
endif
if HTEST
HFLAGS += -DTEST
endif
HTEST_SUFFIX = hpc
HTEST_FLAGS = $(HFLAGS) -fhpc -itest/hs \
-osuf .$(HTEST_SUFFIX)_o \
-hisuf .$(HTEST_SUFFIX)_hi
# extra flags that can be overriden on the command line (e.g. -Wwarn, etc.)
HEXTRA =
# internal extra flags (used for test/hs/htest mainly)
......@@ -989,60 +1012,46 @@ install-exec-hook:
$(LN_S) -f htools $(DESTDIR)$(bindir)/$$role ; \
done
HNORMAL_SUFFIX = .o
HPROFILE_SUFFIX = .prof.o
HCOVERAGE_SUFFIX = .hpc.o
HTEST_SUFFIX = .test.o
HS_SRCS = $(HS_LIBTESTBUILT_SRCS)
HSUFFIX = $(if $(HPROFILE),$(HPROFILE_SUFFIX), \
$(if $(HCOVERAGE),$(HCOVERAGE_SUFFIX), \
$(if $(HTEST),$(HTEST_SUFFIX), \
$(HNORMAL_SUFFIX))))
Makefile.ghc: $(HS_ALL_PROGS:%=%.hs) $(HS_SRCS) Makefile | $(built_base_sources)
$(GHC) -M -dep-makefile $@ -dep-suffix $(HTEST_SUFFIX) $(HFLAGS) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) $(HS_ALL_PROGS:%=%.hs) $(HS_SRCS)
HFLAGS += $(if $(HPROFILE),-prof -auto-all,)
HFLAGS += $(if $(HCOVERAGE),-fhpc,)
HFLAGS += $(if $(HTEST),-DTEST,)
@include_makefile_ghc@
HS_SRCS = $(HS_LIBTESTBUILT_SRCS)
%.o:
$(GHC) -c $(HFLAGS) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) $(@:%.o=%.hs)
%.$(HTEST_SUFFIX)_o:
$(GHC) -c $(HTEST_FLAGS) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) $(@:%.$(HTEST_SUFFIX)_o=%.hs)
.NOTPARALLEL: $(HS_ALL_PROGS)
.PHONY: $(HS_ALL_PROGS)
$(HS_ALL_PROGS): %: %.hs $(HS_SRCS) Makefile
@if [ "$(notdir $@)" = "test" ] && [ "$(HS_NODEV)" ]; then \
%.hi: %.o ;
%.$(HTEST_SUFFIX)_hi: %.$(HTEST_SUFFIX)_o ;
$(HS_SRC_PROGS): %: %.o | stamp-directories
$(GHC) $(HFLAGS) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) --make $(@:%=%.hs)
@rm -f $(notdir $@).tix
@touch "$@"
$(HS_TEST_PROGS): %: %.$(HTEST_SUFFIX)_o \
| stamp-directories $(BUILT_PYTHON_SOURCES)
@if [ "$(HS_NODEV)" ]; then \
echo "Error: cannot run unittests without the development" \
" libraries (see devnotes.rst)" 1>&2; \
exit 1; \
fi
$(GHC) $(HTEST_FLAGS) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) --make $(@:%=%.hs)
@rm -f $(notdir $@).tix
$(GHC) --make $(HFLAGS) \
-osuf $(HSUFFIX) \
-hisuf $(patsubst %.o,%.hi,$(HSUFFIX)) \
$(HS_PARALLEL3) $(HS_REGEX_PCRE) $(HEXTRA) $@
@touch "$@"
# for the test/hs/htest binary, we need to enable profiling/coverage
test/hs/htest: HCOVERAGE = true
test/hs/htest: HFLAGS += -itest/hs
test/hs/htest: | $(BUILT_PYTHON_SOURCES)
# we compile the hpc-htools binary with the program coverage
test/hs/hpc-htools: HCOVERAGE = true
# we compile the hpc-mon-collector binary with the program coverage
test/hs/hpc-mon-collector: HCOVERAGE = true
# test dependency
test/hs/offline-test.sh: test/hs/hpc-htools test/hs/hpc-mon-collector
# rule for building profiling-enabled versions of the haskell programs
.PHONY: hs-prof
hs-prof:
@if [ -z "$(TARGET)" ]; then \
echo "You need to define TARGET when running this rule" 1>&2; \
exit 1; \
fi
$(MAKE) $(AM_MAKEFLAGS) HPROFILE=y $(TARGET)
dist_sbin_SCRIPTS = \
tools/ganeti-listrunner
......
......@@ -809,6 +809,18 @@ fi
AC_SUBST(PY_NODEV)
AM_CONDITIONAL([PY_UNIT], [test -n $PY_NODEV])
include_makefile_ghc='
ifneq ($(MAKECMDGOALS),ganeti)
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
include Makefile.ghc
endif
endif
endif
'
AC_SUBST([include_makefile_ghc])
AM_SUBST_NOTMAKE([include_makefile_ghc])
AC_CONFIG_FILES([ Makefile ])
AC_OUTPUT
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment