import sys import os import shutil import multiprocessing import SCons.Util ## Configuration opts = Variables('Local.sc') opts.AddVariables( ("CC", "C Compiler"), ("CXX", "C++ Compiler"), ("AS", "Assembler"), ("LINK", "Linker"), ("AR", "Archiver"), ("RANLIB", "Archiver Indexer"), ("BUILDTYPE", "Build type (RELEASE, DEBUG, or PERF)", "RELEASE"), ("VERBOSE", "Show full build information (0 or 1)", "0"), ("NUMCPUS", "Number of CPUs to use for build (0 means auto).", "0"), ("WITH_GPROF", "Include gprof profiling (0 or 1).", "0"), ("PREFIX", "Installation target directory.", "#pxelinux"), ("ARCH", "Target Architecture", "amd64"), ("BOOTDISK", "Build boot disk (0 or 1)", "1"), ("BOOTDISK_SIZE", "Boot disk size", "128") ) env = Environment(options = opts, tools = ['default'], ENV = os.environ) Help(opts.GenerateHelpText(env)) # Copy environment variables if 'CC' in os.environ: env["CC"] = os.getenv('CC') if 'CXX' in os.environ: env["CXX"] = os.getenv('CXX') if 'AS' in os.environ: env["AS"] = os.getenv('AS') if 'LD' in os.environ: env["LINK"] = os.getenv('LD') if 'AR' in os.environ: env["AR"] = os.getenv('AR') if 'RANLIB' in os.environ: env["RANLIB"] = os.getenv('RANLIB') if 'CFLAGS' in os.environ: env.Append(CCFLAGS = SCons.Util.CLVar(os.environ['CFLAGS'])) if 'CPPFLAGS' in os.environ: env.Append(CPPFLAGS = SCons.Util.CLVar(os.environ['CPPFLAGS'])) if 'CXXFLAGS' in os.environ: env.Append(CXXFLAGS = SCons.Util.CLVar(os.environ['CXXFLAGS'])) if 'LDFLAGS' in os.environ: env.Append(LINKFLAGS = SCons.Util.CLVar(os.environ['LDFLAGS'])) #env.Append(CPPFLAGS = [ "-Wall", "-Wformat=2", "-Wextra", "-Wwrite-strings", # "-Wno-unused-parameter", "-Wmissing-format-attribute", # "-Werror" ]) # env.Append(CFLAGS = [ "-Wshadow", "-Wno-typedef-redefinition" ]) #env.Append(CXXFLAGS = [ "-Wno-non-template-friend", "-Woverloaded-virtual", # "-Wcast-qual", "-Wcast-align", "-Wconversion", # "-Weffc++", "-std=c++0x", "-Werror" ]) env.Append(CXXFLAGS = [ "-fno-builtin" ]) if env["WITH_GPROF"] == "1": env.Append(CPPFLAGS = [ "-pg" ]) env.Append(LINKFLAGS = [ "-pg" ]) env.Append(CPPFLAGS = "-DBUILDTYPE=" + env["BUILDTYPE"]) if env["BUILDTYPE"] == "DEBUG": env.Append(CPPFLAGS = [ "-g", "-DDEBUG", "-Wall", "-Wno-deprecated-declarations" ]) env.Append(LINKFLAGS = [ "-g", "-rdynamic" ]) elif env["BUILDTYPE"] == "PERF": env.Append(CPPFLAGS = [ "-g", "-DNDEBUG", "-Wall", "-O2"]) env.Append(LDFLAGS = [ "-g", "-rdynamic" ]) elif env["BUILDTYPE"] == "RELEASE": env.Append(CPPFLAGS = ["-DNDEBUG", "-Wall", "-O2"]) else: print("Error BUILDTYPE must be RELEASE or DEBUG") sys.exit(-1) if env["ARCH"] != "amd64": print("Unsupported architecture: " + env["ARCH"]) sys.exit(-1) try: hf = open(".git/HEAD", 'r') head = hf.read() if head.startswith("ref: "): if head.endswith("\n"): head = head[0:-1] with open(".git/" + head[5:]) as bf: branch = bf.read() if branch.endswith("\n"): branch = branch[0:-1] env.Append(CPPFLAGS = [ "-DGIT_VERSION=\\\"" + branch + "\\\""]) except IOError: pass if env["VERBOSE"] == "0": env["CCCOMSTR"] = "Compiling $SOURCE" env["CXXCOMSTR"] = "Compiling $SOURCE" env["SHCCCOMSTR"] = "Compiling $SOURCE" env["SHCXXCOMSTR"] = "Compiling $SOURCE" env["ARCOMSTR"] = "Creating library $TARGET" env["RANLIBCOMSTR"] = "Indexing library $TARGET" env["LINKCOMSTR"] = "Linking $TARGET" env["ASCOMSTR"] = "Assembling $TARGET" env["ASPPCOMSTR"] = "Assembling $TARGET" env["ARCOMSTR"] = "Archiving $TARGET" env["RANLIBCOMSTR"] = "Indexing $TARGET" def GetNumCPUs(env): if env["NUMCPUS"] != "0": return int(env["NUMCPUS"]) return 2*multiprocessing.cpu_count() env.SetOption('num_jobs', GetNumCPUs(env)) def CopyTree(dst, src, env): def DirCopyHelper(src, dst): for f in os.listdir(src): srcPath = os.path.join(src, f) dstPath = os.path.join(dst, f) if f.startswith("."): # Ignore hidden files pass elif os.path.isdir(srcPath): if not os.path.exists(dstPath): os.makedirs(dstPath) DirCopyHelper(srcPath, dstPath) else: env.Command(dstPath, srcPath, Copy("$TARGET", "$SOURCE")) if (not os.path.exists(dst)): os.makedirs(dst) DirCopyHelper(src, dst) # XXX: Hack to support clang static analyzer def CheckFailed(): if os.getenv('CCC_ANALYZER_OUTPUT_FORMAT') != None: return Exit(1) # Configuration conf = env.Configure() if not conf.CheckCC(): print('Your C compiler and/or environment is incorrectly configured.') CheckFailed() if not conf.CheckCXX(): print('Your C++ compiler and/or environment is incorrectly configured.') CheckFailed() conf.Finish() Export('env') # Program start/end env["CRTBEGIN"] = [ "#build/lib/libc/crti.o", "#build/lib/libc/crt1.o" ] env["CRTEND"] = [ "#build/lib/libc/crtn.o" ] # Debugging Tools # Create include tree CopyTree('build/include', 'include', env) CopyTree('build/include/sys', 'sys/include', env) CopyTree('build/include/machine', 'sys/' + env['ARCH'] + '/include', env) #CopyTree('build/include/', 'lib/liblwip/src/include', env) # Build Targets SConscript('sys/SConscript', variant_dir='build/sys') SConscript('lib/libc/SConscript', variant_dir='build/lib/libc') #SConscript('lib/liblwip/SConscript', variant_dir='build/lib/liblwip') SConscript('bin/cat/SConscript', variant_dir='build/bin/cat') SConscript('bin/date/SConscript', variant_dir='build/bin/date') SConscript('bin/ethdump/SConscript', variant_dir='build/bin/ethdump') SConscript('bin/ethinject/SConscript', variant_dir='build/bin/ethinject') SConscript('bin/ls/SConscript', variant_dir='build/bin/ls') SConscript('bin/shell/SConscript', variant_dir='build/bin/shell') SConscript('sbin/ifconfig/SConscript', variant_dir='build/sbin/ifconfig') SConscript('sbin/init/SConscript', variant_dir='build/sbin/init') SConscript('sbin/sysctl/SConscript', variant_dir='build/sbin/sysctl') SConscript('tests/SConscript', variant_dir='build/tests') # Build Tools env["TOOLCHAINBUILD"] = "TRUE" env["CC"] = "cc" env["CXX"] = "c++" env["LINK"] = "cc" SConscript('sbin/newfs_o2fs/SConscript', variant_dir='build/tools/newfs_o2fs') # Install Targets env.Install('$PREFIX/','build/sys/castor') env.Alias('install','$PREFIX') # Boot Disk Target if env["BOOTDISK"] == "1": newfs = Builder(action = 'build/tools/newfs_o2fs/newfs_o2fs -s $BOOTDISK_SIZE -m $SOURCE $TARGET') env.Append(BUILDERS = {'BuildImage' : newfs}) bootdisk = env.BuildImage('#build/bootdisk.img', '#release/bootdisk.manifest') Depends(bootdisk, "#build/tools/newfs_o2fs/newfs_o2fs") Depends(bootdisk, "#build/bin/cat/cat") Depends(bootdisk, "#build/bin/date/date") Depends(bootdisk, "#build/bin/ethdump/ethdump") Depends(bootdisk, "#build/bin/ethinject/ethinject") Depends(bootdisk, "#build/bin/ls/ls") Depends(bootdisk, "#build/bin/shell/shell") Depends(bootdisk, "#build/sbin/ifconfig/ifconfig") Depends(bootdisk, "#build/sbin/init/init") Depends(bootdisk, "#build/sbin/sysctl/sysctl") Depends(bootdisk, "#build/sys/castor") #Depends(bootdisk, "#build/tests/lwiptest") Depends(bootdisk, "#build/tests/pthreadtest") Depends(bootdisk, "#build/tests/threadtest") env.Alias('bootdisk', '#build/bootdisk.img') env.Install('$PREFIX/','#build/bootdisk.img')