kjam build tool
WARNINGThis web site is designed for Firefox, Internet Explorer 6+, Safari, and Opera 9+. We apologize if this site does not render correctly on your browser.
KJam main page KJam performance information KJam is faster than perforce jam. \n Using KJam achieves the fastest compile time. \n KJam is an efficient build tool. It runs on Windows and Linux. \n Reduces your incremental build time. Improves compile time.\n You need it for faster compile times.\n KJam is a distributed build tool.\n KJam is the fastest build system.\n KJam is a parallel build tool.\n It does a similar job to tools like Gnu Make, MSBuild, Ant, Nant, Maven, Scons, Rake, nmake, qmake, Electric Cloud, Xoreax Incredibuild.\n It produces the fastest build time.\n KJam results in the shortest incremental build times.\n Use KJam if your build is too slow, or if your build takes too long. It is also good if you have long link times.\n

This file contains build rules. Kjam would use these declarations to determine how files depend on each other, which ones need to be updated and the actions that need to be taken. The actual action scripts are defined elsewhere, and may be platform specific. The list of clean targets is also defined as these rules are evaluated.


#
#  Shared definitions for building with KJAM.
#
#  Target type:
#
#  StaticExecutable - an exe linked with static libraries
#  SharedExecutable - an exe linked with dynamic libraries
#  StaticLibrary    - a statically linked library
#  SharedLibrary    - a dynamically linked library, a dll, and its associated stub library
#  Clean            - a pseudo target which deletes all its dependents.
#
#  Most of the targets take 5 argument lists:
#  1. the name of the file to generate
#  2. a list of source files
#  3. a list of static libraries, dll export libs, and objects to link with
#  4. a list of dynamic libraries to copy into the local directory
#  5. an optional directory to dump the generated target into.
#

PLATFORM ?= $(JAMPLATFORM:L) ;
CURFLAV ?= debug ;

# include the actions files - but first we tell jam where they can be found:
SEARCH on script_dir = . scripts ../scripts ;
notfile script_dir ;

JAMWRAP = 21 $(COLUMNS:E=80) 20 ;

if ( $(PLATFORM) == win32 )
   on script_dir { include "jambase.win32" ; }
else
   on script_dir { include "jambase.linux" ; }

# this is the header pattern that matches both "" and <> includes.
# HDRPATTERN      = "#[\t ]*include[\t ]*[<\"]([^\">]*)[\">]" ;

# matches only "" includes
HDRPATTERN        = "#[\t ]*include[\t ]*[\"]([^\"]*)[\"]" ;

notfile all clean ;
always clean ;

# if this is set to true, then we automatically build a list of dependencies for 'all'
# until we see a group named all.
AUTOALL ?= true ;

# rules --------------------------------------------

rule InitDirs
{
   if ( $(INIT_DIRS_DONE) ) return ;
   INIT_DIRS_DONE = true ;
   
   BIN_DIR   = bin/$(PLATFORM)/$(CURFLAV)/ ;
   LIB_DIRS += $(BIN_DIR) $(LIB_DIRS)/$(BIN_DIR) ;
   
   # for generated headers that end up in the bin dir.
   INCLUDE_DIRS += $(BIN_DIR) ;

   ActionInitDirs ;
   
   SEARCH += . $(INCLUDE_DIRS) ; 
   
   # only search in directories that actually exist
   SEARCH    = $(SEARCH:A) ;
   LIB_DIRS  = $(LIB_DIRS:A) ;

   HDRRULE   = HeaderRule ;
   HDRSEARCH = $(SEARCH) ;
}

rule Group TARGET : SOURCES
{
   InitDirs ;
   
   if ( $(TARGET) == all ) 
   {
      AUTOALL = false ;
      cleardep all ; # remove any dependencies 'all' may have accumulated up to this point
   } else {
      if ( $(AUTOALL) == true ) depends all : $(TARGET) ;
   }
   
   if ( $(PLATFORM) == win32 )
      SOURCES =                          lib$(SOURCES:I="\.a"S=.lib) lib$(SOURCES:I="\.so"S=.dll) $(SOURCES:X="\.a"X="\.so") ;
   else
      SOURCES = $(SOURCES:I="\.exe"S="") lib$(SOURCES:I="\.lib"S=.a) lib$(SOURCES:I="\.dll"S=.so) $(SOURCES:X="\.exe"X="\.lib"X="\.dll") ;

   depends $(TARGET) : $(SOURCES) ;
}

