Best practices for automated process Generation Based on Team (VI)-system modular Conditional compilation

Source: Internet
Author: User

Software production and management are facing the most severe challenges. with the unlimited expansion of demand, enterprise-level software systems are becoming larger and larger. to meet management requirements, reusability requirements, and scalability requirements, based on software engineering practices, we began to split and modularize the system by function or by deployment. as a result, the compilation and generation process of the source code of the entire system requires splitting by module, because the generation of the entire software system may be quite time-consuming. for example, the system divides the modules A/B/C/D/E according to the function, at the same time, 1/2/3/4/5 teams are responsible for developing these five functional modules. assume that the five modules of ABCDE are compiled in reverse order according to the writing order. The time required for compiling each module is 5 minutes. if I am a member of Team 1, I do not care about the generation failure of other modules in the team build process, or the generation failure of other modules in the local build process. On the contrary, if I waited for 25 minutes to see if I could compile a little modification to my code, and 20 minutes had nothing to do with me, I would be crazy. therefore, we hope that team build and desktop build can be configured to generate only the parts I care about to save my time. this configuration is Conditional compilation.

 

What kind of Conditional compilation do we want?

The source code of the software system is physically organized in folders. the division of functional modules inside the software system is reflected in the source code organization, often in folders. according to our general understanding, the functional modules are refined from coarse to fine in the parent-child Cascade form of folders from top-level functional division to a single C # project (csproj, C # is used as an example ). how to logically reflect this physical Division so that the source code scope of build can be easily customized is the first important practical choice.
I have seen the source code logical organization of some C ++ software projects. It uses hierarchical directories and places one under each level directory. INC or a function-like file to point to which directories in the next-level directory (possibly not all of them) contain the code to be compiled. this not only satisfies the physical division, but also makes proper arrangements for the logical association of source code. however, I am very opposed to directly porting this practice. NET software project! Because the features of the language and compiler directly affect the generation process, C ++ and C # are completely different. c ++ requires the appropriate header file and MAKEFILE file, while C # requires the appropriate SLN file and csproj file.
There is also a very confusing approach. It is similar to the method mentioned above, but uses the features of msbuild. It provides a msbuild compatible format proj file in each level directory, pointing to the csproj project file to be compiled in the next level directory, or the next level of the proj file (if the next level also contains a directory of the next level ). This method is quite confusing, because it manages the physical storage of source code and the logical association, and can control the scope of build. However, it does not bring any benefits to developers. Every project is scattered in various directories like a leaf. It is difficult for developers to track projects that depend on other projects. Developer prefers to enable a proper solution based on their own judgment (modify, debug, and compile ). So what we need is a solution that can meet the following requirements:
1. It can meet the physical requirements for storing source code by function
2. The source code can be logically organized together for compilation.
3. msbuild-friendly and easy to control the compilation Scope
4. developer friendly and can provide source code selection of different sizes for developers

The comparison is as follows:
1. Use the hierarchical directory storage function to separate the code;
2. Code is stored at the function level, from large to small, from abstraction to detail, from coarse granularity to Fine Granularity;
3. Provide an SLN file in each level (except the lowest level directory) directory, and add the project related to this level of functions to this solution file.
4. Modify the default team build process of TFs to accept the conditions and compile all or part of the functional modules according to the conditions;
5. Modify the default desktop Build Process of TFs to accept the conditions and compile all or part of the functional modules according to the conditions;

Use a simple example. Suppose we are writing a ticket sales and analysis report system. As you can imagine, the function is mainly divided into three major parts: Sales client, air ticket sales web service, and analysis report module. The Web Service for air ticket sales is divided into more details modules, such as ticket seat division, ticket acquisition/modification, and ticket reservation. The analysis report module may contain more detailed modules, such as report generation and intelligent trend analysis. In this case, we use the method shown in the left figure to implement source code management according to the proposed practice.

The green nodes in the left figure represent the most basic projects, and all the brown nodes represent the sln files set at different levels. for example, if I am a client team, I only need to open orderingclient every day. SLN can work properly. note that the top-level SLN file contains all projects. in addition, we are just a schematic here, so the examples used are not complicated, just to illustrate the problem.

 

Modify team build process to adapt to modular condition Compilation

The team build process provided in the first and fourth sections of this series will seriously affect the overall generation time. The following are the four steps:

1. Get-in Conditional compilation, get operations on the source code of other modules that do not participate in compilation.

2. Compile-in Conditional compilation, we need to remove some modules that do not participate in compilation.

3. Test-in Conditional compilation, running a test on a module that does not participate in compilation is not a waste of time, and an error occurs because there is no executable assembly.

4. Packaging-in Conditional compilation, it is not a waste of time to package the Assembly generated by the module that does not participate in compilation, but it will cause errors due to the lack of packaged objects.

5. Drop-in Conditional compilation, the module that does not participate in compilation does not generate the corresponding assembly, so drop will cause an error.

Therefore, we need to modify these five targets to meet the compilation requirements of the module. because compile, test, and packaging are the parts of team build and desktop build, we will first describe how to adjust get and drop.

Adjust get

