User:Wunderboy/sandbox

From Valve Developer Community
Jump to: navigation, search

The following are various notes, scribbles, thoughts, etc. from doing various Source-type things. None of these are structured of "definate" - just things I write down for reference. If anything you find here is useful, great, but use it at your own risk!!!

This is a personal page on my own namespace. If you have anything to add, questions, comments, or managed to find something I didn't, please post on the talk page instead. Thanks!

Compiling the SDK under Linux with Fedora Core 6

The following are some notes on how I set-up a build environment and sucessfullly compiled the linux server for Ham and Jam. This are based on the SDK codebase as of from 31st October, 2006.

Note.pngNote:This overview was done using a HL2MP based mod method and the Visual Studio 2005 project files.

Install Fedora Core 6

You'll need a working install of Fedora Core 6 "Zod" (knowns as FC6 from here on) available. If you don't have a spare machine or don't want to dual-boot you can create a virtual machine under Windows using WMWare Player and a virtual appliance image of FC6.

If you're going the VMWare route with a pre-packaged appliance, it's a good idea to ensure you have access to the Internet from it as this will help with installing packages and updates. A couple of tips - you'll probably find setting your network to NAT will work better. Also, beware that the Linux firewall and possibly any Windows firewall software (ZoneAlarm, PeerGuardian2) might block access to the Internet too. This will become apparent later on when we have to use hlds_l.

The actual process of installing FC6 and getting it up and running is down to the reader and beyond the scope of this article, however as a general guide, make sure you have at least installed the development packages and have around 4Gb of free disk space.

Packages needed for the SDK

There are a number of pieces of software (or packages) you'll need installed to compile the Source SDK. The following is a list and a brief outline of how to install and configure them.

GCC 3.4.6

The Compiling under Linux page states that GCC 3.4.X is recommended for compiling the SDK and that GCC 4.X doesn't work.

FC6 comes with a compatible version of GCC 3.4.6 which works fine with the SDK and can be installed using the Software Updater tool under Gnome or via the command line as follows:

yum install compat-gcc-34
yum install compat-gcc-34-g77
yum install compat-gcc-34-c++
yum install compat-libstdc++-33
yum install compat-db
yum install compat-readline43

We're including some extra stuff in here like the Fortran compiler, BerkleyDB and ReadLine. Their probably not needed but it doesn't hurt to install them.

We can check GCC 3.4.6 is installed and the right version with the following:

gcc34 -dumpversion
3.4.6

We can also check we have the library files we need installed as follows:

locate libstdc++.a
/usr/lib/gcc/i386-redhat-linux/3.4.6/libstdc++.a
/usr/lib/gcc/i386-redhat-linux/4.1.1/libstdc++.a


locate libgcc_eh.a
/usr/lib/gcc/i386-redhat-linux/3.4.6/libgcc_eh.a
/usr/lib/gcc/i386-redhat-linux/4.1.1/libgcc_eh.a

In the above case, we would use the 3.4.6 versions.

Xerces 2.6.0

Using Xerces 2.7.0 as a pre-compiled package caused all sort of problems. The only way I could get vcpm to work was to re-build Xerces 2.6.0 from source and use that instead.

I downloaded the 2.6.0 source from the link above and placed the .tar.gz file in /usr/local/src/ and compiled it as follows:

cd /usr/local/src
tar zxvf xerces-c-src_2_6_0.tar.gz
cd /usr/local/src/xerces-c-src_2_6_0/src/xerces
export XERCESCROOT=/usr/local/src/xerces-c-src_2_6_0
./runConfigure -p linux -c gcc34 -x g++34
gmake
gmake install

This configures, compiles and then installs the Xerces 2.6.0 package. The lib and header files needed by vcpm are then located in /usr/local/src/xerces-c-src_2_6_0/lib or /usr/local/lib and /usr/local/src/xerces-c-src_2_6_0/includes respectively.

Install hlds_l

You'll need the Half-Life Dedicated Server for Linux (hlds_l) installed and run at least once to make a couple of library files available during compile. In this example I installed hlds_l in /hlds_l for simplicity.

Installing hlds_l goes beyond the scope of this article, but there are plenty of tutorials out there on how to do it.

Copy SDK Source

