Merge script path searching restrictions for release builds and user project scripts

This commit is contained in:
Jason Perkins 2015-02-15 16:10:46 -05:00
commit 5e51b54c3d
6 changed files with 247 additions and 119 deletions

View File

@ -28,6 +28,7 @@
p.main.elements = function()
return {
p.main.locateUserScript,
p.main.installModuleLoader,
}
end
@ -48,14 +49,6 @@
_PREMAKE_DIR = path.getdirectory(_PREMAKE_COMMAND)
premake.path = premake.path .. ";" .. _PREMAKE_DIR
local file = _OPTIONS["file"] or "premake5.lua"
_MAIN_SCRIPT = os.locate(file, file .. ".lua", "premake4.lua")
if _MAIN_SCRIPT then
_MAIN_SCRIPT_DIR = path.getdirectory(_MAIN_SCRIPT)
else
_MAIN_SCRIPT_DIR = _WORKING_DIR
end
p.callArray(p.main.elements)
-- Look for and run the system-wide configuration script; make sure any
@ -79,7 +72,7 @@
-- If there is a project script available, run it to get the
-- project information, available options and actions, etc.
if _MAIN_SCRIPT then
if os.isfile(_MAIN_SCRIPT) then
dofile(_MAIN_SCRIPT)
end
@ -119,8 +112,8 @@
return 1
end
if not _MAIN_SCRIPT then
print("No Premake script (premake5.lua) found!")
if not os.isfile(_MAIN_SCRIPT) then
print(string.format("No Premake script (%s) found!", path.getname(_MAIN_SCRIPT)))
return 1
end
end
@ -153,6 +146,34 @@
---
-- Look for a user project script, and set up the related global
-- variables if I can find one.
---
function p.main.locateUserScript()
local defaults = { "premake5.lua", "premake4.lua" }
for i = 1, #defaults do
if os.isfile(defaults[i]) then
_MAIN_SCRIPT = defaults[i]
break
end
end
if not _MAIN_SCRIPT then
_MAIN_SCRIPT = defaults[1]
end
if _OPTIONS.file then
_MAIN_SCRIPT = _OPTIONS.file
end
_MAIN_SCRIPT = path.getabsolute(_MAIN_SCRIPT)
_MAIN_SCRIPT_DIR = path.getdirectory(_MAIN_SCRIPT)
end
---
-- Add a new module loader that knows how to use the Premake paths like
-- PREMAKE_PATH and the --scripts option, and follows the module/module.lua

View File

