diff --git a/src/CodeGen_Metal_Dev.cpp b/src/CodeGen_Metal_Dev.cpp index d31e97e30427..aa4f4338d7b4 100644 --- a/src/CodeGen_Metal_Dev.cpp +++ b/src/CodeGen_Metal_Dev.cpp @@ -883,16 +883,11 @@ vector CodeGen_Metal_Dev::compile_to_src() { // Compile the Metal source to a metallib. string metalir = tmpfile + ".ir"; string metallib = tmpfile + "lib"; - string cmd = string(metal_compiler) + " -c -o " + metalir + " " + tmpfile; - debug(2) << "Running: " << cmd << "\n"; - int ret = system(cmd.c_str()); + int ret = run_process({metal_compiler, "-c", "-o", metalir, tmpfile}); user_assert(ret == 0) << "Metal compiler set, but failed to compile Metal source to Metal IR.\n"; - cmd = string(metal_linker) + " -o " + metallib + " " + metalir; - debug(2) << "Running: " << cmd << "\n"; - - ret = system(cmd.c_str()); + ret = run_process({metal_linker, "-o", metallib, metalir}); user_assert(ret == 0) << "Metal linker set, but failed to compile Metal IR to Metal library.\n"; // Read the metallib into a buffer. diff --git a/src/CodeGen_PTX_Dev.cpp b/src/CodeGen_PTX_Dev.cpp index fcc4a85ad5f6..c72ac011a316 100644 --- a/src/CodeGen_PTX_Dev.cpp +++ b/src/CodeGen_PTX_Dev.cpp @@ -756,11 +756,8 @@ vector CodeGen_PTX_Dev::compile_to_src() { f.write(buffer.data(), buffer.size()); f.close(); - string cmd = "ptxas --gpu-name " + mcpu_target() + " " + ptx.pathname() + " -o " + sass.pathname(); - if (system(cmd.c_str()) == 0) { - cmd = "nvdisasm " + sass.pathname(); - int ret = system(cmd.c_str()); - (void)ret; // Don't care if it fails + if (run_process({"ptxas", "--gpu-name", mcpu_target(), ptx.pathname(), "-o", sass.pathname()}) == 0) { + (void)run_process({"nvdisasm", sass.pathname()}); // Don't care if it fails } // Note: It works to embed the contents of the .sass file in diff --git a/src/HexagonOffload.cpp b/src/HexagonOffload.cpp index e540a9697513..08f225f60367 100644 --- a/src/HexagonOffload.cpp +++ b/src/HexagonOffload.cpp @@ -1101,11 +1101,8 @@ Buffer compile_module_to_hexagon_shared_object(const Module &device_cod write_entire_file(input.pathname(), shared_object); debug(1) << "Signing tool: (" << signer << ")\n"; - std::string cmd = signer + " " + input.pathname() + " " + output.pathname(); - int result = system(cmd.c_str()); - internal_assert(result == 0) - << "HL_HEXAGON_CODE_SIGNER failed: result = " << result - << " for cmd (" << cmd << ")"; + int result = run_process({signer, input.pathname(), output.pathname()}); + internal_assert(result == 0) << "HL_HEXAGON_CODE_SIGNER failed: result = " << result; shared_object = read_entire_file(output.pathname()); } diff --git a/src/Util.cpp b/src/Util.cpp index 241c4e17d146..b86a1141d465 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -18,11 +18,16 @@ #ifdef _MSC_VER #include +#include // For _spawnvp #else #include +#include #include // For mmap +#include #include +extern char **environ; #endif + #include #include @@ -31,9 +36,11 @@ #include // For PATH_MAX #include // For swapcontext #endif + #if defined(_MSC_VER) && !defined(NOMINMAX) #define NOMINMAX #endif + #ifdef _WIN32 #include // needed for CoCreateGuid #include // needed for SHGetFolderPath @@ -41,6 +48,7 @@ #else #include #endif + #ifdef __APPLE__ #define CAN_GET_RUNNING_PROGRAM_NAME #include @@ -497,6 +505,32 @@ void write_entire_file(const std::string &pathname, const void *source, size_t s f.close(); } +int run_process(std::vector args) { + internal_assert(!args.empty()) << "run_process called with empty args\n"; + + std::vector argv; + argv.reserve(args.size() + 1); + for (auto &a : args) { + argv.push_back(a.data()); + } + argv.push_back(nullptr); + + debug(2) << "Running process: " << PrintSpan(args) << "\n"; + +#ifdef _WIN32 + // Wait for completion; return the child's exit code. + int rc = _spawnvp(_P_WAIT, argv[0], argv.data()); + return (rc >= 0) ? rc : -1; +#else + pid_t pid = 0; + int status = posix_spawnp(&pid, argv[0], nullptr, nullptr, argv.data(), environ); + if (status != 0 || waitpid(pid, &status, 0) == -1) { + return -1; + } + return WIFEXITED(status) ? WEXITSTATUS(status) : -1; +#endif +} + bool add_would_overflow(int bits, int64_t a, int64_t b) { int64_t max_val = 0x7fffffffffffffffLL >> (64 - bits); int64_t min_val = -max_val - 1; diff --git a/src/Util.h b/src/Util.h index 9a625351d3b9..46439d3982af 100644 --- a/src/Util.h +++ b/src/Util.h @@ -371,6 +371,13 @@ class TemporaryFile final { TemporaryFile &operator=(TemporaryFile &&) = delete; }; +/** Run an executable with the given arguments without going through + * the shell. The first element of args should be the program name/path. + * If a name without a path-separator is given, it will be searched for + * in the PATH. Returns the exit code of the process, or -1 if the process + * could not be started. */ +int run_process(std::vector args); + /** Routines to test if math would overflow for signed integers with * the given number of bits. */ // @{