summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-08-17 15:52:07 +0000
committerAlan Conway <aconway@apache.org>2007-08-17 15:52:07 +0000
commitfd00bd1ca14d2ac2add8b0d0dba9477aafebc7d2 (patch)
treed277cf2d25a29a7688b43be1a008056f5cfdd655
parentc534d81e9ef0b19a57dce9c115e6a436d9a82320 (diff)
downloadqpid-python-fd00bd1ca14d2ac2add8b0d0dba9477aafebc7d2.tar.gz
* Fixes for code generation.
- Generate make fragments in $(srcdir) to fix VPATH builds. - rubygen: generates its own .mk fragment - rubygen: moved template info from Makefile.am to generated rubygen.mk, fixes circular dependency between Makefile and rubygen.mk - removed unused templates. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@567072 13f79535-47bb-0310-9956-ffa450edef68
-rwxr-xr-xcpp/bootstrap11
-rwxr-xr-xcpp/rubygen/amqpgen.rb9
-rwxr-xr-xcpp/rubygen/generate44
-rwxr-xr-xcpp/rubygen/templates/ClassBodyVariant.rb29
-rwxr-xr-xcpp/rubygen/templates/method_variants.rb72
-rw-r--r--cpp/src/Makefile.am51
-rwxr-xr-xcpp/src/generate.sh3
7 files changed, 72 insertions, 147 deletions
diff --git a/cpp/bootstrap b/cpp/bootstrap
index 2ecdefabd2..d96749e14b 100755
--- a/cpp/bootstrap
+++ b/cpp/bootstrap
@@ -14,8 +14,15 @@ export JAVA JAVAC
perl -ne '/^(include |if |else|endif)/ or print' Makefile.am \
| make -f - abs_srcdir=`dirname $(pwd)` gen.mk > /dev/null )
-# Create empty Makefile include files, make will generate the real contents.
-touch src/rubygen.mk src/generate.mk
+# Create initial Makefile fragments that will force make to generate
+# the real ones.
+cat > src/rubygen.mk <<EOF
+\$(srcdir)/rubygen.mk: force
+ \$(rgen_cmd)
+EOF
+
+touch src/generate.mk
+
automake
autoconf
diff --git a/cpp/rubygen/amqpgen.rb b/cpp/rubygen/amqpgen.rb
index 333c7dd654..7d635c99c2 100755
--- a/cpp/rubygen/amqpgen.rb
+++ b/cpp/rubygen/amqpgen.rb
@@ -174,6 +174,13 @@ class AmqpRoot < AmqpElement
end
+# Collect information about generated files.
+class GenFiles
+ @@files =[]
+ def GenFiles.add(f) @@files << f; puts f; end
+ def GenFiles.get() @@files; end
+end
+
# Base class for code generators.
# Supports setting a per-line prefix, useful for e.g. indenting code.
#
@@ -191,7 +198,7 @@ class Generator
# Create a new file, set @out.
def file(file)
- puts file
+ GenFiles.add file
if (@outdir != "-")
path=Pathname.new "#{@outdir}/#{file}"
path.parent.mkpath
diff --git a/cpp/rubygen/generate b/cpp/rubygen/generate
index ce9e7afc1b..4641bcd097 100755
--- a/cpp/rubygen/generate
+++ b/cpp/rubygen/generate
@@ -4,10 +4,11 @@ require 'amqpgen'
#
# Run a set of code generation templates.
#
-
if ARGV.size < 3
puts <<EOS
Usage: #{ARGV[0]} OUTDIR SPEC.xml [ ... ] TEMPLATE.rb [ ... ]
+or: #{ARGV[0]} OUTDIR SPEC.xml [ ... ] all [ makefragment.mk ]
+
Parse all SPEC.xml files to create an AMQP model, run each TEMPLATE
putting the resulting files under OUTDIR. Prints a list of files
generated to standard output.
@@ -16,8 +17,43 @@ If OUTDIR is '-' then just prints file list without generating files.
EOS
exit 1
end
+
Outdir=ARGV[0]
-specs=ARGV.grep(/\.xml$/)
-templates=ARGV.grep(/\.rb$/)
-Amqp=AmqpRoot.new(*specs)
+Specs=ARGV.grep(/\.xml$/)
+Amqp=AmqpRoot.new(*Specs)
+
+# Run selected templates
+if ARGV.grep("^all$")
+ templates=Dir["#{File.dirname __FILE__}/templates/*.rb"]
+else
+ templates=ARGV.grep(/\.rb$/)
+end
templates.each { |t| require t }
+
+# Generate makefile
+makefile=ARGV.grep(/.mk$/)[0]
+if makefile
+ dir=Dir.getwd
+ Dir.chdir File.dirname(__FILE__)
+ generator_files=Dir["**/*.rb"] << File.basename(__FILE__)
+ Dir.chdir dir
+ rgen_generator=generator_files.map{ |f| "$(rgen_dir)/#{f}" }
+
+ File.open(makefile, 'w') { |out|
+ out << <<EOS
+# Generated makefile fragment.
+# Including makefile defines $(rgen_dir) $(rgen_cmd) and $(specs).
+
+rgen_generator=#{rgen_generator.join(" \\\n ")}
+
+rgen_srcs=#{GenFiles.get.join(" \\\n ")}
+
+$(rgen_srcs) $(srcdir)/#{File.basename makefile}: $(rgen_generator) $(specs)
+ $(rgen_cmd)
+
+# Empty rule in case a generator file is renamed/removed.
+$(rgen_generator):
+EOS
+ }
+end
+
diff --git a/cpp/rubygen/templates/ClassBodyVariant.rb b/cpp/rubygen/templates/ClassBodyVariant.rb
deleted file mode 100755
index dce14c5652..0000000000
--- a/cpp/rubygen/templates/ClassBodyVariant.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env ruby
-$: << ".." # Include .. in load path
-require 'cppgen'
-
-class ClassBodyVariant < CppGen
-
- def initialize(outdir, amqp)
- super(outdir, amqp)
- end
-
- def class_body(c)
- h_file (c.body_name) {
- c.amqp_methods.each { |m| genl "#include \"#{m.body_name}.h\""; }
- genl
- genl "#include <boost/visitor.hpp>"
- genl
- gen "typedef boost::variant<"
- indent { genl c.amqp_methods().collect { |m| m.body_name }.join(",\n") }
- genl "> #{c.body_name};"
- }
- end
-
- def generate()
- @amqp.amqp_classes.each{ |c| class_body c }
- end
-end
-
-ClassBodyVariant.new(Outdir, Amqp).generate();
-
diff --git a/cpp/rubygen/templates/method_variants.rb b/cpp/rubygen/templates/method_variants.rb
deleted file mode 100755
index 886c7559bb..0000000000
--- a/cpp/rubygen/templates/method_variants.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/env ruby
-$: << ".." # Include .. in load path
-require 'cppgen'
-
-# Generate the full AMQP class/method model as C++ types.
-class AmqpCppModelGen < CppGen
-
- def initialize(outdir, amqp)
- super(outdir, amqp)
- end
-
- def gen_set_variant(varname, idtype, pairs, errmsg)
- pairs.sort!
- scope("inline void setVariant(#{varname}& var, #{idtype} id) {") {
- scope("switch (id) {") {
- pairs.each { |i,t|
- genl "case #{i}: var=#{t}(); break;";
- }
- genl "default: THROW_QPID_ERROR(FRAMING_ERROR, (boost::format(\"#{errmsg}\")%id).str());"
- }
- }
- genl
- end
-
- def gen_class(c)
- varname="#{c.name.caps}Variant"
- mtypes=c.amqp_methods.map { |m| m.body_name }
- typedef(blank_variant(mtypes), varname)
- genl
- pairs=c.amqp_methods.map { |m| [m.index.to_i,m.body_name] }
- gen_set_variant(varname, "MethodId", pairs,
- "%d is not a valid method index in class #{c.name}")
- mtypes.each { |t|
- genl "template<> struct ClassVariant<#{t}> { typedef #{varname} value; };"
- }
- genl
- end
-
- def gen_all()
- varname="MethodVariant"
- types=@amqp.amqp_classes.map { |c| "#{c.name.caps}Variant" }
- pairs=@amqp.amqp_classes.map { |c| [c.index.to_i,"#{c.name.caps}Variant"] }
- typedef(blank_variant(types), varname)
- genl
- gen_set_variant(varname, "ClassId", pairs,
- "%d is not a valid class index.")
- end
-
- def generate()
- h_file("qpid/framing/method_variants.h") {
- @amqp.amqp_methods.each { |m| include "qpid/framing/#{m.body_name}.h"}
- include "qpid/framing/amqp_types.h"
- include "qpid/QpidError.h"
- include "qpid/framing/variant.h"
- include "<boost/format.hpp>"
- genl
- namespace("qpid::framing") {
- genl "// Metafunction returns class variant containing method T."
- genl "template <class T> struct ClassVariant {};"
- genl
- @amqp.amqp_classes.each { |c| gen_class c }
- }
- namespace("qpid::framing") {
- gen_all
- genl
- }
- }
- end
-end
-
-AmqpCppModelGen.new(Outdir, Amqp).generate();
-
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index 977db7ea36..32f5b3845b 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -1,24 +1,20 @@
SUBDIRS = . tests
+EXTRA_DIST= $(platform_dist)
+
## Generated code
# Note: generated soure and makefiles included in distribution so a
# distribution can be built without code generation tools and XML
# sources.
-EXTRA_DIST= $(platform_dist)
-
-EXTRA_DIST += generate.mk generate.sh $(generated_cpp) $(generated_h) \
- rubygen.mk $(rgen_srcs)
+# This phony target is needed by generated makefile fragments:
+force:
# AMQP_XML is defined in ../configure.ac
specs=@AMQP_XML@ $(top_srcdir)/xml/cluster.xml
-# Makefiles are either generated or copied from $srcdir.
-include generate.mk
-include rubygen.mk
-
-DISTCLEANFILES=generate.mk rubygen.mk
+EXTRA_DIST += generate.mk generate.sh $(generated_cpp) $(generated_h) $(rgen_srcs)
if GENERATE
@@ -28,7 +24,7 @@ if GENERATE
gentools_dir=$(top_srcdir)/gentools
-generate.mk $(generated_cpp) $(generated_h): generate.timestamp
+$(srcdir)/generate.mk $(generated_cpp) $(generated_h): generate.timestamp
generate.timestamp: generate.sh $(specs) $(generator)
env gentools_dir=$(gentools_dir) specs="$(specs)" $(srcdir)/generate.sh
touch $@
@@ -40,37 +36,16 @@ maintainer-clean-local:
rm -rf gen
# Ruby generator.
-
rgen_dir=$(top_srcdir)/rubygen
-rgen_tdir=$(rgen_dir)/templates
-rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate
-
-rgen_templates=$(rgen_tdir)/MethodHolder.rb \
- $(rgen_tdir)/MethodBodyConstVisitor.rb \
- $(rgen_tdir)/frame_body_lists.rb \
- $(rgen_tdir)/Session.rb \
- $(rgen_tdir)/all_method_bodies.rb \
- $(rgen_tdir)/Proxy.rb
-
-rgen_generator=$(rgen_dir)/generate \
- $(rgen_dir)/amqpgen.rb \
- $(rgen_dir)/cppgen.rb
-
-rubygen.mk $(rgen_srcs): rubygen.timestamp
-rubygen.timestamp: $(rgen_generator) $(specs) $(rgen_templates)
- srcs=`$(rgen_cmd) . $(specs) $(rgen_templates) ` && { \
- echo -n "rgen_srcs= "; \
- for f in $$srcs; do echo "\\"; echo -n " $$f "; done; \
- echo; } > rubygen.mk
- touch $@
-else # !GENERATE
-# If not generating, copy generated makefiles from source dir to build dir.
-generate.mk:
- cp $(srcdir)/$@ $@
-rubygen.mk:
- cp $(srcdir)/$@ $@
+rgen_cmd=ruby -I $(rgen_dir) $(rgen_dir)/generate . $(specs) all $(srcdir)/rubygen.mk
+
endif # GENERATE
+include $(srcdir)/generate.mk
+include $(srcdir)/rubygen.mk
+
+DISTCLEANFILES=generate.mk rubygen.mk
+
# Code generated by C++
noinst_PROGRAMS=generate_MethodHolderMaxSize_h
generate_MethodHolderMaxSize_h_SOURCES=generate_MethodHolderMaxSize_h.cpp
diff --git a/cpp/src/generate.sh b/cpp/src/generate.sh
index 3869696bc7..3582893f24 100755
--- a/cpp/src/generate.sh
+++ b/cpp/src/generate.sh
@@ -7,6 +7,7 @@ set -e
test -z "$JAVA" && JAVA=java ;
test -z "$JAVAC" && JAVAC=javac ;
+srcdir=`dirname $0`
checkspecs() {
for s in $specs; do test -f $s || return 1; done
return 0
@@ -41,7 +42,7 @@ make_assign() {
`find ../gentools \( -name '*.java' -o -name '*.tmpl' \) -print`
fi
) > generate.mk-t
-mv generate.mk-t generate.mk
+mv generate.mk-t $srcdir/generate.mk