Source Configuration Architecture

From OpenPetra Wiki
Jump to navigation Jump to search

OpenPetra is a very large and complex project. Several parts of it are automatically generated by other parts. The easiest way to understand how it all fits together is to take a bird's-eye view of the build process. In real life, this is handled automatically by clicking "Generate Solution" in the OpenPetra Developers' Assistant, or by typing "nant generateSolution" at the command prompt in a newly checked-out working directory.

OpenPetra uses NAnt as its build tool. NAnt uses buildfiles containing lists of Targets and the instructions to build those Targets. The default buildfile is the first *.build file in the current directory; in our case that would be OpenPetra.build at the top of the working directory tree. We have defined many NAnt Tasks for OpenPetra, some of which are listed on this page.

By opening up what happens during Generate Solution, we can see what all the generated code is, where it comes from, and how to control it.

Detailed reference, with some more "How-To's": Build system with our own NAnt tools and tasks


The Version Number

The first thing to do is pull the Bazaar version info for the current branch into delivery\bin\vcs-revision.txt. Now it can be included in the source code and displayed in the application.

nant pullVCSVersionInfo

The Namespace Map

OpenPetra was designed to support different development environments: Visual Studio, SharpDevelop and MonoDevelop. The project and solution files differ between these systems, and we don't store them in the project repository; they are generated dynamically from the source code. The first part of this process is to generate delivery\projects\namespace.map. This file links every namespace defined in the project files with the default namespace of the project it belongs to. The generateNamespaceMap task is a dependency of the NAnt build tasks and will happen as needed.

For example, the Ict.Petra.Server.lib.MCommon project contains the​​ Ict.Petra.Server.MCommon, Ict.Petra.Server.MCommon.Cacheable, and several other namespaces.

The Project Files

The project files – delivery\projects\*\*.csproj and *.sln – define the different Projects within the overall Solution for the different development environments and the msbuild compiler. To build them, first namespace.map and the source code are analysed to create project.map and projectuuid.map in delivery\projects. The former contains all the project References; the latter, the GUIDs (used internally by the IDE). These in turn are used to build the final project and solution files. New GUIDs are created as necessary. Like generating namespace.map, this is written as a dependency within NAnt to ensure it happens as needed.

If you add new files to a project (or updating your branch pulls in new files) then Visual Studio won't be able to build the project properly until the project file is updated too. Note that the first time you do this on a new branch, it will warn you that it doesn't know where to put all the files. That's normal: a lot of the code it needs will be generated in the following steps. The first pass generates the project files to build the tools; those tools then build the remainder of the code and after that ​you generate the project files again to complete the solution.

nant generateProjectFiles

The Tools

The next thing to do is build the tools that are used in the remainder of the build process. This includes the following files:

delivery\bin\Ict.Tools.CodeGeneration.dll
delivery\bin\Ict.Tools.GenerateWinForms.exe
delivery\bin\Ict.Tools.GenerateSQL.exe
delivery\bin\Ict.Tools.GenerateORM.exe
delivery\bin\Ict.Tools.GenerateGlue.exe

as well as come Common code needed by the tools.

nant generateTools

The Forms

OpenPetra's forms and user controls are defined in .yaml files. This step parses petra.xml and the form & control .yaml files to build them into the C# *-generated.Designer.cs and *-generated.cs files required by the compiler.

A form's -generated.cs code is supplemented by a .ManualCode.cs file to handle specific processing. If you add a new method to a form's .ManualCode.cs file, it won't be called unless you regenerate the form (see Documentation YAML for OpenPetra Forms#ManualCode)! In certain cases one also needs to add the appropriate section to the form's .yaml file and regenerate the form. For example, to add verification code to a report, you add a ReadControlsVerify() method. But you also need to add the corresponding READCONTROLSLOCALVARS to the TemplateParameters section of the .yaml and regerate the form, or the call won't be included in the main generated code.

nant generateWinforms

The Object-Relational Model

The Object-Relational Model (ORM) is the Data Access Layer for accessing the DB data in a typesafe way by creating typed data tables, typed datasets and typed access classes that provide convenient access to them. There are 4 parts to the process:

generateORMCachedTables
Generates the cached tables.
Parses csharp\ICT\Petra\Shared\lib\data\*.TypedDataSets.xml to produce *Cacheable-generated.cs
Details: Documentation Cacheable Tables
generateORMData
Generates the files for Ict.Petra.Shared.lib.data, ie. the typed tables and typed datasets.
Parses typed table namespaces, validation and datasets to produce *Tables-generated.cs, *Validation-generated.cs, *DataSets-generated.cs
generateORMAccess
Generates the files for Ict.Petra.Server.lib.data, ie. the access files for reading from and writing to the database.
Parses typed table namespaces and datasets to produce *Access-generated.cs and Cascading-generated.cs
generateORMReferenceCounts
Generates the server web connector classes that perform table reference counting.
Parses *.yaml files and produces csharp\ICT\Petra\Server\lib\*\web\ReferenceCount-generated.cs

nant generateORM

The Glue

The "glue" is the set of interfaces and instantiators between the client and server. This parses .cs files for methods in the Remoting namespaces, such as WebConnectors, ​and produces Shared\lib\Interfaces\*Interfaces-generated.cs, Server\lib\*\connect\Instantiator.AutoHierarchy-generated.cs, and Server\lib\*\connect\Instantiator.Connectors-generated.cs. The interfaces-generated.cs files together make up the Ict.Petra.Shared.lib.Interfaces project in the development environment. Some of the Project References and using statements can be calculated automatically, but others need to be specified manually. You do this in the file csharp\ICT\Petra\Shared\lib\Interfaces\InterfacesUsingNamespaces.yml. When you add a namespace against an interface here, it will be added to the generated file's using statements, and its project will be added to the Interfaces project's Reference list.

nant generateGlue

The 3rd-Party DLLs

OpenPetra uses a number of 3rd-party DLLs. The vast majority of these are freely distributable and automatically included as part of the application; others can only be distributed under licence. This step is used where permitted to copy the licensed FastReport DLLs from the location specified by the FASTREPORT_DLL_PATH environment variable to delivery\bin.

nant copyFrDlls

The SOLUTION!

Now all the generated project files, forms, datasets, tables, access code, interfaces, instantiators etc. are in place, we must run nant generateProjectFiles ​again to complete the set of project files. Then we can use msbuild to compile the entire application from the generated OpenPetra.sln solution file (NAnt drives msbuild for us, no need to know about it in detail!).

If anything changes that the generated code or manually written code depends upon, remember to regenerate the appropriate code before recompiling (with nant quickCompile) with either the single steps lined out above, or by using

nant generateSolution: this will execute all build steps lined up on this page in correct order and hence will ensure that all generated code and manually written code will be tied together. It is also a requirement to run this NAnt Task before a Branch gets committed to 'trunk' to ensure that the whole process runs through without any hiccups!

Developer's Assistant

Your reward for a successful build is the OpenPetra Developers' Assistant, which is built along with everything else. It provides an extremely helpful front-end and guide to NAnt and Bazaar so that you don't have to remember all these commands, and it manages all your database configurations. Find it in delivery\bin\Ict.Tools.DevelopersAssistant.exe and copy it to your desktop or somewhere. It maintains its settings in your AppData\Local folder, and updates itself automatically if it detects a newer copy of itself in your current branch.