The next step is to copy the source code for your mod over to the Linux system. In my own case, I copied the contents of the D:\HLMP2Mod\src folder on my Windows machine to /usr/local/src/hl2mpmod/src folder on my Linux box.

Set-up symbolic links

We need a couple of symbolic links back to some static objects that ship with hlds_l. They should get created as part of the build process but it doesn't hurt to make them ourselves:

cd /usr/local/src/hl2mpmod/src/linux_sdk
ln -s /hlds_l/bin/tier0_i486.so
ln -s /hlds_l/bin/vstdlib_i486.so

Create the Makefile

Next step is to put the relevent details for our build environment into /usr/local/src/hl2mpmod/src/linux_sdk/Makefile. The following is a complete Makefile - you should recognise paths and filenames from earlier stages:

#
# SDK Makefile for x86 Linux
#
#

#############################################################################
# Developer configurable items
#############################################################################

# the name of the mod binary (_i486.so is appended to the end)
NAME=server

# the location of the vcproj that builds the mod
MOD_PROJ=../dlls/server_hl2mp-2005.vcproj

# the name of the mod configuration (typically <proj name>_<build type><build target>)
MOD_CONFIG=server_hl2mp_ReleaseHL2MPWin32

# the directory the base binaries (tier0_i486.so, etc) are located
GAME_DIR=/hlds_l

# compiler options (gcc 3.4.1 or above is required)
CC=/usr/bin/gcc34
CPLUS=/usr/bin/g++34
CLINK=/usr/bin/gcc34
CPP_LIB="/usr/lib/gcc/i386-redhat-linux/3.4.6/libstdc++.a /usr/lib/gcc/i386-redhat-linux/3.4.6/libgcc_eh.a"

# put any compiler flags you want passed here
USER_CFLAGS=

# link flags for your mod, make sure to include any special libraries here
LDFLAGS="-lm -ldl tier0_i486.so vstdlib_i486.so mathlib_i486.a choreoobjects_i486.a tier1_i486.a"

# XERCES 2.6.0 or above ( http://xml.apache.org/xerces-c/ ) is used by the vcproj to makefile converter
# it must be installed before being able to run this makefile
XERCES_INC_DIR=/usr/local/src/xerces-c-src_2_6_0/include
XERCES_LIB_DIR=/usr/local/src/xerces-c-src_2_6_0/lib


#############################################################################
# Things below here shouldn't need to be altered
#############################################################################
MAKE=gmake

# the dir we want to put binaries we build into
BUILD_DIR=.
# the place to put object files
BUILD_OBJ_DIR=$(BUILD_DIR)/obj

# the location of the source code
SOURCE_DIR=..

# the CPU target for the build, must be i486 for now
ARCH=i486
ARCH_CFLAGS=-mtune=i686 -march=pentium3 -mmmx -O3

# -fpermissive is so gcc 3.4.x doesn't complain about some template stuff
BASE_CFLAGS=-fpermissive -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp
SHLIBEXT=so
SHLIBCFLAGS=-fPIC
SHLIBLDFLAGS=-shared -Wl,-Map,$@_map.txt -Wl

#flags passed to the c compiler
CFLAGS="$(USER_CFLAGS) $(DEFINES) $(ARCH_CFLAGS) $(BASE_CFLAGS) -Usprintf=use_Q_snprintf_instead_of_sprintf -Ustrncpy=use_Q_strncpy_instead -UPROTECTED_THINGS_ENABLE"

# define list passed to make for the sub makefile
BASE_DEFINES=CC=$(CC) CPLUS=$(CPLUS) CPP_LIB=$(CPP_LIB) \
	BUILD_DIR=$(BUILD_DIR) BUILD_OBJ_DIR=$(BUILD_OBJ_DIR) \
	SOURCE_DIR=$(SOURCE_DIR) SHLIBLDFLAGS=$(SHLIBLDFLAGS) SHLIBEXT=$(SHLIBEXT) \
	CLINK=$(CLINK) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) \
	ARCH=$(ARCH) GAME_DIR=$(GAME_DIR) MOD_CONFIG=$(MOD_CONFIG) NAME=$(NAME) \
	XERCES_INC_DIR=$(XERCES_INC_DIR) XERCES_LIB_DIR=$(XERCES_LIB_DIR)

# Project Makefile
MAKE_MOD=Makefile.mod
MAKE_VCPM=Makefile.vcpm
MAKE_PLUGIN=Makefile.plugin

