Work in progress on configuration blocks (r414:421)

This commit is contained in:
starkos 2008-06-27 16:53:36 +00:00
parent a99ff72d9f
commit 5c50a9f9d5
33 changed files with 738 additions and 53 deletions

View File

@ -29,7 +29,7 @@ project.name = "Premake4"
REPOS = "https://premake.svn.sourceforge.net/svnroot/premake"
TRUNK = "/trunk"
BRANCHES = "/branches/4.0-alpha/"
TAGS = "/tags/4.0-alpha/"
function dorelease(cmd, arg)
@ -60,7 +60,7 @@ project.name = "Premake4"
local folder = "premake-"..version
local trunk = REPOS..TRUNK
local branch = REPOS..BRANCHES..version
local branch = REPOS..TAGS..version
-------------------------------------------------------------------
-- Build and run all automated tests on working copy

View File

@ -86,7 +86,7 @@ int gmake_solution_default_config(Session sess, Solution sln, Stream strm)
assert(sln);
assert(strm);
default_config_name = solution_get_config_name(sln, 0);
default_config_name = solution_get_config(sln, 0);
z = stream_writeline(strm, "ifndef CONFIG");
z |= stream_writeline(strm, " CONFIG=%s", default_config_name);
z |= stream_writeline(strm, "endif");
@ -208,7 +208,7 @@ int gmake_solution_signature(Session sess, Solution sln, Stream strm)
z |= stream_writeline(strm, "# Usage: make [ CONFIG=config_name ]");
z |= stream_writeline(strm, "# Where {config_name} is one of:");
config_names = solution_get_config_names(sln);
config_names = solution_get_configs(sln);
z |= stream_writeline_strings(strm, config_names, "# ", " ", "", ",");
z |= stream_writeline(strm, "");

View File

@ -30,8 +30,8 @@ struct FxAction
session_add_solution(sess, sln);
solution_set_name(sln, "MySolution");
solution_set_base_dir(sln, "/Root");
solution_add_config_name(sln, "Debug");
solution_add_config_name(sln, "Release");
solution_add_config(sln, "Debug");
solution_add_config(sln, "Release");
prj = project_create();
solution_add_project(sln, prj);

View File