rule StaticExecutable  TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   InitDirs ;
   
   TARGET = $(TARGET:B)$(EXE_SUFFIX) ;
   
   SOURCES = [ ExpandSources $(SOURCES) ] ;
   
   if ( $(AUTOALL) == true ) depends all : $(TARGET) ;
      
   if ( $(TARGET_DIR) ) TARGET_DIR = $(TARGET_DIR)/ ;
   else                 TARGET_DIR = $(BIN_DIR) ;
   LOCATE on $(TARGET)  = $(TARGET_DIR) ;
   CreateDirectory $(TARGET_DIR) ;
   CleanTarget $(TARGET) : $(TARGET_DIR) ;

   local OBJECTS ;
   if ( $(SOURCES) ) OBJECTS = [ ObjectSet $(TARGET) : $(SOURCES) : static ] ;
   
   LINKOBJS = [ GetLinkObjs $(LIBS) ] ;
   LINKLIBS = [ GetLinkLibs $(LIBS) $(DLLS) ] ;
   LINKDLLS = [ GetLinkDlls $(LIBS) ] ;
   COPYDLLS = [ GetCopyDlls $(DLLS) ] ;
   
   SEARCH on $(LINKLIBS) = $(LIB_DIRS) ;
   
   depends           $(TARGET) : $(TARGET_DIR) $(LINKOBJS) $(LINKLIBS) $(LINKDLLS) $(COPYDLLS) ;
   LinkExecutable    $(TARGET) : $(OBJECTS)    $(LINKOBJS) : $(LINKLIBS) ;
   ExternalDlls      $(TARGET) : $(COPYDLLS) : $(TARGET_DIR) ;
}

rule SharedExecutable  TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   InitDirs ;
   
   TARGET = $(TARGET:B)$(EXE_SUFFIX) ;
   
   SOURCES = [ ExpandSources $(SOURCES) ] ;
   
   if ( $(AUTOALL) == true ) depends all : $(TARGET) ;
   
   if ( $(TARGET_DIR) ) TARGET_DIR = $(TARGET_DIR)/ ;
   else                 TARGET_DIR = $(BIN_DIR) ;
   LOCATE on $(TARGET)  = $(TARGET_DIR) ;
   CreateDirectory $(TARGET_DIR) ;
   CleanTarget $(TARGET) : $(TARGET_DIR) ;

   local OBJECTS ;
   if ( $(SOURCES) ) OBJECTS = [ ObjectSet $(TARGET) : $(SOURCES) : shared ] ;
   
   LINKOBJS = [ GetLinkObjs $(LIBS) ] ;
   LINKLIBS = [ GetLinkLibs $(LIBS) $(DLLS) ] ;
   LINKDLLS = [ GetLinkDlls $(LIBS) ] ;
   COPYDLLS = [ GetCopyDlls $(DLLS) ] ;
   
   SEARCH on $(LINKLIBS) = $(LIB_DIRS) ;

   depends           $(TARGET) : $(TARGET_DIR) $(LINKOBJS) $(LINKLIBS) $(LINKDLLS) $(COPYDLLS) ;
   LinkExecutable    $(TARGET) : $(OBJECTS)    $(LINKOBJS) : $(LINKLIBS) ;
   ExternalDlls      $(TARGET) : $(COPYDLLS) : $(TARGET_DIR) ;
}

