Skip to content

Commit 84c06a7

Browse files
committed
Feature: Add initial support for compilation and execution of c++ script.
1 parent 4622d88 commit 84c06a7

8 files changed

Lines changed: 151 additions & 25 deletions

File tree

SolutionProjectModel/CppReflect.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,14 @@
55
#include <memory> //shared_ptr
66
#include <vector>
77
#include <string>
8+
#include "helpers.h"
89

910
// warning C4275: non dll-interface class 'pugi::xml_document' used as base for dll-interface class 'Solution'
1011
#pragma warning( disable: 4275 )
1112

1213
// warning C4251: ... needs to have dll-interface to be used by clients of class ...
1314
#pragma warning( disable: 4251 )
1415

15-
#ifdef SPM_EXPORT
16-
#define SPM_DLLEXPORT __declspec(dllexport)
17-
#else
18-
#define SPM_DLLEXPORT __declspec(dllimport)
19-
#endif
20-
2116
class FieldInfo;
2217
class ReflectClass;
2318

SolutionProjectModel/Project.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ wstring Project::GetSaveDirectory()
6868
return dir;
6969
}
7070

71+
wstring Project::GetProjectSaveLocation()
72+
{
73+
auto file = GetSaveDirectory();
74+
file += L"\\" + name + L".vcxproj";
75+
return file;
76+
}
77+
7178

7279
void Project::SetVsVersion(int _vsVersion)
7380
{

SolutionProjectModel/Project.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class SPM_DLLEXPORT Project :
2525
// Gets project save directory.
2626
//
2727
std::wstring GetSaveDirectory();
28+
std::wstring GetProjectSaveLocation();
2829

2930
//
3031
// Clears existing project

SolutionProjectModel/SolutionProjectModel.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
<ClCompile Include="ProjectFile.cpp" />
202202
<ClCompile Include="ProjectFileTypes.cpp" />
203203
<ClCompile Include="Solution.cpp" />
204+
<ClCompile Include="helpers.cpp" />
204205
<ClCompile Include="VCConfiguration.cpp" />
205206
</ItemGroup>
206207
<ItemGroup>
@@ -215,6 +216,7 @@
215216
<ClInclude Include="ProjectFile.h" />
216217
<ClInclude Include="Solution.h" />
217218
<ClInclude Include="ProjectFileTypes.h" />
219+
<ClInclude Include="helpers.h" />
218220
<ClInclude Include="TypeTraits.h" />
219221
<ClInclude Include="VCConfiguration.h" />
220222
</ItemGroup>

SolutionProjectModel/SolutionProjectModel.vcxproj.filters

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<ClCompile Include="pch.cpp" />
1313
<ClCompile Include="ProjectFileTypes.cpp" />
1414
<ClCompile Include="VCConfiguration.cpp" />
15+
<ClCompile Include="helpers.cpp" />
1516
</ItemGroup>
1617
<ItemGroup>
1718
<ClInclude Include="Solution.h" />
@@ -31,6 +32,7 @@
3132
<ClInclude Include="pch.h" />
3233
<ClInclude Include="boolinq.h" />
3334
<ClInclude Include="VCConfiguration.h" />
35+
<ClInclude Include="helpers.h" />
3436
</ItemGroup>
3537
<ItemGroup>
3638
<Filter Include="pugixml">

SolutionProjectModel/cppexec/cppexec.cpp

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "..\Project.h"
22
#include "expdef.h" //printPeExports
3+
#include "..\helpers.h"
34
#include <filesystem>
45
#include <atlconv.h> //CW2A
56
#include <algorithm> //transform
@@ -177,30 +178,34 @@ int _wmain(int argc, wchar_t** argv)
177178
return -4;
178179
}
179180

180-
// Idea copied from vswhere, except whole implementation was re-written from scratch.
181-
ISetupConfigurationPtr setupCfg;
182-
IEnumSetupInstancesPtr enumInstances;
183-
184181
vector<VisualStudioInfo> instances;
185-
auto lcid = GetUserDefaultLCID();
186182

187-
function< void(HRESULT)> hrc = [](HRESULT hr)
183+
// Idea copied from vswhere, except whole implementation was re-written from scratch.
188184
{
189-
if (FAILED(hr))
190-
throw _com_error(hr);
191-
};
185+
ISetupConfigurationPtr setupCfg;
186+
IEnumSetupInstancesPtr enumInstances;
187+
188+
auto lcid = GetUserDefaultLCID();
189+
190+
function<void(HRESULT)> hrc = [](HRESULT hr)
191+
{
192+
if (FAILED(hr))
193+
{
194+
USES_CONVERSION;
195+
throw exception(CW2A(_com_error(hr).ErrorMessage()));
196+
}
197+
};
192198