@ -31,7 +31,7 @@ int vs2002_solution_configuration(Session sess, Solution sln, Stream strm)
n = solution_num_configs(sln);
for (i = 0; i < n; ++i)
{
const char* config_name = solution_get_config_name(sln, i);
const char* config_name = solution_get_config(sln, i);
z |= stream_writeline(strm, "\t\tConfigName.%d = %s", i, config_name);
}
@ -101,7 +101,7 @@ int vs2002_solution_project_configuration(Session sess, Solution sln, Stream str
cn = solution_num_configs(sln);
for (ci = 0; ci < cn; ++ci)
{
const char* config_name = solution_get_config_name(sln, ci);
const char* config_name = solution_get_config(sln, ci);
z |= stream_writeline(strm, "\t\t{%s}.%s.ActiveCfg = %s|Win32", prj_id, config_name, config_name);
z |= stream_writeline(strm, "\t\t{%s}.%s.Build.0 = %s|Win32", prj_id, config_name, config_name);
}

View File

@ -28,7 +28,7 @@ int vs2003_solution_configuration(Session sess, Solution sln, Stream strm)
n = solution_num_configs(sln);
for (i = 0; i < n; ++i)
{
const char* config_name = solution_get_config_name(sln, i);
const char* config_name = solution_get_config(sln, i);
z |= stream_writeline(strm, "\t\t%s = %s", config_name, config_name);
}

View File

@ -28,7 +28,7 @@ int vs2005_solution_platforms(Session sess, Solution sln, Stream strm)
n = solution_num_configs(sln);
for (i = 0; i < n; ++i)
{
const char* config_name = solution_get_config_name(sln, i);
const char* config_name = solution_get_config(sln, i);
z |= stream_writeline(strm, "\t\t%s|Win32 = %s|Win32", config_name, config_name);
}
@ -59,7 +59,7 @@ int vs2005_solution_project_platforms(Session sess, Solution sln, Stream strm)
cn = solution_num_configs(sln);
for (ci = 0; ci < cn; ++ci)
{
const char* config_name = solution_get_config_name(sln, ci);
const char* config_name = solution_get_config(sln, ci);
z |= stream_writeline(strm, "\t\t{%s}.%s|Win32.ActiveCfg = %s|Win32", prj_id, config_name, config_name);
z |= stream_writeline(strm, "\t\t{%s}.%s|Win32.Build.0 = %s|Win32", prj_id, config_name, config_name);
}

68
src/project/block.c Normal file
View File

@ -0,0 +1,68 @@
/**
* \file block.c
* \brief The configuration block class.
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
*/
#include <assert.h>
#include <stdlib.h>
#include "premake.h"
#include "project/block.h"
struct FieldInfo BlockFieldInfo[] =
{
{ "defines", ListField, NULL },
{ "objdir", StringField, NULL },
{ 0, 0, NULL }
};
DEFINE_CLASS(Block)
{
Fields fields;
};
/**
* Create and initialize a new configuration block.
* \returns A new configuration block.
*/
Block block_create()
{
Block blk = ALLOC_CLASS(Block);
blk->fields = fields_create(BlockFieldInfo);
return blk;
}
/**
* Destroy a configuration block and release the associated memory.
* \param blk The configuration block to destroy.
*/
void block_destroy(Block blk)
{
assert(blk);
fields_destroy(blk->fields);
free(blk);
}
/**
* Retrieve the list of defines associated with a block.
*/
Strings block_get_defines(Block blk)
{
assert(blk);
return fields_get_values(blk->fields, BlockDefines);
}
/**
* Retrieve the fields object for this block; used to unload values from the script.
*/
Fields block_get_fields(Block blk)
{
assert(blk);
return blk->fields;
}

39
src/project/block.h Normal file
View File

@ -0,0 +1,39 @@
/**
* \file block.h
* \brief Configuration blocks API.
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
*
* \addtogroup project
* @{
*/
#if !defined(PREMAKE_BLOCK_H)
#define PREMAKE_BLOCK_H
#include "fields.h"
/**
* Configuration block field index.
* \note If you modify this list, you must also update BlockFieldInfo[].
*/
enum BlockField
{
BlockDefines,
BlockObjDir,
NumBlockFields
};
extern struct FieldInfo BlockFieldInfo[];
DECLARE_CLASS(Block)
Block block_create(void);
void block_destroy(Block blk);
Strings block_get_defines(Block blk);
Fields block_get_fields(Block blk);
#endif
/** @} */

View File

@ -33,6 +33,7 @@ struct FieldInfo ProjectFieldInfo[] =
DEFINE_CLASS(Project)
{
Solution solution;
Array blocks;
Fields fields;
const char* config_filter;
};
@ -46,6 +47,7 @@ Project project_create()
{
Project prj = ALLOC_CLASS(Project);
prj->solution = NULL;
prj->blocks = array_create();
prj->fields = fields_create(ProjectFieldInfo);
prj->config_filter = NULL;
return prj;
@ -58,12 +60,36 @@ Project project_create()
*/
void project_destroy(Project prj)
{
int i, n;
assert(prj);
n = project_num_blocks(prj);
for (i = 0; i < n; ++i)
{
Block blk = project_get_block(prj, i);
block_destroy(blk);
}
array_destroy(prj->blocks);
fields_destroy(prj->fields);
free(prj);
}
/**
* Add a configuration block to a project.
* \param prj The project to contain the project.
* \param blk The configuration block to add.
*/
void project_add_block(Project prj, Block blk)
{
assert(prj);
assert(blk);
array_add(prj->blocks, blk);
}
/**
* Get the base directory for the project; any properties containing relative
* paths are relative to this location.
@ -76,6 +102,33 @@ const char* project_get_base_dir(Project prj)
}
/**
* Retrieve a configuration block from a project.
* \param prj The project to query.
* \param index The index of the block to retreive.
* \returns The block at the given index within the project.
*/
Block project_get_block(Project prj, int index)
{
Block blk;
assert(prj);
blk = (Block)array_item(prj->blocks, index);
return blk;
}
/**
* Retrieve the list of configuration blocks associated with a project.
* \param prj The project to query.
* \returns A list of configuration blocks.
*/
Array project_get_blocks(Project prj)
{
assert(prj);
return prj->blocks;
}
/**
* Retrieve the current configuration filter. All subsequent requests for configuration
* values will return settings from this configuration only.
@ -90,7 +143,7 @@ const char* project_get_configuration_filter(Project prj)
/**
* Retrieve the fields object for this solution; used to unload values from the script.
* Retrieve the fields object for this project; used to unload values from the script.
*/
Fields project_get_fields(Project prj)
{
@ -249,6 +302,18 @@ int project_is_valid_language(const char* language)
}
/**
* Return the number of configuration blocks contained by this project.
* \param prj The project to query.
* \returns The number of blocks contained by the project.
*/
int project_num_blocks(Project prj)
{
assert(prj);
return array_size(prj->blocks);
}
/**
* Set the base directory of the project.
* \param prj The project object to modify.

View File

@ -13,11 +13,13 @@
#define PREMAKE_PROJECT_H
#include "fields.h"
#include "block.h"
#include "base/array.h"
/**
* Project field index.
* \note If you modify this list, you must also update SolutionFieldInfo[].
* \note If you modify this list, you must also update ProjectFieldInfo[].
*/
enum ProjectField
{
@ -38,7 +40,10 @@ DECLARE_CLASS(Project)
Project project_create(void);
void project_destroy(Project prj);
void project_add_block(Project prj, Block blk);
const char* project_get_base_dir(Project prj);
Block project_get_block(Project prj, int index);
Array project_get_blocks(Project prj);
const char* project_get_configuration_filter(Project prj);
Fields project_get_fields(Project prj);
const char* project_get_filename(Project prj, const char* basename, const char* ext);
@ -50,6 +55,7 @@ const char* project_get_name(Project prj);
const char* project_get_outfile(Project prj);
const char* project_get_value(Project prj, enum ProjectField field);
int project_is_valid_language(const char* language);
int project_num_blocks(Project prj);
void project_set_base_dir(Project prj, const char* base_dir);
void project_set_configuration_filter(Project prj, const char* cfg_name);
void project_set_guid(Project prj, const char* guid);

View File

@ -31,6 +31,7 @@ DEFINE_CLASS(Solution)
{
Fields fields;
Array projects;
Array blocks;
};
@ -43,6 +44,7 @@ Solution solution_create()
Solution sln = ALLOC_CLASS(Solution);
sln->fields = fields_create(SolutionFieldInfo);
sln->projects = array_create();
sln->blocks = array_create();
return sln;
}
@ -58,6 +60,14 @@ void solution_destroy(Solution sln)
assert(sln);
fields_destroy(sln->fields);
n = solution_num_blocks(sln);
for (i = 0; i < n; ++i)
{
Block blk = solution_get_block(sln, i);
block_destroy(blk);
}
array_destroy(sln->blocks);
n = solution_num_projects(sln);
for (i = 0; i < n; ++i)
{
@ -70,12 +80,25 @@ void solution_destroy(Solution sln)
}
/**
* Add a configuration block to a solution.
* \param sln The solution to contain the project.
* \param blk The configuration block to add.
*/
void solution_add_block(Solution sln, Block blk)
{
assert(sln);
assert(blk);
array_add(sln->blocks, blk);
}
/**
* Add a configuration name to a solution.
* \param sln The solution to contain the project.
* \param config_name The name of the configuration add.
*/
void solution_add_config_name(Solution sln, const char* config_name)
void solution_add_config(Solution sln, const char* config_name)
{
assert(sln);
assert(config_name);
@ -109,13 +132,40 @@ const char* solution_get_base_dir(Solution sln)
}
/**
* Retrieve a configuration block from the solution.
* \param sln The solution to query.
* \param index The index of the block to retreive.
* \returns The block at the given index within the solution.
*/
Block solution_get_block(Solution sln, int index)
{
Block blk;
assert(sln);
blk = (Block)array_item(sln->blocks, index);
return blk;
}
/**
* Retrieve the list of configuration blocks associated with a solution.
* \param sln The solution to query.
* \returns A list of configuration blocks.
*/
Array solution_get_blocks(Solution sln)
{
assert(sln);
return sln->blocks;
}
/**
* Get the configuration name at a given index.
* \param sln The solution to query.
* \param index The configuration index to query.
* \returns The configuration name at the given index.
*/
const char* solution_get_config_name(Solution sln, int index)
const char* solution_get_config(Solution sln, int index)
{
Strings names;
const char* name;
@ -131,7 +181,7 @@ const char* solution_get_config_name(Solution sln, int index)
* \param sln The solution to query.
* \returns The configuration name at the given index.
*/
Strings solution_get_config_names(Solution sln)
Strings solution_get_configs(Solution sln)
{
assert(sln);
return fields_get_values(sln->fields, SolutionConfigurations);
@ -246,6 +296,18 @@ const char* solution_get_value(Solution sln, enum SolutionField field)
}
/**
* Return the number of configuration blocks contained by this solution.
* \param sln The solution to query.
* \returns The number of blocks contained by the solution.
*/
int solution_num_blocks(Solution sln)
{
assert(sln);
return array_size(sln->blocks);
}
/**
* Return the number of configurations contained by this solution.
* \param sln The solution to query.

View File

@ -11,6 +11,7 @@
#include "fields.h"
#include "project.h"
#include "block.h"
#include "base/strings.h"
@ -36,11 +37,14 @@ DECLARE_CLASS(Solution)
Solution solution_create(void);
void solution_destroy(Solution sln);
void solution_add_config_name(Solution sln, const char* config_name);
void solution_add_block(Solution sln, Block blk);
void solution_add_config(Solution sln, const char* config_name);
void solution_add_project(Solution sln, Project prj);
const char* solution_get_base_dir(Solution sln);
const char* solution_get_config_name(Solution sln, int index);
Strings solution_get_config_names(Solution sln);
Block solution_get_block(Solution sln, int index);
Array solution_get_blocks(Solution sln);
const char* solution_get_config(Solution sln, int index);
Strings solution_get_configs(Solution sln);
Fields solution_get_fields(Solution sln);
const char* solution_get_filename(Solution sln, const char* basename, const char* ext);
const char* solution_get_language(Solution sln);
@ -48,6 +52,7 @@ const char* solution_get_location(Solution sln);
const char* solution_get_name(Solution sln);
Project solution_get_project(Solution sln, int index);
const char* solution_get_value(Solution sln, enum SolutionField field);
int solution_num_blocks(Solution sln);
int solution_num_configs(Solution sln);
int solution_num_projects(Solution sln);
void solution_set_base_dir(Solution sln, const char* base_dir);

View File

@ -0,0 +1,46 @@
/**
* \file block_tests.cpp
* \brief Automated tests for the configuration blocks API.
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
*/
#include "premake.h"
#include "testing/testing.h"
extern "C" {
#include "project/solution.h"
#include "project/project.h"
#include "project/block.h"
}
struct FxBlock
{
Solution sln;
Project prj;
Block blk;
FxBlock()
{
sln = solution_create();
prj = project_create();
blk = block_create();
}
~FxBlock()
{
block_destroy(blk);
project_destroy(prj);
solution_destroy(sln);
}
};
SUITE(project)
{
TEST_FIXTURE(FxBlock, Create_ReturnsObject_OnSuccess)
{
CHECK(blk != NULL);
}
}

View File

@ -87,32 +87,59 @@ SUITE(project)
TEST_FIXTURE(FxSolution, AddConfig_IncrementsNumConfigs)
{
solution_add_config_name(sln, "Debug");
solution_add_config(sln, "Debug");
int result = solution_num_configs(sln);
CHECK(result == 1);
}
TEST_FIXTURE(FxSolution, AddConfig_CanRoundtrip)
{
solution_add_config_name(sln, "Debug");
const char* result = solution_get_config_name(sln, 0);
solution_add_config(sln, "Debug");
const char* result = solution_get_config(sln, 0);
CHECK_EQUAL("Debug", result);
}
TEST_FIXTURE(FxSolution, GetConfigs_ReturnsEmptyList_OnStartup)
{
Strings result = solution_get_config_names(sln);
Strings result = solution_get_configs(sln);
CHECK(strings_size(result) == 0);
}
TEST_FIXTURE(FxSolution, GetConfigs_ReturnsList_OnItemsAdded)
{
solution_add_config_name(sln, "Debug");
Strings result = solution_get_config_names(sln);
solution_add_config(sln, "Debug");
Strings result = solution_get_configs(sln);
CHECK_EQUAL("Debug", strings_item(result, 0));
}
/**********************************************************************
* Block containment tests
**********************************************************************/
TEST_FIXTURE(FxSolution, NumBlocks_IsZero_OnStartup)
{
int result = solution_num_blocks(sln);
CHECK(result == 0);
}
TEST_FIXTURE(FxSolution, AddBlock_IncrementsNumBlocks)
{
Block blk = block_create();
solution_add_block(sln, blk);
int result = solution_num_blocks(sln);
CHECK(result == 1);
}
TEST_FIXTURE(FxSolution, AddBlock_CanRoundtrip)
{
Block blk = block_create();
solution_add_block(sln, blk);
Block result = solution_get_block(sln, 0);
CHECK(result == blk);
}
/**********************************************************************
* Language tests
**********************************************************************/

View File

@ -10,9 +10,9 @@
#include "base/error.h"
static int fn_accessor_object_has_field(struct FieldInfo* fields, const char* field_name);
static int fn_accessor_register(lua_State* L, struct FieldInfo* fields);
static int fn_accessor_register_field(lua_State* L, struct FieldInfo* field);
static int fn_accessor_object_has_field(struct FieldInfo* fields, const char* field_name);
static int fn_accessor_register(lua_State* L, struct FieldInfo* fields);
static int fn_accessor_register_field(lua_State* L, struct FieldInfo* field);
static void fn_accessor_append_value(lua_State* L, struct FieldInfo* field, int tbl, int idx);
@ -28,6 +28,7 @@ int fn_accessor_register_all(lua_State* L)
int z = OKAY;
if (z == OKAY) z = fn_accessor_register(L, SolutionFieldInfo);
if (z == OKAY) z = fn_accessor_register(L, ProjectFieldInfo);
if (z == OKAY) z = fn_accessor_register(L, BlockFieldInfo);
return z;
}
@ -68,6 +69,7 @@ static int fn_accessor_register_field(lua_State* L, struct FieldInfo* field)
container_type = 0;
if (fn_accessor_object_has_field(SolutionFieldInfo, field->name)) container_type |= SolutionObject;
if (fn_accessor_object_has_field(ProjectFieldInfo, field->name)) container_type |= ProjectObject;
if (fn_accessor_object_has_field(BlockFieldInfo, field->name)) container_type |= BlockObject;
/* register the accessor function */
lua_pushnumber(L, container_type);

View File

@ -0,0 +1,32 @@
/**
* \file fn_configuration.c
* \brief Implements the configuration() function.
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
*/
#include "premake.h"
#include "script_internal.h"
/**
* Specify the build configurations for a solution.
*/
int fn_configuration(lua_State* L)
{
/* if there are parameters, create a new configuration block */
if (lua_gettop(L) > 0)
{
/* get the active object, which will contain this new configuration */
if (!script_internal_get_active_object(L, SolutionObject | ProjectObject, REQUIRED))
{
return 0;
}
/* create a new configuration block in the container */
script_internal_create_block(L);
}
script_internal_get_active_object(L, BlockObject, OPTIONAL);
return 1;
}

View File

@ -62,6 +62,11 @@ int fn_project(lua_State* L)
lua_pushstring(L, guid_create());
lua_setfield(L, -2, ProjectFieldInfo[ProjectGuid].name);
/* configure the initial configuration block list */
lua_newtable(L);
lua_setfield(L, -2, BLOCKS_KEY);
script_internal_create_block(L);
/* use the list of fields to populate the object properties and accessor functions */
script_internal_populate_object(L, ProjectFieldInfo);

View File

@ -44,6 +44,11 @@ int fn_solution(lua_State* L)
lua_newtable(L);
lua_setfield(L, -2, PROJECTS_KEY);
/* configure the initial configuration block list */
lua_newtable(L);
lua_setfield(L, -2, BLOCKS_KEY);
script_internal_create_block(L);
/* use the list of fields to populate the object properties and accessor functions */
script_internal_populate_object(L, SolutionFieldInfo);

View File

@ -15,6 +15,7 @@
/** Functions to add to the global namespace */
static const luaL_Reg global_funcs[] = {
{ "configuration", fn_configuration },
{ "configurations", fn_configurations },
{ "dofile", fn_dofile },
{ "include", fn_include },

View File

@ -11,6 +11,38 @@
#include "base/path.h"
/**
* Create a new configuration block in the object at the top of the stack.
* \param L The Lua state.
*/
int script_internal_create_block(lua_State* L)
{
int i;
/* get the current list of configuration blocks */
lua_getfield(L, -1, BLOCKS_KEY);
/* create a new block and make it active */
lua_newtable(L);
script_internal_set_active_object(L, BlockObject);
/* set all list-type configuration block values to empty tables */
for (i = 0; i < NumBlockFields; ++i)
{
if (BlockFieldInfo[i].kind != StringField)
{
lua_newtable(L);
lua_setfield(L, -2, BlockFieldInfo[i].name);
}
}
/* add it to the list of blocks */
lua_rawseti(L, -2, luaL_getn(L,-2) + 1);
lua_pop(L, 1);
return OKAY;
}
/**
* Pushes the active value for the given object type to the top of the stack.
* This function is used to retrieve the current solution, project, etc.
@ -31,7 +63,7 @@ int script_internal_get_active_object(lua_State* L, enum ObjectType type, int is
lua_getregistry(L);
top = lua_gettop(L);
if (lua_gettop(L) == top && (type & ConfigObject))
if (lua_gettop(L) == top && (type & BlockObject))
{
lua_getfield(L, -1, CONFIGURATION_KEY);
if (lua_isnil(L, -1))
@ -83,14 +115,14 @@ int script_internal_get_active_object(lua_State* L, enum ObjectType type, int is
case ProjectObject:
strcat(buffer, "project");
break;
case ConfigObject:
strcat(buffer, "configuration");
case BlockObject:
strcat(buffer, "configuration block");
break;
case SolutionObject | ProjectObject:
strcat(buffer, "solution or project");
break;
case SolutionObject | ProjectObject | ConfigObject:
strcat(buffer, "solution, project, or configuration");
case SolutionObject | ProjectObject | BlockObject:
strcat(buffer, "solution, project, or configuration block");
break;
default:
strcat(buffer, "object");

View File

@ -17,6 +17,7 @@
/* string constants for script variables and functions */
#define ACTION_KEY "_ACTION"
#define BLOCKS_KEY "blocks"
#define CONFIGURATION_KEY "configuration"
#define FILE_KEY "_FILE"
#define PROJECT_KEY "project"
@ -30,7 +31,7 @@ enum ObjectType
{
SolutionObject = 0x01,
ProjectObject = 0x02,
ConfigObject = 0x04
BlockObject = 0x04
};
#define OPTIONAL (0)
@ -39,6 +40,7 @@ enum ObjectType
lua_State* script_get_lua(Script script);
/* internal state management */
int script_internal_create_block(lua_State* L);
int script_internal_get_active_object(lua_State* L, enum ObjectType type, int is_required);
void script_internal_set_active_object(lua_State* L, enum ObjectType type);
const char* script_internal_script_dir(lua_State* L);
@ -51,6 +53,7 @@ int fn_accessor_set_list_value(lua_State* L, struct FieldInfo* field);
/* script function handlers */
int fn_accessor(lua_State* L);
int fn_configuration(lua_State* L);
int fn_configurations(lua_State* L);
int fn_dofile(lua_State* L);
int fn_error(lua_State* L);
@ -66,11 +69,12 @@ struct UnloadFuncs
{
int (*unload_solution)(lua_State* L, Solution sln);
int (*unload_project)(lua_State* L, Project prj);
int (*unload_block)(lua_State* L, Block blk);
};
int unload_all(lua_State* L, Array slns, struct UnloadFuncs* funcs);
int unload_solution(lua_State* L, Solution sln);
int unload_project(lua_State* L, Project prj);
int unload_block(lua_State* L, Block blk);
#endif

View File

@ -0,0 +1,83 @@
/**
* \file fn_configuration_tests.cpp
* \brief Automated tests for the configuration() function.
* \author Copyright (c) 2007-2008 Jason Perkins and the Premake project
*/
#include "premake.h"
#include "script_tests.h"
struct FnConfiguration : FxScript
{
FnConfiguration()
{
script_run_string(script,
"sln = solution('MySolution');"
" configurations {'Debug','Release'};"
"prj = project('MyProject');"
"cfg = configuration('Debug')");
}
};
SUITE(script)
{
/**************************************************************************
* Initial state tests
**************************************************************************/
TEST_FIXTURE(FxScript, Configuration_Exists_OnStartup)
{
const char* result = script_run_string(script,
"return (configuration ~= nil)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FxScript, Configuration_ReturnsNil_OnNoActiveProject)
{
const char* result = script_run_string(script,
"return (configuration() == nil)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FxScript, Configuration_RaisesError_OnNoActiveContainer)
{
const char* result = script_run_string(script, "configuration('Debug')");
CHECK_EQUAL("no active solution or project", result);
}
/**************************************************************************
* Object creation tests
**************************************************************************/
TEST_FIXTURE(FnConfiguration, Configuration_ReturnsObject_OnConfigName)
{
const char* result = script_run_string(script, "return (cfg ~= nil)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FnConfiguration, Configuration_ReturnsPreviousObject_OnNoParameters)
{
const char* result = script_run_string(script, "return (cfg == configuration())");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FnConfiguration, Configuration_AddsToContainer)
{
const char* result = script_run_string(script, "return (#prj.blocks == 2)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FnConfiguration, Configuration_DoesNothing_OnSimpleField)
{
const char* result = script_run_string(script, "return (cfg.objdir == nil)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FnConfiguration, Configuration_SetsEmptyList_OnListField)
{
const char* result = script_run_string(script, "return (#cfg.defines == 0)");
CHECK_EQUAL("true", result);
}
}

View File

@ -18,10 +18,8 @@ SUITE(script)
TEST_FIXTURE(FxScript, Configurations_Error_OnNoActiveSolution)
{
Script script = script_create();
const char* result = script_run_string(script, "configurations {'Debug'}");
CHECK_EQUAL("no active solution", result);
script_destroy(script);
}
TEST_FIXTURE(FxScript, Configurations_CanRoundtrip)

View File

@ -0,0 +1,35 @@
/**
* \file fn_defines_tests.cpp
* \brief Automated tests for the defines() function.
* \author Copyright (c) 2007-2008 Jason Perkins and the Premake project
*/
#include "premake.h"
#include "script_tests.h"
SUITE(script)
{
TEST_FIXTURE(FxAccessor, Defines_Exists_OnStartup)
{
const char* result = script_run_string(script,
"return (defines ~= nil)");
CHECK_EQUAL("true", result);
}
TEST_FIXTURE(FxAccessor, Defines_Error_OnNoActiveObject)
{
Script script = script_create();
const char* result = script_run_string(script, "defines {'DEBUG'}");
CHECK_EQUAL("no active configuration block", result);
script_destroy(script);
}
TEST_FIXTURE(FxAccessor, Defines_CanRoundtrip)
{
const char* result = script_run_string(script,
"defines {'DEBUG'};"
"return defines()[1]");
CHECK_EQUAL("DEBUG", result);
}
}

View File

@ -40,6 +40,7 @@ SUITE(script)
CHECK_EQUAL("true", result);
}
/**************************************************************************
* Object creation tests
**************************************************************************/
@ -92,7 +93,7 @@ SUITE(script)
"return (prj == project('MyProject'))");
CHECK_EQUAL("true", result);
}
/*
TEST_FIXTURE(FxScript, Project_RaisesError_OnNoConfigurations)
{
const char* result = script_run_string(script,
@ -100,7 +101,6 @@ SUITE(script)
"prj = project('MyProject')");
CHECK_EQUAL("no configurations defined", result);
}
*/
/**************************************************************************
* Initial object state tests
@ -112,6 +112,12 @@ SUITE(script)
CHECK_EQUAL("MyProject", result);
}
TEST_FIXTURE(FnProject, Project_CreatesEmptyConfigList)
{
const char* result = script_run_string(script, "return (#prj.blocks[1])");
CHECK_EQUAL("0", result);
}
TEST_FIXTURE(FnProject, Project_SetsBaseDir)
{
const char* result = script_run_string(script, "return prj.basedir");

View File

@ -104,6 +104,12 @@ SUITE(script)
CHECK_EQUAL("MySolution", result);
}
TEST_FIXTURE(FnSolution, Solution_CreatesEmptyConfigList)
{
const char* result = script_run_string(script, "return (#sln.blocks[1])");
CHECK_EQUAL("0", result);
}
TEST_FIXTURE(FnSolution, Solution_SetsBaseDir)
{
const char* result = script_run_string(script,

View File

@ -0,0 +1,53 @@
/**
* \file unload_block_tests.cpp
* \brief Automated tests for configuration block unloading from the script environment.
* \author Copyright (c) 2008 Jason Perkins and the Premake project
*/
#include "premake.h"
#include "testing/testing.h"
extern "C" {
#include "script/script_internal.h"
}
struct FxUnloadBlock
{
lua_State* L;
Script script;
Block blk;
FxUnloadBlock()
{
script = script_create();
L = script_get_lua(script);
blk = block_create();
script_run_string(script,
"solution('MySolution');"
" defines { 'DEBUG', 'DEBUG2' };"
" return configuration()");
}
~FxUnloadBlock()
{
block_destroy(blk);
script_destroy(script);
}
};
SUITE(unload)
{
TEST_FIXTURE(FxUnloadBlock, UnloadBlock_UnloadsDefines)
{
unload_block(L, blk);
Strings defines = block_get_defines(blk);
CHECK(strings_size(defines) == 2);
if (strings_size(defines) == 2) {
CHECK_EQUAL("DEBUG", strings_item(defines, 0));
CHECK_EQUAL("DEBUG2", strings_item(defines, 1));
}
}
}

View File

@ -58,8 +58,8 @@ SUITE(unload)
{
unload_solution(L, sln);
CHECK(solution_num_configs(sln) == 2);
CHECK_EQUAL("Debug", solution_get_config_name(sln, 0));
CHECK_EQUAL("Release", solution_get_config_name(sln, 1));
CHECK_EQUAL("Debug", solution_get_config(sln, 0));
CHECK_EQUAL("Release", solution_get_config(sln, 1));
}
}

View File

@ -14,6 +14,7 @@ extern "C" {
static int num_solution_calls;
static int num_project_calls;
static int num_block_calls;
static int stub_solution_func(lua_State* L, Solution sln)
{
@ -43,6 +44,20 @@ static int stub_project_fail_func(lua_State* L, Project prj)
return !OKAY;
}
static int stub_block_func(lua_State* L, Block blk)
{
UNUSED(L); UNUSED(blk);
num_block_calls++;
return OKAY;
}
static int stub_block_fail_func(lua_State* L, Block blk)
{
UNUSED(L); UNUSED(blk);
num_block_calls++;
return !OKAY;
}
struct FxUnload
{
@ -60,8 +75,10 @@ struct FxUnload
funcs.unload_solution = stub_solution_func;
funcs.unload_project = stub_project_func;
funcs.unload_block = stub_block_func;
num_solution_calls = 0;
num_project_calls = 0;
num_block_calls = 0;
}
~FxUnload()
@ -81,6 +98,7 @@ struct FxUnload2 : FxUnload
" configurations{'Debug','Release'};"
" project 'MyProject';"
" project 'MyProject2';"
" configuration 'Debug';"
"solution 'MySolution2';");
}
};
@ -172,4 +190,37 @@ SUITE(unload)
CHECK(num_project_calls == 1);
}
/**********************************************************************
* Configuration block enumeration tests
**********************************************************************/
TEST_FIXTURE(FxUnload2, Unload_AddsBlocks_OnNonEmptySession)
{
unload_all(L, slns, &funcs);
Solution sln = (Solution)array_item(slns, 0);
int n = solution_num_blocks(sln);
CHECK(n == 1);
}
TEST_FIXTURE(FxUnload2, Unload_CallsBlockFunc_OnEachConfig)
{
unload_all(L, slns, &funcs);
CHECK(num_block_calls == 5);
}
TEST_FIXTURE(FxUnload2, Unload_ReturnsNotOkay_OnBlockFailure)
{
funcs.unload_block = stub_block_fail_func;
int result = unload_all(L, slns, &funcs);
CHECK(result != OKAY);
}
TEST_FIXTURE(FxUnload2, Unload_AbortsBlockLoop_OnNotOkay)
{
funcs.unload_block = stub_block_fail_func;
unload_all(L, slns, &funcs);
CHECK(num_block_calls == 1);
}
}

View File

@ -9,7 +9,8 @@
#include "script/script_internal.h"
static int unload_solution_projects(lua_State* L, struct UnloadFuncs* funcs, Solution sln);
static int unload_blocks(lua_State* L, struct UnloadFuncs* funcs, Array blocks);
static int unload_projects(lua_State* L, struct UnloadFuncs* funcs, Solution sln);
/**
@ -34,19 +35,27 @@ int unload_all(lua_State* L, Array slns, struct UnloadFuncs* funcs)
sn = luaL_getn(L, -1);
for (si = 1; z == OKAY && si <= sn; ++si)
{
/* add a new solution to the master list */
Solution sln = solution_create();
array_add(slns, sln);
/* get the scripted solution object from the solutions list */
lua_rawgeti(L, -1, si);
/* hardcoded a standard set of configurations for now */
solution_add_config_name(sln, "Debug");
solution_add_config_name(sln, "Release");
solution_add_config(sln, "Debug");
solution_add_config(sln, "Release");
/* extract the project fields */
/* unload the solution fields, then configuration blocks, then projects */
z = funcs->unload_solution(L, sln);
if (z == OKAY)
{
z = unload_solution_projects(L, funcs, sln);
Array blocks = solution_get_blocks(sln);
z = unload_blocks(L, funcs, blocks);
}
if (z == OKAY)
{
z = unload_projects(L, funcs, sln);
}
/* remove solution object from stack */
@ -59,7 +68,7 @@ int unload_all(lua_State* L, Array slns, struct UnloadFuncs* funcs)
}
static int unload_solution_projects(lua_State* L, struct UnloadFuncs* funcs, Solution sln)
static int unload_projects(lua_State* L, struct UnloadFuncs* funcs, Solution sln)
{
int pi, pn, z = OKAY;
@ -68,12 +77,20 @@ static int unload_solution_projects(lua_State* L, struct UnloadFuncs* funcs, Sol
pn = luaL_getn(L, -1);
for (pi = 1; z == OKAY && pi <= pn; ++pi)
{
/* add a new project to the master list */
Project prj = project_create();
solution_add_project(sln, prj);
/* unload the project fields */
/* get the scripted project object from the solutions list */
lua_rawgeti(L, -1, pi);
/* unload the project fields, then configuration blocks */
z = funcs->unload_project(L, prj);
if (z == OKAY)
{
Array blocks = project_get_blocks(prj);
z = unload_blocks(L, funcs, blocks);
}
/* remove project object from stack */
lua_pop(L, 1);
@ -85,6 +102,32 @@ static int unload_solution_projects(lua_State* L, struct UnloadFuncs* funcs, Sol
}
static int unload_blocks(lua_State* L, struct UnloadFuncs* funcs, Array blocks)
{
int ci, cn, z = OKAY;
/* iterate over the list configuration blocks from the solution */
lua_getfield(L, -1, BLOCKS_KEY);
cn = luaL_getn(L, -1);
for (ci = 1; z == OKAY && ci <= cn; ++ci)
{
Block blk = block_create();
array_add(blocks, blk);
/* unload the configuration block fields */
lua_rawgeti(L, -1, ci);
z = funcs->unload_block(L, blk);
/* remove the configuration block object from the stack */
lua_pop(L, 1);
}
/* remove the list of blocks from the stack */
lua_pop(L, 1);
return z;
}
int unload_fields(lua_State* L, Fields fields, struct FieldInfo* info)
{
const char* value;
@ -144,8 +187,8 @@ int unload_solution(lua_State* L, Solution sln)
/**
* Unload information from the scripting environment for a particular project.
* \param L The Lua scripting engine state.
* \param prj The project object to be populated.
* \param L The Lua scripting engine state.
* \param prj The project object to be populated.
* \returns OKAY if successful.
*/
int unload_project(lua_State* L, Project prj)
@ -154,3 +197,13 @@ int unload_project(lua_State* L, Project prj)
}
/**
* Unload information from the scripting environment for a particular configuration.
* \param L The Lua scripting engine state.
* \param blk The configuration block to be populated.
* \returns OKAY if successful.
*/
int unload_block(lua_State* L, Block blk)
{
return unload_fields(L, block_get_fields(blk), BlockFieldInfo);
}

View File

@ -150,7 +150,7 @@ int session_enumerate_objects(Session sess, SessionSolutionCallback* sln_funcs,
for (ci = 0; result == OKAY && ci < cn; ++ci)
{
int cfi;
const char* cfg_name = solution_get_config_name(sln, ci);
const char* cfg_name = solution_get_config(sln, ci);
project_set_configuration_filter(prj, cfg_name);
/* enumerate configurations */

View File

@ -17,6 +17,7 @@
#include "base/stream.h"
#include "project/solution.h"
#include "project/project.h"
#include "project/block.h"
DECLARE_CLASS(Session)

View File

@ -319,7 +319,7 @@ SUITE(session)
SessionProjectCallback cfg_funcs[] = { test_config_okay, test_config_okay, NULL };
AddSolution();
AddProject();
solution_add_config_name(sln, "Debug");
solution_add_config(sln, "Debug");
session_enumerate_objects(sess, sln_funcs, prj_funcs, cfg_funcs);
CHECK(num_config_calls == 2);
}
@ -331,7 +331,7 @@ SUITE(session)
SessionProjectCallback cfg_funcs[] = { test_config_okay, test_config_okay, NULL };
AddSolution();
AddProject();
solution_add_config_name(sln, "Debug");
solution_add_config(sln, "Debug");
session_enumerate_objects(sess, sln_funcs, prj_funcs, cfg_funcs);
CHECK_EQUAL("Debug", last_config_filter);
}