# This Jamfile requires boost-build v2 to build.
# The version shipped with boost 1.34.0

import modules ;
import path ;
import os ;
import errors ;
import feature : feature ;
import package ;
import virtual-target ;

BOOST_ROOT = [ modules.peek : BOOST_ROOT ] ;
CXXFLAGS = [ modules.peek : CXXFLAGS ] ;
LDFLAGS = [ modules.peek : LDFLAGS ] ;

ECHO "BOOST_ROOT =" $(BOOST_ROOT) ;
ECHO "OS =" [ os.name ] ;

if $(BOOST_ROOT)
{
	use-project /boost : $(BOOST_ROOT) ;
}

VERSION = 0.15.7 ;

# rule for linking the correct libraries depending
# on features and target-os
rule linking ( properties * )
{
	local result ;

	# openssl libraries, if enabled
	if <openssl>sha-1 in $(properties)
		|| <openssl>pe in $(properties)
	{
		# exclude gcc from a regular windows build to make mingw
		# link against the regular unix library name

		if <target-os>windows in $(properties)
		{
			result += <library>gdi32 ;
		}

		if <target-os>windows in $(properties) && ! <toolset>gcc in $(properties)
		{
			result += <library>ssleay32
				<library>libeay32
				<library>advapi32
				<library>user32
				<library>shell32
			;
		}
		else
		{
			result += <library>crypto <library>ssl ;
		}
	}

	if <geoip>shared in $(properties)
	{
		result += <library>GeoIP ;
	}

	# socket functions on windows require winsock libraries
	if <target-os>windows in $(properties)
		|| <target-os>cygwin in $(properties)
	{
		result += <library>ws2_32
			<library>wsock32
			<define>WIN32_LEAN_AND_MEAN
			<define>_WIN32_WINNT=0x0500
			<define>__USE_W32_SOCKETS
			<define>WIN32
			<define>_WIN32
		;
	}

	if <target-os>solaris in $(properties)
	{
		result += <library>libsocket <library>libnsl ;
	}

	if <test-coverage>on in $(properties)
		&& ( <toolset>gcc in $(properties)
		|| <toolset>darwin in $(properties) )
	{
		result += <cxxflags>-fprofile-arcs <cxxflags>-ftest-coverage
			<linkflags>-lgcov <define>NDEBUG ;
	}

	# clock_gettime on linux requires librt
	if <need-librt>yes in $(properties)
	{
		result += <library>librt ;
	}

	if <tcmalloc>yes in $(properties)
	{
		result += <library>tcmalloc ;
	}

	if <boost>system in $(properties)
	{
		result += <library>boost_filesystem
			<library>boost_thread
			<library>boost_system
		;
	}

	if <toolset>gcc in $(properties)
		&& <target-os>linux in $(properties)
		&& <variant>debug in $(properties)
	{
		# for backtraces in assertion failures
		# which only works on ELF targets with gcc
		result += <linkflags>-export-dynamic <cxxflags>-rdynamic ;
	}

	if <boost>source in $(properties)
	{
		if <boost-link>static in $(properties)
		{
			if <toolset>gcc in $(properties) && <link>shared in $(properties)
			{
				result += <fpic>on ;
			}

			result += <library>/boost/filesystem//boost_filesystem/<link>static
				<library>/boost/system//boost_system/<link>static
				;

			# if we're building a shared library
			# we need to link dynamically against the
			# pthread library
			if <fpic>on in $(properties) && <target-os>linux in $(properties)
			{
				result += <library>/boost/thread//boost_thread/<link>shared ;
			}
			else
			{
				result += <library>/boost/thread//boost_thread/<link>static ;
			}
		}
		else
		{
			result += <library>/boost/thread//boost_thread/<link>shared
				<library>/boost/filesystem//boost_filesystem/<link>shared
				<library>/boost/system//boost_system/<link>shared
				;
		}
		result += <include>$(BOOST_ROOT) <define>BOOST_ALL_NO_LIB ;
	}

	if <boost>system in $(properties)
	{
		# on mac the boost headers are installed in
		# a directory that isn't automatically accessable
		result += <include>/opt/local/include/boost-1_35
			<include>/opt/local/include
			;
	}

	return $(result) ;
}

