diff --git a/components/process/examples/CMakeLists.txt b/components/process/examples/CMakeLists.txt index 6c6633577fb0..2089aa5249bc 100644 --- a/components/process/examples/CMakeLists.txt +++ b/components/process/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 The STE||AR-Group +# Copyright (c) 2024 The STE||AR-Group # # SPDX-License-Identifier: BSL-1.0 # Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -13,4 +13,30 @@ if(HPX_WITH_EXAMPLES) tests.examples.components tests.examples.components.process ) endif() +else() + return() endif() + +set(example_programs launch_command) +set(launch_command_FLAGS DEPENDENCIES process_component) + +foreach(example_program ${example_programs}) + set(sources ${example_program}.cpp) + + source_group("Source Files" FILES ${sources}) + + # add example executable + add_hpx_executable( + ${example_program} INTERNAL_FLAGS + SOURCES ${sources} ${${example_program}_FLAGS} + FOLDER "Examples/Components/Process" + ) + + add_hpx_example_target_dependencies("components.process" ${example_program}) + + if(HPX_WITH_TESTS AND HPX_WITH_TESTS_EXAMPLES) + add_hpx_example_test( + "components.process" ${example_program} ${${example_program}_PARAMETERS} + ) + endif() +endforeach() diff --git a/components/process/examples/launch_command.cpp b/components/process/examples/launch_command.cpp new file mode 100644 index 000000000000..831534b5ab1e --- /dev/null +++ b/components/process/examples/launch_command.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2024 Hartmut Kaiser +// +// SPDX-License-Identifier: BSL-1.0 +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// This example demonstrates how the Process component can be used to launch +// arbitrary commands on any of the participating localities. + +#include +#include +#include +#include + +#include +#include + +inline int get_arraylen(char** arr) +{ + int count = 0; + if (nullptr != arr) + { + while (nullptr != arr[count]) + ++count; // simply count the strings + } + return count; +} + +std::vector get_environment() +{ + std::vector env; +#if defined(HPX_WINDOWS) + int len = get_arraylen(_environ); + std::copy(&_environ[0], &_environ[len], std::back_inserter(env)); +#elif defined(linux) || defined(__linux) || defined(__linux__) || \ + defined(__AIX__) || defined(__APPLE__) || defined(__FreeBSD__) + int len = get_arraylen(environ); + std::copy(&environ[0], &environ[len], std::back_inserter(env)); +#else +#error "Don't know, how to access the execution environment on this platform" +#endif + return env; +} + +int main() +{ + namespace process = hpx::components::process; + + // use hpx::find_all_localities(); if you want to include the current + // locality as well + std::vector localities = hpx::find_remote_localities(); + std::vector children; + children.reserve(localities.size()); + + for (auto const& locality : localities) + { +#if defined(HPX_WINDOWS) + std::string exe = "cmd.exe"; +#else + std::string exe = "ls"; +#endif + + // set up command line for launched executable + std::vector args; + args.push_back(exe); +#if defined(HPX_WINDOWS) + args.push_back("/c"); + args.push_back("dir"); +#endif + + // set up environment for launched executable (propagate current env) + std::vector env = get_environment(); + + // launch test executable + process::child c = process::execute(locality, process::run_exe(exe), + process::set_args(args), process::set_env(env), + process::start_in_dir("."), process::throw_on_error()); + + children.push_back(c); + } + + // wait for the processes to start executing + hpx::wait_all(children); + + // wait for the processes to terminate + for (auto& c : children) + { + int retval = c.wait_for_exit(hpx::launch::sync); + std::cout << retval << '\n'; + } + + return 0; +}