193-
try {
194199
hrc(CoInitialize(nullptr));
195200
hrc(setupCfg.CreateInstance(__uuidof(SetupConfiguration)));
196201
hrc(setupCfg->EnumInstances(&enumInstances));
197202

198-
while(true)
203+
while (true)
199204
{
200205
ISetupInstance* p = nullptr;
201206
unsigned long ul = 0;
202207
HRESULT hr = enumInstances->Next(1, &p, &ul);
203-
if (hr != S_OK )
208+
if (hr != S_OK)
204209
break;
205210

206211
ISetupInstancePtr setupi(p, false);
@@ -220,15 +225,45 @@ int _wmain(int argc, wchar_t** argv)
220225
vsinfo.InstallPath = instpath;
221226
instances.push_back(vsinfo);
222227
}
223-
224-
CoUninitialize();
225-
}
226-
catch (_com_error ce)
227-
{
228-
printf("Error: %S\n", ce.ErrorMessage());
229228
}
229+
CoUninitialize();
230+
231+
auto it = max_element(instances.begin(), instances.end(), [](auto e1, auto e2) { return e1.version < e2.version; });
232+
if (it == instances.end())
233+
throw exception("No Visual Studio installation found");
234+
235+
auto devenv = path(it->InstallPath).append("Common7\\IDE\\devenv.com");
236+
237+
auto quoted = [](wstring f) -> wstring
238+
{
239+
return wstring(L"\"") + f + L"\"";
240+
};
241+
242+
wprintf(L"%s: compile... ", scriptToRun.filename().c_str());
243+
wstring cmd = wstring(L"cmd /C ") + quoted( quoted(devenv.c_str()) + L" /build " + quoted(L"Debug^|x64") + L" " + quoted(p.GetProjectSaveLocation()) ) + L" >logBuild.txt";
244+
// printf("%S\n", cmd.c_str());
245+
int error = 0;
246+
error = _wsystem(cmd.c_str());
247+
if (error != 0)
248+
throw exception("Compilation failured");
249+
250+
auto dllPath = path(projectDir).append(scriptToRun.stem().wstring() + L".dll");
251+
if( !exists(dllPath) )
252+
throw exception(sFormat("Compilation failed: dll does not exists: '%s'", dllPath.u8string().c_str()).c_str());
253+
254+
HMODULE h = LoadLibraryW(dllPath.c_str());
255+
if (!h)
256+
ThrowLastError();
257+
258+
FARPROC proc = GetProcAddress(h, "main");
259+
260+
if (!proc)
261+
throwFormat("Dll entry point function 'main' not found.");
230262

231-
return 0;
263+
printf("execute:\n\n");
264+
int r = (int)proc();
265+
FreeLibrary(h);
266+
return r;
232267
}
233268

234269
int wmain(int argc, wchar_t** argv)

SolutionProjectModel/helpers.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "pch.h"
2+
#include "helpers.h"
3+
#include <atlstr.h> //CStringA
4+
5+
using namespace std;
6+
7+
void SPM_DLLEXPORT throwFormat(const char* format, ...)
8+
{
9+
va_list args;
10+
va_start(args, format);
11+
12+
throw exception(svaFormat(format, args).c_str());
13+
}
14+
15+
string GetLastErrorMessageA( DWORD code )
16+
{
17+
char* buf = nullptr;
18+
DWORD len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
19+
NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL);
20+
21+
if (!len)
22+
return sFormat("Windows error: %d", code);
23+
24+
string msg(buf, len);
25+
LocalFree(buf);
26+
return msg;
27+
}
28+
29+
void ThrowLastError(DWORD code)
30+
{
31+
throw exception(GetLastErrorMessageA(code).c_str());
32+
}
33+

SolutionProjectModel/helpers.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#pragma once
2+
#include <string>
3+
#include <windows.h>
4+
5+
#ifdef SPM_EXPORT
6+
#define SPM_DLLEXPORT __declspec(dllexport)
7+
#else
8+
#define SPM_DLLEXPORT __declspec(dllimport)
9+
#endif
10+
11+
12+
template <typename T>
13+
std::basic_string<T> svaFormat(const T* format, va_list args)
14+
{
15+
int size;
16+
17+
if constexpr (std::is_same_v<T, char>)
18+
size = vsnprintf(nullptr, 0, format, args);
19+
else
20+
size = _vsnwprintf(nullptr, 0, format, args);
21+
22+
size++; // Zero termination
23+
std::basic_string<T> s;
24+
s.resize(size);
25+
26+
if constexpr (std::is_same_v<T, char>)
27+
vsnprintf(&s[0], size, format, args);
28+
else
29+
_vsnwprintf(&s[0], size, format, args);
30+
31+
return s;
32+
}
33+
34+
//
35+
// Formats string/wstring according to format, if formatting fails (e.g. invalid %s pointer - returns empty string)
36+
//
37+
template <typename T>
38+
std::basic_string<T> sFormat(const T* format, ...)
39+
{
40+
va_list args;
41+
va_start(args, format);
42+
return svaFormat(format, args);
43+
}
44+
45+
void SPM_DLLEXPORT throwFormat(const char* format, ...);
46+
47+
std::string SPM_DLLEXPORT GetLastErrorMessageA( DWORD code = GetLastError() );
48+
49+
void SPM_DLLEXPORT ThrowLastError( DWORD code = GetLastError() );
50+
51+

0 commit comments

Comments
 (0)