├── results └── .gitignore ├── graphs ├── pdfs │ └── .gitignore └── graph-style.R ├── waf ├── .gitignore ├── scenarios ├── disabled │ └── README.md └── README.md ├── extensions └── README.md ├── .waf-tools ├── ns3.py ├── default-compiler-flags.py └── boost.py ├── README.md ├── run.py └── wscript /results/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /graphs/pdfs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | 4 | -------------------------------------------------------------------------------- /waf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/named-data-ndnSIM/scenario-template/HEAD/waf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .waf-1* 2 | .waf3-1* 3 | .waf-2* 4 | .waf3-2* 5 | .DS* 6 | .lock* 7 | build/ 8 | *.pyc 9 | -------------------------------------------------------------------------------- /scenarios/disabled/README.md: -------------------------------------------------------------------------------- 1 | If you do not want (temporarily) some scenario to be automatically compiled, place it in this folder and it will be ignored during build phase. 2 | 3 | -------------------------------------------------------------------------------- /extensions/README.md: -------------------------------------------------------------------------------- 1 | In this directory you can put any .cc file you want to be compiled and linked to your scenarios. 2 | 3 | This mainly useful for custom extension of ndnSIM and NS-3. 4 | 5 | -------------------------------------------------------------------------------- /scenarios/README.md: -------------------------------------------------------------------------------- 1 | Each .cc file in this directory will be treated as a separate scenario 2 | (i.e., each .cc should contain their own main function). Each scenario will 3 | be linked together with all extensions, placed in ../extensions/ folder. 4 | 5 | -------------------------------------------------------------------------------- /.waf-tools/ns3.py: -------------------------------------------------------------------------------- 1 | ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | ''' 3 | 4 | When using this tool, the wscript will look like: 5 | 6 | def options(opt): 7 | opt.tool_options('ns3') 8 | 9 | def configure(conf): 10 | conf.load('compiler_cxx ns3') 11 | 12 | conf.check_ns3_modules() 13 | 14 | def build(bld): 15 | bld(source='main.cpp', target='app', use='CCNX') 16 | 17 | Options are generated, in order to specify the location of ccnx includes/libraries. 18 | 19 | 20 | ''' 21 | 22 | import waflib 23 | from waflib.Configure import conf 24 | from waflib import Utils,Logs,Errors 25 | 26 | @conf 27 | def _check_dependencies(conf, modules, mandatory): 28 | # Logs.pprint ('CYAN', ' + %s' % modules) 29 | found = [] 30 | 31 | libversion = "optimized" 32 | if conf.options.debug: 33 | libversion = "debug" 34 | 35 | if not isinstance(modules, list): 36 | modules = Utils.to_list (modules) 37 | 38 | for module in modules: 39 | retval = conf.check_cfg(package = 'libns3-dev-%s-%s' % (module, libversion), 40 | args='--cflags --libs', mandatory=mandatory, 41 | msg="Checking for ns3-%s" % module, 42 | uselib_store='NS3_%s' % module.upper()) 43 | 44 | if not retval is None: 45 | found.append(module) 46 | import copy 47 | if not 'NS3_MODULES_FOUND' in conf.env: 48 | conf.env['NS3_MODULES_FOUND'] = [] 49 | conf.env['NS3_MODULES_FOUND'] = conf.env['NS3_MODULES_FOUND'] + copy.copy(found) 50 | 51 | @conf 52 | def check_ns3_modules(conf, modules, mandatory = True): 53 | import os 54 | 55 | if not 'NS3_CHECK_MODULE_ONCE' in conf.env: 56 | conf.env['NS3_CHECK_MODULE_ONCE'] = '' 57 | 58 | conf.check_cfg(atleast_pkgconfig_version='0.0.0') 59 | 60 | if conf.options.debug: 61 | conf.env.append_value('DEFINES', 'NS3_LOG_ENABLE') 62 | 63 | conf._check_dependencies(modules, mandatory) 64 | 65 | -------------------------------------------------------------------------------- /graphs/graph-style.R: -------------------------------------------------------------------------------- 1 | library(grid) 2 | 3 | theme_custom <- function (base_size = 10, base_family = "serif") { 4 | theme_grey(base_size = base_size, base_family = base_family) %+replace% 5 | theme( 6 | line = element_line(colour = "black", size = 0.5, linetype = 1, lineend = "butt"), 7 | rect = element_rect(fill = "white", colour = "black", size = 0.5, linetype = 1), 8 | text = element_text(family = base_family, face = "plain", colour = "black", size = base_size, hjust = 0.5, vjust = 0.5, angle = 0, lineheight = 0.9), 9 | axis.text = element_text(size = rel(0.8), colour = "grey50"), 10 | strip.text = element_text(size = rel(0.8)), 11 | 12 | axis.line = element_blank(), 13 | axis.text.x = element_text(family = base_family, size = base_size * 0.7, lineheight = 0.8, vjust = 1.2), 14 | axis.text.y = element_text(family = base_family, size = base_size * 0.7, lineheight = 0.8, hjust = 1.2), 15 | axis.ticks = element_line(colour = "black", size=0.2), 16 | axis.title.x = element_text(family = base_family, size = base_size, vjust = 0.5), 17 | axis.title.y = element_text(family = base_family, size = base_size, angle = 90, vjust = 0.5), 18 | axis.ticks.length = unit(0.15, "cm"), 19 | axis.ticks.margin = unit(0.1, "cm"), 20 | 21 | legend.background = element_rect (fill=NA, colour=NA, size=0.1), 22 | legend.margin = unit(0.2, "cm"), 23 | legend.key = element_rect(fill = "grey95", colour = "white"), 24 | legend.key.size = unit(1.2, "lines"), 25 | legend.key.height = NULL, 26 | legend.key.width = NULL, 27 | legend.text = element_text(family = base_family, size = base_size * 0.8), 28 | legend.text.align = NULL, 29 | legend.title = element_text(family = base_family, size = base_size * 0.8, face = "bold", hjust = 1), 30 | legend.title.align = NULL, 31 | legend.position = "right", 32 | legend.direction = NULL, 33 | legend.justification = "center", 34 | legend.box = NULL, 35 | 36 | panel.background = element_rect(fill = "white", colour = NA), 37 | panel.border = element_rect(fill = NA, colour = "grey50"), 38 | panel.grid.major = element_line(colour = "grey60", size = 0.1), 39 | panel.grid.minor = element_line(colour = "grey70", size = 0.1, linetype="dotted"), 40 | ## panel.margin = unit(c(0.1, 0.1, 0.1, 0.1), "lines"), 41 | 42 | strip.background = element_rect(fill = NA, colour = NA), 43 | strip.text.x = element_text(family = base_family, size = base_size * 0.8), 44 | strip.text.y = element_text(family = base_family, size = base_size * 0.8, angle = -90), 45 | 46 | plot.background = element_rect(colour = NA, fill = "white"), 47 | plot.title = element_text(family = base_family, size = base_size), 48 | plot.margin = unit(c(0, 0, 0, 0), "lines") 49 | ) 50 | } 51 | 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Prerequisites 2 | ============= 3 | 4 | Custom version of NS-3 and specified version of ndnSIM needs to be installed. 5 | 6 | The code should also work with the latest version of ndnSIM, but it is not guaranteed. 7 | 8 | mkdir ndnSIM 9 | cd ndnSIM 10 | 11 | git clone -b ndnSIM-2.5 https://github.com/named-data-ndnSIM/ns-3-dev.git ns-3 12 | git clone -b 0.18.0 https://github.com/named-data-ndnSIM/pybindgen.git pybindgen 13 | git clone -b ndnSIM-2.5 --recursive https://github.com/named-data-ndnSIM/ndnSIM ns-3/src/ndnSIM 14 | 15 | # Build and install NS-3 and ndnSIM 16 | cd ns-3 17 | ./waf configure -d optimized 18 | ./waf 19 | sudo ./waf install 20 | 21 | # When using Linux, run 22 | # sudo ldconfig 23 | 24 | # When using Freebsd, run 25 | # sudo ldconfig -a 26 | 27 | cd .. 28 | git clone https://github.com/named-data-ndnSIM/scenario-template.git my-simulations 29 | cd my-simulations 30 | 31 | ./waf configure 32 | ./waf --run scenario 33 | 34 | After which you can proceed to compile and run the code 35 | 36 | For more information how to install NS-3 and ndnSIM, please refer to http://ndnsim.net website. 37 | 38 | Compiling 39 | ========= 40 | 41 | To configure in optimized mode without logging **(default)**: 42 | 43 | ./waf configure 44 | 45 | To configure in optimized mode with scenario logging enabled (logging in NS-3 and ndnSIM modules will still be disabled, 46 | but you can see output from NS_LOG* calls from your scenarios and extensions): 47 | 48 | ./waf configure --logging 49 | 50 | To configure in debug mode with all logging enabled 51 | 52 | ./waf configure --debug 53 | 54 | If you have installed NS-3 in a non-standard location, you may need to set up ``PKG_CONFIG_PATH`` variable. 55 | 56 | Running 57 | ======= 58 | 59 | Normally, you can run scenarios either directly 60 | 61 | ./build/ 62 | 63 | or using waf 64 | 65 | ./waf --run 66 | 67 | If NS-3 is installed in a non-standard location, on some platforms (e.g., Linux) you need to specify ``LD_LIBRARY_PATH`` variable: 68 | 69 | LD_LIBRARY_PATH=/usr/local/lib ./build/ 70 | 71 | or 72 | 73 | LD_LIBRARY_PATH=/usr/local/lib ./waf --run 74 | 75 | To run scenario using debugger, use the following command: 76 | 77 | gdb --args ./build/ 78 | 79 | 80 | Running with visualizer 81 | ----------------------- 82 | 83 | There are several tricks to run scenarios in visualizer. Before you can do it, you need to set up environment variables for python to find visualizer module. The easiest way to do it using the following commands: 84 | 85 | cd ns-dev/ns-3 86 | ./waf shell 87 | 88 | After these command, you will have complete environment to run the vizualizer. 89 | 90 | The following will run scenario with visualizer: 91 | 92 | ./waf --run --vis 93 | 94 | or 95 | 96 | PKG_LIBRARY_PATH=/usr/local/lib ./waf --run --vis 97 | 98 | If you want to request automatic node placement, set up additional environment variable: 99 | 100 | NS_VIS_ASSIGN=1 ./waf --run --vis 101 | 102 | or 103 | 104 | PKG_LIBRARY_PATH=/usr/local/lib NS_VIS_ASSIGN=1 ./waf --run --vis 105 | 106 | Available simulations 107 | ===================== 108 | 109 | 110 | --------------- 111 | 112 | Description 113 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 3 | 4 | from subprocess import call 5 | from sys import argv 6 | import os 7 | import subprocess 8 | import workerpool 9 | import multiprocessing 10 | import argparse 11 | 12 | ###################################################################### 13 | ###################################################################### 14 | ###################################################################### 15 | 16 | parser = argparse.ArgumentParser(description='Simulation runner') 17 | parser.add_argument('scenarios', metavar='scenario', type=str, nargs='*', 18 | help='Scenario to run') 19 | 20 | parser.add_argument('-l', '--list', dest="list", action='store_true', default=False, 21 | help='Get list of available scenarios') 22 | 23 | parser.add_argument('-s', '--simulate', dest="simulate", action='store_true', default=False, 24 | help='Run simulation and postprocessing (false by default)') 25 | 26 | parser.add_argument('-g', '--no-graph', dest="graph", action='store_false', default=True, 27 | help='Do not build a graph for the scenario (builds a graph by default)') 28 | 29 | args = parser.parse_args() 30 | 31 | if not args.list and len(args.scenarios)==0: 32 | print "ERROR: at least one scenario need to be specified" 33 | parser.print_help() 34 | exit (1) 35 | 36 | if args.list: 37 | print "Available scenarios: " 38 | else: 39 | if args.simulate: 40 | print "Simulating the following scenarios: " + ",".join (args.scenarios) 41 | 42 | if args.graph: 43 | print "Building graphs for the following scenarios: " + ",".join (args.scenarios) 44 | 45 | ###################################################################### 46 | ###################################################################### 47 | ###################################################################### 48 | 49 | class SimulationJob (workerpool.Job): 50 | "Job to simulate things" 51 | def __init__ (self, cmdline): 52 | self.cmdline = cmdline 53 | def run (self): 54 | print (" ".join (self.cmdline)) 55 | subprocess.call (self.cmdline) 56 | 57 | pool = workerpool.WorkerPool(size = multiprocessing.cpu_count()) 58 | 59 | class Processor: 60 | def run (self): 61 | if args.list: 62 | print " " + self.name 63 | return 64 | 65 | if "all" not in args.scenarios and self.name not in args.scenarios: 66 | return 67 | 68 | if args.list: 69 | pass 70 | else: 71 | if args.simulate: 72 | self.simulate () 73 | pool.join () 74 | self.postprocess () 75 | if args.graph: 76 | self.graph () 77 | 78 | def graph (self): 79 | subprocess.call ("./graphs/%s.R" % self.name, shell=True) 80 | 81 | class Scenario (Processor): 82 | def __init__ (self, name): 83 | self.name = name 84 | # other initialization, if any 85 | 86 | def simulate (self): 87 | cmdline = ["./build/SCENARIO_TO_RUN"] 88 | job = SimulationJob (cmdline) 89 | pool.put (job) 90 | 91 | def postprocess (self): 92 | # any postprocessing, if any 93 | pass 94 | 95 | try: 96 | # Simulation, processing, and graph building 97 | fig = Scenario (name="NAME_TO_CONFIGURE") 98 | fig.run () 99 | 100 | finally: 101 | pool.join () 102 | pool.shutdown () 103 | -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | VERSION='0.1' 4 | APPNAME='template' 5 | 6 | from waflib import Build, Logs, Options, TaskGen 7 | import subprocess 8 | import os 9 | 10 | def options(opt): 11 | opt.load(['compiler_c', 'compiler_cxx']) 12 | opt.load(['default-compiler-flags', 13 | 'boost', 'ns3'], 14 | tooldir=['.waf-tools']) 15 | 16 | opt.add_option('--logging',action='store_true',default=True,dest='logging',help='''enable logging in simulation scripts''') 17 | opt.add_option('--run', 18 | help=('Run a locally built program; argument can be a program name,' 19 | ' or a command starting with the program name.'), 20 | type="string", default='', dest='run') 21 | opt.add_option('--visualize', 22 | help=('Modify --run arguments to enable the visualizer'), 23 | action="store_true", default=False, dest='visualize') 24 | opt.add_option('--mpi', 25 | help=('Run in MPI mode'), 26 | type="string", default="", dest="mpi") 27 | opt.add_option('--time', 28 | help=('Enable time for the executed command'), 29 | action="store_true", default=False, dest='time') 30 | 31 | MANDATORY_NS3_MODULES = ['core', 'network', 'point-to-point', 'applications', 'mobility', 'ndnSIM'] 32 | OTHER_NS3_MODULES = ['antenna', 'aodv', 'bridge', 'brite', 'buildings', 'click', 'config-store', 'csma', 'csma-layout', 'dsdv', 'dsr', 'emu', 'energy', 'fd-net-device', 'flow-monitor', 'internet', 'lte', 'mesh', 'mpi', 'netanim', 'nix-vector-routing', 'olsr', 'openflow', 'point-to-point-layout', 'propagation', 'spectrum', 'stats', 'tap-bridge', 'topology-read', 'uan', 'virtual-net-device', 'visualizer', 'wifi', 'wimax'] 33 | 34 | def configure(conf): 35 | conf.load(['compiler_c', 'compiler_cxx', 36 | 'default-compiler-flags', 37 | 'boost', 'ns3']) 38 | 39 | if not os.environ.has_key('PKG_CONFIG_PATH'): 40 | os.environ['PKG_CONFIG_PATH'] = ':'.join([ 41 | '/usr/local/lib/pkgconfig', 42 | '/opt/local/lib/pkgconfig']) 43 | 44 | try: 45 | conf.check_ns3_modules(MANDATORY_NS3_MODULES) 46 | for module in OTHER_NS3_MODULES: 47 | conf.check_ns3_modules(module, mandatory = False) 48 | except: 49 | Logs.error ("NS-3 or one of the required NS-3 modules not found") 50 | Logs.error ("NS-3 needs to be compiled and installed somewhere. You may need also to set PKG_CONFIG_PATH variable in order for configure find installed NS-3.") 51 | Logs.error ("For example:") 52 | Logs.error (" PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH ./waf configure") 53 | conf.fatal ("") 54 | 55 | if conf.options.debug: 56 | conf.define ('NS3_LOG_ENABLE', 1) 57 | conf.define ('NS3_ASSERT_ENABLE', 1) 58 | 59 | if conf.env.DEST_BINFMT == 'elf': 60 | # All ELF platforms are impacted but only the gcc compiler has a flag to fix it. 61 | if 'gcc' in (conf.env.CXX_NAME, conf.env.CC_NAME): 62 | conf.env.append_value('SHLIB_MARKER', '-Wl,--no-as-needed') 63 | 64 | conf.check_compiler_flags() 65 | 66 | if conf.options.logging: 67 | conf.define('NS3_LOG_ENABLE', 1) 68 | conf.define('NS3_ASSERT_ENABLE', 1) 69 | 70 | def build (bld): 71 | deps = ' '.join (['ns3_'+dep for dep in MANDATORY_NS3_MODULES + OTHER_NS3_MODULES]).upper () 72 | 73 | common = bld.objects ( 74 | target = "extensions", 75 | features = ["cxx"], 76 | source = bld.path.ant_glob(['extensions/**/*.cc', 'extensions/**/*.cpp']), 77 | use = deps, 78 | ) 79 | 80 | for scenario in bld.path.ant_glob(['scenarios/*.cc', 'scenarios/*.cpp']): 81 | name = scenario.change_ext('').path_from(bld.path.find_node('scenarios/').get_bld()) 82 | app = bld.program ( 83 | target = name, 84 | features = ['cxx'], 85 | source = [scenario], 86 | use = deps + " extensions", 87 | includes = "extensions" 88 | ) 89 | 90 | def shutdown (ctx): 91 | if Options.options.run: 92 | visualize=Options.options.visualize 93 | mpi = Options.options.mpi 94 | 95 | if mpi and visualize: 96 | Logs.error ("You cannot specify --mpi and --visualize options at the same time!!!") 97 | return 98 | 99 | argv = Options.options.run.split (' '); 100 | argv[0] = "build/%s" % argv[0] 101 | 102 | if visualize: 103 | argv.append ("--SimulatorImplementationType=ns3::VisualSimulatorImpl") 104 | 105 | if mpi: 106 | argv.append ("--SimulatorImplementationType=ns3::DistributedSimulatorImpl") 107 | argv.append ("--mpi=1") 108 | argv = ["openmpirun", "-np", mpi] + argv 109 | Logs.error (argv) 110 | 111 | if Options.options.time: 112 | argv = ["time"] + argv 113 | 114 | return subprocess.call (argv) 115 | -------------------------------------------------------------------------------- /.waf-tools/default-compiler-flags.py: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | from waflib import Configure, Logs, Utils 4 | 5 | def options(opt): 6 | opt.add_option('--debug', '--with-debug', action='store_true', default=False, 7 | help='Compile in debugging mode with minimal optimizations (-O0 or -Og)') 8 | 9 | def configure(conf): 10 | conf.start_msg('Checking C++ compiler version') 11 | 12 | cxx = conf.env.CXX_NAME # generic name of the compiler 13 | ccver = tuple(int(i) for i in conf.env.CC_VERSION) 14 | ccverstr = '.'.join(conf.env.CC_VERSION) 15 | errmsg = '' 16 | warnmsg = '' 17 | if cxx == 'gcc': 18 | if ccver < (5, 3, 0): 19 | errmsg = ('The version of gcc you are using is too old.\n' 20 | 'The minimum supported gcc version is 5.3.0.') 21 | conf.flags = GccFlags() 22 | elif cxx == 'clang': 23 | if ccver < (3, 6, 0): 24 | errmsg = ('The version of clang you are using is too old.\n' 25 | 'The minimum supported clang version is 3.6.0.') 26 | conf.flags = ClangFlags() 27 | else: 28 | warnmsg = 'Note: %s compiler is unsupported' % cxx 29 | conf.flags = CompilerFlags() 30 | 31 | if errmsg: 32 | conf.end_msg(ccverstr, color='RED') 33 | conf.fatal(errmsg) 34 | elif warnmsg: 35 | conf.end_msg(ccverstr, color='YELLOW') 36 | Logs.warn(warnmsg) 37 | else: 38 | conf.end_msg(ccverstr) 39 | 40 | conf.areCustomCxxflagsPresent = (len(conf.env.CXXFLAGS) > 0) 41 | 42 | # General flags are always applied (e.g., selecting C++ language standard) 43 | generalFlags = conf.flags.getGeneralFlags(conf) 44 | conf.add_supported_cxxflags(generalFlags['CXXFLAGS']) 45 | conf.add_supported_linkflags(generalFlags['LINKFLAGS']) 46 | conf.env.DEFINES += generalFlags['DEFINES'] 47 | 48 | @Configure.conf 49 | def check_compiler_flags(conf): 50 | # Debug or optimized CXXFLAGS and LINKFLAGS are applied only if the 51 | # corresponding environment variables are not set. 52 | # DEFINES are always applied. 53 | if conf.options.debug: 54 | extraFlags = conf.flags.getDebugFlags(conf) 55 | if conf.areCustomCxxflagsPresent: 56 | missingFlags = [x for x in extraFlags['CXXFLAGS'] if x not in conf.env.CXXFLAGS] 57 | if missingFlags: 58 | Logs.warn('Selected debug mode, but CXXFLAGS is set to a custom value "%s"' 59 | % ' '.join(conf.env.CXXFLAGS)) 60 | Logs.warn('Default flags "%s" will not be used' % ' '.join(missingFlags)) 61 | else: 62 | extraFlags = conf.flags.getOptimizedFlags(conf) 63 | 64 | if not conf.areCustomCxxflagsPresent: 65 | conf.add_supported_cxxflags(extraFlags['CXXFLAGS']) 66 | conf.add_supported_linkflags(extraFlags['LINKFLAGS']) 67 | 68 | conf.env.DEFINES += extraFlags['DEFINES'] 69 | 70 | @Configure.conf 71 | def add_supported_cxxflags(self, cxxflags): 72 | """ 73 | Check which cxxflags are supported by compiler and add them to env.CXXFLAGS variable 74 | """ 75 | if len(cxxflags) == 0: 76 | return 77 | 78 | self.start_msg('Checking supported CXXFLAGS') 79 | 80 | supportedFlags = [] 81 | for flags in cxxflags: 82 | flags = Utils.to_list(flags) 83 | if self.check_cxx(cxxflags=['-Werror'] + flags, mandatory=False): 84 | supportedFlags += flags 85 | 86 | self.end_msg(' '.join(supportedFlags)) 87 | self.env.prepend_value('CXXFLAGS', supportedFlags) 88 | 89 | @Configure.conf 90 | def add_supported_linkflags(self, linkflags): 91 | """ 92 | Check which linkflags are supported by compiler and add them to env.LINKFLAGS variable 93 | """ 94 | if len(linkflags) == 0: 95 | return 96 | 97 | self.start_msg('Checking supported LINKFLAGS') 98 | 99 | supportedFlags = [] 100 | for flags in linkflags: 101 | flags = Utils.to_list(flags) 102 | if self.check_cxx(linkflags=['-Werror'] + flags, mandatory=False): 103 | supportedFlags += flags 104 | 105 | self.end_msg(' '.join(supportedFlags)) 106 | self.env.prepend_value('LINKFLAGS', supportedFlags) 107 | 108 | 109 | class CompilerFlags(object): 110 | def getCompilerVersion(self, conf): 111 | return tuple(int(i) for i in conf.env.CC_VERSION) 112 | 113 | def getGeneralFlags(self, conf): 114 | """Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are always needed""" 115 | return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': []} 116 | 117 | def getDebugFlags(self, conf): 118 | """Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in debug mode""" 119 | return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['_DEBUG']} 120 | 121 | def getOptimizedFlags(self, conf): 122 | """Get dict of CXXFLAGS, LINKFLAGS, and DEFINES that are needed only in optimized mode""" 123 | return {'CXXFLAGS': [], 'LINKFLAGS': [], 'DEFINES': ['NDEBUG']} 124 | 125 | class GccBasicFlags(CompilerFlags): 126 | """ 127 | This class defines basic flags that work for both gcc and clang compilers 128 | """ 129 | def getGeneralFlags(self, conf): 130 | flags = super(GccBasicFlags, self).getGeneralFlags(conf) 131 | flags['CXXFLAGS'] += ['-std=c++14'] 132 | if Utils.unversioned_sys_platform() == 'linux': 133 | flags['LINKFLAGS'] += ['-fuse-ld=gold'] 134 | elif Utils.unversioned_sys_platform() == 'freebsd': 135 | flags['LINKFLAGS'] += ['-fuse-ld=lld'] 136 | return flags 137 | 138 | def getDebugFlags(self, conf): 139 | flags = super(GccBasicFlags, self).getDebugFlags(conf) 140 | flags['CXXFLAGS'] += ['-O0', 141 | '-Og', # gcc >= 4.8, clang >= 4.0 142 | '-g3', 143 | '-pedantic', 144 | '-Wall', 145 | '-Wextra', 146 | # '-Werror', 147 | '-Wnon-virtual-dtor', 148 | '-Wno-error=deprecated-declarations', # Bug #3795 149 | '-Wno-error=maybe-uninitialized', # Bug #1615 150 | '-Wno-unused-parameter', 151 | ] 152 | flags['LINKFLAGS'] += ['-Wl,-O1'] 153 | return flags 154 | 155 | def getOptimizedFlags(self, conf): 156 | flags = super(GccBasicFlags, self).getOptimizedFlags(conf) 157 | flags['CXXFLAGS'] += ['-O2', 158 | '-g', 159 | '-pedantic', 160 | '-Wall', 161 | '-Wextra', 162 | '-Wnon-virtual-dtor', 163 | '-Wno-unused-parameter', 164 | ] 165 | flags['LINKFLAGS'] += ['-Wl,-O1'] 166 | return flags 167 | 168 | class GccFlags(GccBasicFlags): 169 | def getDebugFlags(self, conf): 170 | flags = super(GccFlags, self).getDebugFlags(conf) 171 | flags['CXXFLAGS'] += ['-fdiagnostics-color'] 172 | return flags 173 | 174 | def getOptimizedFlags(self, conf): 175 | flags = super(GccFlags, self).getOptimizedFlags(conf) 176 | flags['CXXFLAGS'] += ['-fdiagnostics-color'] 177 | return flags 178 | 179 | class ClangFlags(GccBasicFlags): 180 | def getGeneralFlags(self, conf): 181 | flags = super(ClangFlags, self).getGeneralFlags(conf) 182 | if Utils.unversioned_sys_platform() == 'darwin' and self.getCompilerVersion(conf) >= (9, 0, 0): 183 | # Bug #4296 184 | flags['CXXFLAGS'] += [['-isystem', '/usr/local/include'], # for Homebrew 185 | ['-isystem', '/opt/local/include']] # for MacPorts 186 | if Utils.unversioned_sys_platform() == 'freebsd': 187 | flags['CXXFLAGS'] += [['-isystem', '/usr/local/include']] # Bug #4790 188 | return flags 189 | 190 | def getDebugFlags(self, conf): 191 | flags = super(ClangFlags, self).getDebugFlags(conf) 192 | flags['CXXFLAGS'] += ['-fcolor-diagnostics', 193 | '-Wextra-semi', 194 | '-Wundefined-func-template', 195 | '-Wno-unused-local-typedef', # Bugs #2657 and #3209 196 | ] 197 | version = self.getCompilerVersion(conf) 198 | if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)): 199 | flags['CXXFLAGS'] += ['-Wno-unknown-pragmas'] 200 | if version < (6, 0, 0): 201 | flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721 202 | return flags 203 | 204 | def getOptimizedFlags(self, conf): 205 | flags = super(ClangFlags, self).getOptimizedFlags(conf) 206 | flags['CXXFLAGS'] += ['-fcolor-diagnostics', 207 | '-Wextra-semi', 208 | '-Wundefined-func-template', 209 | '-Wno-unused-local-typedef', # Bugs #2657 and #3209 210 | ] 211 | version = self.getCompilerVersion(conf) 212 | if version < (3, 9, 0) or (Utils.unversioned_sys_platform() == 'darwin' and version < (8, 1, 0)): 213 | flags['CXXFLAGS'] += ['-Wno-unknown-pragmas'] 214 | if version < (6, 0, 0): 215 | flags['CXXFLAGS'] += ['-Wno-missing-braces'] # Bug #4721 216 | return flags 217 | -------------------------------------------------------------------------------- /.waf-tools/boost.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | # 4 | # partially based on boost.py written by Gernot Vormayr 5 | # written by Ruediger Sonderfeld , 2008 6 | # modified by Bjoern Michaelsen, 2008 7 | # modified by Luca Fossati, 2008 8 | # rewritten for waf 1.5.1, Thomas Nagy, 2008 9 | # rewritten for waf 1.6.2, Sylvain Rouquette, 2011 10 | 11 | ''' 12 | 13 | This is an extra tool, not bundled with the default waf binary. 14 | To add the boost tool to the waf file: 15 | $ ./waf-light --tools=compat15,boost 16 | or, if you have waf >= 1.6.2 17 | $ ./waf update --files=boost 18 | 19 | When using this tool, the wscript will look like: 20 | 21 | def options(opt): 22 | opt.load('compiler_cxx boost') 23 | 24 | def configure(conf): 25 | conf.load('compiler_cxx boost') 26 | conf.check_boost(lib='system filesystem') 27 | 28 | def build(bld): 29 | bld(source='main.cpp', target='app', use='BOOST') 30 | 31 | Options are generated, in order to specify the location of boost includes/libraries. 32 | The `check_boost` configuration function allows to specify the used boost libraries. 33 | It can also provide default arguments to the --boost-mt command-line arguments. 34 | Everything will be packaged together in a BOOST component that you can use. 35 | 36 | When using MSVC, a lot of compilation flags need to match your BOOST build configuration: 37 | - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined. 38 | Errors: C4530 39 | - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC 40 | So before calling `conf.check_boost` you might want to disabling by adding 41 | conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB'] 42 | Errors: 43 | - boost might also be compiled with /MT, which links the runtime statically. 44 | If you have problems with redefined symbols, 45 | self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] 46 | self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc'] 47 | Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases. 48 | 49 | ''' 50 | 51 | import sys 52 | import re 53 | from waflib import Utils, Logs, Errors 54 | from waflib.Configure import conf 55 | from waflib.TaskGen import feature, after_method 56 | 57 | BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] 58 | BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] 59 | 60 | BOOST_VERSION_FILE = 'boost/version.hpp' 61 | BOOST_VERSION_CODE = ''' 62 | #include 63 | #include 64 | int main() { std::cout << BOOST_LIB_VERSION << ":" << BOOST_VERSION << std::endl; } 65 | ''' 66 | 67 | BOOST_ERROR_CODE = ''' 68 | #include 69 | int main() { boost::system::error_code c; } 70 | ''' 71 | 72 | PTHREAD_CODE = ''' 73 | #include 74 | static void* f(void*) { return 0; } 75 | int main() { 76 | pthread_t th; 77 | pthread_attr_t attr; 78 | pthread_attr_init(&attr); 79 | pthread_create(&th, &attr, &f, 0); 80 | pthread_join(th, 0); 81 | pthread_cleanup_push(0, 0); 82 | pthread_cleanup_pop(0); 83 | pthread_attr_destroy(&attr); 84 | } 85 | ''' 86 | 87 | BOOST_THREAD_CODE = ''' 88 | #include 89 | int main() { boost::thread t; } 90 | ''' 91 | 92 | BOOST_LOG_CODE = ''' 93 | #include 94 | int main() { BOOST_LOG_TRIVIAL(info) << "boost_log is working"; } 95 | ''' 96 | 97 | BOOST_LOG_SETUP_CODE = ''' 98 | #include 99 | #include 100 | #include 101 | int main() { 102 | using namespace boost::log; 103 | add_common_attributes(); 104 | add_console_log(std::clog, keywords::format = "%Message%"); 105 | BOOST_LOG_TRIVIAL(info) << "boost_log_setup is working"; 106 | } 107 | ''' 108 | 109 | # toolsets from {boost_dir}/tools/build/v2/tools/common.jam 110 | PLATFORM = Utils.unversioned_sys_platform() 111 | detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il' 112 | detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang' 113 | detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc' 114 | BOOST_TOOLSETS = { 115 | 'borland': 'bcb', 116 | 'clang': detect_clang, 117 | 'como': 'como', 118 | 'cw': 'cw', 119 | 'darwin': 'xgcc', 120 | 'edg': 'edg', 121 | 'g++': detect_mingw, 122 | 'gcc': detect_mingw, 123 | 'icpc': detect_intel, 124 | 'intel': detect_intel, 125 | 'kcc': 'kcc', 126 | 'kylix': 'bck', 127 | 'mipspro': 'mp', 128 | 'mingw': 'mgw', 129 | 'msvc': 'vc', 130 | 'qcc': 'qcc', 131 | 'sun': 'sw', 132 | 'sunc++': 'sw', 133 | 'tru64cxx': 'tru', 134 | 'vacpp': 'xlc' 135 | } 136 | 137 | 138 | def options(opt): 139 | opt = opt.add_option_group('Boost Options') 140 | opt.add_option('--boost-includes', type='string', 141 | default='', dest='boost_includes', 142 | help='''path to the directory where the boost includes are, 143 | e.g., /path/to/boost_1_55_0/stage/include''') 144 | opt.add_option('--boost-libs', type='string', 145 | default='', dest='boost_libs', 146 | help='''path to the directory where the boost libs are, 147 | e.g., path/to/boost_1_55_0/stage/lib''') 148 | opt.add_option('--boost-mt', action='store_true', 149 | default=False, dest='boost_mt', 150 | help='select multi-threaded libraries') 151 | opt.add_option('--boost-abi', type='string', default='', dest='boost_abi', 152 | help='''select libraries with tags (gd for debug, static is automatically added), 153 | see doc Boost, Getting Started, chapter 6.1''') 154 | opt.add_option('--boost-linkage_autodetect', action='store_true', dest='boost_linkage_autodetect', 155 | help="auto-detect boost linkage options (don't get used to it / might break other stuff)") 156 | opt.add_option('--boost-toolset', type='string', 157 | default='', dest='boost_toolset', 158 | help='force a toolset e.g. msvc, vc90, \ 159 | gcc, mingw, mgw45 (default: auto)') 160 | py_version = '%d%d' % (sys.version_info[0], sys.version_info[1]) 161 | opt.add_option('--boost-python', type='string', 162 | default=py_version, dest='boost_python', 163 | help='select the lib python with this version \ 164 | (default: %s)' % py_version) 165 | 166 | 167 | @conf 168 | def __boost_get_version_file(self, d): 169 | if not d: 170 | return None 171 | dnode = self.root.find_dir(d) 172 | if dnode: 173 | return dnode.find_node(BOOST_VERSION_FILE) 174 | return None 175 | 176 | @conf 177 | def boost_get_version(self, d): 178 | """silently retrieve the boost version number""" 179 | node = self.__boost_get_version_file(d) 180 | if node: 181 | try: 182 | txt = node.read() 183 | except EnvironmentError: 184 | Logs.error('Could not read the file %r' % node.abspath()) 185 | else: 186 | re_but1 = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.+)"', re.M) 187 | m1 = re_but1.search(txt) 188 | re_but2 = re.compile('^#define\\s+BOOST_VERSION\\s+(\\d+)', re.M) 189 | m2 = re_but2.search(txt) 190 | if m1 and m2: 191 | return (m1.group(1), m2.group(1)) 192 | return self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[d], execute=True, define_ret=True).split(':') 193 | 194 | @conf 195 | def boost_get_includes(self, *k, **kw): 196 | includes = k and k[0] or kw.get('includes', None) 197 | if includes and self.__boost_get_version_file(includes): 198 | return includes 199 | for d in self.environ.get('INCLUDE', '').split(';') + BOOST_INCLUDES: 200 | if self.__boost_get_version_file(d): 201 | return d 202 | if includes: 203 | self.end_msg('headers not found in %s' % includes, 'YELLOW') 204 | self.fatal('The configuration failed') 205 | else: 206 | self.end_msg('headers not found, please provide a --boost-includes argument (see help)', 'YELLOW') 207 | self.fatal('The configuration failed') 208 | 209 | 210 | @conf 211 | def boost_get_toolset(self, cc): 212 | toolset = cc 213 | if not cc: 214 | build_platform = Utils.unversioned_sys_platform() 215 | if build_platform in BOOST_TOOLSETS: 216 | cc = build_platform 217 | else: 218 | cc = self.env.CXX_NAME 219 | if cc in BOOST_TOOLSETS: 220 | toolset = BOOST_TOOLSETS[cc] 221 | return isinstance(toolset, str) and toolset or toolset(self.env) 222 | 223 | 224 | @conf 225 | def __boost_get_libs_path(self, *k, **kw): 226 | ''' return the lib path and all the files in it ''' 227 | if 'files' in kw: 228 | return self.root.find_dir('.'), Utils.to_list(kw['files']) 229 | libs = k and k[0] or kw.get('libs', None) 230 | if libs: 231 | path = self.root.find_dir(libs) 232 | files = path.ant_glob('*boost_*') 233 | if not libs or not files: 234 | for d in self.environ.get('LIB', '').split(';') + BOOST_LIBS: 235 | if not d: 236 | continue 237 | path = self.root.find_dir(d) 238 | if path: 239 | files = path.ant_glob('*boost_*') 240 | if files: 241 | break 242 | path = self.root.find_dir(d + '64') 243 | if path: 244 | files = path.ant_glob('*boost_*') 245 | if files: 246 | break 247 | if not path: 248 | if libs: 249 | self.end_msg('libs not found in %s' % libs, 'YELLOW') 250 | self.fatal('The configuration failed') 251 | else: 252 | self.end_msg('libs not found, please provide a --boost-libs argument (see help)', 'YELLOW') 253 | self.fatal('The configuration failed') 254 | 255 | self.to_log('Found the boost path in %r with the libraries:' % path) 256 | for x in files: 257 | self.to_log(' %r' % x) 258 | return path, files 259 | 260 | @conf 261 | def boost_get_libs(self, *k, **kw): 262 | ''' 263 | return the lib path and the required libs 264 | according to the parameters 265 | ''' 266 | path, files = self.__boost_get_libs_path(**kw) 267 | files = sorted(files, key=lambda f: (len(f.name), f.name), reverse=True) 268 | toolset = self.boost_get_toolset(kw.get('toolset', '')) 269 | toolset_pat = '(-%s[0-9]{0,3})' % toolset 270 | version = '-%s' % self.env.BOOST_VERSION 271 | 272 | def find_lib(re_lib, files): 273 | for file in files: 274 | if re_lib.search(file.name): 275 | self.to_log('Found boost lib %s' % file) 276 | return file 277 | return None 278 | 279 | def format_lib_name(name): 280 | if name.startswith('lib') and self.env.CC_NAME != 'msvc': 281 | name = name[3:] 282 | return name[:name.rfind('.')] 283 | 284 | def match_libs(lib_names, is_static): 285 | libs = [] 286 | lib_names = Utils.to_list(lib_names) 287 | if not lib_names: 288 | return libs 289 | t = [] 290 | if kw.get('mt', False): 291 | t.append('-mt') 292 | if kw.get('abi', None): 293 | t.append('%s%s' % (is_static and '-s' or '-', kw['abi'])) 294 | elif is_static: 295 | t.append('-s') 296 | tags_pat = t and ''.join(t) or '' 297 | ext = is_static and self.env.cxxstlib_PATTERN or self.env.cxxshlib_PATTERN 298 | ext = ext.partition('%s')[2] # remove '%s' or 'lib%s' from PATTERN 299 | 300 | for lib in lib_names: 301 | if lib == 'python': 302 | # for instance, with python='27', 303 | # accepts '-py27', '-py2', '27' and '2' 304 | # but will reject '-py3', '-py26', '26' and '3' 305 | tags = '({0})?((-py{2})|(-py{1}(?=[^0-9]))|({2})|({1}(?=[^0-9]))|(?=[^0-9])(?!-py))'.format(tags_pat, kw['python'][0], kw['python']) 306 | else: 307 | tags = tags_pat 308 | # Trying libraries, from most strict match to least one 309 | for pattern in ['boost_%s%s%s%s%s$' % (lib, toolset_pat, tags, version, ext), 310 | 'boost_%s%s%s%s$' % (lib, tags, version, ext), 311 | # Give up trying to find the right version 312 | 'boost_%s%s%s%s$' % (lib, toolset_pat, tags, ext), 313 | 'boost_%s%s%s$' % (lib, tags, ext), 314 | 'boost_%s%s$' % (lib, ext), 315 | 'boost_%s' % lib]: 316 | self.to_log('Trying pattern %s' % pattern) 317 | file = find_lib(re.compile(pattern), files) 318 | if file: 319 | libs.append(format_lib_name(file.name)) 320 | break 321 | else: 322 | self.end_msg('lib %s not found in %s' % (lib, path.abspath()), 'YELLOW') 323 | self.fatal('The configuration failed') 324 | return libs 325 | 326 | return path.abspath(), match_libs(kw.get('lib', None), False), match_libs(kw.get('stlib', None), True) 327 | 328 | @conf 329 | def _check_pthread_flag(self, *k, **kw): 330 | ''' 331 | Computes which flags should be added to CXXFLAGS and LINKFLAGS to compile in multi-threading mode 332 | 333 | Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, 334 | boost/thread.hpp will trigger a #error if -pthread isn't used: 335 | boost/config/requires_threads.hpp:47:5: #error "Compiler threading support 336 | is not turned on. Please set the correct command line options for 337 | threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" 338 | 339 | Based on _BOOST_PTHREAD_FLAG(): https://github.com/tsuna/boost.m4/blob/master/build-aux/boost.m4 340 | ''' 341 | 342 | var = kw.get('uselib_store', 'BOOST') 343 | 344 | self.start_msg('Checking the flags needed to use pthreads') 345 | 346 | # The ordering *is* (sometimes) important. Some notes on the 347 | # individual items follow: 348 | # (none): in case threads are in libc; should be tried before -Kthread and 349 | # other compiler flags to prevent continual compiler warnings 350 | # -lpthreads: AIX (must check this before -lpthread) 351 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) 352 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) 353 | # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) 354 | # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) 355 | # -pthreads: Solaris/GCC 356 | # -mthreads: MinGW32/GCC, Lynx/GCC 357 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it 358 | # doesn't hurt to check since this sometimes defines pthreads too; 359 | # also defines -D_REENTRANT) 360 | # ... -mt is also the pthreads flag for HP/aCC 361 | # -lpthread: GNU Linux, etc. 362 | # --thread-safe: KAI C++ 363 | if Utils.unversioned_sys_platform() == 'sunos': 364 | # On Solaris (at least, for some versions), libc contains stubbed 365 | # (non-functional) versions of the pthreads routines, so link-based 366 | # tests will erroneously succeed. (We need to link with -pthreads/-mt/ 367 | # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather 368 | # a function called by this macro, so we could check for that, but 369 | # who knows whether they'll stub that too in a future libc.) So, 370 | # we'll just look for -pthreads and -lpthread first: 371 | boost_pthread_flags = ['-pthreads', '-lpthread', '-mt', '-pthread'] 372 | else: 373 | boost_pthread_flags = ['', '-lpthreads', '-Kthread', '-kthread', '-llthread', '-pthread', 374 | '-pthreads', '-mthreads', '-lpthread', '--thread-safe', '-mt'] 375 | 376 | for boost_pthread_flag in boost_pthread_flags: 377 | try: 378 | self.env.stash() 379 | self.env['CXXFLAGS_%s' % var] += [boost_pthread_flag] 380 | self.env['LINKFLAGS_%s' % var] += [boost_pthread_flag] 381 | self.check_cxx(code=PTHREAD_CODE, msg=None, use=var, execute=False, quiet=True) 382 | self.end_msg(boost_pthread_flag) 383 | return 384 | except self.errors.ConfigurationError: 385 | self.env.revert() 386 | self.end_msg('none') 387 | 388 | @conf 389 | def check_boost(self, *k, **kw): 390 | """ 391 | Initialize boost libraries to be used. 392 | 393 | Keywords: you can pass the same parameters as with the command line (without "--boost-"). 394 | Note that the command line has the priority, and should preferably be used. 395 | """ 396 | if not self.env['CXX']: 397 | self.fatal('load a c++ compiler first, conf.load("compiler_cxx")') 398 | 399 | params = { 400 | 'lib': k and k[0] or kw.get('lib', None), 401 | 'stlib': kw.get('stlib', None) 402 | } 403 | for key, value in self.options.__dict__.items(): 404 | if not key.startswith('boost_'): 405 | continue 406 | key = key[len('boost_'):] 407 | params[key] = value and value or kw.get(key, '') 408 | 409 | var = kw.get('uselib_store', 'BOOST') 410 | 411 | if not self.env.DONE_FIND_BOOST_COMMON: 412 | self.find_program('dpkg-architecture', var='DPKG_ARCHITECTURE', mandatory=False) 413 | if self.env.DPKG_ARCHITECTURE: 414 | deb_host_multiarch = self.cmd_and_log([self.env.DPKG_ARCHITECTURE[0], '-qDEB_HOST_MULTIARCH']) 415 | BOOST_LIBS.insert(0, '/usr/lib/%s' % deb_host_multiarch.strip()) 416 | 417 | self.start_msg('Checking boost includes') 418 | self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params) 419 | versions = self.boost_get_version(inc) 420 | self.env.BOOST_VERSION = versions[0] 421 | self.env.BOOST_VERSION_NUMBER = int(versions[1]) 422 | self.end_msg('%d.%d.%d' % (int(versions[1]) / 100000, 423 | int(versions[1]) / 100 % 1000, 424 | int(versions[1]) % 100)) 425 | if Logs.verbose: 426 | Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var]) 427 | 428 | self.env.DONE_FIND_BOOST_COMMON = True 429 | 430 | if not params['lib'] and not params['stlib']: 431 | return 432 | if 'static' in kw or 'static' in params: 433 | Logs.warn('boost: static parameter is deprecated, use stlib instead.') 434 | self.start_msg('Checking boost libs') 435 | path, libs, stlibs = self.boost_get_libs(**params) 436 | self.env['LIBPATH_%s' % var] = [path] 437 | self.env['STLIBPATH_%s' % var] = [path] 438 | self.env['LIB_%s' % var] = libs 439 | self.env['STLIB_%s' % var] = stlibs 440 | self.end_msg(' '.join(libs + stlibs)) 441 | if Logs.verbose: 442 | Logs.pprint('CYAN', ' path : %s' % path) 443 | Logs.pprint('CYAN', ' shared libs : %s' % libs) 444 | Logs.pprint('CYAN', ' static libs : %s' % stlibs) 445 | 446 | def has_shlib(lib): 447 | return params['lib'] and lib in params['lib'] 448 | def has_stlib(lib): 449 | return params['stlib'] and lib in params['stlib'] 450 | def has_lib(lib): 451 | return has_shlib(lib) or has_stlib(lib) 452 | if has_lib('thread'): 453 | # not inside try_link to make check visible in the output 454 | self._check_pthread_flag(k, kw) 455 | 456 | def try_link(): 457 | if has_lib('system'): 458 | self.check_cxx(fragment=BOOST_ERROR_CODE, use=var, execute=False) 459 | if has_lib('thread'): 460 | self.check_cxx(fragment=BOOST_THREAD_CODE, use=var, execute=False) 461 | if has_lib('log') or has_lib('log_setup'): 462 | if not has_lib('thread'): 463 | self.env['DEFINES_%s' % var] += ['BOOST_LOG_NO_THREADS'] 464 | if has_shlib('log') or has_shlib('log_setup'): 465 | self.env['DEFINES_%s' % var] += ['BOOST_LOG_DYN_LINK'] 466 | if has_lib('log_setup'): 467 | self.check_cxx(fragment=BOOST_LOG_SETUP_CODE, use=var, execute=False) 468 | else: 469 | self.check_cxx(fragment=BOOST_LOG_CODE, use=var, execute=False) 470 | 471 | if params.get('linkage_autodetect', False): 472 | self.start_msg('Attempting to detect boost linkage flags') 473 | toolset = self.boost_get_toolset(kw.get('toolset', '')) 474 | if toolset in ('vc',): 475 | # disable auto-linking feature, causing error LNK1181 476 | # because the code wants to be linked against 477 | self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] 478 | 479 | # if no dlls are present, we guess the .lib files are not stubs 480 | has_dlls = False 481 | for x in Utils.listdir(path): 482 | if x.endswith(self.env.cxxshlib_PATTERN % ''): 483 | has_dlls = True 484 | break 485 | if not has_dlls: 486 | self.env['STLIBPATH_%s' % var] = [path] 487 | self.env['STLIB_%s' % var] = libs 488 | del self.env['LIB_%s' % var] 489 | del self.env['LIBPATH_%s' % var] 490 | 491 | # we attempt to play with some known-to-work CXXFLAGS combinations 492 | for cxxflags in (['/MD', '/EHsc'], []): 493 | self.env.stash() 494 | self.env['CXXFLAGS_%s' % var] += cxxflags 495 | try: 496 | try_link() 497 | self.end_msg('ok: winning cxxflags combination: %s' % (self.env['CXXFLAGS_%s' % var])) 498 | exc = None 499 | break 500 | except Errors.ConfigurationError as e: 501 | self.env.revert() 502 | exc = e 503 | 504 | if exc is not None: 505 | self.end_msg('Could not auto-detect boost linking flags combination, you may report it to boost.py author', ex=exc) 506 | self.fatal('The configuration failed') 507 | else: 508 | self.end_msg('Boost linkage flags auto-detection not implemented (needed ?) for this toolchain') 509 | self.fatal('The configuration failed') 510 | else: 511 | self.start_msg('Checking for boost linkage') 512 | try: 513 | try_link() 514 | except Errors.ConfigurationError as e: 515 | self.end_msg('Could not link against boost libraries using supplied options', 'YELLOW') 516 | self.fatal('The configuration failed') 517 | self.end_msg('ok') 518 | 519 | 520 | @feature('cxx') 521 | @after_method('apply_link') 522 | def install_boost(self): 523 | if install_boost.done or not Utils.is_win32 or not self.bld.cmd.startswith('install'): 524 | return 525 | install_boost.done = True 526 | inst_to = getattr(self, 'install_path', '${BINDIR}') 527 | for lib in self.env.LIB_BOOST: 528 | try: 529 | file = self.bld.find_file(self.env.cxxshlib_PATTERN % lib, self.env.LIBPATH_BOOST) 530 | self.bld.install_files(inst_to, self.bld.root.find_node(file)) 531 | except: 532 | continue 533 | install_boost.done = False 534 | --------------------------------------------------------------------------------