# rule for adding the right source files
# depending on target-os and features
rule building ( properties * )
{
	local result ;

	if ( <target-os>linux in $(properties)
		|| <target-os>darwin in $(properties) )
		&& ( <toolset>gcc in $(properties)
		|| <toolset>darwin in $(properties) )
	{
		result += <source>src/assert.cpp ;
	}

	if <geoip>static in $(properties)
	{
		result += <source>src/GeoIP.c ;
	}

	if <openssl>off in $(properties)
	{
		result += <source>src/sha1.cpp ;
	}
	else
	{
		if <openssl>pe in $(properties)
		{
			result += <source>src/pe_crypto.cpp ;
		}

		if <target-os>linux in $(properties)
		{
			# linker library on linux, required when using openssl
			result += <source>/usr/lib/libdl.so ;
		}

	}

	if <memdebug>on in $(properties)
	{
		result += <source>src/memdebug.cpp ;
	}

	return $(result) ;
}

rule tag ( name : type  ? : property-set )
{
	name = [ virtual-target.add-prefix-and-suffix $(name) : $(type) : $(property-set) ] ;

	if $(type) = SHARED_LIB &&
		( ! ( [ $(property-set).get <target-os> ] in windows cygwin ) )
	{
		name = $(name).$(VERSION) ;
	}

	return $(name) ;
}

feature tcmalloc : no yes : composite propagated link-incompatible ;

feature need-librt : no yes : composite propagated link-incompatible ;

feature fiemap : off on : composite propagated ;
feature.compose <fiemap>on : <define>HAVE_LINUX_FIEMAP_H ;

feature pool-allocators : on off : composite propagated link-incompatible ;
feature.compose <pool-allocators>off : <define>TORRENT_DISABLE_POOL_ALLOCATOR ;

feature piece-allocator : valloc memalign posix_memalign : composite propagated ;
feature.compose <piece-allocator>memalign : <define>TORRENT_USE_MEMALIGN=1 ;
feature.compose <piece-allocator>posix_memalign : <define>TORRENT_USE_POSIX_MEMALIGN=1 ;

feature geoip : off static shared : composite propagated link-incompatible ;
feature.compose <geoip>off : <define>TORRENT_DISABLE_GEO_IP ;

feature bandwidth-limit-logging : off on : composite propagated link-incompatible ;
feature.compose <bandwidth-limit-logging>on : <define>TORRENT_VERBOSE_BANDWIDTH_LIMIT ;

feature invariant-checks : on off full : composite propagated link-incompatible ;
feature.compose <invariant-checks>off : <define>TORRENT_DISABLE_INVARIANT_CHECKS ;
feature.compose <invariant-checks>full : <define>TORRENT_EXPENSIVE_INVARIANT_CHECKS ;

feature disk-stats : off on : composite propagated link-incompatible ;
feature.compose <disk-stats>on : <define>TORRENT_DISK_STATS ;

feature memdebug : off on : composite propagated ;
feature.compose <memdebug>on : <define>TORRENT_MEMDEBUG ;

feature simulate-slow-read : off on : composite propagated ;
feature.compose <simulate-slow-read>on : <define>TORRENT_SIMULATE_SLOW_READ ;

feature logging : none default errors verbose : composite propagated link-incompatible ;
feature.compose <logging>default : <define>TORRENT_LOGGING ;
feature.compose <logging>errors : <define>TORRENT_ERROR_LOGGING ;
feature.compose <logging>verbose : <define>TORRENT_VERBOSE_LOGGING ;

feature dht-support : on off logging : composite propagated link-incompatible ;
feature.compose <dht-support>off : <define>TORRENT_DISABLE_DHT ;
feature.compose <dht-support>logging : <define>TORRENT_DHT_VERBOSE_LOGGING ;

