Browse Source

Process command arguments can now be changed

* Fix bug where first command argument was being ignored
* Convert linker to use new commands
* Support setting arguments from Cakelisp
* Add #error to set Windows defaults
* Print command arguments if the subprocess returns failure
GeneralDependencyResolver
Macoy Madson 1 month ago
parent
commit
588e39756b
6 changed files with 108 additions and 24 deletions
  1. +3
    -3
      runtime/Macros.cake
  2. +25
    -19
      src/Evaluator.cpp
  3. +4
    -0
      src/EvaluatorEnums.hpp
  4. +53
    -1
      src/Generators.cpp
  5. +10
    -0
      src/ModuleManager.cpp
  6. +13
    -1
      src/RunProcess.cpp

+ 3
- 3
runtime/Macros.cake View File

@@ -1,9 +1,9 @@
(set-cakelisp-option compile-time-compiler "/usr/bin/clang++")
(set-cakelisp-option compile-time-build-arguments
"-g" "-c" 'sourceInput "-o" 'objectOutput 'cakelispHeadersInclude "-fPIC")
(set-cakelisp-option compile-time-compile-arguments
"-g" "-c" 'source-input "-o" 'object-output 'cakelisp-headers-include "-fPIC")
(set-cakelisp-option compile-time-linker "/usr/bin/clang++")
(set-cakelisp-option compile-time-link-arguments
"-shared" "-o" 'libraryOutput 'objectInput)
"-shared" "-o" 'library-output 'object-input)

;; TODO: This should be builtin to macros and generators
(defmacro destructure-arguments ()


+ 25
- 19
src/Evaluator.cpp View File

@@ -495,21 +495,23 @@ void PrintProcessArguments(const char** processArguments)
const char** MakeProcessArgumentsFromCommand(ProcessCommand& command,
const ProcessCommandInput* inputs, int numInputs)
{
int numArguments = command.arguments.size();
// +1 for file to execute
int numArguments = command.arguments.size() + 1;
// +1 again for the null terminator
const char** newArguments = (const char**)calloc(sizeof(const char*), numArguments + 1);
for (int i = 0; i < numArguments; ++i)
int numFinalArguments = numArguments + 1;
// +1 again for the null terminator
const char** newArguments = (const char**)calloc(sizeof(const char*), numFinalArguments + 1);
for (int i = 0; i < numFinalArguments; ++i)
newArguments[i] = nullptr;
newArguments[numArguments] = nullptr;
newArguments[numFinalArguments] = nullptr;
newArguments[0] = command.fileToExecute.c_str();

for (int i = 1; i < numArguments - 1; ++i)
for (int i = 0; i < numArguments; ++i)
{
int finalArgumentIndex = i + 1;
ProcessCommandArgument& argument = command.arguments[i];

if (argument.type == ProcessCommandArgumentType_String)
newArguments[i] = argument.contents.c_str();
newArguments[finalArgumentIndex] = argument.contents.c_str();
else
{
bool found = false;
@@ -517,7 +519,7 @@ const char** MakeProcessArgumentsFromCommand(ProcessCommand& command,
{
if (inputs[input].type == argument.type)
{
newArguments[i] = inputs[input].value;
newArguments[finalArgumentIndex] = inputs[input].value;
found = true;
break;
}
@@ -726,22 +728,26 @@ int BuildExecuteCompileTimeFunctions(EvaluatorEnvironment& environment,
if (log.buildProcess)
printf("Compiled %s successfully\n", buildObject.definition->name->contents.c_str());

char linkerExecutable[MAX_PATH_LENGTH] = {0};
PrintBuffer(linkerExecutable, "/usr/bin/clang++");

const char* arguments[] = {linkerExecutable,
"-shared",
"-o",
buildObject.dynamicLibraryPath.c_str(),
buildObject.buildObjectName.c_str(),
nullptr};
ProcessCommandInput linkTimeInputs[] = {
{ProcessCommandArgumentType_DynamicLibraryOutput,
buildObject.dynamicLibraryPath.c_str()},
{ProcessCommandArgumentType_ObjectInput, buildObject.buildObjectName.c_str()}};
const char** linkArgumentList = MakeProcessArgumentsFromCommand(
environment.compileTimeLinkCommand, linkTimeInputs, ArraySize(linkTimeInputs));
if (!linkArgumentList)
{
// TODO: Abort building if cannot invoke compiler
continue;
}
RunProcessArguments linkArguments = {};
linkArguments.fileToExecute = linkerExecutable;
linkArguments.arguments = arguments;
linkArguments.fileToExecute = environment.compileTimeLinkCommand.fileToExecute.c_str();
linkArguments.arguments = linkArgumentList;
if (runProcess(linkArguments, &buildObject.status) != 0)
{
// TODO: Abort if linker failed?
// free(linkArgumentList);
}
free(linkArgumentList);
}

// The result of the linking will go straight to our definitionsToBuild


+ 4
- 0
src/EvaluatorEnums.hpp View File

@@ -75,7 +75,11 @@ enum ObjectReferenceGuessState
enum ProcessCommandArgumentType
{
ProcessCommandArgumentType_String,

ProcessCommandArgumentType_SourceInput,
ProcessCommandArgumentType_ObjectOutput,
ProcessCommandArgumentType_CakelispHeadersInclude,

ProcessCommandArgumentType_ObjectInput,
ProcessCommandArgumentType_DynamicLibraryOutput,
};

+ 53
- 1
src/Generators.cpp View File

@@ -35,6 +35,58 @@ bool SetProcessCommandFileToExec(EvaluatorEnvironment& environment,
bool SetProcessCommandArguments(EvaluatorEnvironment& environment, const std::vector<Token>& tokens,
int startTokenIndex, ProcessCommand* command)
{
command->arguments.clear();

int endInvocationIndex = FindCloseParenTokenIndex(tokens, startTokenIndex);
int startArgsIndex = getArgument(tokens, startTokenIndex, 2, endInvocationIndex);
// No args is weird, but we'll allow it
if (startArgsIndex == -1)
return true;

for (int argumentIndex = startArgsIndex; argumentIndex < endInvocationIndex; ++argumentIndex)
{
const Token& argumentToken = tokens[argumentIndex];
if (argumentToken.type == TokenType_String)
{
command->arguments.push_back(
{ProcessCommandArgumentType_String, argumentToken.contents});
}
else if (argumentToken.type == TokenType_Symbol)
{
struct
{
const char* symbolName;
ProcessCommandArgumentType type;
} symbolsToCommandTypes[] = {
{"'source-input", ProcessCommandArgumentType_SourceInput},
{"'object-output", ProcessCommandArgumentType_ObjectOutput},
{"'cakelisp-headers-include", ProcessCommandArgumentType_CakelispHeadersInclude},
{"'object-input", ProcessCommandArgumentType_ObjectInput},
{"'library-output", ProcessCommandArgumentType_DynamicLibraryOutput},
};
bool found = false;
for (unsigned int i = 0; i < ArraySize(symbolsToCommandTypes); ++i)
{
if (argumentToken.contents.compare(symbolsToCommandTypes[i].symbolName) == 0)
{
command->arguments.push_back({symbolsToCommandTypes[i].type, EmptyString});
found = true;
break;
}
}
if (!found)
{
ErrorAtToken(argumentToken, "unrecognized symbol");
return false;
}
}
else
{
ErrorAtTokenf(argumentToken, "expected string argument or symbol, got %s",
tokenTypeToString(argumentToken.type));
return false;
}
}
return true;
}

@@ -125,7 +177,7 @@ bool SetCakelispOption(EvaluatorEnvironment& environment, const EvaluatorContext

for (unsigned int i = 0; i < ArraySize(commandOptions); ++i)
{
if (tokens[optionNameIndex].contents.compare(commandOptions[i].optionName))
if (tokens[optionNameIndex].contents.compare(commandOptions[i].optionName) == 0)
{
return commandOptions[i].handler(environment, tokens, startTokenIndex,
commandOptions[i].command);


+ 10
- 0
src/ModuleManager.cpp View File

@@ -51,6 +51,11 @@ void moduleManagerInitialize(ModuleManager& manager)
{ProcessCommandArgumentType_String, "-fPIC"}};

manager.environment.compileTimeLinkCommand.fileToExecute = "/usr/bin/clang++";
manager.environment.compileTimeLinkCommand.arguments = {
{ProcessCommandArgumentType_String, "-shared"},
{ProcessCommandArgumentType_String, "-o"},
{ProcessCommandArgumentType_DynamicLibraryOutput, EmptyString},
{ProcessCommandArgumentType_ObjectInput, EmptyString}};

manager.environment.buildTimeBuildCommand.fileToExecute = "/usr/bin/clang++";
manager.environment.buildTimeBuildCommand.arguments = {
@@ -64,6 +69,11 @@ void moduleManagerInitialize(ModuleManager& manager)
manager.environment.buildTimeLinkCommand.fileToExecute = "/usr/bin/clang++";
}

// TODO: Add defaults for Windows
#ifdef WINDOWS
#error Set sensible defaults for compile time build command
#endif

makeDirectory(cakelispWorkingDir);
printf("Using cache at %s\n", cakelispWorkingDir);
}


+ 13
- 1
src/RunProcess.cpp View File

@@ -26,6 +26,7 @@ struct Subprocess
int* statusOut;
ProcessId processId;
int pipeReadFileDescriptor;
std::string command;
};

static std::vector<Subprocess> s_subprocesses;
@@ -131,7 +132,14 @@ int runProcess(const RunProcessArguments& arguments, int* statusOut)
if (log.processes)
printf("Created child process %d\n", pid);

s_subprocesses.push_back({statusOut, pid, pipeFileDescriptors[PipeRead]});
std::string command = "";
for (const char** arg = arguments.arguments; *arg != nullptr; ++arg)
{
command.append(*arg);
command.append(" ");
}

s_subprocesses.push_back({statusOut, pid, pipeFileDescriptors[PipeRead], command});
}

return 1;
@@ -162,6 +170,10 @@ void waitForAllProcessesClosed(SubprocessOnOutputFunc onOutput)
close(process.pipeReadFileDescriptor);

waitpid(process.processId, process.statusOut, 0);

// It's pretty useful to see the command which resulted in failure
if (*process.statusOut != 0)
printf("%s\n", process.command.c_str());
#endif
}



Loading…
Cancel
Save