# -*- mode: perl -*-
# cons script for cgame game q3_ui ui .so and .qvm builds
#
# Oct. 2001 TTimo <ttimo@idsoftware.com>
#

# the top directory is
# <config>-<cpu>-<OS>-<libc version>
# where:
#   <config> is "debug" or "release"
#   <cpu> is "x86" or "ppc"
#   <OS> is "Linux" "BSD" "IRIX" etc.
#   <libc version> is major.minor of libc config

# source the compiler version utility
BEGIN {
  push @INC, './unix';
}
use Cons_gcc;

# defaults
$config = 'debug';
$do_smp = 1;
$do_masterserver = 0;
$do_authserver = 0;
$do_authport = 0;
$do_setup = 0;
$do_bspc = 0;
$do_sdk = 0;
$do_pk3 = 0;
# those are exported
$DO_WIN32 = 0;
$NO_VM = 0;
$NO_SO = 0;
$CC='gcc';
$CXX='g++';

# detect an sdk build (don't attempt client build and other things)
if ( -r 'unix/Conscript-client' )
{
  $no_core = 0;
}
else
{
  $no_core = 1;
}

# detection of CPU type
$cpu = `uname -m`;
chop ($cpu);
if ($cpu +~ /i?86/)
{
  $cpu = 'x86';
}
# OS
$OS = `uname`;
chop ($OS);
# hacky win32 detection and win32 specifics code
if ($OS =~ CYGWIN)
{
	$DO_WIN32 = 1;
}
else
{
	# libc .. do the little magic!
	$libc_cmd = '/lib/libc.so.6 |grep "GNU C "|grep version|awk -F "version " \'{ print $2 }\'|cut -b -3';
	$libc = `$libc_cmd`;
	chop ($libc);
}

if ($DO_WIN32 eq 1)
{
	print("Win32 build\n");

	$config = $ARGV[0];

	# TODO: option to override $Q3BASE from command line
	$Q3BASE = $ENV{Q3BASE}; # FIXME: this doesn't play nice with cygwin path syntax
	print("\$Q3BASE: $Q3BASE\n");	

	if($config eq 'debug')
	{
	  $DIR = 'Debug';
		system("cp -v $DIR/quake3.exe \$Q3BASE");
		system("cp -v $DIR/cgamex86.dll $DIR/qagamex86.dll $DIR/uix86.dll \$Q3BASE/baseq3");
	}
	elsif ($config eq 'debug-TA')
	{
		$DIR = 'Debug_TA';
		system("cp -v $DIR/quake3.exe \$Q3BASE");
		system("cp -v $DIR/cgamex86.dll $DIR/qagamex86.dll $DIR/uix86.dll \$Q3BASE/missionpack");
	}
	elsif($config eq 'release-TA')
	{
		$DIR = 'Release_TA';
		# spank!
		system("./spank.sh");
		system("cp -v $DIR/quake3.exe \$Q3BASE");
	}
	else
	{
		printf("ERROR: no config option (debug debug-TA release-TA)");
		exit;
	}

	# copy selected stuff to shared media
	$DESTDIR='/cygdrive/e/incoming/Id/q3-1.32';
	system("cp -v $DIR/quake3.exe $DESTDIR");
	system("cp -v /cygdrive/e/Q3SetupMedia/quake3/CHANGES-1.32.txt $DESTDIR");

	exit;	
}

if(@ARGV gt 0)
{
  foreach $cmdopt (@ARGV)
  {
    if(lc($cmdopt) eq 'release')
    {
      $config = 'release';
      next;
    }
    elsif(lc($cmdopt) eq 'debug')
    {
      $config = 'debug';
      next;
    }
    elsif(lc($cmdopt) eq 'novm')
    {
      $NO_VM = 1;
      next;
    }
    elsif(lc($cmdopt) eq 'noso')
    {
      $NO_SO = 1;
      next;
    }
    elsif(lc($cmdopt) eq 'nosmp')
    {
      $do_smp = 0;
      next;
    }
    elsif(lc($cmdopt) =~ 'master_server=.*')
    {
      $do_masterserver = 1;
      $master_server = lc($cmdopt);
      $master_server =~ s/master_server=(.*)/\1/;
      next;
    }
    elsif(lc($cmdopt) =~ 'auth_server=.*')
    {
      $do_authserver = 1;
      $auth_server = lc($cmdopt);
      $auth_server =~ s/auth_server=(.*)/\1/;
      next;
    }
    elsif(lc($cmdopt) =~ 'auth_port=.*')
    {
      $do_authport = 1;
      $auth_port = lc($cmdopt);
      $auth_port =~ s/auth_port=(.*)/\1/;
      next;
    }
    elsif(lc($cmdopt) =~ 'setup')
    {
      $do_setup = 1;
      next;
    }
    elsif(lc($cmdopt) =~ 'bspc')
    {
      $do_bspc = 1;
      next;
    }
    elsif(lc($cmdopt) =~ 'sdk')
    {
      $do_sdk = 1;
      next;
    }
    elsif(lc($cmdopt) =~ 'pk3')
    {
      $do_pk3 = 1;
      next;
    }
	elsif(lc($cmdopt) =~ 'gcc=.*')
    {
      $CC=lc($cmdopt);
      $CC =~ s/gcc=(.*)/\1/;
      next;
    }
    elsif(lc($cmdopt) =~ 'g\+\+=.*')
    {
      $CXX=lc($cmdopt);
      $CXX=~s/g\+\+=(.*)/\1/;
      next;
    }
    else
    {
      # output an error & exit
      print("Error\n  $0: Unknown command line option: [ $cmdopt ]\n");
      system("cons -h");
      exit;
    }
  }
}

