cxx: Modify how to generate C++ headers and allow cyclic dependencies
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Thu, 19 Jan 2017 00:25:02 +0000 (22:25 -0200)
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Thu, 19 Jan 2017 00:47:04 +0000 (22:47 -0200)
Allow cyclic dependencies in generated C++ headers by changing order
of includes and creating forward declarations.

25 files changed:
src/Makefile_Cxx.am
src/Makefile_Eolian_Cxx.am
src/bin/eolian_cxx/eolian_cxx.cc
src/bindings/cxx/eldbus_cxx/Eldbus_Model.hh [new file with mode: 0644]
src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
src/examples/elementary/button_cxx_example_00.cc
src/examples/elementary/calendar_cxx_example_02.cc
src/examples/eolian_cxx/eolian_cxx_inherit_01.cc
src/examples/eolian_cxx/eolian_cxx_simple_01.cc
src/examples/eolian_cxx/eolian_cxx_simple_01_cxx_impl.cc
src/lib/.gitignore
src/lib/edje/Edje.hh [new file with mode: 0644]
src/lib/efl/.gitignore
src/lib/efl/Efl.hh [new file with mode: 0644]
src/lib/eio/Eio.hh [new file with mode: 0644]
src/lib/elementary/.gitignore
src/lib/elementary/Elementary.hh [new file with mode: 0644]
src/lib/eolian_cxx/grammar/class_declaration.hpp
src/lib/eolian_cxx/grammar/header.hpp
src/lib/eolian_cxx/grammar/implementation_include_directive.hpp
src/lib/eolian_cxx/grammar/keyword.hpp
src/lib/eolian_cxx/grammar/klass_def.hpp
src/lib/evas/Evas.hh [new file with mode: 0644]
src/tests/eolian_cxx/eolian_cxx_test_binding.cc
src/tests/eolian_cxx/eolian_cxx_test_cyclic.cc

index febc123..72d5713 100644 (file)
@@ -21,63 +21,46 @@ bindings/cxx/eo_cxx/eo_private.hh
 ### Elementary C++
 installed_elementarycxxmainheadersdir = $(includedir)/elementary-cxx-@VMAJ@/
 nodist_installed_elementarycxxmainheaders_DATA = $(elementary_eolian_cxx_hh) $(elementary_eolian_cxx_impl_hh) \
