Browse Source

Got CL.exe executing

Environment variables are properly used to find the right
compiler. The compiler isn't returning a useful exit code, however.
windows-support
Macoy Madson 6 months ago
parent
commit
4c6f793e88
6 changed files with 166 additions and 19 deletions
  1. +3
    -3
      Bootstrap_MSVC.cake
  2. +16
    -1
      Build.bat
  3. +2
    -2
      src/FileUtilities.cpp
  4. +1
    -1
      src/Main.cpp
  5. +1
    -1
      src/ModuleManager.cpp
  6. +143
    -11
      src/RunProcess.cpp

+ 3
- 3
Bootstrap_MSVC.cake View File

@ -38,18 +38,18 @@
;; (add-compile-time-hook pre-link cakelisp-link-hook)
(set-cakelisp-option build-time-compiler "CL")
(set-cakelisp-option build-time-compiler "cl.exe")
(set-cakelisp-option build-time-compile-arguments
"/c" 'source-input "/Fo" 'object-output
'include-search-dirs 'additional-options)
(set-cakelisp-option compile-time-compiler "CL")
(set-cakelisp-option compile-time-compiler "cl.exe")
(set-cakelisp-option compile-time-compile-arguments
"/c" 'source-input "/Fo" 'object-output
'cakelisp-headers-include)
;; "-fPIC"
(set-cakelisp-option build-time-linker "CL")
(set-cakelisp-option build-time-linker "cl.exe")
(set-cakelisp-option build-time-link-arguments
"/Fo" 'executable-output 'object-input)


+ 16
- 1
Build.bat View File

@ -1,6 +1,17 @@
rem Set environment variables. The user may need to adjust this path
rem See https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160#developer_command_file_locations
if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" (
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
) else (
echo This script builds using MSVC.
echo You must download and install MSVC before it will work. Download it here:
echo https://visualstudio.microsoft.com/downloads/
echo Select workloads for C++ projects. Ensure you install the C++ developer tools.
echo If you're still seeing this, you may need to edit Build.bat to your vcvars path
echo Please see the following link:
echo https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160
goto :fail
)
if not exist "bin" (
mkdir bin
@ -24,15 +35,19 @@ CL.exe src/Tokenizer.cpp ^
/EHsc /DWINDOWS /Fe"bin\cakelisp_bootstrap"
@if ERRORLEVEL == 0 (
rem Clean up working directory
del *.obj
rem TODO Go to bootstrap build
"bin\cakelisp_bootstrap.exe"
) else (
echo "Error while building"
goto :fail
)
) else (
"bin\cakelisp_bootstrap.exe" --verbose-processes Bootstrap_Windows.cake
"bin\cakelisp_bootstrap.exe" --verbose-processes Bootstrap_MSVC.cake
rem Left off: Remove space between /Fo and output, -Isrc isn't going to work either
rem Figure out why CL isn't being found by CreateProcess
rem Can I list all the variables/paths being set in Cakelisp, to see if vcvars is applying, or if CreateProcess isn't passing them?
rem CL /c src/Tokenizer.cpp /Fo"cakelisp_cache/Bootstrap_Windows/Tokenizer.cpp.o" -Isrc /DWINDOWS /EHsc
)


+ 2
- 2
src/FileUtilities.cpp View File