all: check vcpm mod

check:
	if [ -z "$(CC)" ]; then echo "Compiler not defined."; exit; fi
	if [ ! -d $(BUILD_DIR) ];then mkdir $(BUILD_DIR);fi
	cd $(BUILD_DIR)

vcpm:
	$(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES)

mod: vcpm
	if [ ! -f "tier0_i486.so" ]; then ln -s $(GAME_DIR)/bin/tier0_i486.so .; fi
	if [ ! -f "vstdlib_i486.so" ]; then ln -s $(GAME_DIR)/bin/vstdlib_i486.so .; fi
	./vcpm $(MOD_PROJ)
	$(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES)

plugin:
	$(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES)

clean:
	 $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) clean
	 $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) clean
	 $(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES) clean

Fixing code errors

Filename case and .vcproj errors

There are a number of errors which will stop the SDK source code from compiling. These are:

  • .cpp and .h filenames are mixed case.
  • #include statements refer to mixed-case filenames.
  • .vcproj filenames are mixed-case.
  • .vcproj contains bad seperator in include paths.
  • Makefile.vcpm contains mixed-case filnames.

You can fix all of the above using the following bash script. Save it as/usr/local/src/hl2mpmod/src/sdk_fixes.sh and run it with:

cd /usr/local/src/hl2mpmod/src/
/bin/bash sdk_fixes.sh
#!/bin/bash

# Move command
MVCMD="mv"

# For subversion integration renaming (or cvs).
#MVCMD="svn mv --force"

# SVN directory prefix (cvs users can change this as needed)
SVNDIR=.svn

############################################
# Make all .cpp and .h filenames lowercase #
############################################

for ((i=1;i<10;i++))
{
	echo Renaming dirs pass $i ...

	IFS=$'\n'
	for file in $(find -path *$SVNDIR -prune -o -type d -print)
	do
		file_new="$(echo $file |tr '[:upper:]' '[:lower:]')"

		if [ "$file" != "$file_new" ]
		then
			echo "Rename $file to $file_new ..."
			IFS=$OLDIFS
			$MVCMD "$file" "$file_new"
			IFS=$'\n'
		fi
	done
}

#######################################################
# Make all include statements use lowercase filenames #
#######################################################

IFS=$OLDIFS
for ext in cpp h
do
	echo Searching .$ext ...	

	IFS=$'\n'
	for file in $(find -path *$SVNDIR -prune -o -name "*.$ext" -print)
	do
		file_new="$(echo $file |tr '[:upper:]' '[:lower:]')"
		
		if [ "$file" != "$file_new" ]
		then
			echo "Rename $file to $file_new ..."
			IFS=$OLDIFS
			$MVCMD "$file" "$file_new"
			IFS=$'\n'
		fi
		
		echo "Parsing $file_new ..."
		sed -i 's/\(#include.*"\)\(.*\)\(\.h"\)/\1\L\2\3/g' "$file_new"
		sed -i 's/\(#include.*<\)\(.*\)\(\.h>\)/\1\L\2\3/g' "$file_new"
	done
done

########################################
# Make all .vcproj filenames lowercase #
########################################

echo Searching .vcproj ...

IFS=$'\n'
for file in $(find -path *$SVNDIR -prune -o -name "*.vcproj" -print)
do
	echo "Parsing $file ..."
	sed -i 's/\(RelativePath="\)\(.*\)\(\.h"\)/\1\L\2\3/g' "$file"
	sed -i 's/\(RelativePath="\)\(.*\)\(\.cpp"\)/\1\L\2\3/g' "$file"
done

###########################################
# Fix broken include path in .vcproj file #
###########################################

echo Searching server_hl2mp-2005.vcproj ...

file="$(find -path *$SVNDIR -prune -o -name server_hl2mp-2005.vcproj -print)"
echo Parsing $file ...
sed -i 's%../game_shared/hl2mp;./episodic%../game_shared/hl2mp,./episodic%g' "$file"

#####################################
# Make filenames lowercase for vcpm #
#####################################

echo Searching Makefile.vcpm ...
file="$(find -path *$SVNDIR -prune -o -name Makefile.vcpm -print)"
echo Parsing $file ...
sed -i 's/KeyValues.o/keyvalues.o/' "$file"