New content are available at http://tis-method.org/. All articles from this site will be moved to the new location.

понедельник, 29 ноября 2010 г.

WIX include file generation

When you create an installation of the product you should list all of its components.
This process not only tedious, but also can generate synchronization errors of the project output components and the installation package.

For some products, the composition of components may changing significantly during development.
In such cases, automating the process of creating installation is a must.

WIX installation file description can include additional files using the <?include ?> instruction.
Such mechanism would create the main installation file once, and localize all changes into external files.
So, we need two external files. One to describe the included files, the second to define the components to install.

Installation files sample
Main installation file:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  ...
  <Product Id="$(var.ProductGUID)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.CompanyName)" UpgradeCode="$(var.UpgradeCode)">
    ...
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="PFiles">
        <Directory Id="COMPANYDIR" Name="$(var.CompanyName)">
          <Directory Id="ProductDir" Name="$(var.ProductName)">
            <Directory Id="IncDir" Name="z3d">
              <?include inc1.wxs ?>
            </Directory>
            ...
          </Directory>
        </Directory>
      </Directory>
    </Directory>
    ...
    <Feature Id="ProductFeatures" Title="$(var.ProductName)" Level="1" ConfigurableDirectory="COMPANYDIR">
      <?include inc2.wxs ?>
      ...
    </Feature>
    ...
  </Product>
</Wix>

Enumeration for installing files (inc1.wxs):
<Include>
 <Directory Id="inc_dir1" Name="boost">
  <Component Id="inc_comp1" Guid="{B2B874BA-6480-4F20-9B5A-49F6DB83E830}">
   <File Id="inc_comp1_0" Name="cast.hpp" DiskId="1" Source="b:\prjs\z3d\z3d\boost\cast.hpp"/>
  </Component>
 </Directory>
 ...
</Include>

Enumeration for installing components (inc2.wxs):
<Include>
 <ComponentRef Id="inc_comp1"/>
 ...
</Include>

scan4wix command line parameters
Console utility scan4wix.exe is used for generating wix include files.
--help                    Show this help
  --root arg                Scan root path
  --prefix arg              ID's prefix string
  --regex arg               Regular expression for file content scanning
  --include_dirs arg (=.*)  Include dirs regular expression
  --exclude_dirs arg        Exclude dirs regular expression
  --include_files arg (=.*) Include files regular expression
  --exclude_files arg       Exclude files regular expression
  --out1 arg                Output file name for WIX dir&files list
  --out2 arg                Output file name for WIX features list

Usage example
scan4wix.exe --root="с:\project\bin" --prefix="prj" --exclude_dirs=".svn" --out1="prj1.wxs" --out2="prj2.wxs"

Utility will scan directory structure beginning from "с:\project\bin". Scan will exclude any ".svn" directories.
Output file prj1.wxs will contain all files from the selected directories. Output file prj2.wxs will contain corresponding components list.

Additionally, you can specify regular expression for files content. If you set --regex command line argument, utility will evaluate this regular expression for each input file content. If result of evaluation is true, the file will add into install package, otherwise will skip.

Links
You can find scan4wix utility in the tools folder in the z3d.

пятница, 5 ноября 2010 г.

Gateway

The basis of this template is a Pimpl and combination (composition, aggregation) technique.
Template add a new layer of indirection to reduce the coupling of interface and implementation and providing a controlled subset of the interface of the aggregated object. In both cases the "external" object - the interface contains the "inner" object - implementation.
So, gateway provide static/dynamic call forwarding from the interface level to the level of implementation.

Structure
The template consists of two parts. The first part - a pointers to class methods list. This types list defines a subset of the available interfaces to the "hidden" object. The second part - a function object, its purpose - return a reference to the object for which we will be directly implemented method calls.

Implementation
Structurally, Gateway is similar to the Chain of responsibility. Most part of interface is designed to routing method calls from 0 to 10 parameters. But if the "chain of responsibility" works with "arbitrary" function object, the Gateway is working with pointers to class methods.

Example
As an example, consider the following task: route method call from interface to the object, which is located on top of the stack.
///
class base
{
public:
 virtual void update( int const i ) = 0;
};
///
class A : public base
{
public:
 virtual void update( int const i )
 { std::cout << "A::update(" << i << ");" << std::endl; }
};
///
class B : public base
{
public:
 virtual void update( int const i )
 { std::cout << "B::update(" << i << ");" << std::endl; }
};
///
typedef void ( base::* base_update_t )( int const );
///
class manager : public z3d::gateway< manager&, LOKI_TYPELIST_1( base_update_t ) >,
 protected std::stack< boost::reference_wrapper< base > >,
 public boost::noncopyable
{
public:
 ///
 manager() : z3d::gateway< manager&, LOKI_TYPELIST_1( base_update_t ) >( boost::ref( *this ), INITLIST_1( &base::update ) )
 {}
 ///
 base& operator()()
 { return stack< boost::reference_wrapper< base > >::top(); }
 ///
 void push( base& p )
 { stack< boost::reference_wrapper< base > >::push( boost::ref( p ) ); }
 ///
 void pop()
 { stack< boost::reference_wrapper< base > >::pop(); }
};

void main()
{
 A a1;
 A a2;
 B b1;
 manager man;
 man.push( b1 );
 man.push( a1 );
 man.call< base_update_t, void >( 0 );
 man.pop();
 man.call< base_update_t, void >( 1 );
 man.push( a2 );
 man.call< base_update_t, void >( 2 );
}

Program output:
A::update(0);
B::update(1);
A::update(2);


Links
File z3d/gateway.hpp from z3d contains template code.