feature openssl : pe sha-1 off : composite propagated link-incompatible ;
feature.compose <openssl>pe : <define>TORRENT_USE_OPENSSL ;
feature.compose <openssl>sha-1 : <define>TORRENT_USE_OPENSSL <define>TORRENT_DISABLE_ENCRYPTION ;
feature.compose <openssl>off : <define>TORRENT_DISABLE_ENCRYPTION ;

feature resolve-countries : on off : composite propagated link-incompatible ;
feature.compose <resolve-countries>off : <define>TORRENT_DISABLE_RESOLVE_COUNTRIES ;

feature character-set : unicode ansi : composite propagated link-incompatible ;
feature.compose <character-set>unicode : <define>_UNICODE <define>UNICODE ;
feature.compose <character-set>ansi : <define>BOOST_FILESYSTEM_NARROW_ONLY=1 ;

feature zlib : shipped system : composite propagated link-incompatible ;

feature deprecated-functions : on off : composite propagated link-incompatible ;
feature.compose <deprecated-functions>off : <define>TORRENT_NO_DEPRECATE ;

feature statistics : off on : composite propagated link-incompatible ;
feature.compose <statistics>on : <define>TORRENT_STATS ;

feature upnp-logging : off on : composite propagated link-incompatible ;
feature.compose <upnp-logging>on : <define>TORRENT_UPNP_LOGGING ;

feature boost : system source : link-incompatible propagated ;
feature boost-link : static shared : composite ;

feature debug-iterators : off on : composite propagated link-incompatible ;
feature.compose <debug-iterators>on : <define>_SCL_SECURE=1 <define>_GLIBCXX_DEBUG ;

feature test-coverage : off on : composite propagated ;

feature fpic : off on : composite propagated link-incompatible ;
feature.compose <fpic>on : <cflags>-fPIC ;
feature.compose <fpic>off : <toolset>darwin:<cflags>-mdynamic-no-pic ;

feature visibility : default hidden : composite propagated link-incompatible ;
feature.compose <visibility>hidden : <cflags>-fvisibility=hidden ;

# required for openssl on windows
lib ssleay32 : : <name>ssleay32 ;
lib libeay32 : : <name>libeay32 ;
lib advapi32 : : <name>Advapi32 ;
lib user32 : : <name>User32 ;
lib shell32 : : <name>shell32 ;
lib gdi32 : : <name>gdi32 ;

local boost-library-search-path =
  <search>/opt/local/lib
  <search>/usr/lib
  <search>/usr/local/lib
  <search>/sw/lib
  ;

lib boost_filesystem : : <target-os>darwin <name>boost_filesystem-mt $(boost-library-search-path) ;
lib boost_thread : : <target-os>darwin <name>boost_thread-mt $(boost-library-search-path) ;
lib boost_system : : <target-os>darwin <name>boost_system-mt $(boost-library-search-path) ;

lib boost_filesystem : : <name>boost_filesystem ;
lib boost_thread : : <name>boost_thread ;
lib boost_system : : <name>boost_system ;

# openssl on linux/bsd/macos etc.
lib crypto : : <name>crypto <search>/lib ;
lib ssl : : <name>ssl ;

# time functions used on linux require librt
lib librt : : <name>rt ;

lib libsocket : : <use>libnsl <name>socket <link>shared <search>/usr/sfw/lib ;
lib libnsl : : <name>nsl <link>shared <search>/usr/sfw/lib ;

lib tcmalloc : : <name>tcmalloc ;

# libz
lib zlib-target : : <name>z ;

# GeoIP shared library
lib GeoIP : : <name>GeoIP ;

# socket libraries on windows
lib wsock32 : : <name>wsock32 ;
lib ws2_32 : : <name>ws2_32 ;

