Skip to content
Snippets Groups Projects
Commit d8fb9a6b authored by Steffen Müthing's avatar Steffen Müthing
Browse files

[Autotools] Add new configure test for Threading Building Blocks

dune-common now tests for TBB by default. As TBB has a rather "unique" way
of handling installation (it doesn't do it), the test uses the tbbvars.sh
environment setup script generated during the build process to locate the
library. Stuff is further complicated by the fact that the library names
depend on the type of build. Oh joy...

So, here is how to use it:

--with-tbb=/path/to/tbbvars.sh tells the script where to find the correct version
of the library. Unfortunately, there are two different kinds of tbbvars.sh scripts:
There is a global one in TBB_DIR/bin (don't use that one) and there are per-build-type
versions in TBB_DIR/build/some_path_encoding_the_build type. You need to point the
test at one of those (depending on whether you want the debug or the release version).
If you omit the option or just say --with-tbb, the script assumes that the headers and
libraries can be found somewhere in the default system paths (might be useful when using
Intel icc). When --with-tbb is used and the library cannot be found, configure aborts
with an error.

If the path to the tbbvars.sh script is not passed on the command line, the test will
also look at the environment variable TBBVARS_SH.

--enable-tbb-allocator links to the tbb_malloc library in addition to the main tbb
library, which gives access to the thread-scalable allocator in TBB. Defaults to yes.

--enable-tbb-rpath causes the script to try and encode the location of the TBB libraries
into the rpath of any generated libraries or programs. This is mainly a convenience
feature to avoid having to update (DY)LD_LIBRARY_PATH if TBB is in some non-standard
location. You can't get around the shared libraries with TBB (well, you can with some
tricks, but upstream *strongly* advises against doing so because you can easily shoot
yoursel in the foot. So better only do that on very large machines where the dynamic
loader overhead would kill you otherwise).

The outcome of the test resembles most other tests in DUNE. If it succeeds, it defines

- the preprocessor macro HAVE_TBB to ENABLE_TBB
- the preprocessor macro HAVE_TBB_ALLOCATOR to ENABLE_TBB  if --enable-allocator is yes
- the preprocessor macro HAVE_TBB_PREVIEW to ENABLE_TBB if the community preview
  features are enabled
- the automake conditional TBB
- TBB_{CPPFLAGS,LDFLAGS,LIBS} to the appropriate values. Moreover, TBB_CPPFLAGS also
  defines ENABLE_TBB to 1.

In short, to use TBB you have to set up your program / library to be built with
TBB_{CPPFLAGS,LDFLAGS,LIBS} and you can enable/disable the build with the automake
conditional.

Some minor points:
- the exact preprocessor flags required depend on the type of build (release / debug
  and whether or not the community preview features are enabled).
- when TBB is enabled, the test also adds -pthread to the CPPFLAGS to make sure that the
  compiler doesn't use non-reentrant versions of system functions.
parent bb168ddd
No related branches found
No related tags found
No related merge requests found
......@@ -43,6 +43,7 @@ install(PROGRAMS
opengl.m4
parmetis.m4
shared_ptr.m4
tbb.m4
xdr.m4
DESTINATION share/aclocal
)
......@@ -47,6 +47,7 @@ ALLM4S = \
opengl.m4 \
parmetis.m4 \
shared_ptr.m4 \
tbb.m4 \
xdr.m4
aclocaldir = $(datadir)/aclocal
......
......@@ -73,6 +73,7 @@ AC_DEFUN([DUNE_COMMON_CHECKS],
AC_CHECK_FUNCS([sqrt strchr])
AC_LANG_POP([C++])
AC_REQUIRE([DUNE_PATH_TBB])
AC_REQUIRE([DUNE_PATH_GMP])
])
......
m4/tbb.m4 0 → 100644
dnl -*- mode: autoconf; tab-width: 8; indent-tabs-mode: nil; -*-
dnl vi: set et ts=8 sw=2 sts=2:
# searches for Threading Building Blocks headers and libs
AC_DEFUN([DUNE_PATH_TBB],[
AC_MSG_NOTICE([checking for Threading Building Blocks library...])
AC_REQUIRE([AC_PROG_CXX])
AC_REQUIRE([GXX0X])
AC_REQUIRE([LAMBDA_EXPR_CHECK])
AC_LANG_PUSH([C++])
#
# user hints
#
AC_ARG_VAR([TBBVARS_SH], [Location of Threading Building Blocks tbbvars.sh script])
AC_ARG_ENABLE([tbb_allocator],
[AS_HELP_STRING([--enable-tbb-allocator],
[When using Threading Building Blocks, also link against the tbbmalloc library to enable the optional scalable memory allocator that is part of TBB @<:@default=yes@:>@])],
[
AS_CASE(["$enableval"],
[yes], [tbb_allocator="yes"],
[no ], [tbb_allocator="no" ],
[AC_MSG_ERROR(["invalid value 'enableval' for --enable-tbb-allocator, must be 'yes' or 'no'"])
])
],
[
tbb_allocator="yes"
])
AC_ARG_ENABLE([tbb_rpath],
[AS_HELP_STRING([--enable-tbb-rpath],
[When using Threading Building Blocks, embed the path to the libraries into all generated binaries instead of relying a correctly set LD_LIBRARY_PATH. Warning, this does not work on every system due to differences in the linker syntax! @<:@default=no@:>@])],
[
AS_CASE(["$enableval"],
[yes], [tbb_rpath="yes"],
[no ], [tbb_rpath="no" ],
[AC_MSG_ERROR(["invalid value 'enableval' for --enable-tbb-rpath, must be 'yes' or 'no'"])
])
],
[
tbb_rpath="no"
])
AC_ARG_WITH([tbb],
[AS_HELP_STRING([--with-tbb=<tbbvars.sh>],
[Enable support for the Threading Building Blocks library. If TBB is not in the default paths, you need to pass the full path to the tbbvars.sh script inside the precise library directory you want to use (release/debug). Note that this library is always linked dynamically, so make sure to either update your LD_LIBRARY_PATH or use "--enable-tbb-rpath". When the provided tbbvars.sh script points to a debug or a community preview feature version of TBB, configure will try to detect this and set the necessary preprocessor flags. @<:@default=check@:>@])],
[
tbbvars="$withval"
],
[
# grab value from environment variable if available
AS_IF([ test -n "$TBBVARS_SH" ],
[ tbbvars="$TBBVARS_SH" ],
[ tbbvars="check" ])
])
AC_MSG_CHECKING([for TBB installation])
AS_IF([ test "x$tbbvars" = "xno" ],
[
AC_MSG_RESULT([disabled by user])
with_tbb="no"
],
[ test "x$tbbvars" = "xcheck" ],
[
# look for TBB somewhere in the system standard paths
AC_MSG_RESULT([default])
AS_IF([ test "$tbb_rpath" = "yes" ],
[ AC_MSG_WARN([TBB Library path embedding into rpath only works when specifying tbbvars.sh]) ])
],
[ test "x$tbbvars" = "xyes" ],
[
# look for TBB somewhere in the system standard paths
AC_MSG_RESULT([default])
AS_IF([ test "x$tbb_rpath" = "xyes" ],
[ AC_MSG_WARN([TBB Library path embedding into rpath only works when specifying tbbvars.sh]) ])
# user wants TBB, make sure to fail if we can't find it
tbb_required="yes"
],
[
# user wants TBB, make sure to fail if we can't find it
tbb_required="yes"
# user has provided a tbbvars.sh script, extract information
AS_IF([ test ! -f "$tbbvars" ],
[
# could not find file, abort
AC_MSG_RESULT([failed])
AC_MSG_WARN([tbbvars.sh script "$tbbvars" not found])
with_tbb="no"
],
[
# setup include and library paths from tbbvars.sh
tbb_lib_dir="$(dirname "$tbbvars")"
tbb_root_dir="$(source "$tbbvars"; echo $TBBROOT)"
AS_IF([ test ! -d "$tbb_root_dir" ],
[
# tbbvars.sh contained bogus information, abort
AC_MSG_RESULT([failed])
AC_MSG_WARN([invalid TBB installation root directory "$tbb_root_dir"])
with_tbb="no"
],
[
# convert paths to absolute paths
tbb_lib_dir="$(cd -- "$tbb_lib_dir" ; echo $PWD)"
tbb_root_dir="$(cd -- "$tbb_root_dir" ; echo $PWD)"
TBB_CPPFLAGS="-I$tbb_root_dir/include"
TBB_LDFLAGS="-L$tbb_lib_dir"
AC_MSG_RESULT([from "$tbbvars"])
AC_MSG_NOTICE([ TBB include directory "$tbb_root_dir/include"])
AC_MSG_NOTICE([ TBB library directory "$tbb_lib_dir"])
AS_IF([ test "x$tbb_rpath" = "xyes" ],
[
AC_MSG_NOTICE([ Encoding TBB library directory into binary rpath])
TBB_LDFLAGS="$TBB_LDFLAGS -Wl,-rpath,$tbb_lib_dir"
])
])
])
])
# save compiler variables
ac_save_LDFLAGS="$LDFLAGS"
ac_save_CPPFLAGS="$CPPFLAGS"
ac_save_LIBS="$LIBS"
AS_IF([ test "x$with_tbb" != "xno" ],
[
# check for TBB headers
CPPFLAGS="$CPPFLAGS $TBB_CPPFLAGS"
AC_CHECK_HEADER([tbb/tbb_stddef.h],[],[],[])
AS_IF([ test "x$ac_cv_header_tbb_tbb_stddef_h" = "xno" ],
[ with_tbb="no" ])
])
AS_IF([ test "x$with_tbb" != "xno" ],
[
# try to find a valid library
LDFLAGS="$LDFLAGS $TBB_LDFLAGS"
AC_SEARCH_LIBS([TBB_runtime_interface_version],[tbb tbb_debug tbb_preview tbb_preview_debug])
AS_IF([ test "x$ac_cv_search_TBB_runtime_interface_version" = "xno" ],
[ with_tbb="no" ])
])
AS_IF([ test "x$with_tbb" != "xno" ],
[
tbb_lib="$ac_cv_search_TBB_runtime_interface_version"
# check for debug and / or preview build
AS_IF([ test "x$(echo $tbb_lib | grep -o debug)" = "xdebug" ],
[
tbb_is_debug="yes"
TBB_CPPFLAGS="$TBB_CPPFLAGS -DTBB_USE_DEBUG"
CPPFLAGS="$CPPFLAGS -DTBB_USE_DEBUG"
],
[
tbb_is_debug="no"
])
AS_IF([ test "x$(echo $tbb_lib | grep -o preview)" = "xpreview" ],
[
tbb_is_preview="yes"
TBB_CPPFLAGS="$TBB_CPPFLAGS -DTBB_PREVIEW_TASK_ARENA -DTBB_PREVIEW_LOCAL_OBSERVER"
CPPFLAGS="$CPPFLAGS -DTBB_PREVIEW_TASK_ARENA -DTBB_PREVIEW_LOCAL_OBSERVER"
],
[
tbb_is_preview="no"
])
TBB_LIBS="$tbb_lib"
AS_IF([ test "x$tbb_allocator" = "xyes" ],
[
# add tbbmalloc library
AC_MSG_NOTICE([Adding TBB allocator library...])
AS_IF([ test "x$tbb_is_debug" = "xyes" ],
[ TBB_LIBS="$TBB_LIBS -ltbbmalloc_debug" ],
[ TBB_LIBS="$TBB_LIBS -ltbbmalloc" ])
])
LIBS="$TBB_LIBS $LIBS"
# perform final test to check whether everything really works
AC_MSG_CHECKING([for working TBB])
AC_LINK_IFELSE([
AC_LANG_PROGRAM([[
#include <tbb/tbb.h>
#include <numeric>
#ifndef HAVE_LAMBDA_EXPR
// provide a fallback for compilers without lambdas
struct add
{
add(int* x)
: _x(x)
{}
int* _x;
void operator()(int i) const
{
_x[i] = i;
}
};
#endif
]],
[[
int x[10] = {0};
#ifdef HAVE_LAMBDA_EXPR
tbb::parallel_for(0,10,[&](int i){ x[i] = i; });
#else
tbb::parallel_for(0,10,add(x));
#endif
return std::accumulate(x,x+10,0) == (9*10)/2;
]])],
[
with_tbb="yes"
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([failed])
with_tbb="no"
])
])
# tests are done, set up output
AS_IF([ test "x$with_tbb" = "xyes" ],
[
HAVE_TBB=1
# turn on pthread when using TBB to make sure library function calls are reentrant
TBB_CPPFLAGS="$TBB_CPPFLAGS -pthread -DENABLE_TBB"
AC_SUBST(TBB_CPPFLAGS,$TBB_CPPFLAGS)
AC_SUBST(TBB_LDFLAGS,$TBB_LDFLAGS)
AC_SUBST(TBB_LIBS,$TBB_LIBS)
# define main preprocessor macro
AC_DEFINE(HAVE_TBB,ENABLE_TBB,[Define if you have the Threading Building Blocks library.
This is only true if the library was found _and_ if the
application uses the TBB_CPPFLAGS])
# additional preprocessor macro for allocator
AS_IF([ test "x$tbb_allocator" = "xyes" ],
[
AC_DEFINE(HAVE_TBB_ALLOCATOR,ENABLE_TBB,[Define if you have the optional allocator library from
Threading Building Blocks.
This is only true if the library was found _and_ if the
application uses the TBB_CPPFLAGS])
])
# additional preprocessor macro for community features
AS_IF([ test "x$tbb_is_preview" = "xyes" ],
[
AC_DEFINE(HAVE_TBB_PREVIEW,ENABLE_TBB,[Define if the community preview features of the
Threading Building Blocks library are available.
This is only true if the features are enabled _and_ if the
application uses the TBB_CPPFLAGS])
])
# add to global list
DUNE_ADD_ALL_PKG([TBB],[\${TBB_CPPFLAGS}],[\${TBB_LDFLAGS}],[\${TBB_LIBS}])
# create summary string
AS_IF([ test "x$tbb_is_debug" = "xyes" ],
[ tbb_summary=debug ],
[ tbb_summary=release ])
AS_IF([ test "x$tbb_allocator" = "xyes" ],
[ tbb_summary="$tbb_summary,allocator" ])
AS_IF([ test "x$tbb_is_preview" = "xyes" ],
[ tbb_summary="$tbb_summary,community preview" ])
AS_IF([ test "x$tbb_rpath" = "xyes" ],
[ tbb_summary="$tbb_summary,rpath encoded" ])
tbb_summary="yes ($tbb_summary)"
],
[ test "x$tbb_required" = "xyes" ],
[
# bail out
AC_MSG_FAILURE([Could not find a working version of Threading Building Blocks])
],
[
# TBB is optional, just log that it is missing
tbb_summary="no"
])
# restore compiler variables
LDFLAGS="$ac_save_LDFLAGS"
CPPFLAGS="$ac_save_CPPFLAGS"
LIBS="$ac_save_LIBS"
AC_LANG_POP
# tell automake
AM_CONDITIONAL(TBB, test x$HAVE_TBB = x1)
DUNE_ADD_SUMMARY_ENTRY([TBB],["$tbb_summary"])
])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment