diff mbox

[RFC,4/6] Makefile: introduce common-obj-m and block-obj-m for DSO

Message ID 1378376448-29036-5-git-send-email-famz@redhat.com
State New
Headers show

Commit Message

Fam Zheng Sept. 5, 2013, 10:20 a.m. UTC
Add necessary rules and flags for shared object generation.
common-obj-m will include block-obj-m, as common-obj-y for block-obj-y.
The rules introduced here are:

  QEMU_CFLAGS += -shared -fPIC, for all %.o of shared objects.

  1) %.o in $(common-obj-m) is compiled to %.o, with
     "QEMU_CFLAGS += -shared -fPIC". Then "linked" to %.mo, which is an
     incremental object with "ln -r". This step is for consistency with
     %.mod case and has no effect.

  2) %.mod in $(common-obj-m) is generated by "ln -r", with all its
     dependencies (multiple *.o) as input. Which means the list of
     dependency objects must be ruled out in each sub-Makefile.objs
     like:

        $(obj)/foo.mod: $(addprefix $(obj)/,bar.o baz.o qux.o)

     Notice that $(obj)/ is required for both target and dependency in
     the rule.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 Makefile      | 24 +++++++++++++++++++++---
 Makefile.objs | 10 +++++++++-
 configure     |  3 +++
 rules.mak     |  6 ++++++
 4 files changed, 39 insertions(+), 4 deletions(-)

Comments

Richard Henderson Sept. 5, 2013, 7:24 p.m. UTC | #1
On 09/05/2013 03:20 AM, Fam Zheng wrote:
>   1) %.o in $(common-obj-m) is compiled to %.o, with
>      "QEMU_CFLAGS += -shared -fPIC". Then "linked" to %.mo, which is an
>      incremental object with "ln -r". This step is for consistency with
>      %.mod case and has no effect.

As a general rule, you should avoid ld -r unless you know exactly
what that implies for the given machine.  This is the sort of thing
that's highly likely to work on x86 while failing elsewhere.

E.g. ARM and PPC ld would like to add trampolines for direct calls
to reach the PLT entry.  If you create one object that's too large
then that's no longer possible.

E.g. MIPS and Alpha ld require that any one input object file
reference less than 64K worth of got entries.  Every separate
object file can address its own 64K segment of the got.  If you
combine too many objectsyou could overflow the got subsegments.

If our modules are small enough, we may never see any of these, but...

If you really require a single input file to ld for pattern matching
purposes, I highly recommend an ar file, and then use --whole-archive
to force the entire contents of the .a to be included.  This preserves
the original translation-unit boundaries for ld.


r~
Paolo Bonzini Sept. 5, 2013, 7:41 p.m. UTC | #2
Il 05/09/2013 21:24, Richard Henderson ha scritto:
> On 09/05/2013 03:20 AM, Fam Zheng wrote:
>>   1) %.o in $(common-obj-m) is compiled to %.o, with
>>      "QEMU_CFLAGS += -shared -fPIC". Then "linked" to %.mo, which is an
>>      incremental object with "ln -r". This step is for consistency with
>>      %.mod case and has no effect.
> 
> As a general rule, you should avoid ld -r unless you know exactly
> what that implies for the given machine.  This is the sort of thing
> that's highly likely to work on x86 while failing elsewhere.
> 
> E.g. ARM and PPC ld would like to add trampolines for direct calls
> to reach the PLT entry.  If you create one object that's too large
> then that's no longer possible.
> 
> E.g. MIPS and Alpha ld require that any one input object file
> reference less than 64K worth of got entries.  Every separate
> object file can address its own 64K segment of the got.  If you
> combine too many objectsyou could overflow the got subsegments.
> 
> If our modules are small enough, we may never see any of these, but...
> 
> If you really require a single input file to ld for pattern matching
> purposes, I highly recommend an ar file, and then use --whole-archive
> to force the entire contents of the .a to be included.  This preserves
> the original translation-unit boundaries for ld.

Yes, this is the reason why I suggested using libtool for this.  It
increases the cost of compilation by essentially doing it twice, on the
other hand you can simply use .la convenience libraries and libtool will
be able to link it transparently into either an executable or a shared
library.

Libtool used to be really bad, but most performance problems have been
solved.

