| 
     
      
      
      From: Leif J. <le...@am...> - 2003-04-28 17:09:43
       
   | 
Word. This is a confix/ccmtools issue so I'm posting to both development lists. A brief foreword is that we're moving the CCM Tools to use CPP (the C PreProcessor) to handle things like include files (a nassssty problem, indeed). So the theory is that you'd run something like ccmtools-generate <language> -I. -Iinclude_dir -I/usr/local/include_dir my_file.idl to generate components from all the IDL declarations in my_file.idl *and all included files*. This seems to be the only clean way to handle includes. It also has the benefits of (a) being able to use all the functionality of CPP (e.g. ifdef and define and such in source IDL files), and (b) cleaning up the CCM Tools code by delegating preprocessing to another, more stable, tool. But on with the problems ... On Mon, 28 Apr 2003, Egon Teiniker wrote: > Hey Leif! > > I tryed to run the owudb example > owudb/ > dbsql/ > |-- login_dbsql.idl > |-- user_dbsql.idl > ifaces/ > |-- auth.idl > |-- exc.idl > |-- ldbbrowser.idl > |-- logindata.idl > |-- logindatalist.idl > |-- loginmgr.idl > |-- persdata.idl > |-- udbbrowser.idl > using the cpp tool in different ways: > > a) cpp creates one IDL file per component and each component is build in a > separate package: > > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/user_dbsql.idl userdb.idl > > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/login_dbsql.idl login.idl > > ccmtools-c++-generate -p userdb userdb.idl > > ccmtools-c++-generate -p login login.idl > > ccmtools-c++-make -p userdb > > ccmtools-c++-make -p login > > ccmtools-c++-install -p userdb > > ccmtools-c++-install -p login > This is working until I tryed to compile a test client. Confix stopped with: > Both module login.CCM_Local (prio 0) and module userdb.CCM_Local (prio 0) > resolve #include<CCM_Local/UserPassAuthentication.h> > (from [['UserDB_DBSQL_gen.h']]) Right. From my point of view, this is a Confix issue : Confix complains here because there are two different modules (login and user) that provide the UserPassAuthentication (UPA) interface. On the CCM Tools side, both modules provide this header file because both of the source IDL files contain components that use the UPA interface. Thus the header file for the UPA interface is generated, compiled, and installed with each component (otherwise standalone components could not be installed at all). The CCM Tools have no way of knowing which interfaces are already installed on a system : that's Confix's responsibility. I think Confix should be changed to just go ahead and pick one of the two libraries here. (But maybe only if the --advanced option is specified ?) My reasoning : If the includes are named the same thing, it seems like a programmer error if they actually refer to separate implementations. The interface definitions should be put in separate namespaces if there are two different interfaces with the same name (having same-name anythings is just a bad idea anyway ; I think formal namespaces were invented by lazy programmers). I just thought of an alternative. If there was a way in Confix to give installed modules higher priority than local modules for a particular source directory or package, we could say that installed interfaces should be included preferentially over locally generated interfaces. So an installed component that provided the UPA interface header, for example, would be used to compile a new component that needed that interface, even if the same interface header was in the generated source package. Hope that makes sense. Now that I think of it, did you try the generation process below ? Maybe fully installing a component will allow the second component to use the first one's library / headers ? Confix --bootstrap is called as a part of the -generate script, so dependencies are resolved before the -make script is called. Maybe that's a bad idea ... ccmtools-c++-generate -p userdb userdb.idl ccmtools-c++-make -p userdb ccmtools-c++-install -p userdb ccmtools-c++-generate -p login login.idl ccmtools-c++-make -p login ccmtools-c++-install -p login > b) cpp creates one IDL file per component and the components are build in > the same package: > > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/user_dbsql.idl userdb.idl > > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/login_dbsql.idl login.idl > > ccmtools-c++-generate -p xxx *.idl > > ccmtools-c++-make -p xxx > This does not work: > =>./CCM_Local/include/CCM_Local/userdb_user_types.h:23: > redefinition of `struct CCM_Local::PersData' > ../CCM_Local/include/CCM_Local/login_user_types.h:39: > previous definition here > ../CCM_Local/include/CCM_Local/userdb_user_types.h:40: > redefinition of `class CCM_Local::NoSuchUser' > ../CCM_Local/include/CCM_Local/login_user_types.h:60: > previous definition here > ../CCM_Local/include/CCM_Local/userdb_user_types.h:40: > confused by earlier errors, bailing out > The problem is that the types are generated for every components. Hmm. Not sure what to do about this. We might just want to say that this development method is discouraged. :-/ > c) I created one IDL file that includes all components used in an assembly: > /*** > * owudb.idl > */ > #include "dbsql/login_dbsql.idl" > #include "dbsql/user_dbsql.idl" > Now, I build the owudb.idl file ... > > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp owudb.idl test.idl > > ccmtools-c++-generate -p test test.idl > > ccmtools-c++-make -p test > > ccmtools-c++-install -p test > This solution also works with the test client. That's excellent. This might be a good "best practice" development methodology, but we'll still eventually need to support deployment of individual components. > Summary: I think, we can live with (c) for the pilot project. For the > long term, I have to make (a) work because of the flexibility of > distributed component development. I definitely agree. Again, I think this is a Confix-solvable problem (just need to put a bit more voodoo in Confix). leif -- Leif Morgan Johnson . http://ambient.2y.net/leif/ IAESTE trainee . http://www.iaeste.org/ Salomon Automation . http://www.salomon.at/  | 
| 
     
      
      
      From: Joerg F. <jf...@ao...> - 2003-04-29 07:31:31
       
   | 
>>>>> "Leif" == Leif Johnson <le...@am...> writes: Leif> But on with the problems ... Leif> On Mon, 28 Apr 2003, Egon Teiniker wrote: >> Hey Leif! >> >> I tryed to run the owudb example >> owudb/ >> dbsql/ >> |-- login_dbsql.idl >> |-- user_dbsql.idl >> ifaces/ >> |-- auth.idl >> |-- exc.idl >> |-- ldbbrowser.idl >> |-- logindata.idl >> |-- logindatalist.idl >> |-- loginmgr.idl >> |-- persdata.idl >> |-- udbbrowser.idl >> using the cpp tool in different ways: >> >> a) cpp creates one IDL file per component and each component is build in a >> separate package: >> > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/user_dbsql.idl userdb.idl >> > cpp -P -I /home/eteinik/src/ccmtools/owudb/cpp dbsql/login_dbsql.idl login.idl >> > ccmtools-c++-generate -p userdb userdb.idl >> > ccmtools-c++-generate -p login login.idl >> > ccmtools-c++-make -p userdb >> > ccmtools-c++-make -p login >> > ccmtools-c++-install -p userdb >> > ccmtools-c++-install -p login >> This is working until I tryed to compile a test client. Confix stopped with: >> Both module login.CCM_Local (prio 0) and module userdb.CCM_Local (prio 0) >> resolve #include<CCM_Local/UserPassAuthentication.h> >> (from [['UserDB_DBSQL_gen.h']]) Leif> Right. From my point of view, this is a Confix issue : Confix complains Leif> here because there are two different modules (login and user) that provide Leif> the UserPassAuthentication (UPA) interface. Rightfully (of course :-). At the time Confix barfs about a duplicate provide the unwanted has already happened: one package has overwritten another's include file. Whether the involved include files are identical (because generated) or not is not in the scope of Confix. Leif> On the CCM Tools side, both modules provide this header file because both Leif> of the source IDL files contain components that use the UPA interface. Thus Leif> the header file for the UPA interface is generated, compiled, and installed Leif> with each component (otherwise standalone components could not be installed Leif> at all). The CCM Tools have no way of knowing which interfaces are already Leif> installed on a system : that's Confix's responsibility. It is as you say: both components *use* the UPA interfaces, in that they *include* the interface's IDL. I don't see why this should make them *define* (generate) that interface. What we need is a way to resolve IDL dependencies just as we resolve C/C++ dependencies. At least, when the IDL compiler runs, we need to pass it the include path to the installed IDL file that is being *used*. Leif> I think Confix should be changed to just go ahead and pick one of the two Leif> libraries here. (But maybe only if the --advanced option is specified ?) Yeah, randomly, no doubt. Leif> My reasoning : If the includes are named the same thing, it seems like a Leif> programmer error if they actually refer to separate implementations. That's what I say. Leif> I just thought of an alternative. If there was a way in Confix to give Leif> installed modules higher priority than local modules for a particular Leif> source directory or package, we could say that installed interfaces should Leif> be included preferentially over locally generated interfaces. So an Leif> installed component that provided the UPA interface header, for example, Leif> would be used to compile a new component that needed that interface, even Leif> if the same interface header was in the generated source package. Hope that Leif> makes sense. Sure this is possible. Still, I think we should solve the root of the problem rather than tackle its symptoms. The UPA interface is defined at some place, without knowledge of it being implemented by a component. It could just as well be implemented by a traditional CORBA server (a facet is a plain CORBA 2 interface, after all), and the person who defines that interface just doesn't care about how many times it is implemented. >> Summary: I think, we can live with (c) for the pilot project. For the >> long term, I have to make (a) work because of the flexibility of >> distributed component development. Leif> I definitely agree. Again, I think this is a Confix-solvable problem (just Leif> need to put a bit more voodoo in Confix). Me too, except for what I said above. (There's already quite a bit of voodoo in Confix that makes me search for pragmatic solutions.) Joerg  | 
| 
     
      
      
      From: Leif J. <le...@am...> - 2003-04-29 12:58:00
       
   | 
On Tue, 29 Apr 2003, Joerg Faschingbauer wrote:
> >>>>> "Leif" == Leif Johnson <le...@am...> writes:
> 
> Leif> On the CCM Tools side, both modules provide this header file because both
> Leif> of the source IDL files contain components that use the UPA interface. Thus
> Leif> the header file for the UPA interface is generated, compiled, and installed
> Leif> with each component (otherwise standalone components could not be installed
> Leif> at all). The CCM Tools have no way of knowing which interfaces are already
> Leif> installed on a system : that's Confix's responsibility.
> 
> It is as you say: both components *use* the UPA interfaces, in that
> they *include* the interface's IDL. I don't see why this should make
> them *define* (generate) that interface.
Doh, I was hoping you wouldn't notice that. (/me waves his hands vigorously
to distract Joerg ...)
I agree though. I will be muy pleased when the CCM Tools reach this point.
Unfortunately there are two problems at the moment :
a) the CCM metamodel spec doesn't provide any metadata about the source
   files from which a model element comes.
b) the CCM Tools as currently implemented cannot work with incomplete
   graphs ; that is, if there's a used interface A somewhere in a file,
   interface A must also be included in the model.
(a) is solvable by including some more information in the graph, and by
increasing the complexity of the parser. Quite a bit of work, but still
doable.
(b), I think, is not solvable. There's just no way to have, for example, a
model that omits interface A but includes a component that uses interface
A. There's no way to get appropriate data type information from an
incomplete graph.
This goes a bit further, because the next question is how to communicate to
the code generators whether or not to generate code for a given graph node
in a model. For instance, suppose we have the following IDL :
// data.idl
struct Ocean { int depth; }
// ifaces.idl
#include "data.idl"
interface Fisher { double fish_likelihood( in Ocean o ); }
// boat.idl
#include "ifaces.idl"
component Boat { provides Fisher jane; }
So if data.idl has already been used to generate code and install some
library, we'd like to not receive a new definition of the Ocean struct in
our generated code, because we somehow define it as "extern" and tell the
code generator not to generate the code.
The problem becomes a question of generating the parameters for the
generated Fisher interface. If we define the "Ocean" model node as extern
and tell the code generator to skip extern nodes, the generated
"fish_likelihood" function might not include the "o" parameter as a result.
Maybe we could just define a list of 'toplevel' node types that shouldn't
generate code if they're extern, but all nontoplevel node types would
produce code regardless ?
leif
-- 
Leif Morgan Johnson . http://ambient.2y.net/leif/
IAESTE trainee      . http://www.iaeste.org/
Salomon Automation  . http://www.salomon.at/
 | 
| 
     
      
      
      From: Joerg F. <jf...@ao...> - 2003-04-29 14:02:07
       
   | 
>>>>> "Leif" == Leif Johnson <le...@am...> writes:
Leif> This goes a bit further, because the next question is how to communicate to
Leif> the code generators whether or not to generate code for a given graph node
Leif> in a model. For instance, suppose we have the following IDL :
Leif> // data.idl
Leif> struct Ocean { int depth; }
Leif> // ifaces.idl
Leif> #include "data.idl"
Leif> interface Fisher { double fish_likelihood( in Ocean o ); }
Leif> // boat.idl
Leif> #include "ifaces.idl"
Leif> component Boat { provides Fisher jane; }
Leif> So if data.idl has already been used to generate code and install some
Leif> library, we'd like to not receive a new definition of the Ocean struct in
Leif> our generated code, because we somehow define it as "extern" and tell the
Leif> code generator not to generate the code.
Leif> The problem becomes a question of generating the parameters for the
Leif> generated Fisher interface. If we define the "Ocean" model node as extern
Leif> and tell the code generator to skip extern nodes, the generated
Leif> "fish_likelihood" function might not include the "o" parameter as a result.
How does an extern node behave? I mean, do you still know its
structure and only not generate code for it, or is it more shallow so
that it disappears from parameter lists?
Joerg
 | 
| 
     
      
      
      From: Leif J. <le...@am...> - 2003-04-30 08:35:47
       
   | 
On Tue, 29 Apr 2003, Joerg Faschingbauer wrote:
> How does an extern node behave? I mean, do you still know its
> structure and only not generate code for it, or is it more shallow so
> that it disappears from parameter lists?
I implemented this extern thing briefly in the 0.2 branch and then removed
it because it was evil. The implementation was basically a flag to include
generated code from "extern" child nodes in the metamodel graph. If this
flag was set then generated code from extern nodes would be propagated
upwards in the graph. If the flag was not set the code for such nodes
wouldn't be propagated upwards.
// data.idl
module Nature { struct Ocean { int depth; }; };
// ifaces.idl
#include "data.idl"
module Nature { interface Fisher { double fish_likelihood( in Ocean o ); }; };
// boat.idl
#include "ifaces.idl"
module Nature { component Boat { provides Fisher jane; }; };
If we have this IDL, parsing the boat.idl file will give a metamodel graph :
MContainer 'boat'
` MModuleDef 'Nature'
  + MInterfaceDef 'Fisher' (extern)
  | ` MOperationDef 'fish_likelihood' (extern)
  |   ` MParameterDef 'o' (extern)
  + MStructDef 'Ocean' (extern)
  ` MComponentDef 'Boat'
    ` MProvidesDef 'jane'
So the difficulty is how we indicate to the code generators that, for
example, code from the 'Fisher' subgraph should not be propagated upwards
to the 'boat' container (and then written to disk), but the code from the
'fish_likelihood' subgraph should be propagated to the 'Boat' component
(and then written to disk).
Maybe it's enough to come up with a list of node types for which extern
code should be conditionally included, e.g. anything except struct, union,
and interface. Maybe we ought to say that code should be written to disk
for MStructDef, MUnionDef, MExceptionDef, MAliasDef, and MEnumDef nodes
(currently in the C++ generators code is only written to disk for
MContainer, MComponentDef, MHomeDef, and MInterfaceDef nodes).
leif
--
Leif Morgan Johnson . http://ambient.2y.net/leif/
IAESTE trainee      . http://www.iaeste.org/
Salomon Automation  . http://www.salomon.at/
 |