@ -185,8 +185,8 @@ void makePathRelativeToFile(const char* filePath, const char* referencedFilePath
{
getDirectoryFromPath(filePath, bufferOut, bufferSize);
// TODO: Need to make this safe!
strcat(bufferOut, "/");
strcat(bufferOut, referencedFilePath);
strcat_s(bufferOut, bufferSize, "/");
strcat_s(bufferOut, bufferSize, referencedFilePath);
}
const char* makeAbsolutePath_Allocated(const char* fromDirectory, const char* filePath)


+ 1
- 1
src/Main.cpp View File

@ -236,7 +236,7 @@ int main(int numArguments, char* arguments[])
// Need to use absolute path when executing
const char* executablePath = makeAbsolutePath_Allocated(nullptr, output.c_str());
arguments.fileToExecute = executablePath;
const char* commandLineArguments[] = {strdup(arguments.fileToExecute), nullptr};
const char* commandLineArguments[] = {_strdup(arguments.fileToExecute), nullptr};
arguments.arguments = commandLineArguments;
char workingDirectory[MAX_PATH_LENGTH] = {0};
getDirectoryFromPath(arguments.fileToExecute, workingDirectory,


+ 1
- 1
src/ModuleManager.cpp View File

@ -259,7 +259,7 @@ bool moduleManagerAddEvaluateFile(ModuleManager& manager, const char* filename,
char resolvedPath[MAX_PATH_LENGTH] = {0};
makeAbsoluteOrRelativeToWorkingDir(filename, resolvedPath, ArraySize(resolvedPath));
const char* normalizedFilename = strdup(resolvedPath);
const char* normalizedFilename = _strdup(resolvedPath);
// Enabling this makes all file:line messages really long. For now, I'll keep it as relative to
// current working directory of this executable.
// const char* normalizedFilename = makeAbsolutePath_Allocated(".", filename);


+ 143
- 11
src/RunProcess.cpp View File

@ -14,6 +14,9 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// _tprintf() Remove me!
#include <tchar.h>
#else
#error Platform support is needed for running subprocesses
#endif
@ -63,6 +66,20 @@ void subprocessReceiveStdOut(const char* processOutputBuffer)
// Logf("%s", processOutputBuffer);
// }
// Does not work
#ifdef WINDOWS
void LogLastError()
{
LPTSTR lpMsgBuf = nullptr;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), lpMsgBuf, 0, NULL);
printf("%s\n", lpMsgBuf);
}
#endif
int runProcess(const RunProcessArguments& arguments, int* statusOut)
{
if (logging.processes)
@ -167,6 +184,99 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
return 0;
#elif WINDOWS
// List all environment variables
if (false)
{
LPTSTR lpszVariable;
LPTCH lpvEnv;
lpvEnv = GetEnvironmentStrings();
// If the returned pointer is NULL, exit.
if (lpvEnv == nullptr)
{
Logf("GetEnvironmentStrings failed (%d)\n", GetLastError());
return 1;
}
// Variable strings are separated by NULL byte, and the block is
// terminated by a NULL byte.
lpszVariable = (LPTSTR)lpvEnv;
while (*lpszVariable)
{
_tprintf(TEXT("%s\n"), lpszVariable);
lpszVariable += lstrlen(lpszVariable) + 1;
}
FreeEnvironmentStrings(lpvEnv);
Log("\nDone listing vars\n");
}
// We need to do some extra legwork to find which compiler they actually want to use, based on
// the current environment variables set by vcvars*.bat
// See https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160
char fileToExecuteOverride[MAX_PATH_LENGTH] = {0};
if (_stricmp(arguments.fileToExecute, "CL.exe") == 0 ||
_stricmp(arguments.fileToExecute, "link.exe") == 0)
{
LPTSTR vcInstallDir = nullptr;
LPTSTR vcHostArchitecture = nullptr;
LPTSTR vcTargetArchitecture = nullptr;
const int bufferSize = 4096;
struct
{
const char* variableName;
LPTSTR* outputString;
} msvcVariables[] = {{"VCToolsInstallDir", &vcInstallDir},
{"VSCMD_ARG_HOST_ARCH", &vcHostArchitecture},
{"VSCMD_ARG_TGT_ARCH", &vcTargetArchitecture}};
bool variablesFound = true;
for (int i = 0; i < ArraySize(msvcVariables); ++i)
{
*msvcVariables[i].outputString = (LPTSTR)malloc(bufferSize * sizeof(TCHAR));
if (!GetEnvironmentVariable(msvcVariables[i].variableName,
*msvcVariables[i].outputString, bufferSize) || true)
{
Logf(
"error: could not find environment variable '%s'.\n Please read the "
"following "
"URL:\nhttps://docs.microsoft.com/en-us/cpp/build/"
"building-on-the-command-line?view=msvc-160\nYou must run Cakelisp in a "
"command prompt which has already run vcvars* scripts.\nSee "
"cakelisp/Build.bat for an example.\nYou can define variables when running "
"Cakelisp from Visual Studio via Project -> Properties -> Configuration "
"Properties -> Debugging -> Environment\n",
msvcVariables[i].variableName);
Log("The following vars need to be defined in the environment:\n");
for (int n = 0; n < ArraySize(msvcVariables); ++n)
Logf("\t%s\n", msvcVariables[n].variableName);
variablesFound = false;
break;
}
}
if (variablesFound)
{
// PrintfBuffer(fileToExecuteOverride, "%sHost%s/%s/%s", vcInstallDir, vcHostArchitecture,
PrintfBuffer(fileToExecuteOverride, "%sbin\\Host%s\\%s\\%s", vcInstallDir, vcHostArchitecture,
vcTargetArchitecture, arguments.fileToExecute);
Logf("\nOverriding command to:\n%s\n\n", fileToExecuteOverride);
}
for (int n = 0; n < ArraySize(msvcVariables); ++n)
if (*msvcVariables[n].outputString)
free(*msvcVariables[n].outputString);
if (!variablesFound)
return 1;
}
else
Log("Not doing override\n");
STARTUPINFO startupInfo;
PROCESS_INFORMATION* processInfo = new PROCESS_INFORMATION;
@ -174,6 +284,11 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
startupInfo.cb = sizeof(startupInfo);
ZeroMemory(processInfo, sizeof(PROCESS_INFORMATION));
const char* fileToExecute =
fileToExecuteOverride[0] ? fileToExecuteOverride : arguments.fileToExecute;
// TODO: Make command line use fileToExecuteOverride if necessary!
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
char* commandLineString = nullptr;
{
size_t commandLineLength = 0;
@ -191,6 +306,7 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
{
if (!writeStringToBuffer(*arg, &writeHead, commandLineString, commandLineLength))
{
Log("error: ran out of space to write command\n");
free(commandLineString);
return 1;
}
@ -198,21 +314,36 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
}
// Start the child process.
if (!CreateProcess(arguments.fileToExecute, // No module name (use command line)
commandLineString, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&startupInfo, // Pointer to STARTUPINFO structure
processInfo)) // Pointer to PROCESS_INFORMATION structure
if (!CreateProcess(fileToExecute, // No module name (use command line)
commandLineString, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&startupInfo, // Pointer to STARTUPINFO structure
processInfo)) // Pointer to PROCESS_INFORMATION structure
{
Logf("CreateProcess failed (%d).\n", GetLastError());
int errorCode = GetLastError();
if (errorCode == ERROR_FILE_NOT_FOUND)
{
Logf("CreateProcess failed to find file: %s\n", fileToExecute);
}
else if (errorCode == ERROR_PATH_NOT_FOUND)
{
Logf("CreateProcess failed to find path: %s\n", fileToExecute);
}
else
{
Logf("CreateProcess failed: %d\n", errorCode);
}
// LogLastError();
return 1;
}
Log("Executed successfully\n");
std::string command = "";
for (const char** arg = arguments.arguments; *arg != nullptr; ++arg)
{
@ -221,6 +352,7 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
}
s_subprocesses.push_back({statusOut, processInfo, 0, command});
return 0;
#endif
return 1;
}


Loading…
Cancel
Save