blob: 65c249a9a9881ae2f794650c0a7bce229bfb787d [file] [log] [blame]
Alexander Afanasyevd9b58ac2015-01-06 14:28:59 -08001# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
2
3"""
4Copyright (c) 2014 Regents of the University of California,
5 Arizona Board of Regents,
6 Colorado State University,
7 University Pierre & Marie Curie, Sorbonne University,
8 Washington University in St. Louis,
9 Beijing Institute of Technology
10
11This file is part of NFD (Named Data Networking Forwarding Daemon).
12See AUTHORS.md for complete list of NFD authors and contributors.
13
14NFD is free software: you can redistribute it and/or modify it under the terms
15of the GNU General Public License as published by the Free Software Foundation,
16either version 3 of the License, or (at your option) any later version.
17
18NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20PURPOSE. See the GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License along with
23NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24"""
25
26VERSION = "0.2.0"
27APPNAME = "nfd"
28BUGREPORT = "http://redmine.named-data.net/projects/nfd"
29URL = "http://named-data.net/doc/NFD/"
30GIT_TAG_PREFIX = "NFD-"
31
32from waflib import Logs, Utils, Context
33import os
34
35def options(opt):
36 opt.load(['compiler_cxx', 'gnu_dirs'])
37 opt.load(['boost', 'unix-socket', 'dependency-checker', 'websocket',
38 'default-compiler-flags', 'coverage', 'pch', 'boost-kqueue',
39 'doxygen', 'sphinx_build', 'type_traits', 'compiler-features'],
40 tooldir=['.waf-tools'])
41
42 nfdopt = opt.add_option_group('NFD Options')
43 opt.addUnixOptions(nfdopt)
44 opt.addWebsocketOptions(nfdopt)
45 opt.addDependencyOptions(nfdopt, 'libpcap')
46 nfdopt.add_option('--without-libpcap', action='store_true', default=False,
47 dest='without_libpcap',
48 help='''Disable libpcap (Ethernet face support will be disabled)''')
49
50 opt.addDependencyOptions(nfdopt, 'librt', '(optional)')
51 opt.addDependencyOptions(nfdopt, 'libresolv', '(optional)')
52
53 nfdopt.add_option('--with-tests', action='store_true', default=False,
54 dest='with_tests', help='''Build unit tests''')
55 nfdopt.add_option('--with-other-tests', action='store_true', default=False,
56 dest='with_other_tests', help='''Build other tests''')
57
58def configure(conf):
59 conf.load(['compiler_cxx', 'gnu_dirs',
60 'default-compiler-flags', 'pch', 'boost-kqueue',
61 'boost', 'dependency-checker', 'websocket',
62 'doxygen', 'sphinx_build', 'type_traits', 'compiler-features'])
63
64 conf.find_program('bash', var='BASH')
65
66 if not os.environ.has_key('PKG_CONFIG_PATH'):
67 os.environ['PKG_CONFIG_PATH'] = ':'.join([
68 '/usr/local/lib/pkgconfig',
69 '/opt/local/lib/pkgconfig'])
70 conf.check_cfg(package='libndn-cxx', args=['--cflags', '--libs'],
71 uselib_store='NDN_CXX', mandatory=True)
72
73 conf.checkDependency(name='librt', lib='rt', mandatory=False)
74 conf.checkDependency(name='libresolv', lib='resolv', mandatory=False)
75
76 boost_libs = 'system chrono program_options random'
77 if conf.options.with_tests:
78 conf.env['WITH_TESTS'] = 1
79 conf.define('WITH_TESTS', 1);
80 boost_libs += ' unit_test_framework'
81
82 if conf.options.with_other_tests:
83 conf.env['WITH_OTHER_TESTS'] = 1
84
85 conf.check_boost(lib=boost_libs)
86 if conf.env.BOOST_VERSION_NUMBER < 104800:
87 Logs.error("Minimum required boost version is 1.48.0")
88 Logs.error("Please upgrade your distribution or install custom boost libraries" +
89 " (http://redmine.named-data.net/projects/nfd/wiki/Boost_FAQ)")
90 return
91
92 conf.load('unix-socket')
93 conf.checkWebsocket(mandatory=True)
94
95 if not conf.options.without_libpcap:
96 conf.check_asio_pcap_support()
97 if conf.env['HAVE_ASIO_PCAP_SUPPORT']:
98 conf.checkDependency(name='libpcap', lib='pcap', mandatory=True,
99 errmsg='not found, but required for Ethernet face support. '
100 'Specify --without-libpcap to disable Ethernet face support.')
101 else:
102 Logs.warn('Warning: Ethernet face support is not supported on this platform with Boost libraries version 1.56. '
103 'See http://redmine.named-data.net/issues/1877 for more details')
104 if conf.env['HAVE_LIBPCAP']:
105 conf.check_cxx(function_name='pcap_set_immediate_mode', header_name='pcap/pcap.h',
106 cxxflags='-Wno-error', use='LIBPCAP', mandatory=False)
107
108 conf.load('coverage')
109
110 conf.define('DEFAULT_CONFIG_FILE', '%s/ndn/nfd.conf' % conf.env['SYSCONFDIR'])
111
112 # disable assertions in release builds
113 if not conf.options.debug:
114 conf.define('NDEBUG', 1)
115
116 conf.write_config_header('config.hpp')
117
118def build(bld):
119 version(bld)
120
121 bld(features="subst",
122 name='version',
123 source='version.hpp.in',
124 target='version.hpp',
125 install_path=None,
126 VERSION_STRING=VERSION_BASE,
127 VERSION_BUILD=VERSION,
128 VERSION=int(VERSION_SPLIT[0]) * 1000000 +
129 int(VERSION_SPLIT[1]) * 1000 +
130 int(VERSION_SPLIT[2]),
131 VERSION_MAJOR=VERSION_SPLIT[0],
132 VERSION_MINOR=VERSION_SPLIT[1],
133 VERSION_PATCH=VERSION_SPLIT[2],
134 )
135
136 core = bld(
137 target='core-objects',
138 name='core-objects',
139 features='cxx pch',
140 source=bld.path.ant_glob(['core/**/*.cpp']),
141 use='version BOOST NDN_CXX LIBRT',
142 includes='. core',
143 export_includes='. core',
144 headers='common.hpp',
145 )
146
147 nfd_objects = bld(
148 target='daemon-objects',
149 name='daemon-objects',
150 features='cxx',
151 source=bld.path.ant_glob(['daemon/**/*.cpp'],
152 excl=['daemon/face/ethernet-*.cpp',
153 'daemon/face/unix-*.cpp',
154 'daemon/face/websocket-*.cpp',
155 'daemon/main.cpp']),
156 use='core-objects WEBSOCKET',
157 includes='daemon',
158 export_includes='daemon',
159 )
160
161 if bld.env['HAVE_LIBPCAP']:
162 nfd_objects.source += bld.path.ant_glob('daemon/face/ethernet-*.cpp')
163 nfd_objects.use += ' LIBPCAP'
164
165 if bld.env['HAVE_UNIX_SOCKETS']:
166 nfd_objects.source += bld.path.ant_glob('daemon/face/unix-*.cpp')
167
168 if bld.env['HAVE_WEBSOCKET']:
169 nfd_objects.source += bld.path.ant_glob('daemon/face/websocket-*.cpp')
170
171 bld(target='bin/nfd',
172 features='cxx cxxprogram',
173 source='daemon/main.cpp',
174 use='daemon-objects',
175 )
176
177 rib_objects = bld(
178 target='rib-objects',
179 name='rib-objects',
180 features='cxx',
181 source=bld.path.ant_glob(['rib/**/*.cpp'],
182 excl=['rib/main.cpp']),
183 use='core-objects',
184 )
185
186 bld(target='bin/nrd',
187 features='cxx cxxprogram',
188 source='rib/main.cpp',
189 use='rib-objects',
190 )
191
192 for app in bld.path.ant_glob('tools/*.cpp'):
193 bld(features=['cxx', 'cxxprogram'],
194 target='bin/%s' % (str(app.change_ext(''))),
195 source=['tools/%s' % (str(app))],
196 use='core-objects LIBRESOLV',
197 )
198
199 bld.recurse("tests")
200
201 bld(features="subst",
202 source='nfd.conf.sample.in',
203 target='nfd.conf.sample',
204 install_path="${SYSCONFDIR}/ndn",
205 IF_HAVE_LIBPCAP="" if bld.env['HAVE_LIBPCAP'] else "; ",
206 IF_HAVE_WEBSOCKET="" if bld.env['HAVE_WEBSOCKET'] else "; ")
207
208 if bld.env['SPHINX_BUILD']:
209 bld(features="sphinx",
210 builder="man",
211 outdir="docs/manpages",
212 config="docs/conf.py",
213 source=bld.path.ant_glob('docs/manpages/**/*.rst'),
214 install_path="${MANDIR}/",
215 VERSION=VERSION)
216
217 for script in bld.path.ant_glob(['tools/*.sh', 'tools/*.py']):
218 bld(features='subst',
219 source='tools/%s' % (str(script)),
220 target='bin/%s' % (str(script.change_ext(''))),
221 install_path="${BINDIR}",
222 chmod=Utils.O755,
223 VERSION=VERSION)
224
225 bld.install_files("${DATAROOTDIR}/ndn",
226 bld.path.ant_glob('tools/nfd-status-http-server-files/*'))
227
228def docs(bld):
229 from waflib import Options
230 Options.commands = ['doxygen', 'sphinx'] + Options.commands
231
232def doxygen(bld):
233 version(bld)
234
235 if not bld.env.DOXYGEN:
236 Logs.error("ERROR: cannot build documentation (`doxygen' is not found in $PATH)")
237 else:
238 bld(features="subst",
239 name="doxygen-conf",
240 source=["docs/doxygen.conf.in",
241 "docs/named_data_theme/named_data_footer-with-analytics.html.in"],
242 target=["docs/doxygen.conf",
243 "docs/named_data_theme/named_data_footer-with-analytics.html"],
244 VERSION=VERSION_BASE,
245 HTML_FOOTER="../build/docs/named_data_theme/named_data_footer-with-analytics.html" \
246 if os.getenv('GOOGLE_ANALYTICS', None) \
247 else "../docs/named_data_theme/named_data_footer.html",
248 GOOGLE_ANALYTICS=os.getenv('GOOGLE_ANALYTICS', ""),
249 )
250
251 bld(features="doxygen",
252 doxyfile='docs/doxygen.conf',
253 use="doxygen-conf")
254
255def sphinx(bld):
256 version(bld)
257
258 if not bld.env.SPHINX_BUILD:
259 bld.fatal("ERROR: cannot build documentation (`sphinx-build' is not found in $PATH)")
260 else:
261 bld(features="sphinx",
262 outdir="docs",
263 source=bld.path.ant_glob('docs/**/*.rst'),
264 config="docs/conf.py",
265 VERSION=VERSION_BASE)
266
267def version(ctx):
268 if getattr(Context.g_module, 'VERSION_BASE', None):
269 return
270
271 Context.g_module.VERSION_BASE = Context.g_module.VERSION
272 Context.g_module.VERSION_SPLIT = [v for v in VERSION_BASE.split('.')]
273
274 didGetVersion = False
275 try:
276 cmd = ['git', 'describe', '--always', '--match', '%s*' % GIT_TAG_PREFIX]
277 p = Utils.subprocess.Popen(cmd, stdout=Utils.subprocess.PIPE,
278 stderr=None, stdin=None)
279 out = str(p.communicate()[0].strip())
280 didGetVersion = (p.returncode == 0 and out != "")
281 if didGetVersion:
282 if out.startswith(GIT_TAG_PREFIX):
283 Context.g_module.VERSION = out[len(GIT_TAG_PREFIX):]
284 else:
285 Context.g_module.VERSION = "%s-commit-%s" % (Context.g_module.VERSION_BASE, out)
286 except OSError:
287 pass
288
289 versionFile = ctx.path.find_node('VERSION')
290
291 if not didGetVersion and versionFile is not None:
292 try:
293 Context.g_module.VERSION = versionFile.read()
294 return
295 except (OSError, IOError):
296 pass
297
298 # version was obtained from git, update VERSION file if necessary
299 if versionFile is not None:
300 try:
301 version = versionFile.read()
302 if version == Context.g_module.VERSION:
303 return # no need to update
304 except (OSError, IOError):
305 Logs.warn("VERSION file exists, but not readable")
306 else:
307 versionFile = ctx.path.make_node('VERSION')
308
309 if versionFile is None:
310 return
311
312 try:
313 versionFile.write(Context.g_module.VERSION)
314 except (OSError, IOError):
315 Logs.warn("VERSION file is not writeable")
316
317def dist(ctx):
318 version(ctx)
319
320def distcheck(ctx):
321 version(ctx)