In fact, the get target of TFS reserves this location for our Conditional compilation, but we haven't realized it yet. If you compile the microsoft.teamfoundation.build.tar gets file, you can see this section:

Coreget
  1. <! -- The filespec to be used by the get task. When empty, all top-level folders in the workspace are used. -->
  2. <Getfilespec condition = "'$ (getfilespec)' ='' "> </getfilespec>
  3.  
  4. <Target name = "coreget"
  5. Condition = "'$ (skipget )'! = 'True' and '$ (isdesktopbuild )'! = 'True '"
  6. Dependsontargets = "$ (coregetdependson)">
  7. <! -- Get the sources for the given workspace -->
  8. <Get teamfoundationserverurl = "$ (teamfoundationserverurl )"
  9. Builduri = "$ (builduri )"
  10. Workspace = "$ (workspacename )"
  11. Version = "$ (getversion )"
  12. Filespec = "$ (getfilespec )"
  13. Populateoutput = "$ (getpopulateoutput )"
  14. Overwrite = "$ (getoverwrite )"
  15. Preview = "$ (previewget )"
  16. Recursive = "$ (recursiveget )"
  17. Force = "$ (forceget)">
  18. <Output taskparameter = "gets" itemname = "gets"/>
  19. <Output taskparameter = "replaces" itemname = "replaces"/>
  20. <Output taskparameter = "deletes" itemname = "deletes"/>
  21. <Output taskparameter = "Warnings" itemname = "getwarnings"/>
  22. </Get>
  23. <Setbuildproperties condition = "'$ (getversion )'! = '$ (Sourcegetversion )'"
  24. Teamfoundationserverurl = "$ (teamfoundationserverurl )"
  25. Builduri = "$ (builduri )"
  26. Sourcegetversion = "$ (getversion)"/>
  27. <Propertygroup>
  28. <Sourcegetversion >$ (getversion) </sourcegetversion>
  29. </Propertygroup>
  30. </Target>
 

So what we need to do is to create property to provide conditions and values for getfilespec. For example, we generally write in tfsbuild. proj as follows:

Componenttobuild
  1. <Propertygroup>
  2. <! -- If not specified, compile the whole sources of this team project -->
  3. <Componenttobuild condition = "'$ (componenttobuild)' ='' "> all </componenttobuild>
  4. <Getfilespec condition = "'$ (componenttobuild)' = 'all'"> </getfilespec>
  5. <Getfilespec condition = "'$ (componenttobuild)' = 'componenta '"> specify server path containing component A here </getfilespec>
  6. <Getfilespec condition = "'$ (componenttobuild)' = 'componentb'"> specify server path containing component B Here </getfilespec>
  7. </Propertygroup>

In this way, when a team build is triggered, you can specify to compile only module A by entering the parameter:/P: componenttobuild = componenta, it is embodied in the get operation that only obtains the source code related to module.

Adjust drop

The modification of the drop operation is much simpler than the get operation, because the drop operation is essentially a copy, and with the output of different projects, such copies are even more different and cannot be generalized. however, in general, we only need to use the componenttobuild attribute created for get to conditional create a copy of a series of tuples to complete the modification to the drop.

 

Modify desktop build to adapt to modular condition Compilation

This section describes how to adjust compile, test, and packaging.

Adjust compile

In the default tfsbuild. in the proj file, a set of solutiontobuild attributes use include to indicate the solution for compilation. thank God, the source code storage and organization solution we provided earlier not only provided to the developer for convenience, but also greatly facilitated Conditional compilation here. We only need to specify the conditions to complete the adjustment:

Solutiontobuild
  1. <Solutiontobuild include = "$ (solutionroot) \ trunk \ product \ All. sln" condition = "'$ (componenttobuild)' = 'all'"> </solutiontobuild>
  2. <Solutiontobuild include = "$ (solutionroot) \ trunk \ product \ componentafolder \ componenta. sln" condition = "'$ (componenttobuild)' = 'componenta '"> </solutiontobuild>
  3. <Solutiontobuild include = "$ (solutionroot) \ trunk \ product \ componentbfolder \ componentb. sln" condition = "'$ (componenttobuild)' = 'componentb'"> </solutiontobuild>
Adjust Test

Similar to adjusting compile, we will not repeat it here. Of course, you may need to merge those vsmdi files if they are originally scattered.

Adjust Packaging

In general, we will use InstallShield or Wix to compile the packaging script. we recommend Wix again here. in addition, if you are using the vs setup project, please try your own solutions. Because the practice may seem ugly, it is omitted here. we assume that Wix is used to compile the packaging script. the practice of compiling the packaging script is also based on the module. For example, componenta is used in this example. WXS and componentb. WXS. then our conditional packaging will be more direct. you can use componenttobuild to directly specify the execution conditions for Wix target.

 

Where are we standing now?

Congratulations, you have already taken the place where Conditional compilation is implemented. There are two ways to experience the speed of omitting unnecessary consumption:

1. Trigger team build. Enter/P: componenttobuild = componenta in the bottom Frame (replace the name of the module you are concerned with here, of course)

2. Open the command line and enter msbuild tfsbuild. proj/P: componenttobuild = componenta

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.