Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions definitions/process.luau
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ function process.exit(exitcode: number): never
error("not implemented")
end

function process.execpath(): string
error("not implemented")
end

return process
37 changes: 29 additions & 8 deletions lute/cli/src/climain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "lute/runtime.h"
#include "lute/tc.h"
#include "lute/version.h"
#include "uv.h"

#ifdef _WIN32
#include <Windows.h>
Expand All @@ -27,6 +28,24 @@
#include <string>
#include <vector>

namespace
{

struct UvLibraryState
{
UvLibraryState(int argc, char**& argv)
{
argv = uv_setup_args(argc, argv);
}

~UvLibraryState()
{
uv_library_shutdown();
}
};

} // namespace

void* createCliRequireContext(lua_State* L)
{
void* ctx = lua_newuserdatadtor(
Expand Down Expand Up @@ -259,7 +278,7 @@ static std::optional<std::string> getValidPath(std::string filePath)
return std::nullopt;
}

int handleRunCommand(int argc, char** argv, int argOffset)
int handleRunCommand(int argc, char** argv, char* argv0, int argOffset)
{
std::string filePath;
int program_argc = 0;
Expand Down Expand Up @@ -296,7 +315,7 @@ int handleRunCommand(int argc, char** argv, int argOffset)
return 1;
}

Runtime runtime;
Runtime runtime(argv0);
lua_State* L = setupCliState(runtime);

std::optional<std::string> validPath = getValidPath(filePath);
Expand Down Expand Up @@ -411,9 +430,9 @@ int handleCompileCommand(int argc, char** argv, int argOffset)
return compileScript(inputFilePath, outputFilePath, argv[0]);
}

int handleCliCommand(CliCommandResult result, int program_argc, char** program_argv)
int handleCliCommand(CliCommandResult result, int program_argc, char** program_argv, char* argv0)
{
Runtime runtime;
Runtime runtime(argv0);
lua_State* L = setupCliState(runtime);

std::string bytecode = Luau::compile(std::string(result.contents), copts());
Expand All @@ -424,10 +443,12 @@ int cliMain(int argc, char** argv)
{
Luau::assertHandler() = assertionHandler;

UvLibraryState uvlib(argc, argv);

AppendedBytecodeResult embedded = checkForAppendedBytecode(argv[0]);
if (embedded.found)
{
Runtime runtime;
Runtime runtime(argv[0]);
lua_State* GL = setupCliState(runtime);

bool success = runBytecode(runtime, embedded.BytecodeData, "=__EMBEDDED__", GL, argc, argv);
Expand All @@ -451,7 +472,7 @@ int cliMain(int argc, char** argv)

if (strcmp(command, "run") == 0)
{
return handleRunCommand(argc, argv, argOffset);
return handleRunCommand(argc, argv, argv[0], argOffset);
}
else if (strcmp(command, "check") == 0)
{
Expand All @@ -473,12 +494,12 @@ int cliMain(int argc, char** argv)
}
else if (std::optional<CliCommandResult> result = getCliCommand(command); result)
{
return handleCliCommand(*result, argc - argOffset, &argv[argOffset]);
return handleCliCommand(*result, argc - argOffset, &argv[argOffset], argv[0]);
}
else
{
// Default to 'run' command
argOffset = 1;
return handleRunCommand(argc, argv, argOffset);
return handleRunCommand(argc, argv, argv[0], argOffset);
}
}
3 changes: 3 additions & 0 deletions lute/process/include/lute/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ int cwd(lua_State* L);

int exitFunc(lua_State* L);

int execpath(lua_State* L);

static const luaL_Reg lib[] = {
{"run", run},
{"homedir", homedir},
{"cwd", cwd},
{"exit", exitFunc},
{"execpath", execpath},

{nullptr, nullptr}
};
Expand Down
6 changes: 6 additions & 0 deletions lute/process/src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ int cwd(lua_State* L)
return 1;
};

int execpath(lua_State* L)
{
lua_pushstring(L, getRuntime(L)->execPath.c_str());
return 1;
}

static int envIndex(lua_State* L)
{
const char* key = luaL_checkstring(L, 2);
Expand Down
4 changes: 3 additions & 1 deletion lute/runtime/include/lute/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using RuntimeStep = Luau::Variant<StepSuccess, StepErr, StepEmpty>;

struct Runtime
{
Runtime();
Runtime(const char* argv0 = nullptr);
~Runtime();

bool runToCompletion();
Expand Down Expand Up @@ -81,6 +81,8 @@ struct Runtime

std::vector<ThreadToContinue> runningThreads;

std::string execPath;

private:
std::mutex continuationMutex;
std::vector<std::function<void()>> continuations;
Expand Down
21 changes: 20 additions & 1 deletion lute/runtime/src/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,35 @@

#include <string>
#include <assert.h>
#include <climits> // IWYU pragma: keep

#ifdef PATH_MAX
#define LUTE_PATH_MAX PATH_MAX
#else
#define LUTE_PATH_MAX 8192
#endif

static void lua_close_checked(lua_State* L)
{
if (L)
lua_close(L);
}

Runtime::Runtime()
static std::string getExecPath(const char* argv0)
{
char buf[LUTE_PATH_MAX];
size_t len = sizeof(buf);
if (uv_exepath(buf, &len) == 0)
return {buf, len};
if (argv0)
return argv0;
return {};
}

Runtime::Runtime(const char* argv0)
: globalState(nullptr, lua_close_checked)
, dataCopy(nullptr, lua_close_checked)
, execPath(getExecPath(argv0))
{
stop.store(false);
activeTokens.store(0);
Expand Down
2 changes: 1 addition & 1 deletion lute/vm/src/spawn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ int lua_spawn(lua_State* L)
{
const char* file = luaL_checkstring(L, 1);

auto child = std::make_shared<Runtime>();
auto child = std::make_shared<Runtime>(getRuntime(L)->execPath.c_str());

setupState(
*child,
Expand Down