Skip to content

Commit 77bb29a

Browse files
committed
CLI frontend completed + Initial Release
1 parent 8937dae commit 77bb29a

File tree

5 files changed

+207
-149
lines changed

5 files changed

+207
-149
lines changed

Include/RunAsGPU/Shared/HelpPage.hpp

Lines changed: 0 additions & 46 deletions
This file was deleted.

Include/RunAsGPU/Shared/Shared.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55

66
std::filesystem::path GetExecutablePath();
77

8-
std::string TrimString(const std::string& s);
8+
std::string TrimString(const std::string &s);
9+
10+
bool StartsWith(const std::string &s, const std::string &v);
11+
12+
bool EndsWith(const std::string &s, const std::string &v);
13+
14+
bool StringContains(const std::string& str, const std::string& val);
915

1016
#endif //RUNASGPU_SHARED_HPP

Sources/AppCLI/MainCLI.cpp

Lines changed: 182 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,71 @@
11
#include <iostream>
22

33
#include <RunAsGPU/Shared/Shared.hpp>
4-
#include <RunAsGPU/Shared/HelpPage.hpp>
54
#include <RunAsGPU/Shared/Runner.hpp>
65

76
namespace fs = std::filesystem;
87

9-
void list() {
10-
std::vector<GraphicalUnit> gpu_list = Runner::ListGraphicalUnits();
8+
enum FindBy {
9+
Name = 0,
10+
Vendor = 1,
11+
Product = 2,
12+
Global = 3
13+
};
14+
15+
int findUnit(const std::vector<GraphicalUnit> &gpuList, const std::string &name, const FindBy &by) {
16+
for (int i = 0; i < gpuList.size(); i++) {
17+
switch (by) {
18+
case Name:
19+
if (StringContains(gpuList[i].fullName, name))
20+
return i;
21+
22+
break;
23+
case Vendor:
24+
if (StringContains(gpuList[i].vendorName, name))
25+
return i;
26+
27+
if (name.find_first_not_of("0123456789ABCDEFabcdef") == std::string::npos) {
28+
try {
29+
int ven = std::stoi(name, nullptr, 16);
30+
if (gpuList[i].vendor == ven)
31+
return i;
32+
} catch (const std::exception &e) {
33+
std::cerr << "Error: Invalid Vendor ID: " << name << std::endl;
34+
return -1;
35+
}
36+
}
37+
38+
break;
39+
case Product:
40+
if (StringContains(gpuList[i].productName, name))
41+
return i;
42+
43+
if (name.find_first_not_of("0123456789ABCDEFabcdef") == std::string::npos) {
44+
try {
45+
int prod = std::stoi(name, nullptr, 16);
46+
if (gpuList[i].product == prod)
47+
return i;
48+
} catch (const std::exception &e) {
49+
std::cerr << "Error: Invalid Product ID: " << name << std::endl;
50+
return -1;
51+
}
52+
}
53+
54+
break;
55+
case Global:
56+
if (int res = findUnit(gpuList, name, Name); res != -1) return res;
57+
if (int res = findUnit(gpuList, name, Vendor); res != -1) return res;
58+
if (int res = findUnit(gpuList, name, Product); res != -1) return res;
59+
return -1;
60+
}
61+
}
62+
63+
return -1;
64+
}
65+
66+
void list(const std::vector<GraphicalUnit> &gpu_list) {
1167
for (int i = 0; i < gpu_list.size(); i++) {
12-
const GraphicalUnit& unit = gpu_list[i];
68+
const GraphicalUnit &unit = gpu_list[i];
1369

1470
std::cout << "GPU - " << unit.vendorName << " (" << std::hex << unit.vendor << ")\n";
1571
std::cout << "\tName = " << unit.productName << " (" << std::hex << unit.product << ")\n";
@@ -20,45 +76,135 @@ void list() {
2076
}
2177
}
2278

79+
void printHelp(const std::string &exeName) {
80+
std::cout << "RunAsGPU v1.0" << std::endl;
81+
std::cout << "Usage: " << exeName << " [action] [options] [exec [..args]]\n" << std::endl;
82+
std::cout << "Actions:" << std::endl;
83+
std::cout << " list - List all active GPUs" << std::endl;
84+
std::cout << " run <command> - Run an application with GPU selection\n" << std::endl;
85+
std::cout << "Options:" << std::endl;
86+
std::cout << " -ui, --unit-id <ID> - Select a specific GPU by its given ID" << std::endl;
87+
std::cout << " -fu, --find-unit <GPU> - Find a GPU by identification" << std::endl;
88+
std::cout << " -fnu, --find-unit-name <N> - Find a GPU by name" << std::endl;
89+
std::cout << " -fvu, --find-unit-vendor <V> - Find a GPU by vendor name/ID" << std::endl;
90+
std::cout << " -fpu, --find-unit-product <P> - Find a GPU by product name/ID" << std::endl;
91+
}
92+
2393
int main(int argc, char **argv) {
24-
if (argc == 1 || (argc == 2 && (std::string(argv[1]) == "--help" || std::string(argv[1]) == "-h"))) {
25-
std::string fn = GetExecutablePath().filename().string();
26-
27-
std::cout << "RunAsGPU v1.0" << std::endl;
28-
std::cout << "usage: ./" << fn << " [action] [options] [exec [..args]]" << std::endl << std::endl;
29-
std::cout << "actions:" << std::endl;
30-
31-
HelpPage actions;
32-
actions.setStartSpaceWidth(4);
33-
actions.setDescSeparator(" ");
34-
actions.addArg("run", "", "Run an executable");
35-
actions.addArg("list", "", "List all active GPUs");
36-
actions.display(std::cout);
37-
38-
std::cout << std::endl;
39-
std::cout << "options:" << std::endl;
40-
41-
HelpPage options;
42-
options.setStartSpaceWidth(4);
43-
options.setSpaceWidth(3);
44-
options.setDescSeparator("=");
45-
options.addArg("-ui | --unit-id", "ID", "Select a specific GPU by its given ID");
46-
options.addArg("-fu | --find-unit", "[GPU]", "Find a GPU by its identification (Vendor ID, Device / Product ID, Name)");
47-
options.addArg("-fnu | --find-unit-name", "[Name]", "Find a GPU by the name");
48-
options.addArg("-fvu | --find-unit-vendor", "[Vendor]", "Find a GPU by the name or ID of the Vendor (e.g. NVIDIA)");
49-
options.addArg("-fpu | --find-unit-product", "[Product]", "Find a GPU by the name or ID of the Product (e.g. GeForce 6800 XT)");
50-
options.addArg("-ni | --non-interactive", "", "Will not prompt for GPU selection (e.g. running as a script)");
51-
options.display(std::cout);
94+
if (argc < 2) {
95+
printHelp(argv[0]);
96+
return 1;
97+
}
98+
99+
std::string action = argv[1];
52100

101+
if (action == "--help" || action == "-h") {
102+
printHelp(argv[0]);
53103
return 0;
54104
}
55105

56-
std::vector<std::string> args;
57-
std::string action = argv[1];
106+
std::vector<GraphicalUnit> gpu_list = Runner::ListGraphicalUnits();
107+
int unit = 0;
108+
58109
if (action == "list") {
59-
list();
110+
list(gpu_list);
60111
return 0;
61112
}
62113

63-
return 0;
114+
if (action == "run") {
115+
std::vector<std::string> args;
116+
for (int i = 2; i < argc; i++) {
117+
std::string arg = argv[i];
118+
119+
if (arg == "-ui" || arg == "--unit-id") {
120+
if (i + 1 < argc) {
121+
std::string unitStr = argv[++i];
122+
if (unitStr.find_first_not_of("0123456789") == std::string::npos)
123+
unit = std::stoi(unitStr);
124+
else {
125+
std::cerr << "Invalid GPU ID: " << unitStr << "\n";
126+
return 1;
127+
}
128+
} else {
129+
std::cerr << "Missing value for " << arg << "\n";
130+
return 1;
131+
}
132+
} else if (arg == "-fu" || arg == "--find-unit") {
133+
if (i + 1 < argc) {
134+
std::string data = argv[++i];
135+
unit = findUnit(gpu_list, data, Global);
136+
137+
if (unit == -1) {
138+
std::cerr << "Invalid data given: " << data << std::endl;
139+
return 1;
140+
}
141+
} else {
142+
std::cerr << "Missing value for " << arg << "\n";
143+
return 1;
144+
}
145+
} else if (arg == "-fnu" || arg == "--find-unit-name") {
146+
if (i + 1 < argc) {
147+
std::string data = argv[++i];
148+
unit = findUnit(gpu_list, data, Name);
149+
150+
if (unit == -1) {
151+
std::cerr << "Invalid name: " << data << std::endl;
152+
return 1;
153+
}
154+
} else {
155+
std::cerr << "Missing value for " << arg << "\n";
156+
return 1;
157+
}
158+
} else if (arg == "-fvu" || arg == "--find-unit-vendor") {
159+
if (i + 1 < argc) {
160+
std::string data = argv[++i];
161+
unit = findUnit(gpu_list, argv[++i], Vendor);
162+
163+
if (unit == -1) {
164+
std::cerr << "Invalid vendor name/ID: " << argv[i] << "\n";
165+
return 1;
166+
}
167+
} else {
168+
std::cerr << "Missing value for " << arg << "\n";
169+
return 1;
170+
}
171+
} else if (arg == "-fpu" || arg == "--find-unit-product") {
172+
if (i + 1 < argc) {
173+
std::string data = argv[++i];
174+
unit = findUnit(gpu_list, data, Product);
175+
176+
if (unit == -1) {
177+
std::cerr << "Invalid product name/ID: " << data << "\n";
178+
return 1;
179+
}
180+
} else {
181+
std::cerr << "Missing value for " << arg << "\n";
182+
return 1;
183+
}
184+
} else
185+
args.push_back(arg);
186+
}
187+
188+
if (args.empty()) {
189+
std::cerr << "No executable specified.\n";
190+
return 1;
191+
}
192+
193+
std::string execPath = args[0];
194+
args.erase(args.begin());
195+
196+
std::string command = "DRI_PRIME=" + std::to_string(unit) + " " + execPath;
197+
for (const auto& arg : args) {
198+
command += " " + arg;
199+
}
200+
201+
std::cout << "Running: " << command << "\n";
202+
int result = std::system(command.c_str());
203+
204+
return result == 0 ? 0 : 1;
205+
}
206+
207+
std::cerr << "Unknown command: " << action << "\n";
208+
printHelp(argv[0]);
209+
return 1;
64210
}

Sources/AppShared/HelpPage.cpp

Lines changed: 0 additions & 66 deletions
This file was deleted.

Sources/AppShared/Shared.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,22 @@ std::string TrimString(const std::string &s) {
3232

3333
size_t end = s.find_last_not_of(" \t\r\n");
3434
return s.substr(start, end - start + 1);
35+
}
36+
37+
bool StartsWith(const std::string &str, const std::string &prefix) {
38+
if (prefix.size() > str.size())
39+
return false;
40+
41+
return std::equal(prefix.begin(), prefix.end(), str.begin());
42+
}
43+
44+
bool EndsWith(const std::string &str, const std::string &suffix) {
45+
if (suffix.size() > str.size())
46+
return false;
47+
48+
return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
49+
}
50+
51+
bool StringContains(const std::string& str, const std::string& val) {
52+
return str.find(val) != std::string::npos;
3553
}

0 commit comments

Comments
 (0)