Customizable application project generation process and system5754858Abstract Custom application project generators are created to generate specific types of computer application programs using an automated procedure implemented in a customizer tool. The customizer tool creates a custom generator project according to options chosen by a writer from a sequence of generator option selection steps. The custom generator project comprises source code files, templates, and dialogs which the writer can further modify using an editor. The custom generator project is compiled and linked to form a custom application project generator which implements an automated procedure for generating a specific type of application defined by the writer. The custom application project generator interfaces with a services module that provides default user interface and code generation services which can be overridden by the writer. Claims We claim: Description COPYRIGHT AUTHORIZATION
______________________________________
// $$root$$.h : main header file for the $$ROOT$$
// application
#include "resource.h"
// main symbols
///////////////////////////////////////////////////////
///////////////
// $$APP.sub.-- CLASS$$:
// See $$root$$.cpp for the implementation of this
// class
class $$APP.sub.-- CLASS$$ : public $$APP.sub.-- BASE.sub.-- CLASS$$
public:
$$APP.sub.-- CLASS$$();
// Overrides
// ClassWizard generated virtual function
// overrides
//{{AFX.sub.-- VIRTUAL($$APP.sub.-- CLASS$$)
public:
virtual BOOL InitInstance();
//}}AFX.sub.-- VIRTUAL
// Implementation
//{{AFX.sub.-- MSG($$APP.sub.-- CLASS$$)
$$IF(VERBOSE)
// NOTE - the ClassWizard will add and
// remove member functions here.
// DO NOT EDIT what you see in these
// blocks of generated code|
$$ENDIF
//}}AFX.sub.-- MSG
DECLARE.sub.-- MESSAGE.sub.-- MAP ()
};
______________________________________
The macros in the text templates are strings of characters that represent values. In the text templates, the values of the macros (such as $$ROOT$$ and $$APP.sub.-- CLASS$$) control the names of files and classes in the source code of the application project 54. The values of macros (such as VERBOSE) also control whether flow of control directives (such as $$IF) evaluate to true. The values represented by the macros are maintained in a macros dictionary (implemented in the illustrated embodiment as an object of the CMapStringToString class from the MFC library) named projectaw.m.sub.-- Dictionary and declared in a projectAW.H file of the source files 66 (where project is the name of the custom generator project). The automated customizer tool 60 generally includes a set of standard application project generator macros in the text templates 70 and macros dictionary. The writer also can add writer-defined macros to the text templates 70 and macros dictionary when editing the custom generator project 64 with the editor 80. The services module 76 gathers the values of the macros during the process of generating the application project 54, such as from the application project options chosen by the user. In the illustrated text templates 70, the beginning and end of macros are marked with a pair of dollar sign characters ($$) for parsing by the service module 76 when generating the application project 54, as shown in the following example template fragment:
______________________________________
///////////////////////////////////////////////////////
// $$APP CLASS$$
BEGIN.sub.-- MESSAGE.MAP($$APP.sub.-- CLASS$$,
$$APP.sub.-- BASE.sub.-- CLASS$$)
//{{AFX.sub.-- MSG.sub.-- MAP($$APP.sub.-- CLASS$$)
$$IF (VERBOSE)
// NOTE - the ClassWizard will add and
// remove mapping macros here.
// DO NOT EDIT what you see in these
// blocks of generated code|
$$ENDIF
//}}AFX.sub.-- MSG
ON.sub.-- COMMAND(ID.sub.-- HELP, CwinApp::OnHelp)
END.sub.-- MESSAGE.sub.-- MAP()
______________________________________
Macros that are used as arguments to a directive (such as $$IF) do not require marking by dollar signs. If such macros are marked with dollar signs, the dollar signs are interpreted as part of the macro's name (i.e., argument macros still can be marked by dollar signs). For example, both AMACRO and $$AMACRO$$ can serve as macro names in the following two directive statements: $$IF(AMACRO); $$IF ($$AMACRO$$); Directives (such as $$IF and $$ENDIF) serve to generalize the text templates so that the content of the templates can be used by the service module 76 for generating multiple types of application projects. Directives in a template guide the services module 76 as it processes a template to produce a source file in the application project 54. For example, based on the value of a macro, a sequence of $$IF, $$ELIF, $$ELSE, and $$ENDIF directives can force the services module 76 to selectively insert lines of C++ code into a header or an implementation file (.H or .CPP, respectively) used in the application project 54. The illustrated services module 76 recognizes the following directives: $$IF, $$BEGINLOOP, $$ELIF, $$ENDLOOP, $$ELSE, $$SET.sub.-- DEFAULT.sub.-- LANG, $$ENDIF, $$//, and $$INCLUDE. These directives must appear at the beginning of a line with no preceding white space, and, other than any arguments and one optional comment, there can be nothing else on the line. For the service module 76 to emit "$$" literally (and not to signify that a macro or directive will follow), the character string "$$$$" is used. The service module 76 translates occurrences of "$$$$" as "$$". In each custom generator project 64, the automated customizer tool 60 also includes copies of a confirm.inf template and a newproj.inf template. The confirm.inf template contains a human-readable description of each project component (such as the project name and the names of its primary classes). It also contains a description of each feature that the user can choose with the application project options. The following code shows how macros and flow-of-control directives are used to generalize the content of a confirm.inf template:
______________________________________
$$// confirm.inf = the text sent to the New Project
$$// Information dialog box
Application type of $$ROOT$$:
Dialog-Based Application targeting:
Win32
Classes to be created:
Application: $$APP.sub.-- CLASS$$ in $$RQOT$$.h and
$$ROOT$$ . cpp
Dialog: $$DLG.sub.-- CLASS$$ in $$DLG.sub.-- HFILE$$.h and
$$DLG.sub.-- IFILE$$.cpp
Features:
+ About box on system menu
$$IF (INDENTED.sub.-- BRACES)
+ Curly braces indented from previous level
$$ELSE // |INDENTED.sub.-- BRACES
+ Curly braces flush with previous level
$$ENDIF // NOT.sub.-- INDENTED.sub.-- BRACES
$$IF(COMPANY.sub.-- LOGO)
+ A company logo
$$ENDIF //COMPANY.sub.-- LOGO
$$IF(3-D)
+ 3D Controls
$$ENDIF //3-D
______________________________________
This example of the confirm.inf template contains lines of text (such as "Classes to be created:"), macros (such as "$$APP.sub.-- CLASS$$" and "$$ROOT$$"), and flow-of-control directives (such as "$$IF" and "$$ENDIF"). The confirm.inf template is parsed by the services module 76 to generate the contents of a "New Project Information" dialog box for the application project 54. The services module 76 parses the confirm.inf template when the user activates the finish button of the generator user interface 78 in the application project option selection step sequence. The service module 76 parses the confirm.inf template as follows: Each line of text is gathered into a CString object (an object of the CString class of the MFC class library), and each encountered macro is expanded. Any line beginning with the $$// directive is a comment and is ignored. Any line of text between an $$IF directive and an $$ENDIF directive is converted to a CString object if the associated macro, such as "INDENTED.sub.-- BRACES" and "COMPANY.sub.-- LOGO," exists and thus evaluates to true. As described below, this is the same process used by the services module 76 in parsing other text templates. The resulting CString objects reflect the custom application project generator user's choices and are written to the New Project Information dialog box. The user thus can view the features of the application project 54. The newproj.inf template contains the instructions that the services module 76 uses to construct the application project 54. The instructions are statements, directives, and macros that work together to describe the structure of the application project 54. The following code shows how statements and macros are used to generalize the instructions of a NEWPROJ.INF file:
______________________________________
+dlgroot.rc ..backslash.$$RCOT$$.rc
+dlgroot.clw ..backslash.$$ROOT$$.clw
dlgrooth.h ..backslash.$$ROOT$$.h
+dlgroot.cpp . .backslash.$$ROOT$$.cpp
dialog.h ..backslash.$$ROOT$$dlg.h
+dialog.cpp ..backslash.$$ROOT$$dlg.cpp
readme.txt ..backslash.readme.txt
resource.h ..backslash.resource.h
stdafx.h ..backslash.stdafx.h
+stdafx.cpp ..backslash.stdafx.cpp
/RES
=root.ico ..backslash.res.backslash.$$ROOT$$.ico
root.rc2 ..backslash.res.backslash.$$ROOT$$.rc2
______________________________________
In general, there are two kinds of statements in the newproj.inf template: those that create directories, and those that fill the directories with files. The create directory statement has the syntax:/directory, where directory specifies a name. This statement directs the services module 76 to create a subdirectory of the project directory with the specified name. In the previous example, the "/RES" statement causes the services module 76 to create a project subdirectory named RES. The statements for filling directories have the syntax ›flags! template-name tab-character destination-filename. These statements direct the services module 76 to parse the template specified by "template-name" to generate a file named by "destination-filename." The destination-file name can contain a path (i.e., in a file system structure) which must exist, but may be created by a preceding create directory statement. The flags are any of three optional characters, =, +, and *. The "=" flag directs the services module 76 to copy the specified template verbatim to the destination file name. The services module 76 otherwise parses the specified template as a text template by default. The "+" flag specifies that the file being generated is a project file (such as a .CPP source code file or .ODL file) whose name is to be added by the services module 76 to the make file of the application project. (The make file is a conventional file used by the compiler and linker 88 which lists source code files of the application project 54 that must be compiled to build the application 56 from the application project 54.) The "*" flag directs the services module 76 to parse one of the standard template rather than a custom template (out of the templates 70) of the specified template-name if one exists. For example, the "+dlgroot.rc ..backslash.$$ROOT$$.rc" statement in the above example newproj.inf template causes the services module 76 to look for a template named "IDLGROOT.RC," give it a name determined by the value of the $$ROOT$$ macro, and place the resulting file in the new project's root directory. The plus sign (+) is a flag that marks this template for inclusion in the project make file (.MAK). For brevity, directives (such as $$IF, $$ELSE, and $$ENDIF) are not shown in the previous example, but they can be used as shown in the confirm.inf template example. The automated customizer tool 60 creates the templates for the custom generator project 64 differently depending on the custom generator options chosen by the writer. When the custom generator based on existing project option is chosen, the automated customizer tool 60 converts all files of the existing project (which is specified by the writer in the second custom generator options selection step) into binary and text templates for the custom generator project 64. The source code files of the existing project are converted into text templates. Non-text files, such as bitmaps, are copied exactly into binary templates. In converting the source code files into text templates, the automated customizer tool 60 finds and replaces strings that contain remnants of the existing project's name (e.g., source code files of a project named "Foo" may include classes named "CfooView" and "CfooDoc") and replaces such string remnants with macros (e.g., the class names are changed to "C$$ROOT$$View" and "C$$ROOT$$Doc"). When the resulting text templates are later parsed by the services module 76 to generate source code files of the application project 54, the macros are expanded based on a new name (entered by the user when choosing application project options at generator user interface 78 of FIG. 2) for the application project 54, and not the original project name. In addition, the automated customizer tool 60 generates the newproj.inf template with statements based on the structure of the existing project. The confirm.inf template for the custom generator project 64 is left empty. The writer adds text, macros and directives to the confirm.inf template that, when parsed by the custom application project generator 52 and services module 76, produce descriptions, in a human-readable form, of the features that the user has chosen from the application project options. The custom application project generator 52 places these descriptions from the parsed confirm.inf template into the user's new application project 54. When the custom generator based on standard steps is chosen, the automated customizer tool 60 copies a set of standard templates into the custom generator project 64 for use as the templates 70. The automated customizer tool 60 copies a different set of custom templates depending on the writer's choice of application project type (i.e., executable or dynamic link library) in the second custom generator option selection step. The standard templates used in the illustrated embodiment are described in detail in Appendix C and include templates from which .H, .CPP, .RC, .CLW, .ODL, and .RC2 files of the application project 54 are generated. The standard templates also include bitmaps of standard user-interface components and templates for help files. The writer can modify these standard templates or add the writer's own custom templates with the editor 80. The automated customizer tool 60 additionally includes standard confirm.inf and newproj.inf templates, which the writer can modify to reflect any custom application project option selection steps added by the writer. When the custom generator based on custom steps is chosen, the writer provides a set of templates which the writer creates using the editor 80. The confirm.inf and newproj.inf templates are initially empty. For the custom application project option selection steps added by the writer, the writer edits the confirm.inf and newproj.inf steps to reflect the features that the user can choose in these custom steps. Framework As described above, the custom application project generator 52 relies on the services module 76 to provide basic or default application project generator functionality such as for the generator user interface 78 and application project 54 generation. The custom application project generator 52 interfaces with the service module 76 to access this functionality using a framework 74 which allows the writer to override the service module's default application project generator functionality as desired by the writer. The Services Module API Functions The framework 74 comprises a set of application programming interface ("API") functions implemented in the services module 76 which the custom application project generator 52 calls to communicate with the services module. In the illustrated embodiment, these API functions include a set custom generator class ("SetCustomAppWizClass") function, a get dialog ("GetDialog") function, a set number of steps ("SetNumberOfSteps") function, a scan for available languages ("ScanForAvailableLanguages") function, and a set supported languages ("SetSupportedLanguages") function. With the set custom generator class function, the custom application project generator 52 passes to the services module 76 a pointer to its instance of a custom application project generator ("CCustomAppWiz") class (described below). The get dialog function returns a pointer to a standard application project option selection step. The custom application project generator 52 calls this function when it uses one of the standard steps in its application project option selection sequence. The custom application project generator 52 calls the set number of steps function to inform the services module 76 how many total steps are in the application project option selection sequence (for the application project options currently chosen by the user). This allows the services module 76 to update its internal state and the display of the generator user interface 78 (i.e., the caption on the title bar of the interface's dialog which states the current step out of the total number--"Custom AppWizard Step 3 of 6") when the total number of steps changes due to the user's current chosen application project options. The scan for available languages function and the set supported languages function are used by the custom application project generator 52 in localizing the application project 54 to a particular language as described below. The Custom Application Project Generator Class and Virtual Member Functions The framework 74 also comprises a custom generator class ("CCustomAppWiz" described in detail in Appendix E) with virtual functions. The custom application project generator 52 includes an instance of a derivation of this class. The services module 76 calls the virtual functions of the custom generator class to communicate with the custom application project generator 52. The declaration of the custom generator class in the illustrated embodiment is as follows:
______________________________________
class CCustomAppWiz : public CObject
public:
CMapStringToString m.sub.-- Dictionary;
virtual void GetPlatforms (CStringList&
rPlatforms) {}
virtual CAppWizStepDlg* Next (CAppWizStepDlg*
pDlg) { return NULL; }
virtual CAppWizStepDlg* Back (CAppWizStepDlg*
pDlg) { return NULL; }
virtual void InitCustomAppWiz() {
m.sub.-- Dictionary.RemoveAll(); }
virtual void ExitCustomAppWiz() {}
virtual LPCTSTR LoadTemplate (LPCTSTR
lpszTemplateName,
DWORD& rdwSize, HINSTANCE hInstance = NULL);
virtual void CopyTemplate(LPCTSTR lpszInput,
DWORD dwSize, OutputStream* pOutput);
virtual void ProcessTemplate (LPCTSTR
lpszInput, DWORD dwSize, OutputStream* pOutput);
virtual void PostProcessTemplate (LPCTSTR
szTemplate) {}
};
______________________________________
Many of these functions are implemented in the base custom generator class. Since the functions are virtual, the writer can chose to override (using conventional C++ programming techniques) some or all of the functions in the custom application project generator's derivative of the class. Then, the services module 76 will transparently call the writer's new implementation of the overridden functions in the derived class, and the original implementation of the functions that the writer chooses not to override. For example, if the writer wishes to have the custom application project generator 52 load its templates differently, the writer can override the "LoadTemplate" function (described in the attached Appendix E) in the derived class, and thereby bypass the original implementation of that function. Thereafter, when the services module 76 calls this virtual function to load a template for the custom application project generator 52, the services module 76 transparently calls into the writer's new implementation of the function in the code of the custom application project generator 52. As described previously, the custom application project generator 52 initially passes a pointer for its instance of the custom generator class to the service module 76 when the custom application project generator calls the set custom generator class API function. The custom application project generator calls this API function when the custom application project generator 52 is first loaded (i.e., by a "LoadLibrary" API function call of the services module 76 to the operating system). The code for the set custom generator class API function call in the custom application project generator is automatically generated by the automated customizer tool 60. The implementation of the set custom generator class API function in the services module 76 sets an internal custom generator class pointer of the services module 76 to be the pointer passed by the custom application project generator 52. The services module 76 makes all of its calls into the custom generator class functions through this internal pointer. So, by setting the internal pointer to be the pointer passed by the custom application project generator 52, the services module 76 causes the code of the custom application project generator's derivation of the CCustomAppWiz class to be executed for each of the CCustomAppWiz functions. Customizing the Application Project Option Selection Step Sequence The system 50 (FIG. 2) allows the writer to customize the custom application project generator's sequence of application project option selection steps to include any mix of standard steps and writer-defined custom steps. The framework 74 exposes the ability for the writer to mix standard and custom steps with the GetDialog API function, along with the Next and Back virtual functions which are mentioned above and described in detail in Appendices D and E. The GetDialog, Next and Back functions allow the custom application project generator 52 and the services module 76 to operate together in presenting a customized sequence of application project option selection steps to the user at the generator user interface 78. The custom application project generator 52 prepares in advance for displaying standard steps by calling the get dialog API function with an argument specifying a particular standard step. The custom application project generator 52 calls the get dialog API function separately for each of the standard steps that it uses at initialization of the custom application project generator. The services module 76 maintains pointers to dialogs (e.g., the step's corresponding inner dialog 156 such as shown in FIG. 4) for all of the standard steps, and responds to the call by looking-up and returning a pointer to the step specified in the call. The custom application project generator 52 stores the returned dialog pointers internally. For example, if the custom application project generator 52 uses the standard step for selecting object linking and embedding ("OLE") application project options, the custom application project generator 52 makes the call: "GetDialog(APWZDLG.sub.-- OLE)." The services module 76 responds by retrieving and returning the dialog for this step to the custom application project generator. The custom application project generator stores this pointer internally (e.g., as a pointer "pOleDlg"). Later, as the user navigates through the application project option selection steps with the next and back buttons 160-161 (FIG. 4), the services module 76 calls the Next and Back virtual functions of the custom generator class implemented in the custom application project generator 52. In response to such calls, the custom application project generator 52 returns the dialog pointer for the step (which may be a dialog pointer for a standard step obtained by the custom application project generator with the GetDialog function or a dialog pointer for a custom step) that follows or precedes, respectively, the current step of the sequence. With the returned dialog pointer, the services module 76 calls a function, "Create()," to display that step's dialog as the inner dialog 156 of the dialog 150 (FIG. 4) of the generator user interface 78 (FIG. 2). With this structure for the framework 74, the writer can customize the application project options selection sequence by overriding the next and back functions of the derived custom generator class implemented in the custom application project generator 52 so as to return dialog pointers to a desired sequence of standard and/or custom steps. The customizer tool 60 generates the source files 66 of the custom application project generator with a default derived custom generator class including the next and back functions when the writer chooses the create custom generator based on standard steps option described above. The writer then overrides the next and back functions by editing the custom generator class in the source files 66 with the editor 80. Customizing the Application Project Files Generated by the Custom Application Project Generator The system 50 (FIG. 2) allows the writer to customize the files of the application project 54 that the custom application project generator 52 generates. As discussed above, the writer can modify standard templates or add the writer's own custom templates to change the application project 54 files that the custom application project generator 52 generates. The framework 74 also exposes the ability for the writer to modify the way in which the custom application project generator 52 parses the templates to generate the application project 54 with the following virtual member functions of the custom generator class: a load template function ("CCustomAppWiz::LoadTemplate"), a copy template function ("CCustomAppWiz::CopyTemplate"), a process template function ("CCustomAppWiz::ProcessTemplate"), and a post process template function ("CCustomAppWiz::PostProcessTemplate"). When processing the templates 70 to generate the application project 54, the services module 76 first loads the newproj.inf template by calling the load template function of the custom generator class which has the following form: virtual LPCTSTR LoadTemplate(LPCTSTR lpszTemplateName, DWORD& rdwSize, HINSTANCE hInstance=NULL); The default or custom generator base-class implementation of the load template function loads the template specified by the argument LpszTemplateName in the module hInstance. The argument hInstance is a handle to an instance of a module. If hInstance is NULL, the base-class implementation of the load template function first looks in the custom application project generator's DLL for the custom resource template named by the argument lpszTemplateName. If the template is not there, the function searches among the standard templates of the services module 76. If hInstance is not NULL, the base-class implementation of LoadTemplate looks in the Win32 module hInstance. When the named template is found by LoadTemplate, it loads the resource with the following code: HRESOURCE hrsrc=::FindResource(hInstance, lpszTemplateName, "TEMPLATE"); dwSize=::SizeofResource(hInstance, hrsrc); HGLOBAL hglb=::LoadResource(hInstance, hrsrc); LPCTSTR lpszTemplate=(LPCTSTR) ::LockResource(hglb); The services module 76 next parses the newproj.inf template by calling the process template function, which has the following form: virtual void ProcessTemplate(LPCTSTR lpszinput, DWORD dwSize, Outputstream* pOutput); The process template function operates as a simple text processor which expands the template's macros, and performs the template's directives as described above. The arguments include pointers lpszInput and pOutput to the input and output streams of the parser. For parsing the newproj.inf template, the services module 76 passes as the output stream argument a pointer to an object of the CStringList class (a conventional MFC class) rather than a file pointer. The parser's output then goes into the string list data structure. After the process template function call, the services module 76 calls the post process template function. The default implementation of the post process function does nothing, but can be overridden by the writer to perform clean-up work. The services module 76 then iterates through a loop which read each line of the parsed newproj.inf template (as stored in the string list data structure). For each line, the services module 76 calls the process template function with pointers to the template and destination file specified in the line as the function's input and output stream arguments. After each process template function call, the services module 76 calls the post process template function call to perform clean-up work. With this default functionality of the framework 74, the writer can customize which templates are processed into application project files by including appropriate template processing directives in the newproj.inf file as described above. The writer also can customize the manner in which the custom application project generator processes the templates by overriding the load template, copy template, process template, and post process template functions of the base custom generator class with the writer's own versions of the functions in the writer's derived custom generator class. The writer can, for example, change the manner in which the process template function expands the macros of the templates by overriding the default process template function with a modified process template function. Customizing to Different Languages The system 50 (FIG. 2) allows the writer to create the custom application project generator 52 with the ability to localize the application project 54 to a particular language chosen by the user. The system 50 accomplishes localization through standard templates for different languages, a naming convention for localizable templates, a set default language template directive (the "$$SET.sub.-- DEFAULT.sub.-- LANGUAGE" directive), and a set supported languages API function. As discussed above, when the writer chooses the custom generator based on standard steps option, the customizer tool 60 prompts the writer to choose which languages the custom application project generator 52 is to support (the default is to select all languages supported in the standard templates) in the second custom generator options selection step. When creating the custom generator project 64, the customizer tool 60 then duplicates each of the standard templates that is localizable in the templates 70 of the custom generator project 64 to each of the chosen languages. For example, if the writer chooses for the custom application project generator 52 to support French and German, the customizer tool 60 duplicates the localizable template loc.rc in a French version (named loc.sub.-- fra.rc) and in a German version (named loc.sub.-- deu.rc) in the templates 70. The customizer tool 60 also duplicates all other localizable standard templates. The customizer tool 60 names the duplicated, localized templates according to a naming convention in which the language is identified by a three letter suffix appended to the template name. For displaying a list of the languages supported by the custom application project generator 52 in the standard application project options selection step for language localization, the custom application project generator 52 calls the set supported languages API function of the services module 76 at initialization. In the argument of the function call, the custom application project generator 52 passes a string consisting of the names and translation identifiers of the languages that it supports. The translation identifiers are 32 bit integers which encode the language, sublanguage, and code page of the language used by the Microsoft Windows.RTM. operating system API. In response to the function call, the service module 76 sets up an internal list of the supported languages and their translation identifiers. Referring again to FIG. 4, the services module 76 can then display, in the dialog of a standard application project options selection step which includes choosing the language of the application project 54, a list box control 168 with a drop down list of the languages supported by the custom application project generator 52 (for custom application project generators that include this standard step). When the user chooses one of the languages in the list with the input device 28 (FIG. 1), the services module 76 (FIG. 2) stores the name and identifier of the chosen language for use in application project generation. Returning to FIG. 2, the custom application project generator 52 uses the set default language directive to determine which of the localized templates to parse into the source files of the application project 54. For this purpose, the set default language directive is included as a line in the newproj.inf template as follows: $$SET.sub.-- DEFAULT.sub.-- LANG(LANG.sub.-- SUFFIX) When the services module 76 parses this line in the newproj.inf template, the macro "LANG.sub.-- SUFFIX" is expanded to the three letter suffix of the language chosen by the user. For example, if the user chooses to generate the application project 54 in French, this macro is expanded to "FRA." This directive instructs the custom application project generator's parser to thereafter append this three letter language suffix to the name of any template that is not otherwise found in the templates 70. For example, if the newproj.inf template thereafter has the line: =afxcore.rtf AfxCore.rtf which instructs the parser to process the afxcore.rtf template, the custom application project generator first searches for the afxcore.rtf template. If it is a localizable template, the customizer tool 60 will have duplicated the template to templates with the three letter language suffixes as explained above. The parser therefore does not find the template with the name afxcore.rtf. Accordingly, due to the preceding set default language directive in the newproj.inf template, the parser expands the template name to afxcore.sub.-- fra.rtf (the french version of the template) and searches for the template with that name. Thus, the custom application project generator parses the localized templates'for the language selected by the user. Customizing to Different Platforms The system 50 (FIG. 2) allows the writer to create the custom application project generator 52 with the ability to generate the application project 54 to a specific computing platform (specifically the operating system and hardware platform, e.g., Microsoft Corporation's Win32 operating system and IBM compatible PC; Apple Computer, Inc.'s Macintosh operating system and computer; etc.) chosen by the user. The system 50 accomplishes platform specific application project generation through a get platforms virtual function in the custom generator class ("CCustomAppWiz::GetPlatforms"), a standard application project options selection step, and a set of macros. In the illustrated system 50, the user chooses to run the custom application project generator 52 for generating the user's application project 54 from a "create new project" dialog which is controlled by the Visual C++ development environment. The user opens the create new project dialog with a menu command in Visual C++. The create new project dialog includes user interface controls with which the user can choose to generate the user's new application project 54 with the custom application project generator 52. The create new project dialog also includes a list control in which a list of the available platforms to which the custom application project generator can target the application project 54. The user chooses from the list the platforms for which the application project 54 is to be targeted. When the user chooses to run the custom application project generator 52 from the create new project dialog, the create new project dialog is followed by the dialogs for the sequence of project option steps of the custom application project generator. For displaying the list control of the create new project dialog, the services module 76 calls the get platforms function of the custom generator class, and passes as an argument to the function call a list (also implemented as an object of the CStringList class from the MFC class library) of names of available platforms (i.e., those currently installed in the development system). The default implementation of the get platforms function in the base custom generator class does not change the list. The get platforms function can be overridden by the writer in the derived custom generator class in the source files 66 (FIG. 2) with a function that removes the names of the platforms not supported by the custom application project generator. Thus, as a result of this call, the services module 76 has a list of only the platforms supported by the custom application project generator 52 which the services module 76 can display in the list control at the generator user interface 78 for user selection of platforms to be targeted. After the user chooses the platform or platforms to target with the list control, the services module 76 enters a separate macro ("platform targeting macro") for each platform in the macros dictionary of the custom application project generator 52 (and removes the platform targeting macros, if any, for the platforms not chosen by the user from the macros dictionary). For example, if the user chooses to target the application project 54 for the Power Macintosh platform, the services module 76 enters the macro "TARGET.sub.-- POWERMAC" in the macros dictionary. In later generating the application project, the existence of the platform targeting macro(s) in the macros dictionary then indicates to the custom application project generator 52 which platform(s) is(are) to be targeted. (The actual value assigned to the platform targeting macro in the macros dictionary is not significant.) Specifically, directives such as the following can be included by the writer in the templates 70 to cause the services module 76 to generate platform specific code in the application project 54 for the platform or platforms chosen by the user: $$IF(TARGET.sub.-- POWERMAC) powermac-specific code goes here . . . $$ENDIF Additionally, the writer can include code in the custom application project generator (such as in the process template and post process template functions of the custom generator class) to perform platform specific application project generation conditioned on the existence of the platform targeting macros in the macros dictionary. Customizing the Custom Application Project Generator to Create Replicas of an Existing Project As discussed above, one of the generator options that can be chosen by the writer when creating the custom generator project 64 (FIG. 2) with the customizer tool 60 (FIG. 2) is the create custom generator based on existing project option. When the writer chooses this option, the customizer tool 60 generates templates 70 for the custom generator project 64 from the source files of the existing project and creates the custom application project generator 52 to use these templates for generating the application project 54 as a replica of the existing project. As further discussed above, the customizer tool 64 generates the templates from the existing project by parsing the source files of the existing project and replacing any strings in those source files that contain remnants of the existing project's name with macros (e.g., replacing strings like "CFooView" and "CFooDoc" in an existing project named "Foo" with "C$$ROOT$$View" and "C$$ROOT$$Doc"). With this substitution, the custom application project generator 52 can generate the application project 54 from the templates by expanding the macros (e.g., $$ROOT$$) with a new project name chosen by the user. Thus, the resulting templates are capable of creating new files with strings based on the new project name chosen by the user, in place of the existing project's name. In the illustrated embodiment, the customizer tool 60 does not make the existing project name to macro substitution for all strings in the existing project, but instead performs the substitution only for strings in the existing project that have predetermined contexts (where substitution is needed). This overcomes the problem that for some project names, substituting all occurrences of the project name with macros can have disastrous consequences to the source code. For example, if "while" (which is a reserved word in C++ and many other programming languages) is used as the name of the existing project, the source code would be rendered inoperative if all occurrences of "while" in the existing project's source code files were substituted by a macro and the macro later expanded to a new user-chosen name of the application project 54. The contexts in which the customizer tool 60 makes the existing project name to macro substitution is controlled by a table (which is located in the zap.cpp source code file having the following form:
______________________________________
static ZapRawData zrdGeneral›! =
{.sub.-- T(" "), ZRD.sub.-- ROOT, .sub.-- T(".h"), {.sub.-- T("$$root$$.h
"),
.sub.-- T("root.h") }},
{.sub.-- T(" "), ZRD.sub.-- ROOT, .sub.-- T(".cpp"),
{.sub.-- T("$$root$$.cpp"), .sub.-- T("root.cpp")}},
{.sub.-- T(" "), ZRD.sub.-- ROOT, .sub.-- T(".rc"), {.sub.-- T("$$root$$.
rc"),
.sub.-- T("root.rc")}},
{.sub.-- T(" "), ZRD.sub.-- ROOT.sub.-- UPR, .sub.-- R(".RC"),
{.sub.-- T("$$ROOT$$.RC"), NULL}},
. . .
}
______________________________________
The customizer tool 60 searches for strings in the source code files of the existing project that have the contexts listed in this table, and makes the project name to macro substitution only for those strings having these contexts. The contexts are selected to be safe (i.e., contexts where the substitution does not render the source code file inoperative) for source code files of projects that are generated from the standard templates. Thus, for existing projects that were originally based on the standard templates, the customizer tool 60 (and the custom application project generator 52 that it creates) makes the existing project name to macro to user chosen project name substitution in only the context where the substitution should be made to replicate the existing project's files into the application project 54. In some embodiments of the invention, a collection or library of custom application project generators as described herein for generating various specific application project types can be formed and made available to users for developing the specific application types. Such a library can be distributed to users on a computer readable storage medium (e.g., floppy disk or CD-ROM), or alternatively made available for access over a computer network (e.g., from a server on a local client/server network, or from a forum or site on a commercial on-line service or the Internet). The library preferably provides a list of available custom application project generators from which the user can choose. Having described and illustrated the principles of our invention with reference to an illustrated embodiment, it will be recognized that the illustrated embodiment can be modified in arrangement and detail without departing from such principles. It should be understood that the programs, processes, or methods described herein are not related or limited to any particular type of computer apparatus, unless indicated otherwise. Various types of general purpose or specialized computer apparatus may be used with or perform operations in accordance with the teachings described herein. Elements of the illustrated embodiment shown in software may be implemented in hardware and vice versa. For example, although the framework 74 (FIG. 2) for interfacing between the custom application project generator 52 and services module 76 is implemented in the illustrated embodiment using C++ virtual functions and exports, the framework 74 can alternatively be implemented using other software interfacing techniques such as Microsoft Corporation's object linking and embedding ("OLE") type objects. The advantage of implementing the framework 74 as OLE objects is that the writer will not have to update the custom application project generator 52 for each new version or update of the services module 76. With the illustrated framework 74 implemented as C++ virtual functions and exports, the custom application project generators would need to be recompiled. An alternative implementation of framework 74 as OLE objects adds a buffering layer of code between the application project generator 52 and the services module 76 which eliminates the need to recompile the custom application project generator 52 for any new version or updating of the service module 76. In view of the many possible embodiments to which the principles of our invention may be applied, it should be recognized that the detailed embodiments are illustrative only and should not be taken as limiting the scope of our invention. Rather, we claim as our invention all such embodiments as may come within the scope and spirit of the following claims and equivalents thereto.
|
Same subclass Same class Consider this |
||||||||||
