Home > Articles > Programming > Visual Studio

  • Print
  • + Share This
This chapter is from the book

Compiling Projects

Compiling a project (or building according to the Visual Studio terminology) is the process that produces a .NET assembly starting from your project and source code (according to the .NET architecture described in Chapter 1, “Introducing the .NET Framework 4.5”). An assembly can be a standalone application (.exe assembly) or a .NET class library (.dll assembly). To compile your project into an assembly, you need to click the Build command in the Build menu. Notice that the Build command is followed by the name of your project. When invoking this command, Visual Studio launches, behind the scenes, the Visual Basic command-line compiler (Vbc.exe) and provides this tool all the necessary command-line options. For solutions containing different kinds of projects, Visual Studio launches MSBuild.exe, a command-line utility that can compile entire solutions containing several projects written in different languages and of different types. At the end of the build process, Visual Studio shows a log inside the Output window. Figure 2.23 shows the output log of the build process for the MyFirst2012Program sample application.

Figure 2.23

Figure 2.23. The Output window shows the compilation process results.

The compilation log shows useful messages that help you understand what happened. In this case there were no errors, but in situations in which the compilation process fails because of some errors in the code, you will be notified of the errors found by the compiler. The Error List window shows a complete list of error messages and warnings and enables you to easily understand where the errors happened by double-clicking the error message. This operation redirects you to the code that generated the error. The executable (or the executables, in the case of more than one project in the solution) will be put in a subfolder within the project’s directory, called Bin\Debug or Bin\Release, depending on the output configuration you chose. Configurations are discussed next.

Debug and Release Configurations

Visual Studio provides two default possibilities for compiling your projects. The first one is related to the debugging phase in the development process and includes debug symbols that are necessary for debugging applications. The second one is related to the end of the development process and is the one you will use when releasing the application to your customers. Both ways are represented by configurations. By default, Visual Studio offers two built-in configurations: Debug and Release. When the Debug configuration is active, the Visual Basic compiler generates debug symbols that the Visual Studio debugger can process. Without these symbols, you cannot debug your applications with the Visual Studio debugger. The Release configuration basically excludes debug symbols from the build process. It is the configuration you will use when building the final version of your application—that is, the executable you will release to your customers. To set the current configuration, you have two possibilities:

  • Use the combo box located on the Visual Studio toolbar.
  • Access the Compile options inside the My Project window.

Figure 2.24 shows the Compile tab in My Project.

Figure 2.24

Figure 2.24. Compile options in the My Project window.

At the top of the window is a combo box called Configuration. There you can select the most appropriate configuration for you. By default, Visual Studio 2012 is set up on the Debug configuration. You could also consider building a custom configuration (although both Debug and Release can be customized instead of making new ones), which will be discussed next. For our purposes, it’s suitable to leave unchanged the selection of the Debug configuration as the default because we will study the Visual Studio debugging features in depth.

Creating Custom Configurations with Configuration Manager

You might have situations in which both the Debug and Release configurations are not enough for your needs. As mentioned in the previous paragraph, with Visual Studio 2012 you can also create your custom configuration. To accomplish this, you need to access the Configuration Manager tool (see Figure 2.25), which is reachable using the Configuration Manager command in the Build menu. There you can edit an existing configuration or create a new one.

Figure 2.25

Figure 2.25. The Configuration Manager.

To create a new custom configuration, perform the following steps:

  1. Click the Active Solution Configuration combo box and select the New option.
  2. In the New Solution Configuration window, specify a name for the new configuration and select an existing configuration (such as Debug) from which settings will be copied. Figure 2.26 shows an example.
    Figure 2.26

    Figure 2.26. Creating a custom configuration that imports settings from an existing one.

  3. When done, click Close.
  4. Click the Advanced Compiler Options button in the Compile tab and specify which compile options must affect the new configuration. For example, you could decide to affect just compilations against 64-bit processors, so you would need to change the value in the Target CPU combo box. This is the point at which you can modify your real configuration settings and how your project should be built.

Such modification influences just the new configuration. Moreover, if you decide to use the new configuration, you will have a new subfolder under the Bin subfolder in your project’s main folder, which takes the name of your custom configuration and contains the output of the build process made with that configuration. For our MyFirst2012Program sample, the project folder is named MyFirst2012Program and contains the Bin subfolder, which also contains the default Debug and Release subfolders. With your custom configuration, a new TestConfiguration subfolder will be available under Bin.

Background Compiler