@ -1,7 +1,7 @@
/**
* \file lua_auxlib.c
* \brief Modifications and extensions to Lua's library functions.
* \author Copyright (c) 2014 Jason Perkins and the Premake project
* \author Copyright (c) 2014-2015 Jason Perkins and the Premake project
*/
#include "premake.h"
@ -33,29 +33,38 @@ LUALIB_API int luaL_loadfile (lua_State* L, const char* filename)
int bottom = lua_gettop(L);
int z = !OKAY;
/* If the currently running script was embedded, try to load this file
* as it if were embedded too. */
lua_getglobal(L, "_SCRIPT_DIR");
script_dir = lua_tostring(L, -1);
if (script_dir && script_dir[0] == '$') {
/* Call `path.getabsolute(filename, _SCRIPT_DIR)` to resolve any
* "../" sequences in the filename */
lua_pushcfunction(L, path_getabsolute);
lua_pushstring(L, filename);
lua_pushvalue(L, -3);
lua_call(L, 2, 1);
test_name = lua_tostring(L, -1);
/* if successful, filename and chunk will be on top of stack */
z = premake_load_embedded_script(L, test_name + 2); /* Skip over leading "$/" */
/* remove test_name */
lua_remove(L, bottom + 1);
/* If filename is starts with "$/" then we want to load the version that
* was embedded into the executable and skip the local file system */
if (filename[0] == '$') {
z = premake_load_embedded_script(L, filename + 2); /* Skip over leading "$/" */
if (z != OKAY) return z;
}
/* remove _SCRIPT_DIR */
lua_remove(L, bottom);
/* If the currently running script was embedded, try to load this file
* as it if were embedded too. */
if (z != OKAY) {
lua_getglobal(L, "_SCRIPT_DIR");
script_dir = lua_tostring(L, -1);
if (script_dir && script_dir[0] == '$') {
/* Call `path.getabsolute(filename, _SCRIPT_DIR)` to resolve any
* "../" sequences in the filename */
lua_pushcfunction(L, path_getabsolute);
lua_pushstring(L, filename);
lua_pushvalue(L, -3);
lua_call(L, 2, 1);
test_name = lua_tostring(L, -1);
/* if successful, filename and chunk will be on top of stack */
z = premake_load_embedded_script(L, test_name + 2); /* Skip over leading "$/" */
/* remove test_name */
lua_remove(L, bottom + 1);
}
/* remove _SCRIPT_DIR */
lua_remove(L, bottom);
}
/* Try to locate the script on the filesystem */
if (z != OKAY) {

View File

@ -8,6 +8,20 @@
#include "premake.h"
int do_locate(lua_State* L, const char* filename, const char* path)
{
if (do_pathsearch(L, filename, path)) {
lua_pushstring(L, "/");
lua_pushstring(L, filename);
lua_concat(L, 3);
return 1;
}
return 0;
}
int os_locate(lua_State* L)
{
int i;
@ -26,22 +40,10 @@ int os_locate(lua_State* L)
return 1;
}
/* Call os.pathsearch(arg[i], premake.path) */
lua_pushcfunction(L, os_pathsearch);
lua_pushvalue(L, i);
lua_pushvalue(L, -3);
lua_call(L, 2, 1);
/* os.pathsearch() returns the directory containing the file;
* append the filename to complete the path */
if (!lua_isnil(L, -1)) {
lua_pushstring(L, "/");
lua_pushvalue(L, 1);
lua_concat(L, 3);
/* do_locate(arg[i], premake.path) */
if (do_locate(L, lua_tostring(L, i), lua_tostring(L, -1))) {
return 1;
}
lua_pop(L, 1);
}
return 0;

View File

@ -11,76 +11,82 @@
#include "premake.h"
int do_pathsearch(lua_State* L, const char* filename, const char* path)
{
do
{
const char* split;
/* look for the closest path separator ; or : */
/* can't use : on windows because it breaks on C:\path */
const char* semi = strchr(path, ';');
#if !defined(PLATFORM_WINDOWS)
const char* full = strchr(path, ':');
#else
const char* full = NULL;
#endif
if (!semi)
{
split = full;
}
else if (!full)
{
split = semi;
}
else
{
split = (semi < full) ? semi : full;
}
/* push this piece of the full search string onto the stack */
if (split)
{
lua_pushlstring(L, path, split - path);
}
else
{
lua_pushstring(L, path);
}
/* keep an extra copy around, so I can return it if I have a match */
lua_pushvalue(L, -1);
/* append the filename to make the full test path */
lua_pushstring(L, "/");
lua_pushstring(L, filename);
lua_concat(L, 3);
/* test it - if it exists, return the absolute path */
if (do_isfile(lua_tostring(L, -1)))
{
lua_pop(L, 1);
lua_pushcfunction(L, path_getabsolute);
lua_pushvalue(L, -2);
lua_call(L, 1, 1);
return 1;
}
/* no match, set up the next try */
lua_pop(L, 2);
path = (split) ? split + 1 : NULL;
}
while (path);
return 0;
}
int os_pathsearch(lua_State* L)
{
int i;
const char* filename = luaL_checkstring(L, 1);
for (i = 2; i <= lua_gettop(L); ++i)
{
const char* path;
if (lua_isnil(L, i))
continue;
path = luaL_checkstring(L, i);
do
{
const char* split;
/* look for the closest path separator ; or : */
/* can't use : on windows because it breaks on C:\path */
const char* semi = strchr(path, ';');
#if !defined(PLATFORM_WINDOWS)
const char* full = strchr(path, ':');
#else
const char* full = NULL;
#endif
if (!semi)
{
split = full;
}
else if (!full)
{
split = semi;
}
else
{
split = (semi < full) ? semi : full;
}
/* push this piece of the full search string onto the stack */
if (split)
{
lua_pushlstring(L, path, split - path);
}
else
{
lua_pushstring(L, path);
}
/* keep an extra copy around, so I can return it if I have a match */
lua_pushvalue(L, -1);
/* append the filename to make the full test path */
lua_pushstring(L, "/");
lua_pushvalue(L, 1);
lua_concat(L, 3);
/* test it - if it exists, return the absolute path */
if (do_isfile(lua_tostring(L, -1)))
{
lua_pop(L, 1);
lua_pushcfunction(L, path_getabsolute);
lua_pushvalue(L, -2);
lua_call(L, 1, 1);
return 1;
}
/* no match, set up the next try */
lua_pop(L, 2);
path = (split) ? split + 1 : NULL;
}
while (path);
if (lua_isnil(L, i)) continue;
if (do_pathsearch(L, filename, luaL_checkstring(L, i))) return 1;
}
return 0;

View File

@ -22,6 +22,7 @@
static void build_premake_path(lua_State* L);
static int process_arguments(lua_State* L, int argc, const char** argv);
static int run_premake_main(lua_State* L, const char* script);
/* A search path for script files */
@ -132,13 +133,14 @@ int premake_init(lua_State* L)
}
int premake_execute(lua_State* L, int argc, const char** argv, const char* script)
{
int iErrFunc;
/* push the absolute path to the Premake executable */
lua_pushcfunction(L, path_getabsolute);
premake_locate(L, argv[0]);
premake_locate_executable(L, argv[0]);
lua_call(L, 1, 1);
lua_setglobal(L, "_PREMAKE_COMMAND");
@ -150,8 +152,8 @@ int premake_execute(lua_State* L, int argc, const char** argv, const char* scrip
/* Use --scripts and PREMAKE_PATH to populate premake.path */
build_premake_path(L);
/* load the main script */
if (luaL_dofile(L, script) != OKAY) {
/* Find and run the main Premake bootstrapping script */
if (run_premake_main(L, script) != OKAY) {
printf(ERROR_MESSAGE, lua_tostring(L, -1));
return !OKAY;
}
@ -185,7 +187,7 @@ int premake_execute(lua_State* L, int argc, const char** argv, const char* scrip
* http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c
* http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
*/
int premake_locate(lua_State* L, const char* argv0)
int premake_locate_executable(lua_State* L, const char* argv0)
{
char buffer[PATH_MAX];
const char* path = NULL;
@ -262,6 +264,50 @@ int premake_locate(lua_State* L, const char* argv0)
/**
* Checks one or more of the standard script search locations to locate the
* specified file. If found, returns the discovered path to the script on
* the top of the Lua stack.
*/
int premake_test_file(lua_State* L, const char* filename, int searchMask)
{
int i;
if (searchMask & TEST_LOCAL) {
if (do_isfile(filename)) {
lua_pushcfunction(L, path_getabsolute);
lua_pushstring(L, filename);
lua_call(L, 1, 1);
return OKAY;
}
}
if (scripts_path && (searchMask & TEST_SCRIPTS)) {
if (do_locate(L, filename, scripts_path)) return OKAY;
}
if (searchMask & TEST_PATH) {
const char* path = getenv("PREMAKE_PATH");
if (path && do_locate(L, filename, path)) return OKAY;
}
if ((searchMask & TEST_EMBEDDED) != 0) {
/* Try to locate a record matching the filename */
for (i = 0; builtin_scripts_index[i] != NULL; ++i) {
if (strcmp(builtin_scripts_index[i], filename) == 0) {
lua_pushstring(L, "$/");
lua_pushstring(L, filename);
lua_concat(L, 2);
return OKAY;
}
}
}
return !OKAY;
}
static const char* set_scripts_path(const char* relativePath)
{
char* path = (char*)malloc(PATH_MAX);
@ -376,6 +422,41 @@ static int process_arguments(lua_State* L, int argc, const char** argv)
/**
* Find and run the main Premake bootstrapping script. The loading of the
* bootstrap and the other core scripts use a limited set of search paths
* to avoid mismatches between the native host code and the scripts
* themselves.
*/
static int run_premake_main(lua_State* L, const char* script)
{
/* Release builds want to load the embedded scripts, with --scripts
* argument allowed as an override. Debug builds will look at the
* local file system first, then fall back to embedded. */
#if defined(NDEBUG)
int z = premake_test_file(L, script,
TEST_SCRIPTS | TEST_EMBEDDED);
#else
int z = premake_test_file(L, script,
TEST_LOCAL | TEST_SCRIPTS | TEST_PATH | TEST_EMBEDDED);
#endif
/* If no embedded script can be found, release builds will then
* try to fall back to the local file system, just in case */
#if defined(NDEBUG)
if (z != OKAY) {
z = premake_test_file(L, script, TEST_LOCAL | TEST_PATH);
}
#endif
if (z == OKAY) {
z = luaL_dofile(L, lua_tostring(L, -1));
}
return z;
}
/**
* Load a script that was previously embedded into the executable. If
* successful, a function containing the new script chunk is pushed to

View File

@ -1,7 +1,7 @@
/**
* \file premake.h
* \brief Program-wide constants and definitions.
* \author Copyright (c) 2002-2014 Jason Perkins and the Premake project
* \author Copyright (c) 2002-2015 Jason Perkins and the Premake project
*/
#define lua_c
@ -60,6 +60,13 @@
#define OKAY (0)
/* Bitmasks for the different script file search locations */
#define TEST_LOCAL (0x01)
#define TEST_SCRIPTS (0x02)
#define TEST_PATH (0x04)
#define TEST_EMBEDDED (0x08)
/* If a /scripts argument is present, its value */
extern const char* scripts_path;
@ -71,7 +78,9 @@ void do_getabsolute(char* result, const char* value, const char* relative_to);
int do_getcwd(char* buffer, size_t size);
int do_isabsolute(const char* path);
int do_isfile(const char* filename);
int do_locate(lua_State* L, const char* filename, const char* path);
void do_normalize(lua_State* L, char* buffer, const char* path);
int do_pathsearch(lua_State* L, const char* filename, const char* path);
void do_translate(char* value, const char sep);
@ -113,10 +122,10 @@ int string_startswith(lua_State* L);
/* Engine interface */
int premake_init(lua_State* L);
int premake_locate(lua_State* L, const char* argv0);
int premake_execute(lua_State* L, int argc, const char** argv, const char* script);
int premake_find_exe(lua_State* L, const char* argv0);
int premake_load_embedded_script(lua_State* L, const char* filename);
int premake_locate_executable(lua_State* L, const char* argv0);
int premake_test_file(lua_State* L, const char* filename, int searchMask);
extern const char* builtin_scripts_index[];