build: Reviving support for precompiled headers

This commit also includes an update of ./waf, which has several
improvements.  In particular, clang++ is now default compiler on OSX
platform.

This commit also includes reorganization of tests. All unit tests are
now under tests/unit-tests and integrated tests are under
tests/integrated.  This change allows small compilation optimization,
partially related to precompiled headers.

Change-Id: I4c171c04d18e9cb83e461264a35b9ed85ea4d50e
This commit is contained in:
Alexander Afanasyev committed 2014-05-30 02:36:23 +03:00
1 parent 1b01c313c6
commit 8b1674ad59
58 files changed
+217 -180

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
*~
# Mac OSX
.DS_Store
.DS_*
# waf build system
.waf-1*
+131 -25
View File
@@ -1,38 +1,144 @@
#! /usr/bin/env python
# encoding: utf-8
# Alexander Afanasyev (UCLA), 2014
"""
Enable precompiled C++ header support (currently only clang++ and g++ are supported)
To use this tool, wscript should look like:
def options(opt):
opt.load('pch')
# This will add `--with-pch` configure option.
# Unless --with-pch during configure stage specified, the precompiled header support is disabled
def configure(conf):
conf.load('pch')
# this will set conf.env.WITH_PCH if --with-pch is specified and the supported compiler is used
# Unless conf.env.WITH_PCH is set, the precompiled header support is disabled
def build(bld):
bld(features='cxx pch',
target='precompiled-headers',
name='precompiled-headers',
headers='a.h b.h c.h', # headers to pre-compile into `precompiled-headers`
# Other parameters to compile precompiled headers
# includes=...,
# export_includes=...,
# use=...,
# ...
# Exported parameters will be propagated even if precompiled headers are disabled
)
bld(
target='test',
features='cxx cxxprogram',
source='a.cpp b.cpp d.cpp main.cpp',
use='precompiled-headers',
)
# or
bld(
target='test',
features='pch cxx cxxprogram',
source='a.cpp b.cpp d.cpp main.cpp',
headers='a.h b.h c.h',
)
Note that precompiled header must have multiple inclusion guards. If the guards are missing, any benefit of precompiled header will be voided and compilation may fail in some cases.
"""
import os
from waflib import Task, TaskGen, Logs, Utils
from waflib.Tools import c_preproc, cxx
PCH_COMPILER_OPTIONS = {
'clang++': [['-include'], '.pch', ['-x', 'c++-header']],
'g++': [['-include'], '.gch', ['-x', 'c++-header']],
}
from waflib import Logs, Utils, Task, TaskGen
from waflib.Tools import c_preproc
def options(opt):
opt.add_option('--with-pch', action='store_true', default=False, dest='with_pch',
help='''Try to use precompiled header to speed up compilation '''
'''(only gcc and clang)''')
opt.add_option('--without-pch', action='store_false', default=True, dest='with_pch', help='''Try to use precompiled header to speed up compilation (only g++ and clang++)''')
def configure(conf):
conf.env['WITH_PCH'] = conf.options.with_pch
if (conf.options.with_pch and conf.env['COMPILER_CXX'] in PCH_COMPILER_OPTIONS.keys()):
conf.env.WITH_PCH = True
flags = PCH_COMPILER_OPTIONS[conf.env['COMPILER_CXX']]
conf.env.CXXPCH_F = flags[0]
conf.env.CXXPCH_EXT = flags[1]
conf.env.CXXPCH_FLAGS = flags[2]
@TaskGen.feature('pch')
@TaskGen.before('process_source')
def apply_pch(self):
if not self.env.WITH_PCH:
return
if getattr(self.bld, 'pch_tasks', None) is None:
self.bld.pch_tasks = {}
if getattr(self, 'headers', None) is None:
return
self.headers = self.to_nodes(self.headers)
if getattr(self, 'name', None):
try:
task = self.bld.pch_tasks[self.name]
self.bld.fatal("Duplicated 'pch' task with name %r" % self.name)
except KeyError:
pass
out = '%s.%d%s' % (self.target, self.idx, self.env['CXXPCH_EXT'])
out = self.path.find_or_declare(out)
task = self.create_task('gchx', self.headers, out)
# target should be an absolute path of `out`, but without precompiled header extension
task.target = out.abspath()[:-len(out.suffix())]
self.pch_task = task
if getattr(self, 'name', None):
self.bld.pch_tasks[self.name] = task
@TaskGen.feature('cxx')
@TaskGen.before('process_source')
def process_pch(self):
if getattr(self, 'pch', ''):
# for now support only gcc-compatible things
if self.env['COMPILER_CXX'] == 'g++':
nodes = self.to_nodes(self.pch, path=self.path)
for x in nodes:
z = self.create_task('gchx', x, x.change_ext('.hpp.gch'))
z.orig_self = self
@TaskGen.after_method('process_source', 'propagate_uselib_vars')
def add_pch(self):
if not (self.env['WITH_PCH'] and getattr(self, 'use', None) and getattr(self, 'compiled_tasks', None) and getattr(self.bld, 'pch_tasks', None)):
return
pch = None
# find pch task, if any
if getattr(self, 'pch_task', None):
pch = self.pch_task
else:
for use in Utils.to_list(self.use):
try:
pch = self.bld.pch_tasks[use]
except KeyError:
pass
if pch:
for x in self.compiled_tasks:
x.env.append_value('CXXFLAGS', self.env['CXXPCH_F'] + [pch.target])
class gchx(Task.Task):
run_str = '${CXX} -x c++-header ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ' + \
'${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ' + \
'${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}'
scan = c_preproc.scan
ext_out = ['.hpp']
color = 'BLUE'
run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${CXXPCH_FLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXXPCH_F:SRC} ${CXX_SRC_F}${SRC[0].abspath()} ${CXX_TGT_F}${TGT[0].abspath()}'
scan = c_preproc.scan
color = 'BLUE'
ext_out=['.h']
def post_run(self):
super(gchx, self).post_run()
self.orig_self.env['CXXFLAGS'] = ['-include', self.inputs[0].relpath()] + \
self.env['CXXFLAGS']
def runnable_status(self):
ret = Task.Task.runnable_status(self)
if ret == Task.SKIP_ME and self.env.CXX_NAME == 'clang':
t = os.stat(self.outputs[0].abspath()).st_mtime
for n in self.inputs:
if os.stat(n.abspath()).st_mtime > t:
return Task.RUN_ME
return ret
+2 -2
View File
@@ -12,8 +12,8 @@ class sphinx_build(Task.Task):
def __str__(self):
env = self.env
src_str = ' '.join([a.nice_path()for a in self.inputs])
tgt_str = ' '.join([a.nice_path()for a in self.outputs])
src_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.inputs])
tgt_str = ' '.join([a.path_from(a.ctx.launch_node()) for a in self.outputs])
if self.outputs: sep = ' -> '
else: sep = ''
return'%s [%s]: %s%s%s\n'%(self.__class__.__name__.replace('_task',''),
+8
View File
@@ -41,10 +41,18 @@
// Other useful headers to precompile
#include <boost/lexical_cast.hpp>
#include <boost/asio.hpp>
#include <boost/chrono.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/detail/ios.hpp>
#include <boost/iostreams/categories.hpp>
#include <boost/iostreams/stream.hpp>
#include "security/cryptopp.hpp"
#endif // NDN_COMMON_PCH_HPP
-33
View File
@@ -1,33 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#ifndef NDN_TESTS_INTEGRATED_BOOST_TEST_HPP
#define NDN_TESTS_INTEGRATED_BOOST_TEST_HPP
// suppress warnings from Boost.Test
#pragma GCC system_header
#pragma clang system_header
#include <boost/test/unit_test.hpp>
#include <boost/concept_check.hpp>
#include <boost/test/output_test_stream.hpp>
#endif // NDN_TESTS_INTEGRATED_BOOST_TEST_HPP
-25
View File
@@ -1,25 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#define BOOST_TEST_MAIN 1
#define BOOST_TEST_DYN_LINK 1
#include "boost-test.hpp"
-29
View File
@@ -1,29 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
// This file is needed for experimental precompiled header support (gcc and clang)
#ifndef NDN_TESTS_INTEGRATED_TEST_ALL_HPP
#define NDN_TESTS_INTEGRATED_TEST_ALL_HPP
#include "common.hpp"
#endif // NDN_TESTS_INTEGRATED_TEST_ALL_HPP
File renamed without changes.
@@ -5,12 +5,13 @@ from waflib import Utils
top = '..'
def build(bld):
unittests = bld.program (
target="../integrated-tests",
features="cxx cxxprogram",
unittests = bld(
target="integrated-test-objects",
name="integrated-test-objects",
features="cxx",
source=bld.path.ant_glob(['**/*.cpp'],
excl=['**/*-osx.cpp', '**/*-sqlite3.cpp']),
use='ndn-cxx',
excl=['main.cpp', '**/*-osx.cpp', '**/*-sqlite3.cpp']),
use='tests-base',
includes='.',
install_path=None,
)
@@ -21,5 +22,8 @@ def build(bld):
# In case we want to make it optional later
unittests.source += bld.path.ant_glob('**/*-sqlite3.cpp')
if bld.env['WITH_PCH']:
unittests.pch = "test-all.hpp"
bld.program(
target="../integrated-tests",
use="integrated-test-objects",
source="main.cpp",
install_path=None)
-29
View File
@@ -1,29 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
// This file is needed for experimental precompiled header support (gcc and clang)
#ifndef NDN_TESTS_TEST_ALL_HPP
#define NDN_TESTS_TEST_ALL_HPP
#include "common.hpp"
#endif
@@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(ConstructorNormalConfig)
{
using namespace boost::filesystem;
setenv("TEST_HOME", "tests/security/config-file-home", 1);
setenv("TEST_HOME", "tests/unit-tests/security/config-file-home", 1);
BOOST_REQUIRE_NO_THROW(KeyChain());
@@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(ConstructorEmptyConfig)
{
using namespace boost::filesystem;
setenv("TEST_HOME", "tests/security/config-file-empty-home", 1);
setenv("TEST_HOME", "tests/unit-tests/security/config-file-empty-home", 1);
BOOST_REQUIRE_NO_THROW(KeyChain());
@@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(ConstructorMalConfig)
{
using namespace boost::filesystem;
setenv("TEST_HOME", "tests/security/config-file-malformed-home", 1);
setenv("TEST_HOME", "tests/unit-tests/security/config-file-malformed-home", 1);
BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
}
@@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(ConstructorMal2Config)
{
using namespace boost::filesystem;
setenv("TEST_HOME", "tests/security/config-file-malformed2-home", 1);
setenv("TEST_HOME", "tests/unit-tests/security/config-file-malformed2-home", 1);
BOOST_REQUIRE_THROW(KeyChain(), KeyChain::Error); // Wrong configuration. Error expected.
}
@@ -19,6 +19,7 @@
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "encoding/encoding-buffer.hpp"
#include "encoding/buffer-stream.hpp"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -19,8 +19,8 @@
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#ifndef NDN_TESTS_TRANSPORT_DUMMY_FACE_HPP
#define NDN_TESTS_TRANSPORT_DUMMY_FACE_HPP
#ifndef NDN_TESTS_UNIT_TESTS_TRANSPORT_DUMMY_FACE_HPP
#define NDN_TESTS_UNIT_TESTS_TRANSPORT_DUMMY_FACE_HPP
#include "face.hpp"
#include "transport/transport.hpp"
@@ -113,4 +113,4 @@ makeDummyFace()
} // namespace ndn
#endif // NDN_TESTS_TRANSPORT_DUMMY_FACE_HPP
#endif // NDN_TESTS_UNIT_TESTS_TRANSPORT_DUMMY_FACE_HPP
@@ -48,7 +48,7 @@ BOOST_FIXTURE_TEST_SUITE(TransportTestUnixTransport, UnixTransportFixture)
BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameOk)
{
setenv("HOME", "tests/transport/test-homes/ok", 1);
setenv("HOME", "tests/unit-tests/transport/test-homes/ok", 1);
ConfigFile config;
BOOST_REQUIRE_EQUAL(UnixTransport::getDefaultSocketName(config), "/tmp/test/nfd.sock");
@@ -56,21 +56,21 @@ BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameOk)
BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameMissingSocketMissingProtocol)
{
setenv("HOME", "tests/transport/test-homes/missing-unix-socket-missing-protocol", 1);
setenv("HOME", "tests/unit-tests/transport/test-homes/missing-unix-socket-missing-protocol", 1);
ConfigFile config;
BOOST_REQUIRE_EQUAL(UnixTransport::getDefaultSocketName(config), "/var/run/nfd.sock");
}
BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameMissingSocketNdndProtocol)
{
setenv("HOME", "tests/transport/test-homes/missing-unix-socket-with-ndnd-protocol", 1);
setenv("HOME", "tests/unit-tests/transport/test-homes/missing-unix-socket-with-ndnd-protocol", 1);
ConfigFile config;
BOOST_REQUIRE_EQUAL(UnixTransport::getDefaultSocketName(config), "/tmp/.ndnd.sock");
}
BOOST_AUTO_TEST_CASE(TestGetDefaultSocketNameMissingSocketWithProtocol)
{
setenv("HOME", "tests/transport/test-homes/missing-unix-socket-with-protocol", 1);
setenv("HOME", "tests/unit-tests/transport/test-homes/missing-unix-socket-with-protocol", 1);
ConfigFile config;
BOOST_REQUIRE_EQUAL(UnixTransport::getDefaultSocketName(config), "/var/run/nfd.sock");
}
@@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(TestParse)
using namespace boost::filesystem;
// std::cerr << "current home = " << std::getenv("HOME") << std::endl;
setenv("HOME", "tests/util/config-file-home", 1);
setenv("HOME", "tests/unit-tests/util/config-file-home", 1);
path homePath(absolute(std::getenv("HOME")));
homePath /= ".ndn/client.conf";
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(EmptyPathParse)
{
// std::cerr << "current home = " << std::getenv("HOME") << std::endl;
setenv("HOME", "tests/util/does/not/exist", 1);
setenv("HOME", "tests/unit-tests/util/does/not/exist", 1);
try
{
ConfigFile config;
@@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(MalformedParse)
using namespace boost::filesystem;
// std::cerr << "current home = " << std::getenv("HOME") << std::endl;
setenv("HOME", "tests/util/config-file-malformed-home", 1);
setenv("HOME", "tests/unit-tests/util/config-file-malformed-home", 1);
bool fileWasMalformed = false;
try
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+46 -9
View File
@@ -5,21 +5,58 @@ from waflib import Utils
top = '..'
def build(bld):
unittests = bld.program (
target="../unit-tests",
features="cxx cxxprogram",
source=bld.path.ant_glob(['**/*.cpp'],
excl=['**/*-osx.cpp', '**/*-sqlite3.cpp']),
bld(features=['cxx', 'pch'],
name='tests-base',
target='tests-base',
headers=['../src/common-pch.hpp', 'boost-test.hpp'],
use='ndn-cxx',
includes='.',
)
unit_tests = bld(
target="unit-test-objects",
name="unit-test-objects",
features="cxx",
source=bld.path.ant_glob(['unit-tests/**/*.cpp'],
excl=['**/*-osx.cpp', '**/*-sqlite3.cpp']),
use='tests-base',
includes='.',
install_path=None,
)
integrated = bld(
target="integrated-test-objects",
name="integrated-test-objects",
features="cxx",
source=bld.path.ant_glob(['integrated/**/*.cpp'],
excl=['**/*-osx.cpp', '**/*-sqlite3.cpp']),
use='tests-base',
includes='.',
install_path=None,
)
if bld.env['HAVE_OSX_SECURITY']:
unittests.source += bld.path.ant_glob('**/*-osx.cpp')
unit_tests.source += bld.path.ant_glob('unit-tests/**/*-osx.cpp')
integrated.source += bld.path.ant_glob('integrated/**/*-osx.cpp')
# In case we want to make it optional later
unittests.source += bld.path.ant_glob('**/*-sqlite3.cpp')
unit_tests.source += bld.path.ant_glob('unit-tests/**/*-sqlite3.cpp')
integrated.source += bld.path.ant_glob('integrated/**/*-sqlite3.cpp')
if bld.env['WITH_PCH']:
unittests.pch = "test-all.hpp"
unit_test_main = bld(
target='unit-tests-main',
name='unit-tests-main',
features='cxx',
source=bld.path.ant_glob(['*.cpp']),
use='ndn-cxx',
)
bld(features="cxx cxxprogram",
target="../unit-tests",
use="unit-test-objects unit-tests-main",
install_path=None)
bld(features="cxx cxxprogram",
target="../integrated-tests",
use="integrated-test-objects unit-tests-main",
install_path=None)
Vendored
BIN
View File
Binary file not shown.
+3 -6
View File
@@ -50,7 +50,7 @@ def configure(conf):
conf.check_cxx(lib='pthread', uselib_store='PTHREAD', define_name='HAVE_PTHREAD',
mandatory=False)
conf.check_cxx(lib='rt', uselib_store='RT', define_name='HAVE_RT', mandatory=False)
conf.check_cxx(cxxflags=['-fPIC'], uselib_store='cxxstlib', mandatory=False)
conf.check_cxx(cxxflags=['-fPIC'], uselib_store='PIC', mandatory=False)
conf.check_osx_security(mandatory=False)
@@ -116,21 +116,19 @@ def build(bld):
)
libndn_cxx = bld(
features=['cxx', 'cxxstlib'], # 'cxxshlib',
features=['pch', 'cxx', 'cxxstlib'], # 'cxxshlib',
# vnum=VERSION,
target="ndn-cxx",
name="ndn-cxx",
source=bld.path.ant_glob('src/**/*.cpp',
excl=['src/**/*-osx.cpp', 'src/**/*-sqlite3.cpp']),
headers='src/common-pch.hpp',
use='version BOOST OPENSSL CRYPTOPP SQLITE3 RT PIC PTHREAD',
includes=". src",
export_includes="src",
install_path='${LIBDIR}',
)
if bld.env['WITH_PCH']:
libndn_cxx.pch="src/common.hpp"
if bld.env['HAVE_OSX_SECURITY']:
libndn_cxx.source += bld.path.ant_glob('src/**/*-osx.cpp')
libndn_cxx.mac_app = True
@@ -184,7 +182,6 @@ def build(bld):
# Unit tests
if bld.env['WITH_TESTS']:
bld.recurse('tests')
bld.recurse('tests-integrated')
if bld.env['WITH_TOOLS']:
bld.recurse("tools")