The Neoclassic binding of the CCA specification and design pattern. Ben Allan Sandia Laboratories, Livermore, CA March 2004 (1) Overview (2) Software layout (3) Relationship to Classic (4) Relationship to cca.sidl (5) Drivers and scripts. bld2neo. genNeoComponentIndex. configure support scripts. (6) Component mechanics New components. Upgrading from classic: Includes. Namespaces. Reductions of headers. Utility functions. Compiling. Linking. ----------------------------------------------------------------------------- (1) ---------------------------------- Overview: cca-spec-neo , being a specification and simple examples, is alleged to be self-documenting if run through doxygen. This is obviously false. Additional below. Generated docs are installed in $PREFIX/share/doc/ The neo binding and extensions of the CCA specification can be used without reference to Ccaffeine. That is to say, neo components can be built without any configuration info or headers that come from dccafe. At present only Ccaffeine is known to support the neo binding, however. The source tree as checked out from CVS is NOT the neo specification. You get the specification only after a 'make install'. See notes in INSTALL. (2) ---------------------------------- The structure of this repository module is as follows: Directory: What: neo/ The specification source tree neo/include The header sources. neo/include/neobase Core specification. neo/include/neoports Port definitions. neo/include/neosupport Utilities and framework independent fragments. neo/src Source for the neo library and utility scripts. neo/src/treeReader Private detail of XML support. neo/dox Generated documentation scratch area. eg-neo First example component tree. eg-neo/src SimpleStamper implementation. test Tree of tests and other examples, one per subdirectory. test/Parameter Test/example of ParameterPort usage. (3) ---------------------------------- Relationship to Classic The neo binding is intended to have a lower an impact on user code and build processes than the classic binding did. Which is to say, a) Neo allows for the generation of a statically linked executable without requiring that user components be dynamically loadable. In other words, building .so files is not required. There is no plan for a similar facility being added in the classic binding of Ccaffeine. See section 5, drivers and scripts. b) Neo provides the ComponentRelease interface so that component writers can more easily get the component lifecycle memory management and shutdown correct. An example of its use is provided in eg-neo with the SimpleStamper. c) The Ccaffeine-specific classic ParameterPort has been replaced with a map (hash table) facility just like the one defined in cca.sidl's ParameterPort. This eliminates building of components against Ccaffeine internal headers and the management of many trivial objects by the component writer. Now only one object, a TypeMap, must be managed. d) Neo does not impose a memory management model on the application-specific data structures. All interaction of user-allocated objects with the framework are mediated with pure-virtual abstract interfaces. Neo does use boost shared pointers to handle framework-allocated objects that advanced users may choose to access. Port, Services, and Component objects remain pointers as they are in classic. Object pointers, whether appearing as raw (neo::cca::Port *) or boostified (neo::cca::ComponentID_shared), are invoked using arrow syntax. E.g. std::string name = componentID->getInstanceName(); and double x_norm = mathPort->sum_squares(x_vector); Finally, all 'char *' usage in classic has been replaced with STL std::string use. In general use of the STL as much as possible is the rule. (4) ---------------------------------- Relationship to cca.sidl. Neo has a few interfaces that are extensions on cca.sidl. The neo binding is intended to have a lower an impact on user code and build processes than the Babel binding does. Which is to say, a) Neo tracks the interfaces defined in cca.sidl closely. As new sidl interfaces are defined, cca-spec-neo will have similar but pure-virtual interfaces added. b) Neo, once installed as a set of headers, does not require additional tools to preprocess component code. c) Neo does not impose the Babel/Java reference counting on all user data transferred through ports. Instead neo imposes C++ on all components. d) Extensions: ServiceRegistry- allows components to export a port as a service to all other components. Also allows the main program (acting as a component) to add services which cannot be fully encapsulated as components to framework. ComponentFactory- port definition that allows raw component instances to be manufactured and provided to the framework for final framing. ComponentRepository- adds a convenience method to the existing cca.sidl ComponentRepository interface. Services- adds genUniquePortName for service components that need it. (5) ---------------------------------- Drivers and scripts. The neo specification comes with a number of build support utilities. Additionally, example drivers come with Ccaffeine. Scripts: a) $prefix/bin/bld2neo This script will tranform a Ccaffeine bld or batch script (aka benspeak) into a ComponentFactory and driver based on AbstractFramework and BuilderService. Ccaffeine is required only in the final link of the generated code. The same generated code can, with manual modifications, be made into a container component which hides the complexity of the components wired within. Examples of using this script are found in i) dccafe/cxx/dc/neo/test ii) dccafe/cxx/dc/neo/mpitest. The mpitest example demonstrates the use of the ServiceRegistry to support MPI implementations which are not fully in component form. We recommend simplifying the input to bld2neo using the existing Ccaffeine utility script $CCAFE_INSTALL_ROOT/bin/simplify-bld b) $prefix/bin/genNeoComponentIndex This script will generate an XML component description file from a number of arguments. Help is available by running genNeoComponentIndex --help. Examples of using the script are found in i) cca-spec-neo/eg-neo/src/Makefile ii) cca-spec-neo/test/Parameter/src/Makefile c) Configuration/make support scripts are provided. $prefix/bin/ i) cca-spec-neo-config ii) eg-neo-config iii) neotest-parameter-config The configure.in files of cca-spec-neo/eg-neo/ and cca-spec-neo/test/Parameter/ provide examples of how to use cca-spec-neo-config. In fact, this is encapsulated in the autoconf 2.13 macro: NEOCLASSIC_SPEC_CCA defined in the acsite.m4 of either directory. Drivers: The regular ccafe-single/ccafe-batch/ccafe-client drivers work with neo-based components. Additionally: Ccaffeine provides test drivers which use the eg-neo SimpleStamper component. The directory for basic testing dccafe/cxx/dc/neo/test illustrates using build2neo with the input provided in $prefix/share/cca-spec-neo-$version/test-script-ccafe.scr The directory for testing with MPI dccafe/cxx/dc/neo/mpitest illustrates using build2neo with the input mpiTest.scr. The files test-script-ccafe.scr and mpiTest.scr are scripts of the sort saved from the ccaffeine GUI with additional directives !code and !header added. These directives cause C++ code in braces to be pasted into the generated C++ code. These directives are totally optional in the test-script-ccafe.scr example. They are required in the mpiTest.scr example to enable successful building with MPI. The input scripts are converted into a C++ class implementing interface $prefix/include/cca-spec-neo-$version/neosupport/NeoMain.hh. For each test, a main program is provided (driver.cc, mpiDriver.cc). These mains are templates that can be copied and adjusted for user applications. 6) ---------------------------------- Component mechanics When building components or Ccaffeine with cca-spec-neo, we recommend configuring --with-neo-config=/path/of/bin/cca-spec-neo-config to avoid the search process configure follows if the switch --with-cca-neo=/neo/installation/prefix is specified. New components: A component template, intended for cut-n-paste use, is in cca-spec-neo/eg-neo/. The example includes configure.in, Makefiles, and installation scripts. A component example using the CCA ParameterPortFactory, ParameterPort, ParameterGetListener and ParameterSetListener specifications is in cca-spec-neo/test/Parameter. Upgrading from Classic: Classic component authors upgrading to neo will find the major change to be in converting to the new parameter port. The function names are very similar. Other code changes: a) Includes: #include --> #include #include --> #include b) Namespaces: For all core interfaces- classic::gov::cca --> neo::cca For all specification port interfaces are in C++ namespace neo::cca::ports. E.g. neo::cca::ports::GoPort. c) Reductions: Macros CFREE/CDELETE/CONST/ENDSEMI disappear. Interface PortInfo disappears. Just use the two strings name and type in place of a PortInfo argument in the Services interface. Obsolete ports removed: RawData. PrintfPort. KeyValuePort. KeyValueTyped. KeyValueEnumerated. d) Additional convenience and utility functions are provided in #include For TypeMaps and parsing, notably: setParamsFromString transformString putValueByStrings dumpTypeMapStdout e) Compiling: Code using neo must be compiled with proper flags to get the correct included headers. These flags can be obtained with cca-spec-neo-config --var NEOCCA_INC Additional variables are relevant for building dynamically linked code. cca-spec-neo-config --dump gives a long list to pick from. In general, the best way to obtain flags for both compiling and linking is to extract all values at configure time from cca-spec-neo-config and ccafe-config. For sh: . `cca-spec-neo-config --var NEOCCA_VARS_SH` . `ccafe-config --var CCAFE_VARS_SH` For gmake: NEOCCA_MAKEINCL=$(shell cca-spec-neo-config --var NEOCCA_MAKEINCL 2>/dev/null) include $(NEOCCA_MAKEINCL) CCAFE_MAKEINCL=$(shell ccafe-config --var CCAFE_MAKEINCL 2>/dev/null) include $(CCAFE_MAKEINCL) f) Static and dynamic linking: Static linking with the Ccaffeine framework requires the framework, the specification, and any other libraries that were configured into the framework or the specification. libccafeCore.[a,so] libneocca-$version.[a,so] (neo spec) -lxml2 -lz -lm (libxml2 and support) -dl (dynamic loading support) -lmpich (or whatever parallel support) For libneocca, see cca-spec-neo-config --var NEOCCA_STATIC_LIB or cca-spec-neo-config --var NEOCCA_DYNAMIC_LIB to get the correct value. To see all available flags, use cca-spec-neo-config --dump and ccafe-config --dump