if (($do_setup eq 1) && ($config ne 'release'))
{
  print("Error\n  $0: 'setup' requires 'release'\n");
  exit;
}

# sdk
if ($do_sdk eq 1)
{
  # extract the Q3 version from q_shared.h
  $line = `cat game/q_shared.h | grep Q3_VERSION`;
  chomp $line;
  $line =~ s/.*Q3\ (.*)\"/$1/;
  $Q3_VER = $line;
  $SDK_NAME = "linuxq3a-sdk-$Q3_VER.x86.run";
  Default "unix/$SDK_NAME";
  Export qw( SDK_NAME Q3_VER );
  Build 'unix/Conscript-sdk';
  return;
}

# build the config directory
$CONFIG_DIR = $config . '-' . $cpu . '-' . $OS . '-' . $libc;

$COMMON_CFLAGS = '-pipe -fsigned-char ';

if ($config eq 'debug')
{
  # use -Werror for better QA  
  $BASE_CFLAGS = $COMMON_CFLAGS . '-g -Wall -Werror -O ';
	$BSPC_BASE_CFLAGS = $COMMON_CFLAGS . '-g -O -DLINUX -DBSPC -Dstricmp=strcasecmp ';
}
else
{
  $BASE_CFLAGS = $COMMON_CFLAGS . '-DNDEBUG -O6 -mcpu=pentiumpro -march=pentium -fomit-frame-pointer -ffast-math -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strict-aliasing -fstrength-reduce ';
	$BSPC_BASE_CFLAGS = $BASE_CFLAGS . '-DLINUX -DBSPC -Dstricmp=strcasecmp ';
}

if ($do_masterserver eq 1)
{
	$BASE_CFLAGS .= "-DMASTER_SERVER_NAME=\\\"$master_server\\\" ";
}

if ($do_authserver eq 1)
{
	$BASE_CFLAGS .= "-DAUTHORIZE_SERVER_NAME=\\\"$auth_server\\\" ";
}

if ($do_authport eq 1)
{
	$BASE_CFLAGS .= "-DPORT_AUTHORIZE=$auth_port ";
}

my @gcc_version = Cons_gcc::get_gcc_version($CC);
print("GCC version: $gcc_version[1] - $gcc_version[2]\n");
# with 2.95 you can link with gcc, this avoids nasty useless libstdc++ dependency
if ($gcc_version[0] eq '2')
{
	$LINK = $CC;
} else {
	$LINK = $CXX;
}

my @ccache = Cons_gcc::get_ccache();
if ($ccache[0] eq '1')
{
  $CC = $ccache[1] . " " . $CC;
  $CXX = $ccache[1] . " " . $CXX;
}

print 'cpu : ' . $cpu . "\nOS  : " . $OS . "\n";
print "libc: " . $libc . "\n";
print "configured for " . $config . " build\n";
print 'CFLAGS: ' . $BASE_CFLAGS . "\n";

# install config
$INSTALL_BASEDIR='#install';

Default $INSTALL_BASEDIR;

sub build_tools {
  system("mkdir qvmtools 2>/dev/null");
  if (@_[0] eq 'q3lcc')
  {
    system("cd ../lcc ; make all ; cp /tmp/lcc ../code/qvmtools/q3lcc ; cp /tmp/rcc ../code/qvmtools/q3rcc ; cp /tmp/cpp ../code/qvmtools/q3cpp");
  }
  elsif (@_[0] eq 'q3asm')
  {
    system("cd ../q3asm ; make ; cp q3asm ../code/qvmtools");
  }
  else
  {
    printf("build_tools: @_[0] unrecognized command\n");
    die;
  }
  return 1;
}

