Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Framework/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ o2_add_library(Framework
src/O2ControlHelpers.cxx
src/O2ControlLabels.cxx
src/OutputSpec.cxx
src/OptionsHelpers.cxx
src/PropertyTreeHelpers.cxx
src/Plugins.cxx
src/RateLimiter.cxx
Expand Down Expand Up @@ -207,6 +208,7 @@ foreach(t
InputSpec
Kernels
LogParsingHelpers
OptionsHelpers
OverrideLabels
PtrHelpers
Root2ArrowTable
Expand Down
4 changes: 3 additions & 1 deletion Framework/Core/src/DeviceSpecHelpers.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1244,7 +1244,9 @@ void DeviceSpecHelpers::prepareArguments(bool defaultQuiet, bool defaultStopped,
ConfigParamsHelper::dpl2BoostOptions(spec.options, od);
od.add_options()(name, bpo::value<std::string>());
ConfigParamsHelper::dpl2BoostOptions(workflowOptions, foDesc);
foDesc.add(getForwardedDeviceOptions());
auto forwardedOptions = getForwardedDeviceOptions();
/// Add to foDesc the options which are not already there
foDesc.add(forwardedOptions);

// has option --session been specified on the command line?
bool haveSessionArg = false;
Expand Down
62 changes: 62 additions & 0 deletions Framework/Core/src/OptionsHelpers.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#include "OptionsHelpers.h"
#include "Framework/Logger.h"
#include <boost/program_options.hpp>

namespace bpo = boost::program_options;

// Create a unique set of options and add them to the parser
// This is needed to avoid duplicate definitions in the main parser
// (e.g. if a device has a config option and a device-specific option)
// However, we complain if there are duplicate definitions which have
// different default values.
// Notice it's probably a good idea to simply specify string options
// and have the cast done in the user code. In any case what is
// passes on the command line is a string.
auto o2::framework::OptionsHelpers::makeUniqueOptions(bpo::options_description const& od) -> bpo::options_description
{
bpo::options_description uniqueOptions;
std::set<std::string> uniqueNames;
std::map<std::string, std::string> optionDefaults;
for (auto& option : od.options()) {
if (uniqueNames.find(option->format_name()) == uniqueNames.end()) {
uniqueOptions.add(option);
uniqueNames.insert(option->format_name());
boost::any defaultValue;
option->semantic()->apply_default(defaultValue);
// check if defaultValue is a string and if so, store it
if (defaultValue.type() == typeid(std::string)) {
optionDefaults.insert({option->format_name(), boost::any_cast<std::string>(defaultValue)});
} else {
optionDefaults.insert({option->format_name(), "not a string"});
}
} else {
if (option->semantic()->max_tokens() == 1) {
LOG(debug) << "Option " << option->format_name() << " is already defined, skipping";
boost::any defaultValue1;
option->semantic()->apply_default(defaultValue1);
if (defaultValue1.type() != typeid(std::string)) {
LOGP(error, "Option {} is already defined but it's not a string, please fix it. Actualy type {}", option->format_name(), defaultValue1.type().name());
}
auto defaultValueStr1 = boost::any_cast<std::string>(defaultValue1);
auto defaultValueStr2 = optionDefaults.at(option->format_name());
if (defaultValueStr2 == "not a string") {
LOGP(error, "{} is duplicate but strings are the only supported duplicate values", option->format_name());
}
if (defaultValueStr1 != defaultValueStr2) {
LOGP(error, "Option {} has different default values: {} and {}", option->format_name(), defaultValueStr1, defaultValueStr2);
}
}
}
}
return uniqueOptions;
};
38 changes: 38 additions & 0 deletions Framework/Core/src/OptionsHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#ifndef O2_FRAMEWORK_OPTIONSHELPERS_H_
#define O2_FRAMEWORK_OPTIONSHELPERS_H_

#include <boost/program_options/variables_map.hpp>
#include <iosfwd>

namespace boost::program_options
{
class options_description;
class variables_map;
} // namespace boost::program_options

namespace o2::framework
{
struct OptionsHelpers {
template <typename T>
static T as(boost::program_options::variable_value const& v)
{
std::istringstream is(v.as<std::string>());
T t;
is >> t;
return t;
}

static boost::program_options::options_description makeUniqueOptions(boost::program_options::options_description const& od);
};
} // namespace o2::framework
#endif // O2_FRAMEWORK_OPTIONSHELPERS_H_
26 changes: 26 additions & 0 deletions Framework/Core/test/test_OptionsHelpers.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#define BOOST_TEST_MODULE Test Framework OptionsHelpers
#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/program_options.hpp>
#include "../src/OptionsHelpers.h"
namespace bpo = boost::program_options;

BOOST_AUTO_TEST_CASE(Merging)
{
boost::program_options::options_description desc1;
desc1.add_options()("help,h", bpo::value<std::string>()->default_value("foo"), "Print help message")("help,h", bpo::value<std::string>()->default_value("foo"), "Print help message");
auto res = o2::framework::OptionsHelpers::makeUniqueOptions(desc1);
BOOST_CHECK_EQUAL(res.options().size(), 1);
}