rule StaticLibrary     TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   InitDirs ;
   
   TARGET = $(LIB_PREFIX)$(TARGET:B)$(LIB_SUFFIX) ;
   
   SOURCES = [ ExpandSources $(SOURCES) ] ;
   
   if ( $(AUTOALL) == true ) depends all : $(TARGET) ;
   
   if ( $(TARGET_DIR) ) TARGET_DIR = $(TARGET_DIR)/ ;
   else                 TARGET_DIR = $(BIN_DIR) ;
   LOCATE on $(TARGET)  = $(TARGET_DIR) ;
   CreateDirectory $(TARGET_DIR) ;
   CleanTarget $(TARGET) : $(TARGET_DIR) ;

   local OBJECTS ;
   if ( $(SOURCES) ) OBJECTS = [ ObjectSet $(TARGET) : $(SOURCES) : static ] ;
   
   LINKOBJS = [ GetLinkObjs $(LIBS) ] ;
   LINKLIBS = [ GetLinkLibs $(LIBS) $(DLLS) ] ;
   LINKDLLS = [ GetLinkDlls $(LIBS) ] ;
   COPYDLLS = [ GetCopyDlls $(DLLS) ] ;
   
   SEARCH on $(LINKLIBS) = $(LIB_DIRS) ;
   
   depends           $(TARGET) : $(TARGET_DIR) $(LINKOBJS) $(LINKLIBS) $(LINKDLLS) $(COPYDLLS) ;
   LinkStaticLibrary $(TARGET) : $(OBJECTS)    $(LINKOBJS) : $(LINKLIBS) ;
   ExternalDlls      $(TARGET) : $(COPYDLLS) : $(TARGET_DIR) ;
}

rule SharedLibraryRaw     TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   InitDirs ;
   
   SOURCES = [ ExpandSources $(SOURCES) ] ;
   
   if ( $(AUTOALL) == true ) depends all : $(TARGET:X="\.lib$") ;
   
   if ( $(TARGET_DIR) ) TARGET_DIR = $(TARGET_DIR)/ ;
   else                 TARGET_DIR = $(BIN_DIR) ;
   LOCATE on $(TARGET)  = $(TARGET_DIR) ;
   CreateDirectory $(TARGET_DIR) ;
   CleanTarget $(TARGET) : $(TARGET_DIR) ;

   local OBJECTS ;
   if ( $(SOURCES) ) OBJECTS = [ ObjectSet $(TARGET) : $(SOURCES) : shared ] ;
      
   LINKOBJS = [ GetLinkObjs $(LIBS) ] ;
   LINKLIBS = [ GetLinkLibs $(LIBS) $(DLLS) ] ;
   LINKDLLS = [ GetLinkDlls $(LIBS) ] ;
   COPYDLLS = [ GetCopyDlls $(DLLS) ] ;
   
   SEARCH on $(LINKLIBS) = $(LIB_DIRS) ;
   
   depends           $(TARGET) : $(TARGET_DIR) $(LINKOBJS) $(LINKLIBS) $(LINKDLLS) $(COPYDLLS) ;
   LinkSharedLibrary $(TARGET) : $(OBJECTS)    $(LINKOBJS) : $(LINKLIBS) ;
   ExternalDlls      $(TARGET) : $(COPYDLLS) : $(TARGET_DIR) ;
}

rule SharedLibrary     TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   SharedLibraryRaw $(LIB_PREFIX)$(TARGET:B)$(DLL_SUFFIX) : $(SOURCES) : $(LIBS) : $(DLLS) : $(TARGET_DIR) ;
}

rule SharedLibraryNL   TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   SharedLibraryRaw $(LIB_PREFIX)$(TARGET:B)$(DLL_SUFFIX:X=".lib") : $(SOURCES) : $(LIBS) : $(DLLS) : $(TARGET_DIR) ;
}

rule FsmSharedLibrary TARGET : SOURCES : LIBS : DLLS : TARGET_DIR
{
   // roll the fsm into one .cpp source
   FsmRule  $(TARGET:B).cpp : $(SOURCES:I="\.fsm") ;
   
   // fsm shared libraries on windows may not actually have a .lib stub library
   SharedLibraryNL $(TARGET) : $(SOURCES:X="\.fsm") $(TARGET:B).cpp : $(LIBS) : $(DLLS) : $(TARGET_DIR) ;
}

