# vim:filetype=python

#  Network Simulation Cradle
#  Copyright (C) 2003-2005 Sam Jansen
#
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2 of the License, or (at your option)
#  any later version.
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
#  more details.
#
#  You should have received a copy of the GNU General Public License along
#  with this program; if not, write to the Free Software Foundation, Inc., 59
#  Temple Place, Suite 330, Boston, MA 02111-1307 USA

import os, glob

curdir = Dir('.').path + '/'

net = {}

net['core'] = \
Split("""
datagram.c   ethtool.c        iovec.c                       sock.c
dev.c        filter.c         link_watch.c  request_sock.c  stream.c
dev_mcast.c  flow.c           neighbour.c   rtnetlink.c     sysctl_net_core.c
dst.c        gen_estimator.c  net-sysfs.c   scm.c           utils.c
             gen_stats.c                    skbuff.c               
""")

net['ethernet'] = \
Split("""
eth.c         sysctl_net_ether.c
""")

net['ipv4'] = \
Split("""
af_inet.c        igmp.c                  ipmr.c         protocol.c         tcp_ipv4.c
ah4.c            inet_connection_sock.c  ip_options.c   raw.c              tcp_minisocks.c
arp.c            inet_diag.c             ip_output.c    route.c            tcp_output.c
datagram.c       inet_hashtables.c       ip_sockglue.c  syncookies.c       tcp_scalable.c
devinet.c        inetpeer.c              ipconfig.c     sysctl_net_ipv4.c  tcp_timer.c
esp4.c           inet_timewait_sock.c                   tcp_bic.c          tcp_vegas.c
fib_frontend.c                                          tcp.c              tcp_westwood.c
fib_hash.c                                              tcp_cong.c         udp.c
                 ip_forward.c                           tcp_diag.c                      
                 ip_fragment.c                          tcp_highspeed.c                  
fib_semantics.c  ip_gre.c                               tcp_htcp.c                         
                 ip_input.c              netfilter.c    tcp_hybla.c                        
icmp.c                                   proc.c         tcp_input.c                      
""")

net['ipv6'] = \
Split("""
addrconf.c  icmp.c                               protocol.c         udp.c
af_inet6.c  inet6_hashtables.c  ipv6_sockglue.c  raw.c                           
            ip6_fib.c           ipv6_syms.c      reassembly.c                     
anycast.c   ip6_flowlabel.c     mcast.c          route.c                          
datagram.c  ip6_input.c         ndisc.c          sit.c                           
            ip6_output.c        netfilter.c      sysctl_net_ipv6.c                
exthdrs.c                       proc.c           tcp_ipv6.c
""")
# exthdrs_core.c ?
    
net['sctp'] = \
Split("""
associola.c  endpointola.c  outqueue.c       sm_statefuns.c   tsnmap.c
bind_addr.c  input.c        primitive.c      sm_statetable.c  ulpevent.c
chunk.c      inqueue.c      proc.c           socket.c         ulpqueue.c
command.c    ipv6.c         protocol.c       ssnmap.c
crc32c.c                    sm_make_chunk.c  sysctl.c
debug.c      output.c       sm_sideeffect.c  transport.c
""")

net['netlink'] = \
Split("""
af_netlink.c
""")

net['packet'] = [
    'af_packet.c'
    ]

net['sched'] = [
    'sch_generic.c'
    ]
    
net['.'] = [
    'socket.c', 'sysctl_net.c'
    ]

# This array specifies the order. This order is used when linking; we need
# to make sure things are linked in the correct order so the initialisation
# functions -- initcall functions -- are called in the correct order.
# There was a problem earlier where sctp_init was being called before
# inet_init, which caused problems. The array below fixes that.
dir_order = [ '.', 'core', 'packet', 'sched', 'netlink', 'ethernet', 'ipv4', 
        'ipv6', 'sctp',
	]

src = reduce(lambda x,y:x+y, [ ['net/' + d + '/' + f for f in net[d]] 
                                    for d in dir_order ])

src.extend( [ 
    'nsc/unimplemented.c', 'nsc/implemented.c', 'nsc/support.c',
    'kernel/softirq.c', 'kernel/timer.c', 'kernel/itimer.c', 'kernel/sysctl.c',
    'drivers/net/loopback.c', 
] )
# 'nsc/support.c',
# 'nsc/globals.c', 
# 
# -----------------------------------------------

# We might want to change the include dir later 
# used to have: -O2
cflags = '-D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -nostdinc -fno-inline -iwithprefix include -DKBUILD_BASENAME=clnt -DMODVERSIONS -DEXPORT_SYMTAB '
# -fno-strict-aliasing -fno-common -fomit-frame-pointer -pipe -mpreferred-stack-boundary=2 -march=i686 -malign-functions=4
cflags += ' -g -O ' # -finstrument-functions 

# You really need to undefine whatever symbol is defined for the operating
# system you are compiling on and make sure the various linux symbols are
# defined. __linux__ is the only important one I've found; though compilers
# tend to define __linux and __Linux__ and so on and so forth.
cflags += ' -U__FreeBSD__ -D__linux__=1 -Dlinux=1 -D__linux=1 '
# the -DKBUILD_BASENAME probably doesn't matter?

include_path = [ 
    'include', 
    'include/asm/mach-default', 
    '../sim', 'nsc', 'override' ]

cc = 'gcc-3.4'
cxx = 'g++-3.4'
linker_script = 'linker-script-full.ld'

ext_cflags = ''
link_flags = '-Wl,-O1  '

if os.uname()[4] == 'x86_64':
    ext_cflags += '-m32 '
    link_flags += '-m32 '

cflags += ext_cflags

Import('default_env')

env = default_env.Copy(CC=cc, CCFLAGS = cflags, CPPPATH = include_path,
        GLB_LIST = curdir + '/global_list.txt', LINK = cxx)
drv_env = default_env.Copy(CC=cc, CCFLAGS = cflags + '-DEXPORT_SYMTAB', 
        GLB_LIST = curdir + '/global_list.txt', CPPPATH = include_path)

sim_env = Environment(CC=cc,CXX=cxx, 
		CCFLAGS = '-g -Wall -O2 ' + ext_cflags , 
		CPPPATH = [ '../sim', 'nsc' ])

# Tell our Parser to parse everything in input_sources
parsed_sources = []
# The following isn't just "for i in src" because we need to get the order
# correct.
for i in src:
    output = os.path.splitext(i)[0]+'.parsed.c'
    if i[:7] == 'drivers':
        parsed_sources.append( drv_env.Parser(output, i) )
    else:
        parsed_sources.append( env.Parser(output, i) )
    # Make sure the parser is built so we can actually create the output
    # file.
    env.Depends(output, '#' + default_env['GLOBALISER'])

#####
ss = sim_env.SharedObject('nsc/sim_support.cpp')
parsed_sources.append(ss)
parsed_sources.append('asm/getuser.S')
parsed_sources.append('asm/putuser.S')

#parsed_sources.append(
#    Environment(CC=cc,CFLAGS="-g").SharedObject('nsc/debug.c')
#    )

#src.append('linker-script.ld')

# Using Program and -shared is a hacky way to make a shared library in SCons
# without requiring -fPIC.
output = env.Program(source = parsed_sources, target = 'liblinux2.6.14.2.so',
# We need a special linker script to set up some variables for
# initialisation in Linux
    LINKFLAGS = link_flags + '-shared -Wl,-O1 -Wl,-T' + curdir + linker_script
)

Install(dir = "..", source = output)
