1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
#pragma once
#ifdef _MSC_VER
#include <string>
#include <vector>
#include <sstream>
#include <Windows.h>
#ifndef ARRAY_COUNT
#define ARRAY_COUNT(x) (sizeof(x) / sizeof(*x))
#endif
#pragma comment (lib, "shlwapi.lib")
namespace find_vs {
using std::vector;
using std::string;
using std::istringstream;
using std::cout;
using std::endl;
/**
* Utility functions for finding Visual Studio on Windows.
*
* Include from one cpp-file for each project.
*/
// What to look for: It seems "vcvarsall.bat" is always present and works approximately the same across versions.
const char *toolNames[] = {
// "VsDevCmd.bat", // At least on VS2019
"vcvarsall.bat", // At least on VS2008
};
bool isToolFile(const char *file) {
for (size_t i = 0; i < ARRAY_COUNT(toolNames); i++) {
if (_stricmp(file, toolNames[i]) == 0)
return true;
}
return false;
}
// Find vs files.
void find(vector<string> &out, const string &root) {
WIN32_FIND_DATA file;
HANDLE handle = FindFirstFile((root + "*").c_str(), &file);
if (handle == INVALID_HANDLE_VALUE)
return;
do {
if (strcmp(file.cFileName, ".") == 0 || strcmp(file.cFileName, "..") == 0) {
continue;
} else if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
find(out, root + file.cFileName + "\\");
} else if (isToolFile(file.cFileName)) {
out.push_back(root + file.cFileName);
}
} while (FindNextFile(handle, &file) == TRUE);
FindClose(handle);
}
// Pick one out of multiple candidates.
string pick(const vector<string> &candidates) {
if (candidates.size() == 1)
return candidates[0];
cout << "Multiple versions of Visual Studio were found. Please pick the one you want to use:" << endl;
for (size_t i = 0; i < candidates.size(); i++)
cout << (i + 1) << "> " << candidates[i] << endl;
while (true) {
cout << "?> ";
string selection;
if (!getline(std::cin, selection))
exit(1);
istringstream iss(selection);
size_t id;
if (!(iss >> id)) {
cout << "Not a number, try again!" << endl;
continue;
}
if (id > 0 && id <= candidates.size())
return candidates[id - 1];
cout << "Not an option, try again!" << endl;
}
}
// Find vs using default heuristics. Provide a hint if desired.
string find(const string *hint) {
vector<string> candidates;
if (hint) {
DWORD attrs = GetFileAttributes(hint->c_str());
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0) {
return *hint;
} else {
string name = *hint;
if (name[name.size() - 1] != '\\')
name += "\\";
cout << "Looking for the Visual Studio command line tools in " << name << "..." << endl;
find(candidates, name);
}
} else {
cout << "Looking for the Visual Studio command line tools..." << endl;
find(candidates, "C:\\Program Files (x86)\\");
find(candidates, "C:\\Program Files\\");
}
if (candidates.empty()) {
cout << "Unable to find the Visual Studio command line tools using any of the following names:" << endl;
for (size_t i = 0; i < ARRAY_COUNT(toolNames); i++)
cout << " " << toolNames[i] << endl;
cout << "Please try specifying either the path to your Visual Studio installation, or the full path to any of the above files." << endl;
return "";
}
return pick(candidates);
}
}
#endif
|