Paolo
Peter Maydell Sept. 5, 2013, 9:45 p.m. UTC | #3
On 5 September 2013 20:41, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Libtool used to be really bad, but most performance problems have been
> solved.

How about the "it silently creates things in dot-directories,
recompiles things at random times when it really shouldn't,
and is an enormous insane shell script" problems? The positives
would have to be really really strong before we let libtool
into the codebase...

-- PMM
Fam Zheng Sept. 6, 2013, 5:53 a.m. UTC | #4
On Thu, 09/05 12:24, Richard Henderson wrote:
> On 09/05/2013 03:20 AM, Fam Zheng wrote:
> >   1) %.o in $(common-obj-m) is compiled to %.o, with
> >      "QEMU_CFLAGS += -shared -fPIC". Then "linked" to %.mo, which is an
> >      incremental object with "ln -r". This step is for consistency with
> >      %.mod case and has no effect.
> 
> As a general rule, you should avoid ld -r unless you know exactly
> what that implies for the given machine.  This is the sort of thing
> that's highly likely to work on x86 while failing elsewhere.
> 
> E.g. ARM and PPC ld would like to add trampolines for direct calls
> to reach the PLT entry.  If you create one object that's too large
> then that's no longer possible.
> 
> E.g. MIPS and Alpha ld require that any one input object file
> reference less than 64K worth of got entries.  Every separate
> object file can address its own 64K segment of the got.  If you
> combine too many objectsyou could overflow the got subsegments.
> 
> If our modules are small enough, we may never see any of these, but...
> 
> If you really require a single input file to ld for pattern matching
> purposes, I highly recommend an ar file, and then use --whole-archive
> to force the entire contents of the .a to be included.  This preserves
> the original translation-unit boundaries for ld.
> 
OK. Thanks for pointing out. The problem with ar file is that --whole-archive
needs to be done specificly to modules .a, other libs shouldn't be linked with
this flag. I'll drop this step by changing my pattern matching approach in
Makefile, and just compile and link without such intermediate object file.

Fam
Richard Henderson Sept. 6, 2013, 7:20 a.m. UTC | #5
On 09/05/2013 10:53 PM, Fam Zheng wrote:
> OK. Thanks for pointing out. The problem with ar file is that --whole-archive
> needs to be done specificly to modules .a, other libs shouldn't be linked with
> this flag.

See also:

  --whole-archive foo.a --no-whole-archive


r~
Fam Zheng Sept. 6, 2013, 7:27 a.m. UTC | #6
On Fri, 09/06 00:20, Richard Henderson wrote:
> On 09/05/2013 10:53 PM, Fam Zheng wrote:
> > OK. Thanks for pointing out. The problem with ar file is that --whole-archive
> > needs to be done specificly to modules .a, other libs shouldn't be linked with
> > this flag.
> 
> See also:
> 
>   --whole-archive foo.a --no-whole-archive

Yes, this is a way to do it, but will complicates the link command, and may be
more error prone. I expanded foo.mo to its contained .o for static linking in
the next revision that's coming up.

Thanks,

Fam
Paolo Bonzini Sept. 6, 2013, 8:26 a.m. UTC | #7
Il 05/09/2013 23:45, Peter Maydell ha scritto:
> On 5 September 2013 20:41, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Libtool used to be really bad, but most performance problems have been
>> solved.
> 
> How about the "it silently creates things in dot-directories,
> recompiles things at random times when it really shouldn't,
> and is an enormous insane shell script" problems? The positives
> would have to be really really strong before we let libtool
> into the codebase...

How about "we'd break compilation on your favorite OS"? :) Darwin ld
doesn't support --whole-archive, it needs a different incantation.
Relatively recent Solaris now has it, but Apple still holds the bastions.

Paolo
diff mbox

Patch

diff --git a/Makefile b/Makefile
index 806946e..130a497 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,7 @@  Makefile: ;
 configure: ;
 
 .PHONY: all clean cscope distclean dvi html info install install-doc \
-	pdf recurse-all speed test dist
+	pdf recurse-all speed test dist modules
 
 $(call set-vpath, $(SRC_PATH))
 
@@ -121,7 +121,22 @@  ifeq ($(CONFIG_SMARTCARD_NSS),y)
 include $(SRC_PATH)/libcacard/Makefile
 endif
 
