calinka tasks

Copyright notice

©2006- Ongame e-solutions AB, bwin Games AB
Author: Lars Sjödin, Ongame e-solutions AB
, bwin Games AB
Created: 2006-08-08
Last modified: 2006-11-17

Origin

The purpose of this tool is to build c++-programs using the same build tool as for the rest of the products, namely ant. There is already a set of tasks that can do this: cpptasks. Unfortunately the project semms to be dead as small even bugfixes aren't incorporated. We could of course use a patched version of it, but it is very difficult to use anyway.

First it was a very simple tool with a very basic set of functions, but as the needs grew, more and more esotheric builds became supported. The generality of the architecture can be questioned, and it is designed to support the two required platforms: msvc on Intel Win32 and g++ with fat binaries on OSX. Since they are quite different it is very likely that it will be fairly simple to support other OSes/compilers as well.

How does it work?

Basically what we want is a task that launches the compiler and linkers from a tesk which looks identical on all target platforms. calinka is just that. Basically a platform specific kind of quasi ant/shell-script is run whenever a file is compiled. That script is itself defined using ant-constructs making it very transparent and easy to modify per project.

First define the tasks using the ant-task "taskdef". Then, usually, proceed to defining the compiler, static library linker and executable linker for your platform:

<taskdef resource="calinka.properties" classpath="resources/lib/calinka.jar"/>

<compiler os="Windows XP" showcommandline="true">
<command file="cl">
<arg value="/nologo"/>
<arg value="/EHsc"/>
<arg value="/D_WIN32_WINNT=0x0501"/>
<arg value="/D_CRT_SECURE_NO_DEPRECATE=1"/>
<arg value="/c"/>
<arg value="/Zi"/>
<arg value="/Od"/>
<arg value="/RTC1"/>
<arg value="/MDd"/>
<switch attribute="debug">
<case value="true">
<arg value="/D_DEBUG"/>
</case>
<case value="false">
<arg></arg>
</case>
</switch>
<arglist name="srcfiles"/>
<arglist name="includepath" prefix="/I"/>
</command>
</compiler>

<staticlibrarylinker os="Windows XP">
<command file="lib">
<arg value="/nologo"/>
<arg value="/out:" suffix=""/>
<value attribute="output" suffix=".lib "/>
<arglist name="libpath" prefix="/libpath:"/>
<arglist name="lib" suffix=".lib "/>
<arglist name="objfiles"/>
</command>
</staticlibrarylinker>

<executablelinker os="Windows XP">
<command file="link">
<arg value="/out:" suffix=""/>
<value attribute="output" suffix=".exe "/>
<arglist name="libpath" prefix="/libpath:"/>
<arglist name="lib" suffix=".lib "/>
<arglist name="objfiles"/>
</command>
</executablelinker>

It is usually a good idea to keep the compiler and linker definitions in a separate file and perhaps even reuse this one between projects.

Then use them anywhere to compile, linklib and linkexe tasks on that platform:


<target name="test-tasks" depends="build">
<compile debug="false" objdir="${obj.output.dir}">
<srcfiles dir="${cpp.src.dir}" includes="*.cpp"/>
<includepath>
<pathelement path="/usr/include"/>
<pathelement path="/usr/include/sys"/>
</includepath>
</compile>

<linkstaticlibrary output="${deliveries.output.dir}/test-lib">
<objfiles dir="${obj.output.dir}" includes="**/library.*"/>
</linkstaticlibrary>

<linkexecutable output="${deliveries.output.dir}/test-app">
<objfiles dir="${obj.output.dir}" includes="**/hello.*"/>
<libpath>
<pathelement path="${deliveries.output.dir}"/>
</libpath>
<staticlibrary name="test-lib"/>
</linkexecutable>
</target>