Also available at

Also available at my website http://tosh.me/ and on Twitter @toshafanasiev

Monday, 30 January 2012

Copy directory structure MSBuild

When using MSBuild you may find your self wanting to copy some existing directory structure somewhere. If you have a directory structure, the output of a solution for example, like the following:

output_dir/
 - bin/
   - thing.dll
   - thing.pdb
 - lib/
   - thing.lib
 - inc/
   - thing.h

You'll notice that doing this:

<ItemGroup>
  <out_files Include='output_dir/**/*'/>
</ItemGroup>

<Target Name='copy_files'>
  <Copy SourceFiles='@(out_files)' DestinationFolder='deployment_dir'/>
</Target>

Will flatten your output file structure to this:

deployment_dir/
 - thing.dll
 - thing.pdb
 - thing.lib
 - thing.h

In order to preserve your file structure you could create separate specifications for the bin/, lib/ and inc/ directories (which would not only add a maintenance burden in the case that these directories changed, but also require you to type them out in the first place) or you could simply take advantage of the metadata that MSBuild attaches to the path information it returns from a recursive directory search. The RecursiveDir property is attached to each file name in the array yielded by the search; it holds the value of the recursive directory directive (**) as evaluated for each file found, so doing this:

<ItemGroup>
  <out_files Include='output_dir/**/*'/>
</ItemGroup>

<Target Name='copy_files'>
  <Copy SourceFiles='@(out_files)' DestinationFolder='deployment_dir/%(out_files.RecursiveDir)'/>
</Target>

Will give you the structure you were after:

deployment_dir/
 - bin/
   - thing.dll
   - thing.pdb
 - lib/
   - thing.lib
 - inc/
   - thing.h

You've got loads of control over what gets captured too, say you want to exclude debug symbols, you'd do this:

<ItemGroup>
  <out_files Include='output_dir/**/*' Exclude='output_dir/**/*.pdb'/>
</ItemGroup>

<Target Name='copy_files'>
  <Copy SourceFiles='@(out_files)' DestinationFolder='deployment_dir/%(out_files.RecursiveDir)'/>
</Target>

To get this:

deployment_dir/
 - bin/
   - thing.dll
 - lib/
   - thing.lib
 - inc/
   - thing.h

Using these constructs allows you to manage builds of multiple solutions from a central MSBuild project without requiring that that project know all the solutions' intimate details - it gives you good separation of concerns and hence fewer headaches.

Tuesday, 24 January 2012

Overloading new and delete in C++

While writing C++ you might want to be involved in the details of dynamically allocated memory yourself; to ensure that certain types of object sit together in memory; to minimise space wasted on overhead for arrays of small objects; to improve allocation speed (at the cost of memory held) or to satisfy a fixed memory requirement. Whatever the reason (and once the trade-offs are fully understood), the basic plumbing you would need looks something like this:
#include <iostream>

using std::cout;
using std::endl;

class Thing {
public:
  Thing() {
    cout << "new Thing: " << sizeof( Thing ) << " bytes" << endl;
  }
  ~Thing() {
    cout << "~Thing()" << endl;
  }
  static void* operator new( size_t size ) {
    cout << "allocating " << size << " bytes in operator new" << endl;

    return ::operator new( size );
  }
  static void operator delete( void* mem ) {
    cout << "operator delete" << endl;

    ::operator delete( mem );
  }
  static void* operator new[]( size_t size ) {
    cout << "allocating " << size << " bytes in operator new[]" << endl;

    return ::operator new[]( size );
  }
  static void operator delete[]( void* mem ) {
    cout << "operator delete[]" << endl;

    ::operator delete[]( mem );
  }
private:
  unsigned char value_;
  // not worrying about copy/move for this example
  Thing( const Thing& );
  Thing( Thing&& );
  void operator=( const Thing& );
  void operator=( Thing&& );
};

int main( int argc, char* argv[] ) {

  cout << "creating an object ..." << endl;
  auto* t = new Thing;

  delete t;

  const int SIZE = 5;
  cout << "creating a " << SIZE << " element array ..." << endl;
  auto* a = new Thing[SIZE];

  delete[] a;

  return 0;
}

In this example my overloaded operators defer to the default provided versions, so nothing really interesting is being done in terms of memory allocation, but it does serve as an illustration of the mechanism, as the output shows:
creating an object ...
allocating 1 bytes in operator new
new Thing: 1 bytes
~Thing()
operator delete
creating a 5 element array ...
allocating 9 bytes in operator new[]
new Thing: 1 bytes
new Thing: 1 bytes
new Thing: 1 bytes
new Thing: 1 bytes
new Thing: 1 bytes
~Thing()
~Thing()
~Thing()
~Thing()
~Thing()
operator delete[]
It also illustrates the importance of pairing up the scalar and vector forms of new and delete properly - the additional 4 bytes allocated for the array are for tracking the size of the array for deletion - using the wrong form of delete causes that information to be ignored/erroneously read, depending on which way round you get it wrong.