SOURCES =
	alert
	allocator
	assert
	connection_queue
	create_torrent
	disk_buffer_holder
	entry
	error_code
	file_storage
	lazy_bdecode
	escape_string
	file
	gzip
	http_connection
	http_stream
	http_parser
	identify_client
	ip_filter
	peer_connection
	bt_peer_connection
	web_peer_connection
	http_seed_connection
	instantiate_connection
	natpmp
	piece_picker
	policy
	session
	session_impl
	socks5_stream
	stat
	storage
	torrent
	torrent_handle
	torrent_info
	tracker_manager
	http_tracker_connection
	udp_tracker_connection
	sha1
	udp_socket
	upnp
	logger
	file_pool
	lsd
	disk_io_thread
	enum_net
	broadcast_socket
	magnet_uri
	parse_url
	ConvertUTF

# -- extensions --
	metadata_transfer
	ut_pex
	ut_metadata
	lt_trackers
	smart_ban
	;

KADEMLIA_SOURCES =
	closest_nodes
	dht_tracker
	node
	refresh
	rpc_manager
	find_data
	node_id
	routing_table
	traversal_algorithm
	;

ZLIB_SOURCES = 
	adler32
	compress
	crc32
	deflate
	gzio
	infback
	inffast
	inflate
	inftrees
	trees
	uncompr
	zutil
	;

local usage-requirements = 
	<include>./include
	<include>./include/libtorrent
	<include>/usr/sfw/include
	<zlib>shipped:<include>./zlib
	<variant>release:<define>NDEBUG
	<variant>debug:<define>TORRENT_DEBUG
	<define>_FILE_OFFSET_BITS=64
	<define>BOOST_EXCEPTION_DISABLE
	<define>BOOST_FILESYSTEM_VERSION=2
	<conditional>@linking
	<zlib>system:<library>zlib-target
# these compiler settings just makes the compiler standard conforming
	<toolset>msvc:<cflags>/Zc:wchar_t
	<toolset>msvc:<cflags>/Zc:forScope
# disable bogus deprecation warnings on msvc8
	<toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
	<toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
# msvc optimizations
	<toolset>msvc,<variant>release:<linkflags>/OPT:ICF=5
	<toolset>msvc,<variant>release:<linkflags>/OPT:REF
# disable warning C4503: decorated name length exceeded, name was truncated
	<toolset>msvc:<cxxflags>/wd4503
# disable warning C4275: non-dll interface class 'x' used as base for dll-interface struct 'y'
	<toolset>msvc:<cxxflags>/wd4275
# disable warning C4251: 'x' needs to have dll-interface to be used by clients of class 'y'
	<toolset>msvc:<cxxflags>/wd4251
# disable some warnings for gcc
	<toolset>gcc:<cflags>-fno-strict-aliasing
	<toolset>gcc:<cflags>-Wno-missing-braces
	<boost>system:<cxxflags>$(CXXFLAGS)
	<boost>system:<linkflags>$(LDFLAGS)
# this works around a bug in asio in boost-1.39
	<define>BOOST_ASIO_HASH_MAP_BUCKETS=1021
	<tag>@tag
	;

project torrent ;

lib torrent

	: # sources
	src/$(SOURCES).cpp

	: # requirements
	<define>BOOST_THREAD_USE_LIB
	<threading>multi
	<link>shared:<define>TORRENT_BUILDING_SHARED
	<dht-support>on:<source>src/kademlia/$(KADEMLIA_SOURCES).cpp
	<dht-support>logging:<source>src/kademlia/$(KADEMLIA_SOURCES).cpp
	<zlib>shipped:<source>zlib/$(ZLIB_SOURCES).c
	<conditional>@building
	<boost>system:<cxxflags>$(CXXFLAGS)
	$(usage-requirements)

	: # default build
	<link>static
	<threading>multi

	: # usage requirements
	$(usage-requirements)
	;

headers = [ path.glob-tree include/libtorrent : *.hpp ] ;

package.install install
 : <install-header-subdir>libtorrent
   <install-source-root>libtorrent
   <install-no-version-symlinks>on
 :
 : torrent
 : $(headers)
 ;