rule Object TARGET : SOURCE : OBJ_SUBDIR : LOC_CCOPTS
{
   InitDirs ;
   
   if ( $(PLATFORM) == win32 )
      LOC_CCOPTS = "$(LOC_CCOPTS:N=\" \"0=\"\ \")" ;
   
   TARGET = <$(OBJ_SUBDIR)>$(TARGET:B)$(OBJ_SUFFIX) ;
   LOCATE on $(TARGET) = $(BIN_DIR)$(OBJ_SUBDIR) ;
   depends $(TARGET) : $(SOURCE) $(BIN_DIR)$(OBJ_SUBDIR) ;
   temporary $(TARGET) ;
   
   HDRSCAN on $(SOURCE) = $(HDRPATTERN) ;
   
   CreateDirectory $(BIN_DIR)$(OBJ_SUBDIR) ;

   CCOPTS on $(TARGET) += $(LOC_CCOPTS) ;
   
   if ( $(OBJ_SUBDIR) == static )
   {
      if ( $(SOURCE:S) == ".c" )
        CompileStaticObject_C   $(TARGET) : $(SOURCE) ;
      else
        CompileStaticObject_CXX $(TARGET) : $(SOURCE) ;
   }

   if ( $(OBJ_SUBDIR) == shared )
   {
      if ( $(SOURCE:S) == ".c" )
         CompileSharedObject_C   $(TARGET) : $(SOURCE) ;
      else
         CompileSharedObject_CXX $(TARGET) : $(SOURCE) ;
   }

   Clean clean : $(TARGET) ;
   
   return $(TARGET) ;
}

rule SharedObject TARGET : SOURCE : LOC_CCOPTS
{
   Object $(TARGET) : $(SOURCE) : shared : $(LOC_CCOPTS) ;
}

rule StaticObject TARGET : SOURCE : LOC_CCOPTS
{
   Object $(TARGET) : $(SOURCE) : static : $(LOC_CCOPTS) ;
}

