experimental/io/FsUtil.h \
experimental/JSONSchema.h \
experimental/LockFreeRingBuffer.h \
+ experimental/ProgramOptions.h \
experimental/Select64.h \
experimental/StringKeyedCommon.h \
experimental/StringKeyedUnorderedMap.h \
experimental/FunctionScheduler.cpp \
experimental/io/FsUtil.cpp \
experimental/JSONSchema.cpp \
+ experimental/ProgramOptions.cpp \
experimental/Select64.cpp \
experimental/TestUtil.cpp
# check for boost libs
AX_BOOST_BASE([1.51.0], [], [AC_MSG_ERROR(
- [Please install boost >= 1.51.0 (context, thread, regex, and system)])])
+ [Please install boost >= 1.51.0 (context, thread, program_options, regex, and system)])])
AX_BOOST_CONTEXT
+AX_BOOST_PROGRAM_OPTIONS
AX_BOOST_THREAD
AX_BOOST_REGEX
AX_BOOST_SYSTEM
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/experimental/ProgramOptions.h>
+
+#include <unordered_map>
+#include <unordered_set>
+
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+#include <folly/Conv.h>
+#include <folly/Portability.h>
+
+namespace po = ::boost::program_options;
+
+namespace folly {
+
+namespace {
+
+// Information about one GFlag. Handled via shared_ptr, as, in the case
+// of boolean flags, two boost::program_options options (--foo and --nofoo)
+// may share the same GFlag underneath.
+//
+// We're slightly abusing the boost::program_options interface; the first
+// time we (successfully) parse a value that matches this GFlag, we'll set
+// it and remember not to set it again; this prevents, for example, the
+// default value of --foo from overwriting the GFlag if --nofoo is set.
+template <class T>
+class GFlagInfo {
+ public:
+ explicit GFlagInfo(gflags::CommandLineFlagInfo info)
+ : info_(std::move(info)),
+ isSet_(false) { }
+
+ void set(const T& value) {
+ if (isSet_) {
+ return;
+ }
+
+ auto strValue = folly::to<std::string>(value);
+ auto msg = gflags::SetCommandLineOption(
+ info_.name.c_str(),
+ strValue.c_str());
+ if (msg.empty()) {
+ throw po::invalid_option_value(strValue);
+ }
+ isSet_ = true;
+ }
+
+ T get() const {
+ std::string str;
+ CHECK(gflags::GetCommandLineOption(info_.name.c_str(), &str));
+ return folly::to<T>(str);
+ }
+
+ const gflags::CommandLineFlagInfo& info() const { return info_; }
+
+ private:
+ gflags::CommandLineFlagInfo info_;
+ bool isSet_;
+};
+
+template <class T>
+class GFlagValueSemanticBase : public po::value_semantic {
+ public:
+ explicit GFlagValueSemanticBase(std::shared_ptr<GFlagInfo<T>> info)
+ : info_(std::move(info)) { }
+
+ std::string name() const override { return "arg"; }
+ bool is_composing() const override { return false; }
+ bool is_required() const override { return false; }
+ // We handle setting the GFlags from parse(), so notify() does nothing.
+ void notify(const boost::any& valueStore) const override { }
+ bool apply_default(boost::any& valueStore) const override {
+ // We're using the *current* rather than *default* value here, and
+ // this is intentional; GFlags-using programs assign to FLAGS_foo
+ // before ParseCommandLineFlags() in order to change the default value,
+ // and we obey that.
+ auto val = info_->get();
+ this->transform(val);
+ valueStore = val;
+ return true;
+ }
+
+ void parse(boost::any& valueStore,
+ const std::vector<std::string>& tokens,
+ bool utf8) const override;
+
+ private:
+ virtual T parseValue(const std::vector<std::string>& tokens) const = 0;
+ virtual void transform(T& val) const { }
+
+ mutable std::shared_ptr<GFlagInfo<T>> info_;
+};
+
+template <class T>
+void GFlagValueSemanticBase<T>::parse(boost::any& valueStore,
+ const std::vector<std::string>& tokens,
+ bool utf8) const {
+ T val;
+ try {
+ val = this->parseValue(tokens);
+ this->transform(val);
+ } catch (const std::exception& e) {
+ throw po::invalid_option_value(
+ tokens.empty() ? std::string() : tokens.front());
+ }
+ this->info_->set(val);
+ valueStore = val;
+}
+
+template <class T>
+class GFlagValueSemantic : public GFlagValueSemanticBase<T> {
+ public:
+ explicit GFlagValueSemantic(std::shared_ptr<GFlagInfo<T>> info)
+ : GFlagValueSemanticBase<T>(std::move(info)) { }
+
+ unsigned min_tokens() const override { return 1; }
+ unsigned max_tokens() const override { return 1; }
+
+ T parseValue(const std::vector<std::string>& tokens) const override {
+ DCHECK(tokens.size() == 1);
+ return folly::to<T>(tokens.front());
+ }
+};
+
+class BoolGFlagValueSemantic : public GFlagValueSemanticBase<bool> {
+ public:
+ explicit BoolGFlagValueSemantic(std::shared_ptr<GFlagInfo<bool>> info)
+ : GFlagValueSemanticBase<bool>(std::move(info)) { }
+
+ unsigned min_tokens() const override { return 0; }
+ unsigned max_tokens() const override { return 0; }
+
+ bool parseValue(const std::vector<std::string>& tokens) const override {
+ DCHECK(tokens.empty());
+ return true;
+ }
+};
+
+class NegativeBoolGFlagValueSemantic : public BoolGFlagValueSemantic {
+ public:
+ explicit NegativeBoolGFlagValueSemantic(std::shared_ptr<GFlagInfo<bool>> info)
+ : BoolGFlagValueSemantic(std::move(info)) { }
+
+ private:
+ void transform(bool& val) const override {
+ val = !val;
+ }
+};
+
+static const std::unordered_set<std::string> gSkipFlags {
+ "flagfile",
+ "fromenv",
+ "tryfromenv",
+ "undefok",
+ "help",
+ "helpfull",
+ "helpshort",
+ "helpon",
+ "helpmatch",
+ "helppackage",
+ "helpxml",
+ "version",
+ "tab_completion_columns",
+ "tab_completion_word",
+};
+
+static const std::unordered_map<std::string, std::string> gFlagOverrides {
+ // Allow -v in addition to --v
+ {"v", "v,v"},
+};
+
+const std::string& getName(const std::string& name) {
+ auto pos = gFlagOverrides.find(name);
+ return pos != gFlagOverrides.end() ? pos->second : name;
+}
+
+template <class T>
+void addGFlag(gflags::CommandLineFlagInfo&& flag,
+ po::options_description& desc,
+ ProgramOptionsStyle style) {
+ auto gflagInfo = std::make_shared<GFlagInfo<T>>(std::move(flag));
+ auto& info = gflagInfo->info();
+ auto name = getName(info.name);
+
+ switch (style) {
+ case ProgramOptionsStyle::GFLAGS:
+ break;
+ case ProgramOptionsStyle::GNU:
+ std::replace(name.begin(), name.end(), '_', '-');
+ break;
+ }
+ desc.add_options()
+ (name.c_str(),
+ new GFlagValueSemantic<T>(gflagInfo),
+ info.description.c_str());
+}
+
+template <>
+void addGFlag<bool>(gflags::CommandLineFlagInfo&& flag,
+ po::options_description& desc,
+ ProgramOptionsStyle style) {
+ auto gflagInfo = std::make_shared<GFlagInfo<bool>>(std::move(flag));
+ auto& info = gflagInfo->info();
+ auto name = getName(info.name);
+ std::string negationPrefix;
+
+ switch (style) {
+ case ProgramOptionsStyle::GFLAGS:
+ negationPrefix = "no";
+ break;
+ case ProgramOptionsStyle::GNU:
+ std::replace(name.begin(), name.end(), '_', '-');
+ negationPrefix = "no-";
+ break;
+ }
+
+ desc.add_options()
+ (name.c_str(),
+ new BoolGFlagValueSemantic(gflagInfo),
+ info.description.c_str())
+ ((negationPrefix + name).c_str(),
+ new NegativeBoolGFlagValueSemantic(gflagInfo),
+ folly::to<std::string>("(no) ", info.description).c_str());
+}
+
+typedef void(*FlagAdder)(gflags::CommandLineFlagInfo&&,
+ po::options_description&,
+ ProgramOptionsStyle);
+
+const std::unordered_map<std::string, FlagAdder> gFlagAdders = {
+#define X(NAME, TYPE) \
+ {NAME, addGFlag<TYPE>},
+ X("bool", bool)
+ X("int32", int32_t)
+ X("int64", int64_t)
+ X("uint64", uint64_t)
+ X("double", double)
+ X("string", std::string)
+#undef X
+};
+
+} // namespace
+
+po::options_description getGFlags(ProgramOptionsStyle style) {
+ po::options_description desc("GFlags");
+
+ std::vector<gflags::CommandLineFlagInfo> allFlags;
+ gflags::GetAllFlags(&allFlags);
+
+ for (auto& f : allFlags) {
+ if (gSkipFlags.count(f.name)) {
+ continue;
+ }
+ auto pos = gFlagAdders.find(f.type);
+ CHECK(pos != gFlagAdders.end()) << "Invalid flag type: " << f.type;
+ (*pos->second)(std::move(f), desc, style);
+ }
+
+ return desc;
+}
+
+namespace {
+
+NestedCommandLineParseResult doParseNestedCommandLine(
+ po::command_line_parser&& parser,
+ const po::options_description& desc) {
+ NestedCommandLineParseResult result;
+
+ result.options = parser.options(desc).allow_unregistered().run();
+
+ bool setCommand = true;
+ for (auto& opt : result.options.options) {
+ auto& tokens = opt.original_tokens;
+ auto tokensStart = tokens.begin();
+
+ if (setCommand && opt.position_key != -1) {
+ DCHECK(tokensStart != tokens.end());
+ result.command = *(tokensStart++);
+ }
+
+ if (opt.position_key != -1 || opt.unregistered) {
+ // If we see an unrecognized option before the first positional
+ // argument, assume we don't have a valid command name, because
+ // we don't know how to parse it otherwise.
+ //
+ // program --wtf foo bar
+ //
+ // Is "foo" an argument to "--wtf", or the command name?
+ setCommand = false;
+ result.rest.insert(result.rest.end(), tokensStart, tokens.end());
+ }
+ }
+
+ return result;
+}
+
+} // namespace
+
+NestedCommandLineParseResult parseNestedCommandLine(
+ int argc, const char* const argv[],
+ const po::options_description& desc) {
+ return doParseNestedCommandLine(po::command_line_parser(argc, argv), desc);
+}
+
+NestedCommandLineParseResult parseNestedCommandLine(
+ const std::vector<std::string>& cmdline,
+ const po::options_description& desc) {
+ return doParseNestedCommandLine(po::command_line_parser(cmdline), desc);
+}
+
+} // namespaces
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FOLLY_PROGRAMOPTIONS_H_
+#define FOLLY_PROGRAMOPTIONS_H_
+
+#include <boost/program_options.hpp>
+#include <folly/Optional.h>
+#include <gflags/gflags.h>
+
+namespace folly {
+
+enum class ProgramOptionsStyle {
+ GFLAGS,
+ GNU
+};
+
+// Add all GFlags to the given options_description.
+// Use this *instead of* gflags::ParseCommandLineFlags().
+//
+// in GFLAGS style, the flags are named as per gflags conventions:
+// names_with_underscores
+// boolean flags have a "no" prefix
+//
+// in GNU style, the flags are named as per GNU conventions:
+// names-with-dashes
+// boolean flags have a "no-" prefix
+//
+// Consider (for example) a boolean flag:
+// DEFINE_bool(flying_pigs, false, "...");
+//
+// In GFLAGS style, the corresponding flags are named
+// flying_pigs
+// noflying_pigs
+//
+// In GNU style, the corresponding flags are named
+// flying-pigs
+// no-flying-pigs
+//
+// You may not pass arguments to boolean flags, so you must use the
+// "no" / "no-" prefix to set them to false; "--flying_pigs false"
+// and "--flying_pigs=false" are not allowed, to prevent ambiguity.
+boost::program_options::options_description getGFlags(
+ ProgramOptionsStyle style = ProgramOptionsStyle::GNU);
+
+// Helper when parsing nested command lines:
+//
+// program [--common_options...] command [--command_options...] args
+//
+// The result has "command" set to the first positional argument, if any,
+// and "rest" set to the remaining options and arguments. Note that any
+// unrecognized flags must appear after the command name.
+//
+// You may pass "rest" to parseNestedCommandLine again, etc.
+struct NestedCommandLineParseResult {
+ NestedCommandLineParseResult() { }
+
+ boost::program_options::parsed_options options {nullptr};
+
+ Optional<std::string> command;
+ std::vector<std::string> rest;
+};
+
+NestedCommandLineParseResult parseNestedCommandLine(
+ int argc, const char* const argv[],
+ const boost::program_options::options_description& desc);
+
+NestedCommandLineParseResult parseNestedCommandLine(
+ const std::vector<std::string>& cmdline,
+ const boost::program_options::options_description& desc);
+
+} // namespaces
+
+#endif /* FOLLY_PROGRAMOPTIONS_H_ */
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/experimental/ProgramOptions.h>
+
+#include <folly/FileUtil.h>
+#include <folly/Subprocess.h>
+#include <folly/experimental/io/FsUtil.h>
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+namespace folly { namespace test {
+
+namespace {
+
+std::string getHelperPath() {
+ auto path = fs::executable_path();
+ path.remove_filename() /= "program_options_test_helper";
+ return path.native();
+}
+
+std::string callHelper(ProgramOptionsStyle style,
+ std::initializer_list<std::string> args) {
+ static std::string helperPath = getHelperPath();
+
+ std::vector<std::string> allArgs;
+ allArgs.reserve(args.size() + 1);
+ allArgs.push_back(helperPath);
+ allArgs.insert(allArgs.end(), args.begin(), args.end());
+
+ std::vector<std::string> env;
+ switch (style) {
+ case ProgramOptionsStyle::GNU:
+ env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GNU");
+ break;
+ case ProgramOptionsStyle::GFLAGS:
+ env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GFLAGS");
+ break;
+ }
+
+ Subprocess proc(allArgs, Subprocess::pipeStdout(), nullptr, &env);
+ auto p = proc.communicate();
+ EXPECT_EQ(0, proc.wait().exitStatus());
+
+ return p.first;
+}
+
+} // namespace
+
+// name value
+
+TEST(ProgramOptionsTest, GFlagsStyleDefaultValues) {
+ EXPECT_EQ(
+ "flag_bool_true 1\n"
+ "flag_bool_false 0\n"
+ "flag_int 42\n"
+ "flag_string foo\n",
+ callHelper(ProgramOptionsStyle::GFLAGS, {}));
+}
+
+TEST(ProgramOptionsTest, GFlagsStyleFlagsSet) {
+ EXPECT_EQ(
+ "flag_bool_true 1\n"
+ "flag_bool_false 1\n"
+ "flag_int 43\n"
+ "flag_string bar\n",
+ callHelper(ProgramOptionsStyle::GFLAGS, {
+ "--flag_bool_true",
+ "--flag_bool_false",
+ "--flag_int", "43",
+ "--flag_string", "bar"}));
+}
+
+TEST(ProgramOptionsTest, GFlagsStyleBoolFlagsNegation) {
+ EXPECT_EQ(
+ "flag_bool_true 0\n"
+ "flag_bool_false 0\n"
+ "flag_int 42\n"
+ "flag_string foo\n",
+ callHelper(ProgramOptionsStyle::GFLAGS, {
+ "--noflag_bool_true",
+ "--noflag_bool_false"}));
+}
+
+TEST(ProgramOptionsTest, GNUStyleDefaultValues) {
+ EXPECT_EQ(
+ "flag-bool-true 1\n"
+ "flag-bool-false 0\n"
+ "flag-int 42\n"
+ "flag-string foo\n",
+ callHelper(ProgramOptionsStyle::GNU, {}));
+}
+
+TEST(ProgramOptionsTest, GNUStyleFlagsSet) {
+ EXPECT_EQ(
+ "flag-bool-true 1\n"
+ "flag-bool-false 1\n"
+ "flag-int 43\n"
+ "flag-string bar\n",
+ callHelper(ProgramOptionsStyle::GNU, {
+ "--flag-bool-true",
+ "--flag-bool-false",
+ "--flag-int", "43",
+ "--flag-string", "bar"}));
+}
+
+TEST(ProgramOptionsTest, GNUStyleBoolFlagsNegation) {
+ EXPECT_EQ(
+ "flag-bool-true 0\n"
+ "flag-bool-false 0\n"
+ "flag-int 42\n"
+ "flag-string foo\n",
+ callHelper(ProgramOptionsStyle::GNU, {
+ "--no-flag-bool-true",
+ "--no-flag-bool-false"}));
+}
+
+TEST(ProgramOptionsTest, GNUStyleSubCommand) {
+ EXPECT_EQ(
+ "flag-bool-true 1\n"
+ "flag-bool-false 1\n"
+ "flag-int 43\n"
+ "flag-string foo\n"
+ "command hello\n"
+ "arg --wtf\n"
+ "arg 100\n"
+ "arg -x\n"
+ "arg -xy\n",
+ callHelper(ProgramOptionsStyle::GNU, {
+ "--flag-bool-false",
+ "hello",
+ "--wtf",
+ "--flag-int", "43",
+ "100",
+ "-x",
+ "-xy"}));
+}
+
+TEST(ProgramOptionsTest, GNUStyleSubCommandUnrecognizedOptionFirst) {
+ EXPECT_EQ(
+ "flag-bool-true 1\n"
+ "flag-bool-false 1\n"
+ "flag-int 43\n"
+ "flag-string foo\n"
+ "arg --wtf\n"
+ "arg hello\n"
+ "arg 100\n"
+ "arg -x\n"
+ "arg -xy\n",
+ callHelper(ProgramOptionsStyle::GNU, {
+ "--flag-bool-false",
+ "--wtf",
+ "hello",
+ "--flag-int", "43",
+ "100",
+ "-x",
+ "-xy"}));
+}
+
+}} // namespaces
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <iostream>
+#include <folly/Conv.h>
+#include <folly/experimental/ProgramOptions.h>
+#include <glog/logging.h>
+
+DEFINE_bool(flag_bool_true, true, "Bool with true default value");
+DEFINE_bool(flag_bool_false, false, "Bool with false default value");
+DEFINE_int32(flag_int, 42, "Integer flag");
+DEFINE_string(flag_string, "foo", "String flag");
+
+namespace po = ::boost::program_options;
+
+namespace {
+template <class T>
+void print(const po::variables_map& vm, const std::string& name) {
+ auto& v = vm[name];
+ printf("%s %s\n",
+ name.c_str(),
+ folly::to<std::string>(v.as<T>()).c_str());
+}
+} // namespace
+
+int main(int argc, char *argv[]) {
+ po::options_description desc;
+ auto styleEnv = getenv("PROGRAM_OPTIONS_TEST_STYLE");
+
+ CHECK(styleEnv) << "PROGRAM_OPTIONS_TEST_STYLE is required";
+ bool gnuStyle = !strcmp(styleEnv, "GNU");
+ CHECK(gnuStyle || !strcmp(styleEnv, "GFLAGS"))
+ << "Invalid value for PROGRAM_OPTIONS_TEST_STYLE";
+
+ desc.add(getGFlags(
+ gnuStyle ? folly::ProgramOptionsStyle::GNU :
+ folly::ProgramOptionsStyle::GFLAGS));
+ desc.add_options()
+ ("help,h", "help");
+
+ po::variables_map vm;
+ auto result = folly::parseNestedCommandLine(argc, argv, desc);
+ po::store(result.options, vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ std::cout << desc;
+ return 1;
+ }
+
+ print<bool>(vm, gnuStyle ? "flag-bool-true" : "flag_bool_true");
+ print<bool>(vm, gnuStyle ? "flag-bool-false" : "flag_bool_false");
+ print<int32_t>(vm, gnuStyle ? "flag-int" : "flag_int");
+ print<std::string>(vm, gnuStyle ? "flag-string" : "flag_string");
+
+ if (result.command) {
+ printf("command %s\n", result.command->c_str());
+ }
+
+ for (auto& arg : result.rest) {
+ printf("arg %s\n", arg.c_str());
+ }
+
+ return 0;
+}
--- /dev/null
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_boost_program_options.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_BOOST_PROGRAM_OPTIONS
+#
+# DESCRIPTION
+#
+# Test for program options library from the Boost C++ libraries. The macro
+# requires a preceding call to AX_BOOST_BASE. Further documentation is
+# available at <http://randspringer.de/boost/index.html>.
+#
+# This macro calls:
+#
+# AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB)
+#
+# And sets:
+#
+# HAVE_BOOST_PROGRAM_OPTIONS
+#
+# LICENSE
+#
+# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 24
+
+AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS],
+[
+ AC_ARG_WITH([boost-program-options],
+ AS_HELP_STRING([--with-boost-program-options@<:@=special-lib@:>@],
+ [use the program options library from boost - it is possible to specify a certain library for the linker
+ e.g. --with-boost-program-options=boost_program_options-gcc-mt-1_33_1 ]),
+ [
+ if test "$withval" = "no"; then
+ want_boost="no"
+ elif test "$withval" = "yes"; then
+ want_boost="yes"
+ ax_boost_user_program_options_lib=""
+ else
+ want_boost="yes"
+ ax_boost_user_program_options_lib="$withval"
+ fi
+ ],
+ [want_boost="yes"]
+ )
+
+ if test "x$want_boost" = "xyes"; then
+ AC_REQUIRE([AC_PROG_CC])
+ export want_boost
+ CPPFLAGS_SAVED="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ export CPPFLAGS
+ LDFLAGS_SAVED="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ export LDFLAGS
+ AC_CACHE_CHECK([whether the Boost::Program_Options library is available],
+ ax_cv_boost_program_options,
+ [AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/program_options/errors.hpp>
+ ]],
+ [[boost::program_options::error err("Error message");
+ return 0;]])],
+ ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no)
+ AC_LANG_POP([C++])
+ ])
+ if test "$ax_cv_boost_program_options" = yes; then
+ AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available])
+ BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ if test "x$ax_boost_user_program_options_lib" = "x"; then
+ for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.dylib* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.dylib.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.a.*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ if test "x$link_program_options" != "xyes"; then
+ for libextension in `ls $BOOSTLIBDIR/boost_program_options*.dll* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.dll.*$;\1;'` `ls $BOOSTLIBDIR/boost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.a.*$;\1;'` ; do
+ ax_lib=${libextension}
+ AC_CHECK_LIB($ax_lib, exit,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ fi
+ else
+ for ax_lib in $ax_boost_user_program_options_lib boost_program_options-$ax_boost_user_program_options_lib; do
+ AC_CHECK_LIB($ax_lib, main,
+ [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break],
+ [link_program_options="no"])
+ done
+ fi
+ if test "x$ax_lib" = "x"; then
+ AC_MSG_ERROR(Could not find a version of the library!)
+ fi
+ if test "x$link_program_options" != "xyes"; then
+ AC_MSG_ERROR([Could not link against [$ax_lib] !])
+ fi
+ fi
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ fi
+])