Wednesday, November 4, 2015

A difference in complexity

A common task in build systems is to run a custom command. As an example you might want to do this to regenerate a the build definition or run a tool such as clang-format. Different backends have different ways of specifying this.

Let's look at the difference between two such systems to see if we can learn something about design, simplification and other such things. First we examine the way you would define this in the Ninja build system. It looks roughly like this.

build mycommand: CUSTOM_COMMAND PHONY
 COMMAND = do_something.py
 description = 'Doing something'


All right. This seems reasonable. Now let us see how you would do the exact same thing in MSBuild.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <ItemGroup Label="ProjectConfigurations">
   <ProjectConfiguration Include="Debug|Win32">
     <Configuration>debug</Configuration>
     <Platform>Win32</Platform>
   </ProjectConfiguration>
 </ItemGroup>
 <PropertyGroup Label="Globals">
   <ProjectGuid>{1C3873C1-1796-4A8A-A7B2-CA9FA6068A1A}</ProjectGuid>
   <Keyword>Win32Proj</Keyword>
   <Platform>Win32</Platform>
   <ProjectName>something</ProjectName>
 </PropertyGroup>
 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
 <PropertyGroup Label="Configuration">
   <ConfigurationType />
   <CharacterSet>MultiByte</CharacterSet>
   <UseOfMfc>false</UseOfMfc>
 </PropertyGroup>
 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
 <PropertyGroup>
   <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
   <OutDir>.\</OutDir>
   <IntDir>test-temp\</IntDir>
   <TargetName>something</TargetName>
 </PropertyGroup>
 <ItemDefinitionGroup>
   <Midl>
     <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     <OutputDirectory>$(IntDir)</OutputDirectory>
     <HeaderFileName>%(Filename).h</HeaderFileName>
     <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
     <InterfaceIdentifierFilename>%(Filename)_i.c</InterfaceIdentifierFilename>
     <ProxyFileName>%(Filename)_p.c</ProxyFileName>
   </Midl>
   <PostBuildEvent>
     <Message />
     <Command>setlocal
"c:\Python34\python3.exe" do_something.py
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd</Command>
   </PostBuildEvent>
 </ItemDefinitionGroup>
 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>


Here endeth the lesson.

No comments:

Post a Comment