rule ObjectSet  TARGET : SOURCES : OBJ_SUBDIR
{
   if ( $(PLATFORM) != win32 ) OBJ_SUBDIR = static ;
   
   HDRSCAN on $(SOURCES) = $(HDRPATTERN) ;

   local Y_SOURCES   = $(SOURCES:I="\.y$") ;
   local L_SOURCES   = $(SOURCES:I="\.l$") ;
   local FSM_SOURCES = $(SOURCES:I="\.fsm$") ;
   local C_SOURCES   = $(SOURCES:I="\.c$") ;
   local CXX_SOURCES = $(SOURCES:I="\.cpp$") $(FSM_SOURCES:S=.cpp) ;

   local C_OBJECTS ;
   local CXX_OBJECTS ;
            
   if ( $(PARSEGEN_C) )
      C_SOURCES   += $(Y_SOURCES:S=_YY.c) $(L_SOURCES:S=_ll.c) ;
   else
      CXX_SOURCES += $(Y_SOURCES:S=_YY.cpp) $(L_SOURCES:S=_ll.cpp) ;
   
   for ( SRC_FILE in $(C_SOURCES) )
   {
      C_OBJECTS += <$(OBJ_SUBDIR)>$(SRC_FILE:S="$(OBJ_SUFFIX)") ;
      depends <$(OBJ_SUBDIR)>$(SRC_FILE:S="$(OBJ_SUFFIX)") : $(SRC_FILE) ;
   }
   
   for ( SRC_FILE in $(CXX_SOURCES) )
   {
      CXX_OBJECTS += <$(OBJ_SUBDIR)>$(SRC_FILE:S="$(OBJ_SUFFIX)") ;
      depends <$(OBJ_SUBDIR)>$(SRC_FILE:S="$(OBJ_SUFFIX)") : $(SRC_FILE) ;
   }

   if ( $(PARSEGEN_C) )
   {
      for ( Y_SRC in $(Y_SOURCES) )
      {
         C_OBJECTS += <$(OBJ_SUBDIR)>$(Y_SRC:S="_YY$(OBJ_SUFFIX)") ;
         YaccRule $(Y_SRC:S=_YY.c) : $(Y_SRC) ;
      }
     
      for ( L_SRC in $(L_SOURCES) )
      {
         C_OBJECTS += <$(OBJ_SUBDIR)>$(L_SRC:S="_ll$(OBJ_SUFFIX)") ;
         LexRule $(L_SRC:S=_ll.c) : $(L_SRC) ;
      }
      
      for ( FSM_SRC in $(FSM_SOURCES) )
      {
         C_OBJECTS += <$(OBJ_SUBDIR)>$(FSM_SRC:S="$(OBJ_SUFFIX)") ;
         FsmRule $(FSM_SRC:S=.c) : $(FSM_SRC) : $(FSM_TEMPLATE_FILE:E=fsmc.tpl) : $(FSM_ID_FILE:E=id.fsm) ;
      }
      
   } else {
   
      for ( Y_SRC in $(Y_SOURCES) )
      {
         CXX_OBJECTS += <$(OBJ_SUBDIR)>$(Y_SRC:S="_YY$(OBJ_SUFFIX)") ;
         YaccRule $(Y_SRC:S=_YY.cpp) : $(Y_SRC) ;
      }
     
      for ( L_SRC in $(L_SOURCES) )
      {
         CXX_OBJECTS += <$(OBJ_SUBDIR)>$(L_SRC:S="_ll$(OBJ_SUFFIX)") ;
         LexRule $(L_SRC:S=_ll.cpp) : $(L_SRC) ;
      }
      
      for ( FSM_SRC in $(FSM_SOURCES) )
      {
         CXX_OBJECTS += <$(OBJ_SUBDIR)>$(FSM_SRC:S="$(OBJ_SUFFIX)") ;
         FsmRule $(FSM_SRC:S=.cpp) : $(FSM_SRC) : $(FSM_TEMPLATE_FILE:E=fsmc.tpl) : $(FSM_ID_FILE:E=id.fsm) ;
      }
   }

   # if the output directory does not exist it must be created   
   LOCATE on $(BIN_DIR)$(OBJ_SUBDIR) = . ;
   depends $(CXX_OBJECTS) $(C_OBJECTS) : $(BIN_DIR)$(OBJ_SUBDIR) ;
   CreateDirectory $(BIN_DIR)$(OBJ_SUBDIR) ;

   LOCATE on $(CXX_OBJECTS) $(C_OBJECTS) = $(BIN_DIR)$(OBJ_SUBDIR) ;
   
   depends $(TARGET) : $(CXX_OBJECTS) $(C_OBJECTS) ;
   temporary $(CXX_OBJECTS) $(C_OBJECTS) ;

   if ( $(OBJ_SUBDIR) == static )
   {
      if ( $(CXX_SOURCES) ) { CompileStaticObjectList_CXX $(CXX_OBJECTS) : $(CXX_SOURCES) ; }
      if ( $(C_SOURCES)   ) { CompileStaticObjectList_C   $(C_OBJECTS)   : $(C_SOURCES)   ; }
   }

   if ( $(OBJ_SUBDIR) == shared )
   {
      if ( $(CXX_SOURCES) ) { CompileSharedObjectList_CXX $(CXX_OBJECTS) : $(CXX_SOURCES) ; }
      if ( $(C_SOURCES)   ) { CompileSharedObjectList_C   $(C_OBJECTS)   : $(C_SOURCES)   ; }
   }

   Clean clean : $(CXX_OBJECTS) $(C_OBJECTS) ;
   
   return $(CXX_OBJECTS) $(C_OBJECTS) ;
}

rule YaccRule C_SOURCE : Y_SOURCE
{
   depends $(Y_SOURCE:S=_YY.cpp) $(Y_SOURCE:S=_YY.hpp) : $(Y_SOURCE) ;
   LOCATE on $(Y_SOURCE:S=_YY.cpp) $(Y_SOURCE:S=_YY.hpp) = $(BIN_DIR) ;
   ProcessYacc $(Y_SOURCE:S=_YY.cpp) $(Y_SOURCE:S=_YY.hpp) : $(Y_SOURCE) ;
   Clean clean : $(Y_SOURCE:S=_YY.cpp) $(Y_SOURCE:S=_YY.hpp) ;
}