# build tools
$env_tools = new cons();
Command $env_tools 'qvmtools/q3lcc', '[perl] &build_tools(\'q3lcc\')';
Command $env_tools 'qvmtools/q3asm', '[perl] &build_tools(\'q3asm\')';

if ($do_bspc eq 1)
{
	# build bspc
	$BUILD_DIR = $CONFIG_DIR . '/bspc';
	Link $BUILD_DIR => '.';
	$INSTALL_DIR = $INSTALL_BASEDIR . '/utils';
	Export qw( BSPC_BASE_CFLAGS BUILD_DIR INSTALL_DIR CC CXX LINK );
	Build $BUILD_DIR . '/bspc/Conscript';
}

# build vanilla Q3
$TARGET_DIR='Q3';

$INSTALL_DIR = $INSTALL_BASEDIR . '/baseq3';

$BUILD_DIR = $CONFIG_DIR . '/' . $TARGET_DIR . '/cgame';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/cgame/Conscript';

$BUILD_DIR = $CONFIG_DIR . '/' . $TARGET_DIR . '/game';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/game/Conscript';

$BUILD_DIR = $CONFIG_DIR . '/' . $TARGET_DIR . '/q3_ui';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/q3_ui/Conscript';
  
# build TA
$TARGET_DIR='TA';

$INSTALL_DIR = $INSTALL_BASEDIR . '/missionpack';

$BUILD_DIR = $CONFIG_DIR . "/" . $TARGET_DIR . '/cgame';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/cgame/Conscript';

$BUILD_DIR = $CONFIG_DIR . "/" . $TARGET_DIR . '/game';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/game/Conscript';

$BUILD_DIR = $CONFIG_DIR . '/' . $TARGET_DIR . '/ui';
Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS TARGET_DIR INSTALL_DIR NO_VM NO_SO CC CXX LINK );
Build $BUILD_DIR . '/ui/Conscript';

# core
if ($no_core eq 1)
{
  return;
}

$INSTALL_DIR = $INSTALL_BASEDIR;
$BUILD_DIR = $CONFIG_DIR . '/core/dedicated';
Link $BUILD_DIR => '.';
$hack = $BASE_CFLAGS; # hit me!
$BASE_CFLAGS .= '-DDEDICATED ';
Export qw( BASE_CFLAGS BUILD_DIR INSTALL_DIR CC CXX LINK );
Build $BUILD_DIR . '/unix/Conscript-dedicated';
$BASE_CFLAGS = $hack;



$TARGETNAME = 'linuxquake3';
$BUILD_DIR = $CONFIG_DIR . '/core/client';
$BASE_LDFLAGS = '';

Link $BUILD_DIR => '.';
Export qw( BASE_CFLAGS BASE_LDFLAGS BUILD_DIR INSTALL_DIR TARGETNAME CC CXX LINK );
Build $BUILD_DIR . '/unix/Conscript-client';

if ($do_smp eq 1)
{
	$TARGETNAME = 'linuxquake3-smp';
	$BUILD_DIR = $CONFIG_DIR . '/core/client-smp';
	$BASE_CFLAGS .= '-DSMP ';
	$BASE_LDFLAGS = '-lpthread ';
	
  Link $BUILD_DIR => '.';
  Export qw( BASE_CFLAGS BASE_LDFLAGS BUILD_DIR INSTALL_DIR TARGETNAME CC CXX LINK );
  Build $BUILD_DIR . '/unix/Conscript-client';	
}

if ($NO_VM eq 0 && $do_pk3 eq 1)
{
	# build the PK3s
	$INSTALL_DIR = $INSTALL_BASEDIR;
	$BUILD_DIR = $CONFIG_DIR . '/pk3-builder';
	Link $BUILD_DIR => 'unix';
	Export qw( INSTALL_DIR BUILD_DIR CONFIG_DIR CC CXX LINK );
	Build $BUILD_DIR . '/Conscript-pk3';
}

if ($do_setup eq 1)
{
  Link $CONFIG_DIR => '.';
  Export qw( INSTALL_BASEDIR );
  Build $CONFIG_DIR . '/unix/Conscript-setup';
}

Help 
"
Usage: cons [-h] [ -- [release|debug] [novm] [noso] [nosmp] [master_server=<adr>] [auth_server=<adr>] [auth_port=<port>] [pk3] [bspc] [setup] [sdk]]
Default build type is Debug, specifying '-- release' on the
command line builds a Release version (NOTE that this option
only affects the native libraries).

novm: will not build the VMs
noso: will not build the so

below are for core builds only:

nosmp : do not build the SMP-enabled version of the renderer
pk3   : generate the pk3s on the fly (defined in unix/Conscript-pk3)
bspc  : build bspc
setup : build setup 
sdk   : build the mod sdk
"
;
