2012-08-15

Build C++ with MSBuild on Windows by Example


Summary
  • Windows C++ project uses .vcxproj since Visual studio 2010. 
  • Visual Studio 2010 uses MSBuild to build C++ project.
  • The .vcxproj file can be created manually, and you can import common project settings from separate .props files.
  • Some sections of the .vcxproj file have to be in particular order.
  • If open .vcxproj file in Visual Studio and enable 'show all files', it will show the folder structure in the same folder as .vcxproj sits. Files outside of the folder is listed without folder structure.
  • It seems when using relative path to include .cpp or .h files for 'ClInclude' or 'ClCompile', it slows down the Visual Studio very very badly to open the project.
Build the project from command line
   
# Set the environment for VS
%VS100COMNTOOLS%\vsvars32.bat

# Build the project
msbuild xxx.vcxproj /p:Configuration=Debug
Example of .vcxproj file

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- Set the project name and the relative path to the Application folder -->
  <PropertyGroup>
   <ProjectName>Access</ProjectName>
   <TopDir>.</TopDir>
  </PropertyGroup>

  <!-- The main project file has to include this part -->
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>

  <!-- Include the common settings -->
  <Import Project="$(TopDir)\common.props" />

  <!-- Include all the .cpp files here -->
  <ItemGroup>
    <ClCompile Include="App\Access\**\*.cpp" />
    <ClCompile Include="Lib\**\*.cpp" />
  </ItemGroup>

  <!-- Include all the .h files here -->
  <ItemGroup>
    <ClInclude Include="App\Access\**\*.h" />
    <ClInclude Include="Lib\Inc\**\*.h" />
    <ClInclude Include="Lib\Gateway\**\*.h" />
  </ItemGroup>

  <!-- Include CPP defaults -->
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets" />
</Project>

The common settings are in .props file (common.props):
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <Keyword>Win32Proj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>

  <PropertyGroup>
   
   <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>
   <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)d</TargetName>

   <OutDir>$(TopDir)\Build\win32\</OutDir>
   <IntDir>$(TopDir)\Build\win32\$(ProjectName)-$(Configuration)\</IntDir>

   <PocoDir>$(TopDir)\..\Poco</PocoDir>
   <PocoSrcDir>$(PocoDir)\poco-1.4.3p1-all</PocoSrcDir>
   <PocoLibDir>$(PocoSrcDir)\lib</PocoLibDir>
   <PocoBinDir>$(PocoSrcDir)\bin</PocoBinDir>
   
   <OpenSSLDir>$(PocoDir)\OpenSSL-Win32</OpenSSLDir>
   <OpenSSLIncDir>$(OpenSSLDir)\include</OpenSSLIncDir>
   <OpenSSLBinDir>$(OpenSSLDir)\bin</OpenSSLBinDir>

   <CppUnitDir>$(TopDir)\..\CppUnit</CppUnitDir>
   <CppUnitSrcDir>$(CppUnitDir)\cppunit-1.12.1</CppUnitSrcDir>
   <CppUnitLibDir>$(CppUnitDir)\Build\win32</CppUnitLibDir>
   <CppUnitLib Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(CppUnitLibDir)\CppUnit.lib</CppUnitLib> 
   <CppUnitLib Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(CppUnitLibDir)\CppUnitd.lib</CppUnitLib> 

    <AppIncludes>
      $(PocoSrcDir)\Foundation\include;
      $(PocoSrcDir)\Crypto\include;
      $(PocoSrcDir)\Data\include;
      $(PocoSrcDir)\Data\SQLite\include;
      $(PocoSrcDir)\Net\include;
      $(PocoSrcDir)\Util\include;
      $(PocoSrcDir)\XML\include;
      $(PocoSrcDir)\Zip\include;
      $(PocoSrcDir)\NetSSL_OpenSSL\include;
      $(AppIncludes)
    </AppIncludes>

    <AppIncludes>
      $(CppUnitSrcDir)\include;
      $(AppIncludes)
    </AppIncludes>
    
    <AppIncludes>
      $(OpenSSLIncDir);
      $(AppIncludes)
    </AppIncludes>
    
    <AppIncludes>
      $(TopDir)\Lib\Gateway\Framework\External;
      $(TopDir)\Lib\Gateway\Dingo\Gateway\Siemens.Gateway.Linux.Client;
      $(TopDir)\Lib\Gateway\Dingo\Gateway\Siemens.Gateway.Linux.Tools;
      $(TopDir)\Lib\Gateway\Dingo\Gateway\PlatformSpecific\Linux;
      $(TopDir)\Lib\Gateway\Dingo\Client\AccessPoint\GeneratedServices;
      $(AppIncludes)
    </AppIncludes>
    
    <AppIncludes>
      $(TopDir)\Lib;
      $(TopDir)\Lib\Inc;
      $(TopDir)\App\Access;
      $(TopDir)\App\Access\Inc;
      $(TopDir)\App\Diag;
      $(TopDir)\App\Diag\Inc;
      $(TopDir)\App\Supervisor;
      $(TopDir)\App\Supervisor\Inc;
      $(TopDir)\Test\UnitTest;
      $(TopDir)\Test\UnitTest\Lib;
      $(TopDir)\Test\UnitTest\App\Access;
      $(TopDir)\Test\UnitTest\App\Diag;
      $(TopDir)\Test\UnitTest\App\Supervisor;
      $(AppIncludes);
    </AppIncludes>
    
    <AppLibDirs>
      $(PocoLibDir);
      $(PocoBinDir);
      $(OpenSSLBinDir);
      $(OutDir);
      $(AppLibDirs);
    </AppLibDirs>
<AppStaticLibs>
 $(CppUnitLib);
</AppStaticLibs>   
  </PropertyGroup>

  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <AdditionalIncludeDirectories>$(AppIncludes);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <Optimization>Disabled</Optimization>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>$(AppLibDirs);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
 <AdditionalDependencies>$(AppStaticLibs);%(AdditionalDependencies)</AdditionalDependencies>      
      <TargetMachine>MachineX86</TargetMachine>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <AdditionalIncludeDirectories>$(AppIncludes);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>$(AppLibDirs);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
 <AdditionalDependencies>$(AppStaticLibs);%(AdditionalDependencies)</AdditionalDependencies>      <TargetMachine>MachineX86</TargetMachine>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
    </Link>
  </ItemDefinitionGroup>
  
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LocalDebuggerEnvironment>PATH=$(PocoBinDir)$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  
  <PropertyGroup>
    <ShowAllFiles>true</ShowAllFiles>
  </PropertyGroup>
      
</Project>