rule LexRule C_SOURCE : L_SOURCE
{
   depends  $(L_SOURCE:S=_ll.cpp) : $(L_SOURCE) $(L_SOURCE:S=_YY.hpp) ;
   includes $(L_SOURCE:S=_ll.cpp) : $(L_SOURCE:S=_YY.hpp) ;
   LOCATE on $(L_SOURCE:S=_ll.cpp) $(L_SOURCE:S=_ll.hpp) = $(BIN_DIR) ;
   ProcessLex $(L_SOURCE:S=_ll.cpp) : $(L_SOURCE) ;
   Clean clean : $(L_SOURCE:S=_ll.cpp) ;
}

rule FsmIdHeader TARGETS : SOURCES
{
   InitDirs ;
   
   FSM_ID_FILE ?= id.fsm ;
   LOCATE on $(FSM_ID_FILE) = $(BIN_DIR) ;
   
   notfile $(FSM_ID_FILE) ;
   depends $(TARGETS) : $(FSM_ID_FILE) $(FSM_TEMPLATE_FILE:E=fsm.tpl) $(SOURCES:S=.cpp) ;
   LOCATE on $(TARGETS) = $(BIN_DIR) ;
   ProcessFsmIdHeader $(TARGETS) : $(FSM_TEMPLATE_FILE:E=fsm.tpl) : $(FSM_ID_FILE) ;
   Clean clean : $(TARGETS) ;
}

rule FsmRule C_SOURCE : FSM_SOURCE
{
   FSM_ID_FILE ?= id.fsm ;
   LOCATE on $(FSM_ID_FILE) = $(BIN_DIR) ;
   
   depends  $(C_SOURCE:S=.cpp) $(C_SOURCE:S=.h) : $(FSM_SOURCE) $(FSM_TEMPLATE_FILE:E=fsm.tpl) ;
   depends  $(FSM_ID_FILE) : $(C_SOURCE:S=.cpp) $(C_SOURCE:S=.h) ;
   includes $(C_SOURCE:S=.cpp) : $(C_SOURCE:S=.h) ;
   LOCATE on $(C_SOURCE:S=.cpp) $(C_SOURCE:S=.h) = $(BIN_DIR) ;
   ProcessFsm $(C_SOURCE:S=.cpp) $(C_SOURCE:S=.h) : $(FSM_SOURCE) : $(FSM_TEMPLATE_FILE:E=fsm.tpl) : $(FSM_ID_FILE) ;
   Clean clean : $(C_SOURCE:S=.cpp) $(C_SOURCE:S=.h) $(FSM_ID_FILE) ;
}

rule HeaderRule INCLUDER : INCLUDEDS
{
   includes $(INCLUDER) : $(INCLUDEDS) ;
   HDRSCAN on $(INCLUDEDS) = $(HDRPATTERN) ;  # recursively search headers
   
   # Normally in build systems we want this. It means that if a header is not found, that its ok.
   nocare $(INCLUDEDS) ;                      
}

rule CleanTarget TARGET : TARGET_DIR
{
   local LIST = $(TARGET) ;                                                                                      # all the targets
   
   LIST += $(TARGET:HS=.pdb) $(TARGET:HS=.exp) $(TARGET:HS=.ilk) $(TARGET:H).manifest ;                          # clean associated compiler generated file
   LIST += $(TARGET:HS=.suo) $(TARGET:HS=.sln) ;                                                                 # clean msvc ide generated files
   LIST += $(TARGET:HN=".exe"0="_pure.log") $(TARGET:HN=".exe"0="_pure.ini")  $(TARGET:HN=".exe"0="_exe.pft") ;  # clean purify generated files
           
   LOCATE on $(LIST) = $(TARGET_DIR) ;
   Clean clean : $(LIST) ;
}

rule ExternalDlls TARGET : DLLS : TARGET_DIR
{
   if ( !$(TARGET_DIR) ) 
   {
      TARGET_DIR = $(BIN_DIR) ;
      depends $(TARGET) : $(TARGET_DIR) ;
      CreateDirectory $(TARGET_DIR) ;
   }
   
   for ( DLL in $(DLLS) )
   {
      REMOTE_DLL = ;