Allow modules loaded via require() to use script-relative paths
This commit is contained in:
parent
3a4888b810
commit
9044ece96f
@ -36,6 +36,7 @@
|
||||
|
||||
excludes
|
||||
{
|
||||
"src/host/lua-5.1.4/src/lauxlib.c",
|
||||
"src/host/lua-5.1.4/src/lua.c",
|
||||
"src/host/lua-5.1.4/src/luac.c",
|
||||
"src/host/lua-5.1.4/src/print.c",
|
||||
|
@ -1,11 +1,11 @@
|
||||
--
|
||||
-- globals.lua
|
||||
-- Replacements and extensions to Lua's global functions.
|
||||
-- Copyright (c) 2002-2013 Jason Perkins and the Premake project
|
||||
-- Copyright (c) 2002-2014 Jason Perkins and the Premake project
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
---
|
||||
-- Helper for the dofile() and include() function: locate a script on the
|
||||
-- standard search paths of: the /scripts argument provided on the command
|
||||
-- line, then the PREMAKE_PATH environment variable.
|
||||
@ -15,12 +15,10 @@
|
||||
-- is the one that will be returned.
|
||||
-- @return
|
||||
-- The path to file if found, or nil if not.
|
||||
--
|
||||
---
|
||||
|
||||
local function locate(...)
|
||||
for i = 1, select("#",...) do
|
||||
local fname = select(i,...)
|
||||
|
||||
local function find(fname)
|
||||
-- is this a direct path to a file?
|
||||
if os.isfile(fname) then
|
||||
return fname
|
||||
@ -32,41 +30,33 @@
|
||||
return path.join(dir, fname)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, select("#",...) do
|
||||
local fname = select(i, ...)
|
||||
local result = find(fname)
|
||||
if not result then
|
||||
result = find(fname .. ".lua")
|
||||
end
|
||||
if result then
|
||||
return result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- A replacement for Lua's built-in dofile() function, this one sets the
|
||||
-- current working directory to the script's location, enabling script-relative
|
||||
-- referencing of other files and resources.
|
||||
--
|
||||
|
||||
---
|
||||
-- A replacement for Lua's built-in dofile() function that knows how to
|
||||
-- search for script files. Note that I've also modified luaL_loadfile()
|
||||
-- in src/host/lua_auxlib.c to set the _SCRIPT variable and adjust the
|
||||
-- working directory.
|
||||
---
|
||||
|
||||
local builtin_dofile = dofile
|
||||
|
||||
function dofile(fname)
|
||||
-- remember the current working directory and file; I'll restore it shortly
|
||||
local oldcwd = os.getcwd()
|
||||
local oldfile = _SCRIPT
|
||||
|
||||
-- find it; if I can't just continue with the name and let the
|
||||
-- built-in dofile() handle reporting the error as it will
|
||||
fname = locate(fname) or fname
|
||||
|
||||
-- use the absolute path to the script file, to avoid any file name
|
||||
-- ambiguity if an error should arise
|
||||
_SCRIPT = path.getabsolute(fname)
|
||||
|
||||
-- switch the working directory to the new script location
|
||||
local newcwd = path.getdirectory(_SCRIPT)
|
||||
os.chdir(newcwd)
|
||||
|
||||
-- run the chunk. How can I catch variable return values?
|
||||
local a, b, c, d, e, f = builtin_dofile(_SCRIPT)
|
||||
|
||||
-- restore the previous working directory when done
|
||||
_SCRIPT = oldfile
|
||||
os.chdir(oldcwd)
|
||||
return a, b, c, d, e, f
|
||||
return builtin_dofile(fname)
|
||||
end
|
||||
|
||||
|
||||
@ -97,24 +87,23 @@
|
||||
|
||||
|
||||
|
||||
--
|
||||
---
|
||||
-- Load and run an external script file, with a bit of extra logic to make
|
||||
-- including projects easier. if "path" is a directory, will look for
|
||||
-- path/premake5.lua. And each file is tracked, and loaded only once.
|
||||
--
|
||||
-- @param fname
|
||||
-- The name of the directory or file to include. If a directory, will
|
||||
-- automatically include the contained premake5.lua or premake4.lua
|
||||
-- script at that lcoation.
|
||||
---
|
||||
|
||||
io._includedFiles = {}
|
||||
|
||||
function include(fname)
|
||||
local found = locate(fname)
|
||||
if not found then
|
||||
found = locate(path.join(fname, "premake5.lua"))
|
||||
end
|
||||
if not found then
|
||||
found = locate(path.join(fname, "premake4.lua"))
|
||||
end
|
||||
local found = locate(fname, path.join(fname, "premake5.lua"), path.join(fname, "premake4.lua"))
|
||||
|
||||
-- but only load each file once
|
||||
-- only include each file once
|
||||
fname = path.getabsolute(found or fname)
|
||||
if not io._includedFiles[fname] then
|
||||
io._includedFiles[fname] = true
|
||||
|
@ -574,7 +574,7 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
/* skip eventual `#!...' */
|
||||
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
|
||||
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {};
|
||||
lf.extraline = 0;
|
||||
}
|
||||
ungetc(c, lf.f);
|
||||
|
91
src/host/lua_auxlib.c
Normal file
91
src/host/lua_auxlib.c
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* \file lua_auxlib.c
|
||||
* \brief Modifications and extensions to Lua's library functions.
|
||||
* \author Copyright (c) 2014 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
|
||||
|
||||
#define luaL_loadfile original_luaL_loadfile
|
||||
|
||||
#include "lua-5.1.4/src/lauxlib.c"
|
||||
|
||||
#undef luaL_loadfile
|
||||
|
||||
|
||||
/**
|
||||
* Execute a chunk of code previous loaded by my customized version of
|
||||
* luaL_loadfile(), below. Sets the _SCRIPT global variable to the
|
||||
* absolute path of the loaded chunk, and makes its enclosing directory
|
||||
* current so that relative path references to other files or scripts
|
||||
* can be used.
|
||||
*/
|
||||
|
||||
static int chunk_wrapper(lua_State* L)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
char script[PATH_MAX];
|
||||
const char* filename;
|
||||
char* ptr;
|
||||
int i, args;
|
||||
|
||||
args = lua_gettop(L);
|
||||
|
||||
/* Remember the current _SCRIPT and working directory so I can
|
||||
* restore them after the script chunk has been run. */
|
||||
|
||||
do_getcwd(cwd, PATH_MAX);
|
||||
lua_getglobal(L, "_SCRIPT");
|
||||
|
||||
/* Set the new _SCRIPT variable... */
|
||||
|
||||
filename = lua_tostring(L, lua_upvalueindex(2));
|
||||
do_getabsolute(script, filename, NULL);
|
||||
lua_pushstring(L, script);
|
||||
lua_setglobal(L, "_SCRIPT");
|
||||
|
||||
/* ...and make it's containing directory current */
|
||||
|
||||
ptr = strrchr(script, '/');
|
||||
if (ptr) *ptr = '\0';
|
||||
do_chdir(script);
|
||||
if (ptr) *ptr = '/';
|
||||
|
||||
/* Move the function's arguments to the top of the stack and
|
||||
* execute the function created by luaL_loadfile() */
|
||||
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
for (i = 1; i <= args; ++i) {
|
||||
lua_pushvalue(L, i);
|
||||
}
|
||||
|
||||
lua_call(L, args, LUA_MULTRET);
|
||||
|
||||
/* Finally, restore the previous _SCRIPT variable and working directory
|
||||
* before returning control to the previously executing script. */
|
||||
|
||||
do_chdir(cwd);
|
||||
lua_pushvalue(L, args + 1);
|
||||
lua_setglobal(L, "_SCRIPT");
|
||||
|
||||
return lua_gettop(L) - args - 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Extend the default implementation of luaL_loadfile() to call my chunk
|
||||
* wrapper, above, before executing any scripts loaded from a file.
|
||||
*/
|
||||
|
||||
LUALIB_API int luaL_loadfile (lua_State* L, const char* filename)
|
||||
{
|
||||
int z = original_luaL_loadfile(L, filename);
|
||||
if (z == 0) {
|
||||
lua_pushstring(L, filename);
|
||||
lua_pushcclosure(L, chunk_wrapper, 2);
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
@ -1,16 +1,15 @@
|
||||
/**
|
||||
* \file os_chdir.c
|
||||
* \brief Change the current working directory.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
* \author Copyright (c) 2002-2014 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
|
||||
|
||||
int os_chdir(lua_State* L)
|
||||
int do_chdir(const char* path)
|
||||
{
|
||||
int z;
|
||||
const char* path = luaL_checkstring(L, 1);
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
z = SetCurrentDirectory(path);
|
||||
@ -18,6 +17,16 @@ int os_chdir(lua_State* L)
|
||||
z = !chdir(path);
|
||||
#endif
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int os_chdir(lua_State* L)
|
||||
{
|
||||
const char* path = luaL_checkstring(L, 1);
|
||||
|
||||
int z = do_chdir(path);
|
||||
if (!z)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
|
@ -61,6 +61,7 @@
|
||||
|
||||
|
||||
/* Bootstrapping helper functions */
|
||||
int do_chdir(const char* path);
|
||||
unsigned long do_hash(const char* str, int seed);
|
||||
void do_getabsolute(char* result, const char* value, const char* relative_to);
|
||||
int do_getcwd(char* buffer, size_t size);
|
||||
|
Loading…
Reference in New Issue
Block a user