-all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all
+all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
+
+mod-obj-m = $(patsubst %.o,%$(DSOSUF),$(filter %.o,$(common-obj-m))) \
+          $(patsubst %.mo,%$(DSOSUF),$(filter %.mo,$(common-obj-m)))
+mod-obj-y = $(patsubst %.mo,%.mo.o,$(filter %.mo,$(common-obj-y)))
+
+# Generate rules for single file modules (%.mo: %.o).
+# For multi file modules, dependencies should be listed explicitly in
+# Makefile.objs
+$(foreach o,$(mod-obj-m) $(mod-obj-y),$(eval \
+	$(patsubst %$(DSOSUF),%.mo,$o): $(patsubst %.c,%.o,$(wildcard $(patsubst %$(DSOSUF),%.c,$o))) \
+	))
+
+modules: $(mod-obj-m)
+modules: BUILD_DYNAMIC = 1
+modules: QEMU_CFLAGS += -shared -fPIC
 
 config-host.h: config-host.h-timestamp
 config-host.h-timestamp: config-host.mak
@@ -155,7 +170,7 @@  subdir-dtc:dtc/libfdt dtc/tests
 dtc/%:
 	mkdir -p $@
 
-$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y)
+$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(common-obj-m)
 
 ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
 romsubdir-%:
@@ -235,6 +250,9 @@  clean:
 	rm -f qemu-options.def
 	find . -name '*.[oda]' -type f -exec rm -f {} +
 	find . -name '*.l[oa]' -type f -exec rm -f {} +
+	find . -name '*'$(DSOSUF) -type f -exec rm -f {} +
+	find . -name '*.mo' -type f -exec rm -f {} +
+
 	rm -f $(TOOLS) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
 	rm -Rf .libs
 	rm -f qemu-img-cmds.h
diff --git a/Makefile.objs b/Makefile.objs
index f46a4cd..2f178af 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -19,6 +19,8 @@  block-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
 block-obj-y += qemu-coroutine-sleep.o
 block-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
 
+block-obj-m = block/
+
 ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
@@ -83,6 +85,9 @@  common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
 
 common-obj-y += qmp-marshal.o
 common-obj-y += qmp.o hmp.o
+
+common-obj-m = $(block-obj-m)
+
 endif
 
 ######################################################################
@@ -121,5 +126,8 @@  nested-vars += \
 	util-obj-y \
 	qga-obj-y \
 	block-obj-y \
-	common-obj-y
+	block-obj-m \
+	common-obj-y \
+	common-obj-m
+
 dummy := $(call unnest-vars)
diff --git a/configure b/configure
index 48e14b8..8f0a882 100755
--- a/configure
+++ b/configure
@@ -190,6 +190,7 @@  mingw32="no"
 gcov="no"
 gcov_tool="gcov"
 EXESUF=""
+DSOSUF=".so"
 prefix="/usr/local"
 mandir="\${prefix}/share/man"
 datadir="\${prefix}/share"
@@ -580,6 +581,7 @@  fi
 
 if test "$mingw32" = "yes" ; then
   EXESUF=".exe"
+  DSOSUF=".dll"
   QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
   # enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
   QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
@@ -4165,6 +4167,7 @@  echo "LIBTOOLFLAGS=$LIBTOOLFLAGS" >> $config_host_mak
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
+echo "DSOSUF=$DSOSUF" >> $config_host_mak
 echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
 echo "POD2MAN=$POD2MAN" >> $config_host_mak
 echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
diff --git a/rules.mak b/rules.mak
index 8276421..090eee1 100644
--- a/rules.mak
+++ b/rules.mak
@@ -58,6 +58,12 @@  endif
 %.o: %.dtrace
 	$(call quiet-command,dtrace -o $@ -G -s $<, "  GEN   $(TARGET_DIR)$@")
 
+%$(DSOSUF) %.mo.o: %.mo
+	$(call quiet-command,$(LD) $< -o $@ -shared,"  LD[M] $(TARGET_DIR)$@")
+
+%.mo:
+	$(call quiet-command,$(LD) $(sort $^) -r -o $@,"  LD    $(TARGET_DIR)$@")
+
 %$(EXESUF): %.o
 	$(call LINK,$^)