Visual Basic 2012 offers a great feature: the background compiler. While you write your code, the IDE invokes the Visual Basic compiler that will immediately compile the code and notify you about errors that occur, writing messages in the Error List window. This is possible because the Visual Basic compiler can compile your code on-the-fly while you type. As you can imagine, this feature is important because you will not necessarily need to build your project each time to understand whether your code can be successfully compiled. Typical examples of the background compiler in action are error messages shown in the Error List window when typing code. Refer to Figure 2.19 to get an idea of this feature. You can double-click the error message to be redirected to the line of code that caused the error. Also, the IDE underlines code containing errors with squiggly lines so that it is easier to understand where the problem is.

Other Compile Options

Visual Studio 2012 enables developers to get deep control over the build process. With particular regard to Visual Basic, you can control other compile options that are specific to the language. Table 2.3 lists them in detail.

Table 2.3. Visual Basic Compile Options

Option

Meaning

Option Explicit

When set to On, the developer must declare an object before using it in code.

Option Strict

When set to On, the developer must specify the type when declaring objects. In other words, Object is not automatically assigned as the default type. Moreover, Option Strict On disallows late binding and conversions from one type to another where there is a loss of precision or data. You should always set Option Strict On unless required.

Option Compare

Determines which method must be used when comparing strings (Binary or Text). The Binary option enables the compiler to compare strings based on a binary representation of the characters, while the Text option enables string comparisons based on textual sorting, according to the local system international settings.

Option Infer

When set to On, enables local type inference (this feature is discussed in Chapter 20, “Advanced Language Features”).

Options shown in Table 2.3 are also considered by the background compiler, so you will be immediately notified when your code does not match these requirements. You can also specify how the Visual Basic compiler has to treat some kind of errors. This is what you see next.

Target CPU

You can specify the CPU architecture your applications will target. You can choose among 32-bit architectures (x86), 64-bit architectures (x64), Itanium processors, ARM (in the case of Windows Store Apps) or any architecture (AnyCPU). Until Visual Studio 2010 this setting was available in the Advanced Compile Options dialog box.

Warning Configurations

Warning configurations state how the Visual Basic compiler should notify the developer of some particular errors, if just sending warning messages (which will not prevent from compiling the project) or error messages (which will instead prevent from completing the build process).

Depending on how you set the Visual Basic compile options discussed in the previous paragraph, Visual Studio will propose some default scenarios for sending notifications (and, consequently, influencing the build process). Table 2.4 lists the available warning conditions.

Table 2.4. Warning Condition Details

Condition

Description

Implicit conversion

Checked when trying to assign an object of a type to an object of another type. For example, the following code will cause the condition to be checked (implicit conversion from Object to String):

Dim anObject As Object = "Hi!" Dim aString As String = anObject

Late binding

Checked when trying to assign at runtime a typed object to another one of type Object.

Implicit type

Checked when not specifying the type for an object declaration. If Option Infers is on, this condition is checked only for declarations at class level. For example, the following class-level declaration would cause the condition to be checked:

Private Something

This condition is determined by Option Strict On.

Use of variable prior of assignment

Checked when attempting to use a variable that doesn’t have a value yet. This is typical with instance variables. The following code causes this condition to be checked:

Dim p As Process
Console.WriteLine(
p.ProcessName.ToString)

In this case p must get an instance of the Process object before attempting to use it.

Function/operator without return value

Checked when a Function method or an operator definition performs actions without returning a value.

Unused local variable

Checked when a variable is declared but never used. It’s a good practice to remove unused variables both for cleaner code and for memory allocation.

Instance variable accesses shared members

Checked when trying to invoke a member from an instance object that is instead a shared member.

Recursive operator or property access

Checked when trying to use a member (properties or operators) inside the code block that defines the member itself.

Duplicate or overlapping catch blocks

Checked when a Catch clause inside a Try..Catch..End Try code block is never reached because of inheritance. The following code causes the condition to be checked because the FileNotFoundException inherits from Exception and therefore should be caught before the base class; otherwise, Exception would be always caught before derived ones:

Try

Catch ex As Exception
Catch ex As FileNotFoundException

End Try

You also have the ability to change single notifications; just select the most appropriate notification mode for your needs. Based on the explanations provided in Table 2.4, be careful about the consequences that this operation could cause. If you are not sure about consequences, the best thing is leaving default options unchanged. Three other compile options are listed at the bottom of the Compile tab and described in Table 2.5.

Table 2.5. Additional Compile Options

Option

Description

Disable all warnings.

The Visual Basic compiler will not produce warning messages.