-lib/elementary/Elementary.hh
-
-lib/elementary/Elementary.hh: $(elementary_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_ELEMENTARY_HH\n#define EFL_CXX_ELEMENTARY_HH\n" > $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#if defined(ELEMENTARY_H) || defined(ELM_WIDGET_H)" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#error Do not include Elm C API headers before including Elementary.hh" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#endif" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#ifndef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#define EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#endif\n" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#ifndef EFL_EO_API_SUPPORT" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#define EFL_EO_API_SUPPORT" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#endif\n" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#ifndef ELM_INTERNAL_API_ARGESFSDFEFC" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#define ELM_INTERNAL_API_ARGESFSDFEFC" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#endif\n" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "extern \"C\" {" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#include \"Elementary.h\"" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "#include \"elm_widget.h\"" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "}" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @echo @ECHO_E@ "" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-       @for i in $(elementary_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/elementary/Elementary.hh; done
-       @echo @ECHO_E@ "#endif\n" >> $(top_builddir)/src/lib/elementary/Elementary.hh
-
-CLEANFILES += $(elementary_eolian_cxx_hh) $(elementary_eolian_cxx_impl_hh) lib/elementary/Elementary.hh
+lib/elementary/Elementary.eo.hh
+dist_installed_elementarycxxmainheaders_DATA = lib/elementary/Elementary.hh
+
+lib/elementary/Elementary.eo.hh: $(elm_public_eolian_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
+
+CLEANFILES += $(elementary_eolian_cxx_hh) $(elementary_eolian_cxx_impl_hh) lib/elementary/Elementary.eo.hh
 
 ### Efl C++
 installed_eflcxxmainheadersdir = $(includedir)/efl-cxx-@VMAJ@/
-nodist_installed_eflcxxmainheaders_DATA = $(efl_eolian_cxx_hh) $(efl_eolian_cxx_impl_hh) lib/efl/Efl.hh
+nodist_installed_eflcxxmainheaders_DATA = $(efl_eolian_cxx_hh) $(efl_eolian_cxx_impl_hh) lib/efl/Efl.eo.hh
+dist_installed_eflcxxmainheaders_DATA = lib/efl/Efl.hh
 
-lib/efl/Efl.hh: $(efl_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_HH\n#define EFL_CXX_HH\n" > $(top_builddir)/src/lib/efl/Efl.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/efl/Efl.hh
-       @for i in $(efl_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/efl/Efl.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/efl/Efl.hh
+lib/efl/Efl.eo.hh: $(efl_eolian_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
 CLEANFILES += $(efl_eolian_cxx_hh) $(efl_eolian_cxx_impl_hh) lib/efl/Efl.hh
 
 ### Evas C++
 installed_evascxxmainheadersdir = $(includedir)/evas-cxx-@VMAJ@/
-nodist_installed_evascxxmainheaders_DATA = lib/evas/Evas.hh
+dist_installed_evascxxmainheaders_DATA = lib/evas/Evas.hh
+nodist_installed_evascxxmainheaders_DATA = lib/evas/Evas.eo.hh
 
 installed_evascxxcanvasheadersdir = $(includedir)/evas-cxx-@VMAJ@/canvas
 nodist_installed_evascxxcanvasheaders_DATA = $(evas_eolian_cxx_hh) $(evas_eolian_cxx_impl_hh)
 
-lib/evas/Evas.hh: $(evas_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_EVAS_HH\n#define EFL_CXX_EVAS_HH\n" > $(top_builddir)/src/lib/evas/Evas.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/evas/Evas.hh
-       @for i in $(evas_eolian_cxx_hh); do echo "#include <canvas/$$(basename $$i)>" >> $(top_builddir)/src/lib/evas/Evas.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/evas/Evas.hh
+lib/evas/Evas.eo.hh: $(evas_eolian_pub_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
-CLEANFILES += $(evas_eolian_cxx_hh) $(evas_eolian_cxx_impl_hh) lib/evas/Evas.hh
+CLEANFILES += $(evas_eolian_cxx_hh) $(evas_eolian_cxx_impl_hh) lib/evas/Evas.eo.hh
 
 ### Eldbus C++
 installed_eldbuscxxmainheadersdir = $(includedir)/eldbus_cxx-@VMAJ@
-nodist_installed_eldbuscxxmainheaders_DATA = $(eldbus_eolian_cxx_hh) $(eldbus_eolian_cxx_impl_hh) lib/eldbus/Eldbus_Model.hh
+nodist_installed_eldbuscxxmainheaders_DATA = $(eldbus_eolian_cxx_hh) $(eldbus_eolian_cxx_impl_hh) lib/eldbus/Eldbus_Model.eo.hh
 dist_installed_eldbuscxxmainheaders_DATA = \
 bindings/cxx/eldbus_cxx/eldbus_basic.hh \
 bindings/cxx/eldbus_cxx/eldbus_error.hh \
@@ -89,16 +72,15 @@ bindings/cxx/eldbus_cxx/eldbus_message.hh \
 bindings/cxx/eldbus_cxx/eldbus_proxy_call.hh \
 bindings/cxx/eldbus_cxx/eldbus_raw_tuple.hh \
 bindings/cxx/eldbus_cxx/eldbus_service.hh \
-bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh
+bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh \
+bindings/cxx/eldbus_cxx/Eldbus_Model.hh
 
-lib/eldbus/Eldbus_Model.hh: $(eldbus_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_ELDBUS_MODEL_HH\n#define EFL_CXX_ELDBUS_MODEL_HH\n" > $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
-       @echo @ECHO_E@ "#include <Eldbus_Model.h>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
-       @for i in $(eldbus_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eldbus/Eldbus_Model.hh
+lib/eldbus/Eldbus_Model.eo.hh: $(eldbus_eolian_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
-CLEANFILES += $(eldbus_eolian_cxx_hh) $(eldbus_eolian_cxx_impl_hh) lib/eldbus/Eldbus_Model.hh
+CLEANFILES += $(eldbus_eolian_cxx_hh) $(eldbus_eolian_cxx_impl_hh) lib/eldbus/Eldbus_Model.eo.hh
 
 ### Eet C++
 installed_eetcxxheadersdir = $(includedir)/eet-cxx-@VMAJ@
@@ -110,15 +92,15 @@ bindings/cxx/eet_cxx/Eet.hh
 
 ### Generated headers src/lib/edje
 installed_edjecxxmainheadersdir = $(includedir)/edje-cxx-@VMAJ@/
-nodist_installed_edjecxxmainheaders_DATA = $(edje_eolian_cxx_hh) $(edje_eolian_cxx_impl_hh) lib/edje/Edje.hh
+dist_installed_edjecxxmainheaders_DATA = lib/edje/Edje.hh
+nodist_installed_edjecxxmainheaders_DATA = $(edje_eolian_cxx_hh) $(edje_eolian_cxx_impl_hh) lib/edje/Edje.eo.hh
 
-lib/edje/Edje.hh: $(edje_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_EDJE_HH\n#define EFL_CXX_EDJE_HH\n" > $(top_builddir)/src/lib/edje/Edje.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/edje/Edje.hh
-       @for i in $(edje_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/edje/Edje.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/edje/Edje.hh
+lib/edje/Edje.eo.hh: $(edje_eolian_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
-CLEANFILES += $(edje_eolian_cxx_hh) $(edje_eolian_cxx_impl_hh) lib/edje/Edje.hh
+CLEANFILES += $(edje_eolian_cxx_hh) $(edje_eolian_cxx_impl_hh) lib/edje/Edje.eo.hh
 
 ### Ecore src/lib/ecore
 installed_ecorecxxheadersdir = $(includedir)/ecore-cxx-@VMAJ@
@@ -129,11 +111,10 @@ bindings/cxx/ecore_cxx/Ecore_Manual.hh
 nodist_installed_ecorecxxheaders_DATA = $(ecore_eolian_cxx_hh) $(ecore_eolian_cxx_impl_hh) \
 lib/ecore/Ecore.eo.hh
 
-lib/ecore/Ecore.eo.hh: $(ecore_eolian_cxx_hh) $(eo_eolian_cxx_hh) $(efl_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_ECORE_HH\n#define EFL_CXX_ECORE_HH\n" > $(top_builddir)/src/lib/ecore/Ecore.eo.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/ecore/Ecore.eo.hh
-       @for i in $(ecore_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/ecore/Ecore.eo.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/ecore/Ecore.eo.hh
+lib/ecore/Ecore.eo.hh: $(ecore_eolian_files_public) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
 CLEANFILES += $(ecore_eolian_cxx_hh) $(ecore_eolian_cxx_impl_hh) lib/ecore/Ecore.eo.hh
 
@@ -180,15 +161,15 @@ bindings/cxx/eina_cxx/Eina.hh
 
 ### Eio
 installed_eiocxxmainheadersdir = $(includedir)/eio-cxx-@VMAJ@/
-nodist_installed_eiocxxmainheaders_DATA = $(eio_eolian_cxx_hh) $(eio_eolian_cxx_impl_hh) lib/eio/Eio.hh
+nodist_installed_eiocxxmainheaders_DATA = $(eio_eolian_cxx_hh) $(eio_eolian_cxx_impl_hh) lib/eio/Eio.eo.hh
+dist_installed_eiocxxmainheaders_DATA = lib/eio/Eio.hh
 
-lib/eio/Eio.hh: $(eio_eolian_cxx_hh)
-       @echo @ECHO_E@ "#ifndef EFL_CXX_EIO_HH\n#define EFL_CXX_EIO_HH\n" > $(top_builddir)/src/lib/eio/Eio.hh
-       @echo @ECHO_E@ "#ifdef EFL_BETA_API_SUPPORT" >> $(top_builddir)/src/lib/eio/Eio.hh
-       @for i in $(eio_eolian_cxx_hh); do echo "#include <$$(basename $$i)>" >> $(top_builddir)/src/lib/eio/Eio.hh; done
-       @echo @ECHO_E@ "#endif\n\n#endif\n" >> $(top_builddir)/src/lib/eio/Eio.hh
+lib/eio/Eio.eo.hh: $(eio_eolian_files) $(_EOLIAN_CXX_DEP)
+       $(AM_V_EOLCXX) \
+       $(MKDIR_P) $(dir $@); \
+       $(EOLIAN_CXX) $(EOLIAN_FLAGS) -m -o $@ $(filter %.eo, $^)
 
-CLEANFILES += $(eio_eolian_cxx_hh) $(eio_eolian_cxx_impl_hh) lib/eio/Eio.hh
+CLEANFILES += $(eio_eolian_cxx_hh) $(eio_eolian_cxx_impl_hh) lib/eio/Eio.eo.hh
 
 ### Tests
 
index 6d0ae1d..6abb3d6 100644 (file)
@@ -145,8 +145,15 @@ tests/eolian_cxx/complex.eo.impl.hh \
 tests/eolian_cxx/name1_name2_type_generation.eo.hh \
 tests/eolian_cxx/name1_name2_type_generation.eo.impl.hh \
 tests/eolian_cxx/name1_name2_type_generation.eo.h \
-tests/eolian_cxx/name1_name2_type_generation.eo.c
-
+tests/eolian_cxx/name1_name2_type_generation.eo.c \
+tests/eolian_cxx/cyclic1.eo.c \
+tests/eolian_cxx/cyclic1.eo.h \
+tests/eolian_cxx/cyclic1.eo.hh \
+tests/eolian_cxx/cyclic1.eo.impl.hh \
+tests/eolian_cxx/cyclic2.eo.c \
+tests/eolian_cxx/cyclic2.eo.h \
+tests/eolian_cxx/cyclic2.eo.hh \
+tests/eolian_cxx/cyclic2.eo.impl.hh
 
 tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
 -I$(top_builddir)/src/lib/efl \
@@ -181,7 +188,9 @@ tests/eolian_cxx/name_name.eo \
 tests/eolian_cxx/ns_name.eo \
 tests/eolian_cxx/ns_name_other.eo \
 tests/eolian_cxx/name1_name2_type_generation.eo \
-tests/eolian_cxx/complex.eo
+tests/eolian_cxx/complex.eo \
+tests/eolian_cxx/cyclic1.eo \
+tests/eolian_cxx/cyclic2.eo
 
 include Makefile_Eolian_Cxx_Helper.am
 
index 24a9dd6..18978a3 100644 (file)
@@ -32,8 +32,11 @@ namespace eolian_cxx {
 struct options_type
 {
    std::vector<std::string> include_dirs;
-   std::string in_file;
+   std::vector<std::string> in_files;
    std::string out_file;
+   bool main_header;
+
+   options_type() : main_header(false) {}
 };
 
 efl::eina::log_domain domain("eolian_cxx");
@@ -41,7 +44,7 @@ efl::eina::log_domain domain("eolian_cxx");
 static bool
 opts_check(eolian_cxx::options_type const& opts)
 {
-   if (opts.in_file.empty())
+   if (opts.in_files.empty())
      {
         EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
           << "Nothing to generate?" << std::endl;
@@ -68,6 +71,7 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
 
    efl::eolian::grammar::attributes::klass_def klass_def(klass);
    std::vector<efl::eolian::grammar::attributes::klass_def> klasses{klass_def};
+   std::vector<efl::eolian::grammar::attributes::klass_def> forward_klasses{klass_def};
 
    std::set<std::string> c_headers;
    std::set<std::string> cpp_headers;
@@ -82,6 +86,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
         assert(klass);
         c_headers.insert(eolian_class_file_get(klass) + std::string(".h"));
         cpp_headers.insert(eolian_class_file_get(klass) + std::string(".hh"));
+        efl::eolian::grammar::attributes::klass_def cls{klass};
+        if(std::find(forward_klasses.begin(), forward_klasses.end(), cls) == forward_klasses.end())
+          forward_klasses.push_back(cls);
      };
    auto complex_function
      = [&] (efl::eolian::grammar::attributes::complex_type_def const& complex)
@@ -112,6 +119,9 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
            Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator);
            c_headers.insert(eolian_class_file_get(inherit) + std::string(".h"));
            cpp_headers.insert(eolian_class_file_get(inherit) + std::string(".hh"));
+           efl::eolian::grammar::attributes::klass_def klass{inherit};
+           if(std::find(forward_klasses.begin(), forward_klasses.end(), klass) == forward_klasses.end())
+             forward_klasses.push_back(klass);
 
            klass_function(inherit);
          }
@@ -147,7 +157,7 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               , std::vector<efl::eolian::grammar::attributes::klass_def>&
               > attributes
-   {guard_name, c_headers, cpp_headers, klasses, klasses, klasses, klasses};
+   {guard_name, c_headers, cpp_headers, klasses, forward_klasses, klasses, klasses};
 
    if(opts.out_file == "-")
      {
@@ -182,15 +192,11 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
              return false;
           }
 
-#if 1
         efl::eolian::grammar::class_header.generate
           (std::ostream_iterator<char>(header_decl), attributes, efl::eolian::grammar::context_null());
 
         efl::eolian::grammar::impl_header.generate
           (std::ostream_iterator<char>(header_impl), klasses, efl::eolian::grammar::context_null());
-#else
-        efl::eolian::generate(header_decl, header_impl, cls, gen_opts);
-#endif
 
         header_impl.close();
         header_decl.close();
@@ -201,26 +207,75 @@ generate(const Eolian_Class* klass, eolian_cxx::options_type const& opts)
 static void
 run(options_type const& opts)
 {
-   const Eolian_Class *klass = NULL;
-   char* dup = strdup(opts.in_file.c_str());
-   char* base = basename(dup);
-   klass = ::eolian_class_get_by_file(base);
-   free(dup);
-   if (klass)
+   if(!opts.main_header)
      {
-        if (!generate(klass, opts))
-          goto err;
+       const Eolian_Class *klass = NULL;
+       char* dup = strdup(opts.in_files[0].c_str());
+       char* base = basename(dup);
+       klass = ::eolian_class_get_by_file(base);
+       free(dup);
+       if (klass)
+         {
+           if (!generate(klass, opts))
+             {
+               EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+                 << "Error generating: " << ::eolian_class_name_get(klass)
+                 << std::endl;
+               assert(false && "error generating class");
+             }
+         }
+       else
+         {
+           std::abort();
+         }
      }
    else
      {
-        std::abort();
-    }
-   return;
- err:
-   EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
-     << "Error generating: " << ::eolian_class_name_get(klass)
-     << std::endl;
-   assert(false && "error generating class");
+       std::set<std::string> headers;
+       std::set<std::string> eo_files;
+
+       for(auto&& name : opts.in_files)
+         {
+           bool b = ::eolian_file_parse(name.c_str());
+           if(!b)
+             {
+               EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+                 << "Failed parsing: " << name << ".";
+             }
+           char* dup = strdup(name.c_str());
+           char* base = basename(dup);
+           Eolian_Class const* klass = ::eolian_class_get_by_file(base);
+           free(dup);
+           if (klass)
+             {
+               std::string filename = eolian_class_file_get(klass);
+               headers.insert(filename + std::string(".hh"));
+               eo_files.insert(filename);
+             }
+         }
+
+       using efl::eolian::grammar::header_include_directive;
+       using efl::eolian::grammar::implementation_include_directive;
+
+       auto main_header_grammar =
+         *header_include_directive // sequence<string>
+         << *implementation_include_directive // sequence<string>
+         ;
+
+       std::tuple<std::set<std::string>&, std::set<std::string>&> attributes{headers, eo_files};
+
+       std::ofstream main_header;
+       main_header.open(opts.out_file);
+       if (!main_header.good())
+         {
+           EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
+             << "Can't open output file: " << opts.out_file << std::endl;
+           return;
+         }
+       
+       main_header_grammar.generate(std::ostream_iterator<char>(main_header)
+                                    , attributes, efl::eolian::grammar::context_null());
+     }
 }
 
 static void
@@ -240,16 +295,16 @@ database_load(options_type const& opts)
           << "Eolian failed parsing eot files";
         assert(false && "Error parsing eot files");
      }
-   if (opts.in_file.empty())
+   if (opts.in_files.empty())
      {
        EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
          << "No input file.";
        assert(false && "Error parsing input file");
      }
-   if (!::eolian_file_parse(opts.in_file.c_str()))
+   if (!opts.main_header && !::eolian_file_parse(opts.in_files[0].c_str()))
      {
        EINA_CXX_DOM_LOG_ERR(eolian_cxx::domain)
-         << "Failed parsing: " << opts.in_file << ".";
+         << "Failed parsing: " << opts.in_files[0] << ".";
        assert(false && "Error parsing input file");
      }
    if (!::eolian_database_validate())
@@ -307,13 +362,14 @@ opts_get(int argc, char **argv)
 
    const struct option long_options[] =
      {
-       { "in",        required_argument, 0,  'I' },
-       { "out-file",  required_argument, 0,  'o' },
-       { "version",   no_argument,       0,  'v' },
-       { "help",      no_argument,       0,  'h' },
-       { 0,           0,                 0,   0  }
+       { "in",          required_argument, 0,  'I' },
+       { "out-file",    required_argument, 0,  'o' },
+       { "version",     no_argument,       0,  'v' },
+       { "help",        no_argument,       0,  'h' },
+       { "main-header", no_argument,       0,  'm' },
+       { 0,             0,                 0,   0  }
      };
-   const char* options = "I:D:o:c:arvh";
+   const char* options = "I:D:o:c::marvh";
 
    int c, idx;
    while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
@@ -331,15 +387,20 @@ opts_get(int argc, char **argv)
           {
              _usage(argv[0]);
           }
+        else if(c == 'm')
+          {
+            opts.main_header = true;
+          }
         else if (c == 'v')
           {
              _print_version();
              if (argc == 2) exit(EXIT_SUCCESS);
           }
      }
-   if (optind == argc-1)
+   if (optind != argc)
      {
-        opts.in_file = argv[optind];
+       for(int i = optind; i != argc; ++i)
+         opts.in_files.push_back(argv[i]);
      }
 
    if (!eolian_cxx::opts_check(opts))
diff --git a/src/bindings/cxx/eldbus_cxx/Eldbus_Model.hh b/src/bindings/cxx/eldbus_cxx/Eldbus_Model.hh
new file mode 100644 (file)
index 0000000..f2aa9e1
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef EFL_CXX_ELDBUS_MODEL_HH
+#define EFL_CXX_ELDBUS_MODEL_HH
+
+#include <Eldbus_Model.h>
+
+#ifdef EFL_BETA_API_SUPPORT
+
+#include <Eldbus_Model.eo.hh>
+
+#endif
+#endif
+
index 524863e..7a2f8fb 100644 (file)
@@ -279,11 +279,11 @@ T convert_to_c(V&& object);
     
 namespace impl {
 
-template <typename U, typename T>
+template <typename U, typename T, typename V>
 auto convert_to_c_impl
-(T&& v, tag<U, U>, typename std::enable_if<std::is_same<typename std::remove_reference<T>::type, U>::value>::type* =0) -> decltype(std::forward<T>(v))
+(V&& v, tag<U, T>, typename std::enable_if<std::is_same<typename std::remove_reference<T>::type, U>::value>::type* =0) -> decltype(std::forward<V>(v))
 {
-  return std::forward<T>(v);
+  return std::forward<V>(v);
 }
 
 template <typename T>
index 99901d2..9239f74 100644 (file)
@@ -24,7 +24,7 @@ elm_main (int argc, char *argv[])
    win.autohide_set(true);
 
    ::elm::Button btn(win);
-   btn.eo_cxx::efl::Text::text_set("Good-Bye, World!");
+   btn.eo_cxx::elm::Layout::text_set(nullptr,"Good-Bye, World!");
    btn.eo_cxx::efl::Gfx::size_set(120, 30);
    btn.eo_cxx::efl::Gfx::position_set(60, 15);
    btn.visible_set(true);
index 7061e57..02a1ede 100644 (file)
@@ -3,6 +3,7 @@
 #include "elementary_config.h"
 #endif
 
+#include <Efl.hh>
 #include <Elementary.hh>
 
 static char *
index 2fedf12..5cd6b20 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "ns_colourable.eo.hh"
 #include "ns_colourablesquare.eo.hh"
+#include "ns_colourable.eo.impl.hh"
+#include "ns_colourablesquare.eo.impl.hh"
 
 #include <eo_inherit.hh>
 
index eb093d9..028a429 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "ns_colourable.eo.hh"
 #include "ns_colourablesquare.eo.hh"
+#include "ns_colourable.eo.impl.hh"
+#include "ns_colourablesquare.eo.impl.hh"
 
 int
 main()
index 1120978..2ca0e97 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "colourable.eo.hh"
 #include "colourablesquare.eo.hh"
+#include "ns_colourable.eo.impl.hh"
+#include "ns_colourablesquare.eo.impl.hh"
 
 int
 main()
index 190a85e..aaec4c0 100644 (file)
@@ -1,11 +1,12 @@
 /ecore_x/ecore_x_version.h
 /efl/Efl_Config.h
-/efl/Efl.hh
 /eina/eina_config.h
-/ecore_audio/Ecore_Audio.hh
 /ecore/Ecore.eo.hh
-/evas/Evas.hh
-/edje/Edje.hh
 /edje/Edje.eo.hh
-/eio/Eio.hh
-/eldbus/Eldbus_Model.hh
+/eio/Eio.eo.hh
+/elementary/Elementary.eo.hh
+/evas/Evas.eo.hh
+/efl/Efl.eo.hh
+/eldbus/Eldbus_Model.eo.hh
+
+
diff --git a/src/lib/edje/Edje.hh b/src/lib/edje/Edje.hh
new file mode 100644 (file)
index 0000000..4550181
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef EFL_CXX_EDJE_HH
+#define EFL_CXX_EDJE_HH
+
+#ifdef EFL_BETA_API_SUPPORT
+
+#include <Edje.eo.hh>
+
+#endif
+#endif
diff --git a/src/lib/efl/Efl.hh b/src/lib/efl/Efl.hh
new file mode 100644 (file)
index 0000000..20dfc1a
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef EFL_EFL_HH
+#define EFL_EFL_HH
+
+#ifdef EFL_BETA_API_SUPPORT
+
+#include <Efl.eo.hh>
+
+#endif
+#endif
+
+
diff --git a/src/lib/eio/Eio.hh b/src/lib/eio/Eio.hh
new file mode 100644 (file)
index 0000000..78c0f39
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef EFL_CXX_EIO_HH
+#define EFL_CXX_EIO_HH
+#ifdef EFL_BETA_API_SUPPORT
+
+#include "Eio.eo.hh"
+
+#endif
+#endif
+
index 089c32d..9076648 100644 (file)
@@ -1,4 +1,3 @@
-/Elementary.hh
 /Elementary_Options.h
 /elm_intro.h
 /*.eo.c
diff --git a/src/lib/elementary/Elementary.hh b/src/lib/elementary/Elementary.hh
new file mode 100644 (file)
index 0000000..215632b
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef EFL_CXX_ELEMENTARY_HH
+#define EFL_CXX_ELEMENTARY_HH
+#if defined(ELEMENTARY_H) || defined(ELM_WIDGET_H)
+#error "Do not include Elm C API headers before including Elementary.hh"
+#endif
+
+#ifndef EFL_BETA_API_SUPPORT
+#define EFL_BETA_API_SUPPORT
+#endif
+#ifndef EFL_EO_API_SUPPORT
+#define EFL_EO_API_SUPPORT
+#endif
+#ifndef ELM_INTERNAL_API_ARGESFSDFEFC
+#define ELM_INTERNAL_API_ARGESFSDFEFC
+#endif
+
+#include <Efl.hh>
+
+extern "C" {
+#include "Elementary.h"
+#include "elm_widget.h"
+}
+
+#include "Elementary.eo.hh"
+
+#endif
index 6f23641..bed1a56 100644 (file)
@@ -15,6 +15,8 @@ namespace efl { namespace eolian { namespace grammar {
 
 struct class_declaration_generator
 {
+   bool type_traits;
+  
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::klass_def const& cls, Context const& context) const
    {
@@ -30,11 +32,12 @@ struct class_declaration_generator
      auto close_namespace = *(lit("} ")) << "\n";
      if(!as_generator(close_namespace).generate(sink, cpp_namespaces, context)) return false;
 
-     if(!as_generator
-        (
-         "namespace efl { namespace eo { template<> struct is_eolian_object< "
-         "::" << *(lower_case[string] << "::") << string << "> : ::std::true_type {}; } }\n"
-        ).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name), context)) return false;
+     if(type_traits)
+       if(!as_generator
+          (
+           "namespace efl { namespace eo { template<> struct is_eolian_object< "
+           "::" << *(lower_case[string] << "::") << string << "> : ::std::true_type {}; } }\n"
+           ).generate(sink, std::make_tuple(cpp_namespaces, cls.cxx_name), context)) return false;
 
      
      return true;
@@ -49,7 +52,8 @@ template <>
 struct attributes_needed<class_declaration_generator> : std::integral_constant<int, 1> {};
 }
       
-class_declaration_generator const class_declaration = {};
+class_declaration_generator const class_declaration = {true};
+class_declaration_generator const class_forward_declaration = {false};
       
 } } }
 
index 96e1235..63a6095 100644 (file)
@@ -25,11 +25,12 @@ auto class_header =
        "#include <Eo.hh>\n"
     << *header_include_directive // sequence<string>
     << *class_declaration          // sequence<class> | class
+    << *class_forward_declaration          // sequence<class> | class
     << "\nnamespace eo_cxx {\n"
     << *base_class_definition      // sequence<class> | class
     << "}\n"
     << *class_definition           // sequence<class> | class
-    << *implementation_include_directive
+    // << *implementation_include_directive
   ]
   ;
 
index dab1e0a..6c2631a 100644 (file)
@@ -22,6 +22,12 @@ struct implementation_include_directive_generator
      return as_generator("#include \"" << string << ".impl.hh\"\n")
        .generate(sink, std::string(eolian_class_file_get(get_klass(get_klass_name(cls)))), add_lower_case_context(ctx));
    }
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, std::string const& cls, Context const& ctx) const
+   {
+     return as_generator("#include \"" << string << ".impl.hh\"\n")
+       .generate(sink, cls, add_lower_case_context(ctx));
+   }
 };
 
 template <>
index 9359892..b64201e 100644 (file)
@@ -5,7 +5,7 @@ namespace efl { namespace eolian { namespace grammar {
 
 inline std::string escape_keyword(std::string const& name)
 {
-  if(name == "delete" || name == "register")
+  if(name == "delete" || name == "register" || name == "do")
     return "cxx_" + name;
   return name;
 }
index 4b9bc48..c663f28 100644 (file)
@@ -315,6 +315,18 @@ struct parameter_def
   std::string param_name;
   std::string c_type;
 
+  friend inline bool operator==(parameter_def const& lhs, parameter_def const& rhs)
+  {
+    return lhs.direction == rhs.direction
+      && lhs.type == rhs.type
+      && lhs.param_name == rhs.param_name
+      && lhs.c_type == rhs.c_type;
+  }
+  friend inline bool operator!=(parameter_def const& lhs, parameter_def const& rhs)
+  {
+    return !(lhs == rhs);
+  }
+  
   parameter_def(parameter_direction direction, type_def type, std::string param_name, std::string c_type)
     : direction(std::move(direction)), type(std::move(type)), param_name(std::move(param_name)), c_type(std::move(c_type)) {}
   parameter_def(Eolian_Function_Parameter const* param)
@@ -384,6 +396,20 @@ struct function_def
   bool is_beta;
   bool is_protected;
 
+  friend inline bool operator==(function_def const& lhs, function_def const& rhs)
+  {
+    return lhs.return_type == rhs.return_type
+      && lhs.name == rhs.name
+      && lhs.parameters == rhs.parameters
+      && lhs.c_name == rhs.c_name
+      && lhs.is_beta == rhs.is_beta
+      && lhs.is_protected == rhs.is_protected;
+  }
+  friend inline bool operator!=(function_def const& lhs, function_def const& rhs)
+  {
+    return !(lhs == rhs);
+  }
+  
   function_def(type_def return_type, std::string name, std::vector<parameter_def> parameters
                , std::string c_name, bool is_beta)
     : return_type(return_type), name(name), parameters(parameters), c_name(c_name), is_beta(is_beta) {}
@@ -504,6 +530,19 @@ struct event_def
   std::string name, c_name;
   bool beta, protect;
 
+  friend inline bool operator==(event_def const& lhs, event_def const& rhs)
+  {
+    return lhs.type == rhs.type
+      && lhs.name == rhs.name
+      && lhs.c_name == rhs.c_name
+      && lhs.beta == rhs.beta
+      && lhs.protect == rhs.protect;
+  }
+  friend inline bool operator!=(event_def const& lhs, event_def const& rhs)
+  {
+    return !(lhs == rhs);
+  }  
+  
   event_def(type_def type, std::string name, std::string c_name, bool beta, bool protect)
     : type(type), name(name), c_name(c_name), beta(beta), protect(protect) {}
   event_def(Eolian_Event const* event)
@@ -558,6 +597,21 @@ struct klass_def
   class_type type;
   std::vector<event_def> events;
 
+  friend inline bool operator==(klass_def const& lhs, klass_def const& rhs)
+  {
+    return lhs.eolian_name == rhs.eolian_name
+      && lhs.cxx_name == rhs.cxx_name
+      && lhs.namespaces == rhs.namespaces
+      && lhs.functions == rhs.functions
+      && lhs.inherits == rhs.inherits
+      && lhs.type == rhs.type
+      && lhs.events == rhs.events;
+  }
+  friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs)
+  {
+    return !(lhs == rhs);
+  }
+
   klass_def(std::string eolian_name, std::string cxx_name
             , std::vector<std::string> namespaces
             , std::vector<function_def> functions
diff --git a/src/lib/evas/Evas.hh b/src/lib/evas/Evas.hh
new file mode 100644 (file)
index 0000000..4bef419
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef EFL_EVAS_HH
+#define EFL_EVAS_HH
+#ifdef EFL_BETA_API_SUPPORT
+
+#include "Evas.eo.hh"
+
+#endif
+#endif
+
index c9ee5c8..0e46e84 100644 (file)
@@ -5,7 +5,9 @@
 #include <Ecore.h>
 
 #include <generic.eo.hh>
+#include <generic.eo.impl.hh>
 #include <name1_name2_type_generation.eo.hh>
+#include <name1_name2_type_generation.eo.impl.hh>
 
 #include "eolian_cxx_suite.h"
 
index f338133..dcd88ac 100644 (file)
@@ -4,6 +4,13 @@
 
 #include <Eo.hh>
 
+extern "C" {
+typedef Eo Cyclic1;
+typedef Eo Cyclic2;
+}
+
+#include <cyclic1.eo.h>
+#include <cyclic2.eo.h>
 #include <cyclic1.eo.hh>
 #include <cyclic2.eo.hh>