refactor: centralize update_env across binaries with unit test added … (#2029)
* refactor: centralize update_env across binaries with unit test added for testing * removed unused includes suggested by clangd and small cleanup * use centralized update_env in argparse as well * review comments incorporated * move update_env tests closer to common library * fix: missing common:: prefix in rocprof-sys-sample * cmake formatting
This commit is contained in:
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "common/environment.hpp"
|
||||
#include "common/join.hpp"
|
||||
#include "common/path.hpp"
|
||||
#include "core/mproc.hpp"
|
||||
#include "core/utility.hpp"
|
||||
@@ -37,6 +36,7 @@
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
#include <timemory/utility/join.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
@@ -58,6 +58,7 @@ namespace console = ::tim::utility::console;
|
||||
namespace argparse = ::tim::argparse;
|
||||
namespace path = rocprofsys::common::path;
|
||||
using namespace ::timemory::join;
|
||||
using rocprofsys::common::update_mode;
|
||||
using ::rocprofsys::utility::parse_numeric_range;
|
||||
using ::tim::get_env;
|
||||
using ::tim::log::monochrome;
|
||||
@@ -301,61 +302,28 @@ void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
bool _append, std::string_view _join_delim)
|
||||
{
|
||||
updated_envs.emplace(_env_var);
|
||||
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _environ)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) == 0)
|
||||
{
|
||||
if(_append)
|
||||
{
|
||||
if(std::string_view{ itr }.find(join("", _env_val)) ==
|
||||
std::string_view::npos)
|
||||
{
|
||||
auto _val = std::string{ itr }.substr(_key.length());
|
||||
free(itr);
|
||||
if(_env_var == "LD_PRELOAD")
|
||||
{
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _env_val, _val))
|
||||
.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _val, _env_val))
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(itr);
|
||||
itr = strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
_environ.emplace_back(
|
||||
strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str()));
|
||||
auto _mode = _append ? update_mode::APPEND : update_mode::REPLACE;
|
||||
rocprofsys::common::update_env(_environ, _env_var, std::forward<Tp>(_env_val), _mode,
|
||||
_join_delim, updated_envs, original_envs);
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
add_default_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val)
|
||||
{
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _environ)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) == 0) return;
|
||||
}
|
||||
// Check if already exists
|
||||
auto _key = join("", _env_var, "=");
|
||||
const auto exists =
|
||||
std::any_of(_environ.begin(), _environ.end(), [&_key](const char* itr) {
|
||||
return itr && std::string_view{ itr }.find(_key) == 0;
|
||||
});
|
||||
|
||||
updated_envs.emplace(_env_var);
|
||||
_environ.emplace_back(
|
||||
strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str()));
|
||||
if(exists) return;
|
||||
|
||||
// If not exists, use common::update_env
|
||||
rocprofsys::common::update_env(_environ, _env_var, std::forward<Tp>(_env_val),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
}
|
||||
|
||||
std::vector<char*>
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
bool _append = false, std::string_view _join_delim = ":");
|
||||
|
||||
int
|
||||
get_verbose();
|
||||
|
||||
@@ -49,15 +54,6 @@ prepare_command_for_run(char*, std::vector<char*>&);
|
||||
void
|
||||
prepare_environment_for_run(std::vector<char*>&);
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(std::vector<char*>&, std::string_view, Tp&&, bool _append = false,
|
||||
std::string_view _join_delim = ":");
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
add_default_env(std::vector<char*>&, std::string_view, Tp&&);
|
||||
|
||||
std::vector<char*>
|
||||
parse_args(int argc, char** argv, std::vector<char*>&,
|
||||
std::vector<std::map<std::string_view, std::string>>&);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "common/environment.hpp"
|
||||
#include "common/join.hpp"
|
||||
#include "common/path.hpp"
|
||||
#include "core/argparse.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
@@ -76,71 +75,9 @@ to_string(bool _v)
|
||||
|
||||
namespace
|
||||
{
|
||||
using rocprofsys::common::update_mode;
|
||||
|
||||
auto original_envs = std::unordered_set<std::string>{};
|
||||
enum update_mode : int
|
||||
{
|
||||
UPD_REPLACE = 0, // no PREPEND/APPEND bits set
|
||||
UPD_PREPEND = 1 << 0, // 0x01
|
||||
UPD_APPEND = 1 << 1, // 0x02
|
||||
UPD_WEAK = 1 << 2, // 0x04
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
update_mode&& _mode, std::string_view _join_delim = ":")
|
||||
{
|
||||
auto _prepend = (_mode & UPD_PREPEND) != 0;
|
||||
auto _append = (_mode & UPD_APPEND) != 0;
|
||||
auto _weak_upd = (_mode & UPD_WEAK) != 0;
|
||||
|
||||
// if both flags are set, prefer append
|
||||
if(_prepend && _append)
|
||||
{
|
||||
_prepend = false;
|
||||
}
|
||||
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _environ)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) == 0)
|
||||
{
|
||||
if(_weak_upd)
|
||||
{
|
||||
// if the value has changed, do not update but allow overridding the value
|
||||
// inherited from the initial env
|
||||
if(original_envs.find(std::string{ itr }) == original_envs.end()) return;
|
||||
}
|
||||
|
||||
if(_prepend || _append)
|
||||
{
|
||||
if(std::string_view{ itr }.find(join("", _env_val)) ==
|
||||
std::string_view::npos)
|
||||
{
|
||||
auto _val = std::string{ itr }.substr(_key.length());
|
||||
free(itr);
|
||||
if(_prepend)
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _env_val, _val))
|
||||
.c_str());
|
||||
else
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _val, _env_val))
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(itr);
|
||||
itr = strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
_environ.emplace_back(
|
||||
strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str()));
|
||||
}
|
||||
|
||||
int
|
||||
get_verbose(parser_data_t& _data)
|
||||
@@ -172,16 +109,18 @@ get_initial_environment(parser_data_t& _data)
|
||||
auto _libexecpath = path::realpath(path::get_internal_script_path());
|
||||
if(!_libexecpath.empty())
|
||||
{
|
||||
update_env(_data.current, "ROCPROFSYS_SCRIPT_PATH", _libexecpath, UPD_REPLACE);
|
||||
_data.updated.emplace("ROCPROFSYS_SCRIPT_PATH");
|
||||
rocprofsys::common::update_env(_data.current, "ROCPROFSYS_SCRIPT_PATH",
|
||||
_libexecpath, update_mode::REPLACE, ":",
|
||||
_data.updated, original_envs);
|
||||
}
|
||||
|
||||
const bool verbose = (get_verbose(_data) > 0);
|
||||
if(auto llvm_dir = rocprofsys::common::discover_llvm_libdir_for_ompt(verbose);
|
||||
!llvm_dir.empty())
|
||||
{
|
||||
update_env(_data.current, "LD_LIBRARY_PATH", llvm_dir, UPD_APPEND);
|
||||
_data.updated.emplace("LD_LIBRARY_PATH");
|
||||
rocprofsys::common::update_env(_data.current, "LD_LIBRARY_PATH", llvm_dir,
|
||||
update_mode::APPEND, ":", _data.updated,
|
||||
original_envs);
|
||||
auto current_ld = getenv("LD_LIBRARY_PATH");
|
||||
std::string new_ld = current_ld ? (llvm_dir + ":" + current_ld) : llvm_dir;
|
||||
setenv("LD_LIBRARY_PATH", new_ld.c_str(), 1);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "rocprof-sys-sample.hpp"
|
||||
|
||||
#include "common/environment.hpp"
|
||||
#include "common/join.hpp"
|
||||
#include "common/path.hpp"
|
||||
|
||||
#include <timemory/environment.hpp>
|
||||
@@ -46,6 +45,7 @@ namespace color = tim::log::color;
|
||||
namespace path = rocprofsys::common::path;
|
||||
using namespace timemory::join;
|
||||
using rocprofsys::common::remove_env;
|
||||
using rocprofsys::common::update_mode;
|
||||
using tim::get_env;
|
||||
using tim::log::monochrome;
|
||||
using tim::log::stream;
|
||||
@@ -118,21 +118,32 @@ get_initial_environment()
|
||||
auto _libexecpath = path::realpath(path::get_internal_script_path());
|
||||
auto _rootpath = path::realpath(path::get_rocprofsys_root());
|
||||
|
||||
update_env(_env, "ROCPROFSYS_ROOT", _rootpath, UPD_REPLACE);
|
||||
update_env(_env, "LD_PRELOAD", _dl_libpath, UPD_APPEND);
|
||||
update_env(_env, "LD_LIBRARY_PATH", tim::filepath::dirname(_dl_libpath), UPD_APPEND);
|
||||
update_env(_env, "ROCPROFSYS_SCRIPT_PATH", _libexecpath, UPD_REPLACE);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_ROOT", _rootpath,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
rocprofsys::common::update_env(_env, "LD_PRELOAD", _dl_libpath, update_mode::APPEND,
|
||||
":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "LD_LIBRARY_PATH",
|
||||
tim::filepath::dirname(_dl_libpath),
|
||||
update_mode::APPEND, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SCRIPT_PATH", _libexecpath,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
// Discover LLVM libdir containing libomptarget.so and append to LD_LIBRARY_PATH
|
||||
if(auto llvm_dir = rocprofsys::common::discover_llvm_libdir_for_ompt(verbose > 0);
|
||||
!llvm_dir.empty())
|
||||
{
|
||||
update_env(_env, "LD_LIBRARY_PATH", llvm_dir, UPD_APPEND);
|
||||
rocprofsys::common::update_env(_env, "LD_LIBRARY_PATH", llvm_dir,
|
||||
update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
}
|
||||
|
||||
auto _mode = get_env<std::string>("ROCPROFSYS_MODE", "sampling", false);
|
||||
|
||||
update_env(_env, "ROCPROFSYS_USE_SAMPLING", (_mode != "causal"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_USE_SAMPLING", (_mode != "causal"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
return _env;
|
||||
}
|
||||
@@ -184,65 +195,6 @@ print_updated_environment(std::vector<char*> _env)
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
update_mode&& _mode, std::string_view _join_delim)
|
||||
{
|
||||
updated_envs.emplace(_env_var);
|
||||
|
||||
auto _prepend = (_mode & UPD_PREPEND) != 0;
|
||||
auto _append = (_mode & UPD_APPEND) != 0;
|
||||
auto _weak_upd = (_mode & UPD_WEAK) != 0;
|
||||
|
||||
// if both flags are set, prefer append
|
||||
if(_prepend && _append)
|
||||
{
|
||||
_prepend = false;
|
||||
}
|
||||
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _environ)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) == 0)
|
||||
{
|
||||
if(_weak_upd)
|
||||
{
|
||||
// if the value has changed, do not update but allow overridding the value
|
||||
// inherited from the initial env
|
||||
if(original_envs.find(std::string{ itr }) == original_envs.end()) return;
|
||||
}
|
||||
|
||||
if(_prepend || _append)
|
||||
{
|
||||
if(std::string_view{ itr }.find(join("", _env_val)) ==
|
||||
std::string_view::npos)
|
||||
{
|
||||
auto _val = std::string{ itr }.substr(_key.length());
|
||||
free(itr);
|
||||
if(_prepend)
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _env_val, _val))
|
||||
.c_str());
|
||||
else
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _val, _env_val))
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(itr);
|
||||
itr = strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
_environ.emplace_back(
|
||||
strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str()));
|
||||
}
|
||||
|
||||
std::vector<char*>
|
||||
parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
{
|
||||
@@ -335,20 +287,28 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
auto _monochrome = p.get<bool>("monochrome");
|
||||
monochrome() = _monochrome;
|
||||
p.set_use_color(!_monochrome);
|
||||
update_env(_env, "ROCPROFSYS_MONOCHROME", (_monochrome) ? "1" : "0");
|
||||
update_env(_env, "MONOCHROME", (_monochrome) ? "1" : "0");
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_MONOCHROME", (_monochrome) ? "1" : "0",
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "MONOCHROME", (_monochrome) ? "1" : "0",
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser.add_argument({ "--debug" }, "Debug output")
|
||||
.max_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_DEBUG", p.get<bool>("debug"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_DEBUG", p.get<bool>("debug"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser.add_argument({ "-v", "--verbose" }, "Verbose output")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<int>("verbose");
|
||||
verbose = _v;
|
||||
update_env(_env, "ROCPROFSYS_VERBOSE", _v);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_VERBOSE", _v,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
|
||||
parser.start_group("GENERAL OPTIONS",
|
||||
@@ -357,9 +317,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.min_count(0)
|
||||
.dtype("filepath")
|
||||
.action([&](parser_t& p) {
|
||||
update_env(
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_CONFIG_FILE",
|
||||
join(array_config{ ":" }, p.get<std::vector<std::string>>("config")));
|
||||
join(array_config{ ":" }, p.get<std::vector<std::string>>("config")),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-o", "--output" },
|
||||
@@ -369,21 +330,30 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.max_count(2)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::vector<std::string>>("output");
|
||||
update_env(_env, "ROCPROFSYS_OUTPUT_PATH", _v.at(0));
|
||||
if(_v.size() > 1) update_env(_env, "ROCPROFSYS_OUTPUT_PREFIX", _v.at(1));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_OUTPUT_PATH", _v.at(0),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(_v.size() > 1)
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_OUTPUT_PREFIX", _v.at(1),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-T", "--trace" }, "Generate a detailed trace (perfetto output)")
|
||||
.max_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE", p.get<bool>("trace"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_TRACE", p.get<bool>("trace"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--trace-cached" },
|
||||
"Generate a detailed trace (perfetto output) from cached data ")
|
||||
.max_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_CACHED", p.get<bool>("trace-cached"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_CACHED", p.get<bool>("trace-cached"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -392,7 +362,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.max_count(1)
|
||||
.conflicts({ "flat-profile" })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PROFILE", p.get<bool>("profile"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_PROFILE",
|
||||
p.get<bool>("profile"), update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-F", "--flat-profile" },
|
||||
@@ -400,8 +372,12 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.max_count(1)
|
||||
.conflicts({ "profile" })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PROFILE", p.get<bool>("flat-profile"));
|
||||
update_env(_env, "ROCPROFSYS_FLAT_PROFILE", p.get<bool>("flat-profile"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_PROFILE", p.get<bool>("flat-profile"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_FLAT_PROFILE", p.get<bool>("flat-profile"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-H", "--host" },
|
||||
@@ -411,9 +387,16 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.action([&](parser_t& p) {
|
||||
auto _h = p.get<bool>("host");
|
||||
auto _d = p.get<bool>("device");
|
||||
update_env(_env, "ROCPROFSYS_USE_PROCESS_SAMPLING", _h || _d);
|
||||
update_env(_env, "ROCPROFSYS_CPU_FREQ_ENABLED", _h);
|
||||
if(_h) update_env(_env, "ROCPROFSYS_USE_AMD_SMI", _d);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_USE_PROCESS_SAMPLING",
|
||||
_h || _d, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_CPU_FREQ_ENABLED", _h,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(_h)
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_USE_AMD_SMI", _d,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-D", "--device" },
|
||||
@@ -423,9 +406,16 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.action([&](parser_t& p) {
|
||||
auto _h = p.get<bool>("host");
|
||||
auto _d = p.get<bool>("device");
|
||||
update_env(_env, "ROCPROFSYS_USE_PROCESS_SAMPLING", _h || _d);
|
||||
update_env(_env, "ROCPROFSYS_USE_AMD_SMI", _d);
|
||||
if(_d) update_env(_env, "ROCPROFSYS_CPU_FREQ_ENABLED", _h);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_USE_PROCESS_SAMPLING",
|
||||
_h || _d, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_USE_AMD_SMI", _d,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(_d)
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_CPU_FREQ_ENABLED", _h,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-w", "--wait" },
|
||||
@@ -433,8 +423,12 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"'--sampling-wait'. See the descriptions for those two options.")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_DELAY", p.get<double>("wait"));
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_DELAY", p.get<double>("wait"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_TRACE_DELAY",
|
||||
p.get<double>("wait"), update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_DELAY",
|
||||
p.get<double>("wait"), update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -443,8 +437,12 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"'--sampling-duration'. See the descriptions for those two options.")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_DURATION", p.get<double>("duration"));
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_DURATION", p.get<double>("duration"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_DURATION", p.get<double>("duration"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_DURATION", p.get<double>("duration"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
|
||||
parser.start_group("TRACING OPTIONS", "Specific options controlling tracing (i.e. "
|
||||
@@ -456,8 +454,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.count(1)
|
||||
.dtype("filepath")
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PERFETTO_FILE",
|
||||
p.get<std::string>("trace-file"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_PERFETTO_FILE", p.get<std::string>("trace-file"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--trace-buffer-size" },
|
||||
@@ -465,15 +464,19 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.count(1)
|
||||
.dtype("KB")
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PERFETTO_BUFFER_SIZE_KB",
|
||||
p.get<int64_t>("trace-buffer-size"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_PERFETTO_BUFFER_SIZE_KB",
|
||||
p.get<int64_t>("trace-buffer-size"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser.add_argument({ "--trace-fill-policy" }, _trace_policy_desc)
|
||||
.count(1)
|
||||
.choices({ "discard", "ring_buffer" })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PERFETTO_FILL_POLICY",
|
||||
p.get<std::string>("trace-fill-policy"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_PERFETTO_FILL_POLICY",
|
||||
p.get<std::string>("trace-fill-policy"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--trace-wait" },
|
||||
@@ -483,7 +486,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"but that can changed via --trace-clock-id.")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_DELAY", p.get<double>("trace-wait"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_DELAY", p.get<double>("trace-wait"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--trace-duration" },
|
||||
@@ -492,8 +497,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"that can changed via --trace-clock-id.")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_DURATION",
|
||||
p.get<double>("trace-duration"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_DURATION", p.get<double>("trace-duration"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -503,9 +509,11 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"and/or <DELAY>:<DURATION>:<REPEAT>:<CLOCK_ID>.")
|
||||
.min_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_PERIODS",
|
||||
join(array_config{ ",", "", "" },
|
||||
p.get<std::vector<std::string>>("trace-periods")));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_PERIODS",
|
||||
join(array_config{ ",", "", "" },
|
||||
p.get<std::vector<std::string>>("trace-periods")),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -518,8 +526,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"rocprof-sys to auto-scale based on the number of threads.")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_TRACE_PERIOD_CLOCK_ID",
|
||||
p.get<double>("trace-clock-id"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TRACE_PERIOD_CLOCK_ID", p.get<double>("trace-clock-id"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
})
|
||||
.choices(clock_id_choices.first)
|
||||
.choice_aliases(clock_id_choices.second);
|
||||
@@ -534,12 +543,20 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.choices({ "text", "json", "console" })
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::set<std::string>>("profile");
|
||||
update_env(_env, "ROCPROFSYS_PROFILE", true);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_PROFILE", true,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_TEXT_OUTPUT", _v.count("text") != 0);
|
||||
update_env(_env, "ROCPROFSYS_JSON_OUTPUT", _v.count("json") != 0);
|
||||
update_env(_env, "ROCPROFSYS_COUT_OUTPUT", _v.count("console") != 0);
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_TEXT_OUTPUT", _v.count("text") != 0,
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_JSON_OUTPUT", _v.count("json") != 0,
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_COUT_OUTPUT", _v.count("console") != 0,
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -552,9 +569,16 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.max_count(2)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::vector<std::string>>("profile-diff");
|
||||
update_env(_env, "ROCPROFSYS_DIFF_OUTPUT", true);
|
||||
update_env(_env, "ROCPROFSYS_INPUT_PATH", _v.at(0));
|
||||
if(_v.size() > 1) update_env(_env, "ROCPROFSYS_INPUT_PREFIX", _v.at(1));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_DIFF_OUTPUT", true,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_INPUT_PATH", _v.at(0),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(_v.size() > 1)
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_INPUT_PREFIX", _v.at(1),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
|
||||
parser.start_group(
|
||||
@@ -567,8 +591,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"(number of interrupts per second)")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PROCESS_SAMPLING_FREQ",
|
||||
p.get<double>("process-freq"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_PROCESS_SAMPLING_FREQ", p.get<double>("process-freq"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--process-wait" }, "Set the default wait time (i.e. delay) "
|
||||
@@ -576,8 +601,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"(in seconds of realtime)")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_PROCESS_SAMPLING_DELAY",
|
||||
p.get<double>("process-wait"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_PROCESS_SAMPLING_DELAY", p.get<double>("process-wait"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -585,8 +611,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"Set the duration of the host/device sampling (in seconds of realtime)")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_PROCESS_DURATION",
|
||||
p.get<double>("process-duration"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_PROCESS_DURATION",
|
||||
p.get<double>("process-duration"),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--cpus" },
|
||||
@@ -594,9 +622,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.dtype("int or range")
|
||||
.required({ "host" })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_CPUS",
|
||||
join(array_config{ "," }, p.get<std::vector<std::string>>("cpus")));
|
||||
join(array_config{ "," }, p.get<std::vector<std::string>>("cpus")),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "--gpus" },
|
||||
@@ -604,9 +633,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.dtype("int or range")
|
||||
.required({ "device" })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_GPUS",
|
||||
join(array_config{ "," }, p.get<std::vector<std::string>>("gpus")));
|
||||
join(array_config{ "," }, p.get<std::vector<std::string>>("gpus")),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
|
||||
parser.start_group("GENERAL SAMPLING OPTIONS",
|
||||
@@ -616,7 +646,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"(number of interrupts per second)")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_FREQ", p.get<double>("freq"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_FREQ",
|
||||
p.get<double>("freq"), update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -626,7 +658,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"delay of 1 second for CPU-clock sampler may not equal 1 second of realtime")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_DELAY", p.get<double>("sampling-wait"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_DELAY", p.get<double>("sampling-wait"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument(
|
||||
@@ -636,8 +670,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"real-time duration... resulting in zero samples being taken")
|
||||
.count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_DURATION",
|
||||
p.get<double>("sampling-duration"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_DURATION", p.get<double>("sampling-duration"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
parser
|
||||
.add_argument({ "-t", "--tids" },
|
||||
@@ -646,8 +681,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"is assigned an atomically incrementing value.")
|
||||
.min_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_TIDS",
|
||||
join(array_config{ ", " }, p.get<std::vector<int64_t>>("tids")));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "ROCPROFSYS_SAMPLING_TIDS",
|
||||
join(array_config{ ", " }, p.get<std::vector<int64_t>>("tids")),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
|
||||
parser.start_group(
|
||||
@@ -657,21 +694,29 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.min_count(0)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::deque<std::string>>("cputime");
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME", true);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME", true,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_FREQ", _v.front());
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_FREQ",
|
||||
_v.front(), update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
_v.pop_front();
|
||||
}
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_DELAY", _v.front());
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_DELAY",
|
||||
_v.front(), update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
_v.pop_front();
|
||||
}
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_TIDS",
|
||||
join(array_config{ "," }, _v));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME_TIDS",
|
||||
join(array_config{ "," }, _v),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -679,21 +724,29 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.min_count(0)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::deque<std::string>>("realtime");
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME", true);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME", true,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_FREQ", _v.front());
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_FREQ",
|
||||
_v.front(), update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
_v.pop_front();
|
||||
}
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_DELAY", _v.front());
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_DELAY",
|
||||
_v.front(), update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
_v.pop_front();
|
||||
}
|
||||
if(!_v.empty())
|
||||
{
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_TIDS",
|
||||
join(array_config{ "," }, _v));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_REALTIME_TIDS",
|
||||
join(array_config{ "," }, _v),
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -726,7 +779,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::set<std::string>>("include");
|
||||
auto _update = [&](const auto& _opt, bool _cond) {
|
||||
if(_cond || _v.count("all") > 0) update_env(_env, _opt, true);
|
||||
if(_cond || _v.count("all") > 0)
|
||||
rocprofsys::common::update_env(_env, _opt, true, update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
};
|
||||
_update("ROCPROFSYS_USE_KOKKOSP", _v.count("kokkosp") > 0);
|
||||
_update("ROCPROFSYS_USE_MPIP", _v.count("mpip") > 0);
|
||||
@@ -739,7 +794,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
_update("ROCPROFSYS_TRACE_THREAD_SPIN_LOCKS", _v.count("spin-locks") > 0);
|
||||
|
||||
if(_v.count("all") > 0 || _v.count("kokkosp") > 0)
|
||||
update_env(_env, "KOKKOS_TOOLS_LIBS", _omni_libpath, UPD_APPEND);
|
||||
rocprofsys::common::update_env(_env, "KOKKOS_TOOLS_LIBS", _omni_libpath,
|
||||
update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
|
||||
parser.add_argument({ "-E", "--exclude" }, "Exclude data from these backends")
|
||||
@@ -747,7 +804,10 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.action([&](parser_t& p) {
|
||||
auto _v = p.get<std::set<std::string>>("exclude");
|
||||
auto _update = [&](const auto& _opt, bool _cond) {
|
||||
if(_cond || _v.count("all") > 0) update_env(_env, _opt, false);
|
||||
if(_cond || _v.count("all") > 0)
|
||||
rocprofsys::common::update_env(_env, _opt, false,
|
||||
update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
};
|
||||
_update("ROCPROFSYS_USE_KOKKOSP", _v.count("kokkosp") > 0);
|
||||
_update("ROCPROFSYS_USE_MPIP", _v.count("mpip") > 0);
|
||||
@@ -771,7 +831,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.action([&](parser_t& p) {
|
||||
auto _events =
|
||||
join(array_config{ "," }, p.get<std::vector<std::string>>("cpu-events"));
|
||||
update_env(_env, "ROCPROFSYS_PAPI_EVENTS", _events);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_PAPI_EVENTS", _events,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
});
|
||||
|
||||
parser.start_group("MISCELLANEOUS OPTIONS", "");
|
||||
@@ -780,8 +842,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
"Include inline info in output when available")
|
||||
.max_count(1)
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_INCLUDE_INLINES",
|
||||
p.get<bool>("inlines"));
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_INCLUDE_INLINES",
|
||||
p.get<bool>("inlines"), update_mode::REPLACE,
|
||||
":", updated_envs, original_envs);
|
||||
});
|
||||
|
||||
parser.add_argument({ "--hsa-interrupt" }, _hsa_interrupt_desc)
|
||||
@@ -789,7 +852,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
.dtype("int")
|
||||
.choices({ 0, 1 })
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_env, "HSA_ENABLE_INTERRUPT", p.get<int>("hsa-interrupt"));
|
||||
rocprofsys::common::update_env(
|
||||
_env, "HSA_ENABLE_INTERRUPT", p.get<int>("hsa-interrupt"),
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
});
|
||||
|
||||
parser.end_group();
|
||||
@@ -820,7 +885,9 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
|
||||
throw std::runtime_error(_cerr.what());
|
||||
|
||||
if(parser.exists("realtime") && !parser.exists("cputime"))
|
||||
update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME", false);
|
||||
rocprofsys::common::update_env(_env, "ROCPROFSYS_SAMPLING_CPUTIME", false,
|
||||
update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
if(parser.exists("profile") && parser.exists("flat-profile"))
|
||||
throw std::runtime_error(
|
||||
"Error! '--profile' argument conflicts with '--flat-profile' argument");
|
||||
|
||||
@@ -22,17 +22,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
enum update_mode : int
|
||||
{
|
||||
UPD_REPLACE = 0, // no PREPEND/APPEND bits set
|
||||
UPD_PREPEND = 1 << 0, // 0x01
|
||||
UPD_APPEND = 1 << 1, // 0x02
|
||||
UPD_WEAK = 1 << 2, // 0x04
|
||||
};
|
||||
|
||||
void
|
||||
print_command(const std::vector<char*>& _argv);
|
||||
|
||||
@@ -42,10 +33,5 @@ print_updated_environment(std::vector<char*> _env);
|
||||
std::vector<char*>
|
||||
get_initial_environment();
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
update_mode&& _mode = UPD_REPLACE, std::string_view _join_delim = ":");
|
||||
|
||||
std::vector<char*>
|
||||
parse_args(int argc, char** argv, std::vector<char*>& envp);
|
||||
|
||||
@@ -48,3 +48,7 @@ target_compile_definitions(
|
||||
rocprofiler-systems-common-library
|
||||
INTERFACE $<BUILD_INTERFACE:ROCPROFSYS_INTERNAL_BUILD=1>
|
||||
)
|
||||
|
||||
if(ROCPROFSYS_BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -265,5 +265,82 @@ discover_llvm_libdir_for_ompt(bool verbose = false)
|
||||
return {};
|
||||
}
|
||||
|
||||
enum class update_mode : uint8_t
|
||||
{
|
||||
REPLACE = 0,
|
||||
PREPEND,
|
||||
APPEND,
|
||||
WEAK,
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
inline std::string
|
||||
to_env_string(Tp&& val)
|
||||
{
|
||||
using T = std::decay_t<Tp>;
|
||||
static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, const char*> ||
|
||||
std::is_same_v<T, bool> || std::is_arithmetic_v<T>,
|
||||
"to_env_string: unsupported type. Use string, bool, or numeric types.");
|
||||
|
||||
if constexpr(std::is_same_v<T, std::string> || std::is_same_v<T, const char*>)
|
||||
return std::string{ val };
|
||||
else if constexpr(std::is_same_v<T, bool>)
|
||||
return val ? "true" : "false";
|
||||
else
|
||||
return std::to_string(val);
|
||||
}
|
||||
|
||||
template <typename Tp>
|
||||
inline void
|
||||
update_env(std::vector<char*>& _environ, std::string_view _env_var, Tp&& _env_val,
|
||||
update_mode _mode, std::string_view _join_delim,
|
||||
std::unordered_set<std::string_view>& _updated_envs,
|
||||
const std::unordered_set<std::string>& _original_envs)
|
||||
{
|
||||
_updated_envs.emplace(_env_var);
|
||||
|
||||
const bool _prepend = (_mode == update_mode::PREPEND);
|
||||
const bool _append = (_mode == update_mode::APPEND);
|
||||
const bool _weak_upd = (_mode == update_mode::WEAK);
|
||||
|
||||
auto _env_val_str = to_env_string(std::forward<Tp>(_env_val));
|
||||
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _environ)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) != 0) continue;
|
||||
|
||||
if(_weak_upd)
|
||||
{
|
||||
if(_original_envs.find(std::string{ itr }) == _original_envs.end()) return;
|
||||
}
|
||||
|
||||
if(_prepend || _append)
|
||||
{
|
||||
if(std::string_view{ itr }.find(_env_val_str) == std::string_view::npos)
|
||||
{
|
||||
auto _val = std::string{ itr }.substr(_key.length());
|
||||
free(itr);
|
||||
if(_prepend)
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _env_val_str, _val))
|
||||
.c_str());
|
||||
else
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _val, _env_val_str))
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(itr);
|
||||
itr = strdup(join('=', _env_var, _env_val_str).c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
_environ.emplace_back(strdup(join('=', _env_var, _env_val_str).c_str()));
|
||||
}
|
||||
|
||||
} // namespace common
|
||||
} // namespace rocprofsys
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
add_library(lib-common-tests OBJECT test_update_env.cpp)
|
||||
|
||||
target_link_libraries(
|
||||
lib-common-tests
|
||||
PUBLIC rocprofiler-systems-common-library rocprofiler-systems-googletest-library
|
||||
)
|
||||
@@ -0,0 +1,420 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-2025 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "common/environment.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace rocprofsys::common;
|
||||
|
||||
static std::string
|
||||
find_env_var(const std::vector<char*>& env, std::string_view var_name)
|
||||
{
|
||||
std::string prefix = std::string(var_name) + "=";
|
||||
for(auto* itr : env)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(prefix) == 0)
|
||||
{
|
||||
return std::string{ itr };
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
class UpdateEnvTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
env_vars.clear();
|
||||
updated_envs.clear();
|
||||
original_envs.clear();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
for(auto* ptr : env_vars)
|
||||
{
|
||||
if(ptr) free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char*> env_vars;
|
||||
std::unordered_set<std::string_view> updated_envs;
|
||||
std::unordered_set<std::string> original_envs;
|
||||
};
|
||||
|
||||
TEST_F(UpdateEnvTest, ReplaceMode_NewVariable)
|
||||
{
|
||||
update_env(env_vars, "TEST_VAR", "test_value", update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "TEST_VAR=test_value");
|
||||
EXPECT_EQ(updated_envs.count("TEST_VAR"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, ReplaceMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("TEST_VAR=old_value"));
|
||||
original_envs.insert("TEST_VAR=old_value");
|
||||
|
||||
update_env(env_vars, "TEST_VAR", "new_value", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "TEST_VAR=new_value");
|
||||
EXPECT_EQ(updated_envs.count("TEST_VAR"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_NewVariable)
|
||||
{
|
||||
update_env(env_vars, "PATH", "/new/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/new/path");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("PATH=/old/path"));
|
||||
original_envs.insert("PATH=/old/path");
|
||||
|
||||
update_env(env_vars, "PATH", "/new/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/old/path:/new/path");
|
||||
EXPECT_EQ(updated_envs.count("PATH"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, PrependMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_LIBRARY_PATH=/old/lib"));
|
||||
original_envs.insert("LD_LIBRARY_PATH=/old/lib");
|
||||
|
||||
update_env(env_vars, "LD_LIBRARY_PATH", "/new/lib", update_mode::PREPEND, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "LD_LIBRARY_PATH=/new/lib:/old/lib");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_OriginalValue)
|
||||
{
|
||||
env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
original_envs.insert("WEAK_VAR=original");
|
||||
|
||||
update_env(env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "WEAK_VAR=new_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_ModifiedValue)
|
||||
{
|
||||
env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
original_envs.insert("WEAK_VAR=original");
|
||||
|
||||
free(env_vars[0]);
|
||||
env_vars[0] = strdup("WEAK_VAR=modified");
|
||||
|
||||
update_env(env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "WEAK_VAR=modified");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, BooleanValue_True)
|
||||
{
|
||||
update_env(env_vars, "BOOL_VAR", true, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BOOL_VAR=true");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, BooleanValue_False)
|
||||
{
|
||||
update_env(env_vars, "BOOL_VAR", false, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BOOL_VAR=false");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, NumericValue)
|
||||
{
|
||||
update_env(env_vars, "NUM_VAR", 42, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "NUM_VAR=42");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_AvoidsDuplicates)
|
||||
{
|
||||
env_vars.push_back(strdup("PATH=/existing/path"));
|
||||
original_envs.insert("PATH=/existing/path");
|
||||
|
||||
update_env(env_vars, "PATH", "/existing/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/existing/path");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, CustomDelimiter)
|
||||
{
|
||||
env_vars.push_back(strdup("VAR=a"));
|
||||
original_envs.insert("VAR=a");
|
||||
|
||||
update_env(env_vars, "VAR", "b", update_mode::APPEND, ",", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "VAR=a,b");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_LD_LIBRARY_PATH_Append)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib"));
|
||||
original_envs.insert("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib");
|
||||
|
||||
update_env(env_vars, "LD_LIBRARY_PATH", "/opt/rocm/lib", update_mode::APPEND, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/rocm/lib");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_LD_PRELOAD_Prepend)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_PRELOAD=/lib/existing.so"));
|
||||
original_envs.insert("LD_PRELOAD=/lib/existing.so");
|
||||
|
||||
update_env(env_vars, "LD_PRELOAD", "/opt/rocm/librocprof-sys-dl.so",
|
||||
update_mode::PREPEND, ":", updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0],
|
||||
"LD_PRELOAD=/opt/rocm/librocprof-sys-dl.so:/lib/existing.so");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_ROCPROFSYS_Environment_Variables)
|
||||
{
|
||||
update_env(env_vars, "ROCPROFSYS_TRACE", true, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_PROFILE", false, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_USE_SAMPLING", true, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_TRACE").c_str(),
|
||||
"ROCPROFSYS_TRACE=true");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_PROFILE").c_str(),
|
||||
"ROCPROFSYS_PROFILE=false");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_USE_SAMPLING").c_str(),
|
||||
"ROCPROFSYS_USE_SAMPLING=true");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_Timing_DoubleValues)
|
||||
{
|
||||
update_env(env_vars, "ROCPROFSYS_TRACE_DELAY", 1.5, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_SAMPLING_FREQ", 100.0, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 2);
|
||||
std::string delay_var = find_env_var(env_vars, "ROCPROFSYS_TRACE_DELAY");
|
||||
std::string freq_var = find_env_var(env_vars, "ROCPROFSYS_SAMPLING_FREQ");
|
||||
|
||||
EXPECT_TRUE(delay_var.find("ROCPROFSYS_TRACE_DELAY=") == 0);
|
||||
EXPECT_TRUE(freq_var.find("ROCPROFSYS_SAMPLING_FREQ=") == 0);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, StringTypes_StdString)
|
||||
{
|
||||
std::string value = "test_string_value";
|
||||
update_env(env_vars, "STRING_VAR", value, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "STRING_VAR=test_string_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, StringTypes_ConstCharPtr)
|
||||
{
|
||||
const char* value = "const_char_value";
|
||||
update_env(env_vars, "CHAR_VAR", value, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "CHAR_VAR=const_char_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, EmptyStringValue)
|
||||
{
|
||||
update_env(env_vars, "EMPTY_VAR", "", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "EMPTY_VAR=");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, MultipleVariables_DifferentNames)
|
||||
{
|
||||
update_env(env_vars, "VAR1", "value1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR2", "value2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR3", "value3", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 3);
|
||||
EXPECT_EQ(updated_envs.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR1").c_str(), "VAR1=value1");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR2").c_str(), "VAR2=value2");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR3").c_str(), "VAR3=value3");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, NullPointer_InEnvironmentVector)
|
||||
{
|
||||
env_vars.push_back(strdup("VAR1=value1"));
|
||||
env_vars.push_back(nullptr);
|
||||
env_vars.push_back(strdup("VAR2=value2"));
|
||||
original_envs.insert("VAR1=value1");
|
||||
original_envs.insert("VAR2=value2");
|
||||
|
||||
update_env(env_vars, "VAR2", "new_value2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR2").c_str(), "VAR2=new_value2");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, LongPath_Append)
|
||||
{
|
||||
std::string long_path = "/very/long/path/to/some/directory/with/many/subdirectories/"
|
||||
"that/might/be/used/in/real/world";
|
||||
env_vars.push_back(strdup("PATH=/usr/bin:/bin"));
|
||||
original_envs.insert("PATH=/usr/bin:/bin");
|
||||
|
||||
update_env(env_vars, "PATH", long_path, update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
std::string expected = "PATH=/usr/bin:/bin:" + long_path;
|
||||
EXPECT_STREQ(env_vars[0], expected.c_str());
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, SpecialCharacters_InValue)
|
||||
{
|
||||
update_env(env_vars, "SPECIAL_VAR", "value-with_special.chars:123",
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "SPECIAL_VAR=value-with_special.chars:123");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Positive)
|
||||
{
|
||||
update_env(env_vars, "INT_VAR", 12345, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "INT_VAR=12345");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Negative)
|
||||
{
|
||||
update_env(env_vars, "NEGATIVE_VAR", -999, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "NEGATIVE_VAR=-999");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Zero)
|
||||
{
|
||||
update_env(env_vars, "ZERO_VAR", 0, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "ZERO_VAR=0");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, UpdateTracking_MultipleUpdates)
|
||||
{
|
||||
update_env(env_vars, "VAR1", "val1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR2", "val2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR1", "val1_updated", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
EXPECT_EQ(updated_envs.count("VAR1"), 1);
|
||||
EXPECT_EQ(updated_envs.count("VAR2"), 1);
|
||||
EXPECT_EQ(updated_envs.size(), 2);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_SequentialUpdates)
|
||||
{
|
||||
env_vars.push_back(strdup("CONFIG_VAR=initial"));
|
||||
original_envs.insert("CONFIG_VAR=initial");
|
||||
|
||||
update_env(env_vars, "CONFIG_VAR", "weak_update", update_mode::WEAK, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
EXPECT_STREQ(env_vars[0], "CONFIG_VAR=weak_update");
|
||||
|
||||
free(env_vars[0]);
|
||||
env_vars[0] = strdup("CONFIG_VAR=user_modified");
|
||||
|
||||
update_env(env_vars, "CONFIG_VAR", "another_weak_update", update_mode::WEAK, ":",
|
||||
updated_envs, original_envs);
|
||||
|
||||
EXPECT_STREQ(env_vars[0], "CONFIG_VAR=user_modified");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, Append_MultiplePathsInSequence)
|
||||
{
|
||||
update_env(env_vars, "BUILD_PATH", "/path1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path2", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path3", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path4", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BUILD_PATH=/path1:/path2:/path3:/path4");
|
||||
}
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "argparse.hpp"
|
||||
#include "common/environment.hpp"
|
||||
#include "common/join.hpp"
|
||||
#include "common/path.hpp"
|
||||
#include "config.hpp"
|
||||
#include "exception.hpp"
|
||||
@@ -81,71 +80,15 @@ get_clock_id_choices()
|
||||
return std::make_pair(_choices, _aliases);
|
||||
}
|
||||
|
||||
enum update_mode : int
|
||||
{
|
||||
UPD_REPLACE = 0, // no PREPEND/APPEND bits set
|
||||
UPD_PREPEND = 1 << 0, // 0x01
|
||||
UPD_APPEND = 1 << 1, // 0x02
|
||||
UPD_WEAK = 1 << 2, // 0x04
|
||||
};
|
||||
using rocprofsys::common::update_mode;
|
||||
|
||||
template <typename Tp>
|
||||
void
|
||||
update_env(parser_data& _data, std::string_view _env_var, Tp&& _env_val,
|
||||
update_mode&& _mode = UPD_REPLACE, std::string_view _join_delim = ":")
|
||||
update_mode _mode = update_mode::REPLACE, std::string_view _join_delim = ":")
|
||||
{
|
||||
_data.updated.emplace(_env_var);
|
||||
|
||||
auto _prepend = (_mode & UPD_PREPEND) != 0;
|
||||
auto _append = (_mode & UPD_APPEND) != 0;
|
||||
auto _weak_upd = (_mode & UPD_WEAK) != 0;
|
||||
|
||||
// if both flags are set, prefer append
|
||||
if(_prepend && _append)
|
||||
{
|
||||
_prepend = false;
|
||||
}
|
||||
|
||||
auto _key = join("", _env_var, "=");
|
||||
for(auto& itr : _data.current)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(_key) == 0)
|
||||
{
|
||||
if(_weak_upd)
|
||||
{
|
||||
// if the value has changed, do not update but allow overridding the value
|
||||
// inherited from the initial env
|
||||
if(_data.initial.find(std::string{ itr }) == _data.initial.end()) return;
|
||||
}
|
||||
|
||||
if(_prepend || _append)
|
||||
{
|
||||
if(std::string_view{ itr }.find(join("", _env_val)) ==
|
||||
std::string_view::npos)
|
||||
{
|
||||
auto _val = std::string{ itr }.substr(_key.length());
|
||||
free(itr);
|
||||
if(_prepend)
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _env_val, _val))
|
||||
.c_str());
|
||||
else
|
||||
itr =
|
||||
strdup(join('=', _env_var, join(_join_delim, _val, _env_val))
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(itr);
|
||||
itr = strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
_data.current.emplace_back(
|
||||
strdup(rocprofsys::common::join('=', _env_var, _env_val).c_str()));
|
||||
rocprofsys::common::update_env(_data.current, _env_var, std::forward<Tp>(_env_val),
|
||||
_mode, _join_delim, _data.updated, _data.initial);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -199,10 +142,10 @@ init_parser(parser_data& _data)
|
||||
path::realpath(path::get_internal_libpath("librocprof-sys.so").c_str());
|
||||
|
||||
auto _libexecpath = path::realpath(path::get_internal_script_path());
|
||||
update_env(_data, "ROCPROFSYS_SCRIPT_PATH", _libexecpath, UPD_REPLACE);
|
||||
update_env(_data, "ROCPROFSYS_SCRIPT_PATH", _libexecpath, update_mode::REPLACE);
|
||||
|
||||
auto _rootpath = path::realpath(path::get_rocprofsys_root());
|
||||
update_env(_data, "ROCPROFSYS_ROOT", _rootpath, UPD_REPLACE);
|
||||
update_env(_data, "ROCPROFSYS_ROOT", _rootpath, update_mode::REPLACE);
|
||||
|
||||
return _data;
|
||||
}
|
||||
@@ -210,7 +153,7 @@ init_parser(parser_data& _data)
|
||||
parser_data&
|
||||
add_ld_preload(parser_data& _data)
|
||||
{
|
||||
update_env(_data, "LD_PRELOAD", _data.dl_libpath, UPD_APPEND);
|
||||
update_env(_data, "LD_PRELOAD", _data.dl_libpath, update_mode::APPEND);
|
||||
return _data;
|
||||
}
|
||||
|
||||
@@ -219,7 +162,7 @@ add_ld_library_path(parser_data& _data)
|
||||
{
|
||||
auto _libdir = filepath::dirname(_data.dl_libpath);
|
||||
if(filepath::exists(_libdir))
|
||||
update_env(_data, "LD_LIBRARY_PATH", _libdir, UPD_APPEND);
|
||||
update_env(_data, "LD_LIBRARY_PATH", _libdir, update_mode::APPEND);
|
||||
return _data;
|
||||
}
|
||||
|
||||
@@ -413,9 +356,9 @@ add_core_arguments(parser_t& _parser, parser_data& _data)
|
||||
if(!_modes.empty())
|
||||
{
|
||||
update_env(_data, "ROCPROFSYS_SAMPLING_CPUTIME",
|
||||
_modes.count("cputime") > 0, UPD_WEAK);
|
||||
_modes.count("cputime") > 0, update_mode::WEAK);
|
||||
update_env(_data, "ROCPROFSYS_SAMPLING_REALTIME",
|
||||
_modes.count("realtime") > 0, UPD_WEAK);
|
||||
_modes.count("realtime") > 0, update_mode::WEAK);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -472,11 +415,11 @@ add_core_arguments(parser_t& _parser, parser_data& _data)
|
||||
.dtype("seconds")
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_data, "ROCPROFSYS_TRACE_DELAY", p.get<double>("wait"),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
update_env(_data, "ROCPROFSYS_SAMPLING_DELAY", p.get<double>("wait"),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
update_env(_data, "ROCPROFSYS_CAUSAL_DELAY", p.get<double>("wait"),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
});
|
||||
|
||||
_data.processed_environs.emplace("wait");
|
||||
@@ -493,11 +436,11 @@ add_core_arguments(parser_t& _parser, parser_data& _data)
|
||||
.dtype("seconds")
|
||||
.action([&](parser_t& p) {
|
||||
update_env(_data, "ROCPROFSYS_TRACE_DURATION", p.get<double>("duration"),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
update_env(_data, "ROCPROFSYS_SAMPLING_DURATION",
|
||||
p.get<double>("duration"), UPD_WEAK);
|
||||
p.get<double>("duration"), update_mode::WEAK);
|
||||
update_env(_data, "ROCPROFSYS_CAUSAL_DURATION", p.get<double>("duration"),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
});
|
||||
|
||||
_data.processed_environs.emplace("duration");
|
||||
@@ -516,7 +459,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data)
|
||||
update_env(
|
||||
_data, "ROCPROFSYS_TRACE_PERIODS",
|
||||
join(array_config_t{ " ", "", "" }, p.get<strvec_t>("periods")),
|
||||
UPD_WEAK);
|
||||
update_mode::WEAK);
|
||||
});
|
||||
|
||||
_data.processed_environs.emplace("periods");
|
||||
@@ -584,7 +527,7 @@ add_core_arguments(parser_t& _parser, parser_data& _data)
|
||||
|
||||
if(_v.count("all") > 0 || _v.count("kokkosp") > 0)
|
||||
update_env(_data, "KOKKOS_TOOLS_LIBS", _data.omni_libpath,
|
||||
UPD_PREPEND);
|
||||
update_mode::PREPEND);
|
||||
});
|
||||
|
||||
_data.processed_environs.emplace("include");
|
||||
|
||||
@@ -20,9 +20,17 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
add_executable(rocprof-sys-unit-tests dummy.cpp $<TARGET_OBJECTS:trace-cache-tests>)
|
||||
add_executable(
|
||||
rocprof-sys-unit-tests
|
||||
dummy.cpp
|
||||
$<TARGET_OBJECTS:lib-common-tests>
|
||||
$<TARGET_OBJECTS:trace-cache-tests>
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
rocprof-sys-unit-tests
|
||||
PRIVATE rocprofiler-systems-googletest-library rocprofiler-systems-core-library
|
||||
PRIVATE
|
||||
rocprofiler-systems-googletest-library
|
||||
rocprofiler-systems-common-library
|
||||
rocprofiler-systems-core-library
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user