Treat all warnings as errors.

The Visual Basic compiler will treat all warning messages as if they were errors.

Generate XML documentation file.

When flagged, enables Visual Studio to generate an XML file for documenting the source code. If XML comments are included in the code, this file also contains descriptions and detailed documentation for the code. This is useful when you need to automate the documentation process for your class libraries.

Advanced Compile Options

You can specify advanced settings for the build process. To accomplish this, you need to click the Advanced Compile Options button.

Figure 2.27 shows the Advanced Compiler Settings window.

Figure 2.27

Figure 2.27. The Advanced Compiler Settings window.

Here you can set compiler options to drive the build process. Next we discuss options in detail.

Optimizations

The Optimization tab offers options that would potentially lead to building a smaller and faster executable. This tab is composed of four options that we discuss.

Remove Integer Overflow Checks

When you make calculations in your code against Integer or Integer-style data types, the Visual Basic compiler checks that the result of the calculation falls within the range of that particular data type. By default, this option is turned off so that the compiler can do this kind of check. If you flag this check box, the compiler will not check for such overflows, and the application execution might result faster. Be careful about this choice, especially if your code implements calculations.

Enable Optimizations

When this check box is flagged, the compiler basically removes some opcodes that are required for interacting with the debugger. Moreover, the Just-In-Time compilation is optimized because the runtime knows that a debugger will not be attached. On the other hand, this can result in major difficulties when debugging applications. For example, you might not use breakpoints at specific lines of code and, consequently, perform debugging tasks although the optimization process could produce a smaller and faster executable.

DLL Base Address

This option is available when developing class libraries and user controls and provides the ability to specify the Base Address for the assembly. As you might know, the base address is the location in memory where a .dll file is loaded. By default, Visual Studio assigns a base address and represents it in hexadecimal format. If you need to provide a custom base address, this is the place where you can do it.

Generate Debug Information

Generating debug information when building your project allows you to use the debugger against your application. By default, this option is set to Full, which means that full debug information is generated so that the debugger can be fully used to debug an application. (This is the case of the Debug configuration.) If you set this option to None, no debug information will be generated; if you set this option to pdb-only, the compiler will produce just a .pdb file containing debug symbols and project state information.

Compilation Constants

You can use compilation constants to conditionally compile blocks of code. Conditional compilation relies on the evaluation to True of constants that will be included in the final assembly. The Visual Basic compiler defines some default constants you can evaluate within your code; you also have the ability to declare custom constants. In the Advanced Compiler Settings window, you can specify whether the compiler needs to include the DEBUG and TRACE constants. The first one enables you to understand if the application is running in debug mode; in other words, if the application has been compiled using the Debug configuration. The second one is also related to debugging tasks; particularly, the .NET Framework exposes a class called Trace that is used in debugging and that can send the tracing output to the Output window when the TRACE constant is defined. If not, no output is generated because invocations versus the Trace class are ignored. A full list of built-in constants can be found at MSDN Library at http://msdn.microsoft.com/en-us/library/dy7yth1w(VS.110).aspx. Evaluating constants in code is simple. You can use the #If, #Else, #ElseIf, and #EndIf directives. For example, if you want to evaluate whenever an application has been compiled with the Debug configuration, you could write the following code:

#If DEBUG Then
        Console.WriteLine("You are in Debug configuration")
#Else
        Console.WriteLine("You are not in Debug configuration")
#End If

which essentially verifies if the constant is defined and takes some action at that point. In our example, if the DEBUG constant is defined in the assembly, this means that it has been built via the Debug configuration.

Custom Constants

You can also define custom constants. This can be basically accomplished in two ways. The first is adding custom constants in the appropriate field of the Advanced compiler settings window. Each constant must have the form of Name="Value", and constants are separated by commas. The second way for providing custom constants is adding a #Const directive in your code. For example, the following line of code

#Const TestConstant = True

defines a constant named TestConstant whose value is set to True. The big difference in using a #Const directive is that it defines just private constants that have visibility within the code file that defines them.

Generate Serialization Assemblies

As we discuss in Chapter 41, “Serialization,” serialization in .NET development is a technique that allows persisting the state of an object. Among several alternatives, this can be accomplished using a class called XmlSerializer. In such situations, the Visual Basic compiler can optimize applications that use the XmlSerializer class, generating additional assemblies for better performances. By default, this option is set to Auto so that Visual Studio generates serialization assemblies only if you are effectively using XML serialization in your code. Other options are On and Off.

  • + Share This
  • 🔖 Save To Your Account