Started implementation of projects
This commit is contained in:
parent
72f07dd0e8
commit
0cd1e2dd85
@ -12,7 +12,7 @@ BUILDING PREMAKE
|
||||
|
||||
Until an official release is made you will need to use an existing
|
||||
Premake 3.x executable to generate the project files. Grab a binary
|
||||
or executable package from the project site at:
|
||||
or source package from the project site at:
|
||||
|
||||
http://premake.sourceforge.net/
|
||||
|
||||
@ -20,11 +20,11 @@ BUILDING PREMAKE
|
||||
|
||||
$ cd premake-4.0
|
||||
$ premake --target vs2005 # For Visual Studio 2005 files
|
||||
$ premake --target gnu # For GNU makefile
|
||||
|
||||
Run `premake --help` for a complete list of supported toolsets.
|
||||
|
||||
|
||||
|
||||
SUPPORT
|
||||
|
||||
For questions, comments, or more information, visit the project
|
||||
|
225
samples/vs2005/CppExe/CppExe.vcproj
Normal file
225
samples/vs2005/CppExe/CppExe.vcproj
Normal file
@ -0,0 +1,225 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="CppExe"
|
||||
ProjectGUID="{AE2461B7-236F-4278-81D3-F0D476F9A4C0}"
|
||||
RootNamespace="CppExe"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\CppExe.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stdafx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\stdafx.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
20
samples/vs2005/MySolution.sln
Normal file
20
samples/vs2005/MySolution.sln
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppExe", "CppExe\CppExe.vcproj", "{AE2461B7-236F-4278-81D3-F0D476F9A4C0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -52,5 +52,3 @@ const char* make_get_solution_makefile(Session sess, Solution sln)
|
||||
/* all good */
|
||||
return my_path;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,8 @@ struct FxVs200xSln
|
||||
stream_set_buffer(strm, buffer);
|
||||
|
||||
sln = solution_create();
|
||||
solution_set_name(sln, "MySolution");
|
||||
solution_set_base_dir(sln, "/Root");
|
||||
}
|
||||
|
||||
~FxVs200xSln()
|
||||
@ -33,6 +35,16 @@ struct FxVs200xSln
|
||||
stream_destroy(strm);
|
||||
session_destroy(sess);
|
||||
}
|
||||
|
||||
Project AddProject()
|
||||
{
|
||||
Project prj = project_create();
|
||||
project_set_name(prj, "MyProject");
|
||||
project_set_base_dir(prj, "/Root");
|
||||
project_set_guid(prj, "AE2461B7-236F-4278-81D3-F0D476F9A4C0");
|
||||
solution_add_project(sln, prj);
|
||||
return prj;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -70,4 +82,31 @@ SUITE(action)
|
||||
"# Visual Studio 2005\r\n",
|
||||
buffer);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Project entry tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxVs200xSln, ProjectEntry_IsCorrect_OnCppProject)
|
||||
{
|
||||
AddProject();
|
||||
vs200x_solution_projects(sess, sln, strm);
|
||||
CHECK_EQUAL(
|
||||
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"MyProject.vcproj\", \"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
|
||||
"EndProject\n",
|
||||
buffer);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxVs200xSln, ProjectEntry_UsesRelativePath)
|
||||
{
|
||||
Project prj = AddProject();
|
||||
project_set_location(prj, "ProjectFolder");
|
||||
vs200x_solution_projects(sess, sln, strm);
|
||||
CHECK_EQUAL(
|
||||
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"ProjectFolder\\MyProject.vcproj\", \"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
|
||||
"EndProject\n",
|
||||
buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ static SessionSolutionCallback Vs2005SolutionCallbacks[] =
|
||||
{
|
||||
vs200x_solution_create,
|
||||
vs200x_solution_signature,
|
||||
vs200x_solution_projects,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
20
src/action/vs200x/vs200x_project.c
Normal file
20
src/action/vs200x/vs200x_project.c
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* \file vs200x_project.c
|
||||
* \brief Visual Studio 200x project generation functions.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "vs200x_project.h"
|
||||
|
||||
|
||||
/**
|
||||
* Returns the correct project file extension for a particular project definition.
|
||||
* \param prj The project to be identified.
|
||||
* \returns The project file extension for the given project.
|
||||
*/
|
||||
const char* vs200x_project_extension(Project prj)
|
||||
{
|
||||
prj = 0;
|
||||
return ".vcproj";
|
||||
}
|
13
src/action/vs200x/vs200x_project.h
Normal file
13
src/action/vs200x/vs200x_project.h
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* \file vs200x_project.h
|
||||
* \brief Visual Studio 200x project generation functions.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
#if !defined(PREMAKE_VS200X_PROJECT_H)
|
||||
#define PREMAKE_VS200X_PROJECT_H
|
||||
|
||||
#include "engine/session.h"
|
||||
|
||||
const char* vs200x_project_extension(Project prj);
|
||||
|
||||
#endif
|
@ -9,7 +9,10 @@
|
||||
#include "premake.h"
|
||||
#include "vs200x.h"
|
||||
#include "vs200x_solution.h"
|
||||
#include "vs200x_project.h"
|
||||
#include "base/cstr.h"
|
||||
#include "base/error.h"
|
||||
#include "base/path.h"
|
||||
|
||||
|
||||
/**
|
||||
@ -35,6 +38,44 @@ int vs200x_solution_create(Session sess, Solution sln, Stream strm)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write out the list of projects contained by the solution.
|
||||
* \param sess The execution session context.
|
||||
* \param sln The current solution.
|
||||
* \param strm The currently active stream; set with session_set_active_stream().
|
||||
* \returns OKAY if successful.
|
||||
*/
|
||||
int vs200x_solution_projects(Session sess, Solution sln, Stream strm)
|
||||
{
|
||||
const char* sln_path;
|
||||
int i, n;
|
||||
sess = 0; /* unused */
|
||||
|
||||
/* project file paths are specified relative to the solution */
|
||||
sln_path = path_directory(solution_get_filename(sln, NULL, NULL));
|
||||
|
||||
n = solution_num_projects(sln);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
Project prj = solution_get_project(sln, i);
|
||||
const char* prj_name = project_get_name(prj);
|
||||
const char* prj_id = project_get_guid(prj);
|
||||
const char* prj_ext = vs200x_project_extension(prj);
|
||||
const char* prj_file = project_get_filename(prj, prj_name, prj_ext);
|
||||
const char* tool_id = vs200x_solution_tool_guid("c++");
|
||||
|
||||
/* convert absolute project file name to be relative to solution */
|
||||
prj_file = path_relative(sln_path, prj_file);
|
||||
prj_file = path_translate(prj_file, "\\");
|
||||
|
||||
stream_writeline(strm, "Project(\"{%s}\") = \"%s\", \"%s\", \"{%s}\"", tool_id, prj_name, prj_file, prj_id);
|
||||
stream_writeline(strm, "EndProject");
|
||||
}
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write the solution file signature block.
|
||||
* \param sess The execution session context.
|
||||
@ -71,3 +112,26 @@ int vs200x_solution_signature(Session sess, Solution sln, Stream strm)
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Visual Studio GUID for a particular project type.
|
||||
* \param language The programming language used in the project.
|
||||
* \returns The GUID corresponding the programming language.
|
||||
*/
|
||||
const char* vs200x_solution_tool_guid(const char* language)
|
||||
{
|
||||
if (cstr_eq(language, "c") || cstr_eq(language, "c++"))
|
||||
{
|
||||
return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
|
||||
}
|
||||
else if (cstr_eq(language, "c#"))
|
||||
{
|
||||
return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC";
|
||||
}
|
||||
else
|
||||
{
|
||||
error_set("unsupported language '%s'", language);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,9 @@
|
||||
|
||||
#include "engine/session.h"
|
||||
|
||||
int vs200x_solution_create(Session sess, Solution sln, Stream strm);
|
||||
int vs200x_solution_signature(Session sess, Solution sln, Stream strm);
|
||||
int vs200x_solution_create(Session sess, Solution sln, Stream strm);
|
||||
int vs200x_solution_projects(Session sess, Solution sln, Stream strm);
|
||||
int vs200x_solution_signature(Session sess, Solution sln, Stream strm);
|
||||
const char* vs200x_solution_tool_guid(const char* language);
|
||||
|
||||
#endif
|
||||
|
109
src/base/guid.c
Normal file
109
src/base/guid.c
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
* \file guid.c
|
||||
* \brief GUID creation and validation.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "premake.h"
|
||||
#include "guid.h"
|
||||
#include "platform/platform.h"
|
||||
#include "base/buffers.h"
|
||||
|
||||
|
||||
static void stringify(char* src, char* dst, int count);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new GUID, with the format "4E67EBCE-BC8B-4058-9AA9-48EE5E003683".
|
||||
* \returns The new GUID.
|
||||
*/
|
||||
const char* guid_create()
|
||||
{
|
||||
char guid[16];
|
||||
char* result = buffers_next();
|
||||
|
||||
/* get a GUID as an array of 16 bytes */
|
||||
platform_create_guid(guid);
|
||||
|
||||
/* convert that array to a string in the usual format */
|
||||
stringify(guid, result, 4);
|
||||
result[8] = '-';
|
||||
stringify(guid + 4, result + 9, 2);
|
||||
result[13] = '-';
|
||||
stringify(guid + 6, result + 14, 2);
|
||||
result[18] = '-';
|
||||
stringify(guid + 8, result + 19, 2);
|
||||
result[23] = '-';
|
||||
stringify(guid + 10, result + 24, 6);
|
||||
result[36] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the format of a GUID, which should use the form "4E67EBCE-BC8B-4058-9AA9-48EE5E003683".
|
||||
* \param value The guid to validate.
|
||||
* \returns True if valid, zero otherwise.
|
||||
*/
|
||||
int guid_is_valid(const char* value)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
/* make sure it is the right size */
|
||||
if (strlen(value) != 36)
|
||||
return 0;
|
||||
|
||||
/* check for dashes in the right places */
|
||||
if (value[8] != '-' ||
|
||||
value[13] != '-' ||
|
||||
value[18] != '-' ||
|
||||
value[23] != '-')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* make sure only [0-9A-F-] are present; count the number of dashes on the way */
|
||||
n = 0;
|
||||
for (i = 0; i < 36; ++i)
|
||||
{
|
||||
if (value[i] == '-')
|
||||
{
|
||||
++n;
|
||||
}
|
||||
else if ((value[i] < '0' || value[i] > '9') &&
|
||||
(value[i] < 'A' || value[i] > 'F') &&
|
||||
(value[i] < 'a' || value[i] > 'f'))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* make sure I've got the right number of dashes */
|
||||
if (n != 4)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert an array of bytes to a string.
|
||||
* \param src The source array of bytes.
|
||||
* \param dst The destination string buffer.
|
||||
* \param count The number of bytes to convert.
|
||||
*/
|
||||
static void stringify(char* src, char* dst, int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
unsigned value = (unsigned char)src[i];
|
||||
sprintf(dst, "%02X", value);
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
|
12
src/base/guid.h
Normal file
12
src/base/guid.h
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* \file guid.h
|
||||
* \brief GUID creation and validation.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
#if !defined(PREMAKE_GUID_H)
|
||||
#define PREMAKE_GUID_H
|
||||
|
||||
const char* guid_create();
|
||||
int guid_is_valid(const char* value);
|
||||
|
||||
#endif
|
@ -145,6 +145,10 @@ char* path_join(const char* leading, const char* trailing)
|
||||
{
|
||||
char* buffer = buffers_next();
|
||||
|
||||
/* treat nulls like empty paths */
|
||||
leading = (leading != NULL) ? leading : "";
|
||||
trailing = (trailing != NULL) ? trailing : "";
|
||||
|
||||
if (!trailing)
|
||||
{
|
||||
strcpy(buffer, leading);
|
||||
@ -172,6 +176,61 @@ char* path_join(const char* leading, const char* trailing)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compute the relative path between two locations.
|
||||
* \param base The base path.
|
||||
* \param target The target path.
|
||||
* \returns A relative path from the base to the target.
|
||||
*/
|
||||
char* path_relative(const char* base, const char* target)
|
||||
{
|
||||
int start, i;
|
||||
char* result;
|
||||
|
||||
/* normalize the two paths */
|
||||
char* full_base = path_absolute(base);
|
||||
char* full_targ = path_absolute(target);
|
||||
|
||||
strcat(full_base, "/");
|
||||
strcat(full_targ, "/");
|
||||
|
||||
/* trim off the common directories from the start */
|
||||
for (start = 0, i = 0; full_base[i] && full_targ[i] && full_base[i] == full_targ[i]; ++i)
|
||||
{
|
||||
if (full_base[i] == '/')
|
||||
start = i + 1;
|
||||
}
|
||||
|
||||
/* same directory? */
|
||||
if (full_base[i] == 0 && full_targ[i] == 0)
|
||||
return ".";
|
||||
|
||||
/* build a connecting path */
|
||||
result = buffers_next();
|
||||
if (strlen(full_base) - start > 0)
|
||||
{
|
||||
strcpy(result, "../");
|
||||
for (i = start; full_base[i]; ++i)
|
||||
{
|
||||
if (full_base[i] == '/' && full_base[i + 1])
|
||||
strcat(result, "../");
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(full_targ) - start > 0)
|
||||
{
|
||||
strcat(result, full_targ + start);
|
||||
}
|
||||
|
||||
/* remove the trailing slash */
|
||||
result[strlen(result) - 1] = 0;
|
||||
|
||||
if (strlen(result) == 0)
|
||||
strcpy(result, ".");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replace all path separator characters in a path.
|
||||
* \param path The path to translate.
|
||||
|
@ -11,6 +11,7 @@ char* path_assemble(const char* dir, const char* filename, const char* ext);
|
||||
char* path_directory(const char* path);
|
||||
int path_is_absolute(const char* path);
|
||||
char* path_join(const char* leading, const char* trailing);
|
||||
char* path_relative(const char* base, const char* target);
|
||||
char* path_translate(const char* path, const char* sep);
|
||||
|
||||
#endif
|
||||
|
86
src/base/tests/guid_tests.cpp
Normal file
86
src/base/tests/guid_tests.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* \file guid_tests.cpp
|
||||
* \brief Automated tests for GUID generation and validation.
|
||||
* \author Copyright (c) 2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "testing/testing.h"
|
||||
extern "C" {
|
||||
#include "base/guid.h"
|
||||
}
|
||||
|
||||
|
||||
SUITE(base)
|
||||
{
|
||||
TEST(GuidCreate_ReturnsCorrectSize)
|
||||
{
|
||||
const char* guid = guid_create();
|
||||
CHECK(guid != NULL && strlen(guid) == 36);
|
||||
}
|
||||
|
||||
TEST(GuidCreate_CorrectDashes)
|
||||
{
|
||||
const char* guid = guid_create();
|
||||
CHECK(guid[8]=='-' && guid[13]=='-' && guid[18]=='-' && guid[23]=='-');
|
||||
}
|
||||
|
||||
TEST(GuidCreate_CorrectSymbols)
|
||||
{
|
||||
for (const char* guid = guid_create(); *guid; ++guid)
|
||||
{
|
||||
const char ch = *guid;
|
||||
CHECK((ch>='0' && ch<='9') || (ch>='A' && ch<='F') || (ch=='-'));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(GuidCreate_CorrectNumOfDashes)
|
||||
{
|
||||
int num = 0;
|
||||
for (const char* guid = guid_create(); *guid; ++guid)
|
||||
{
|
||||
if (*guid=='-') ++num;
|
||||
}
|
||||
CHECK(num == 4);
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsTrue_OnNoBraces)
|
||||
{
|
||||
CHECK(guid_is_valid("4E67EBCE-BC8B-4058-9AA9-48EE5E003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnTooShort)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE-BC8B-4058-9AA9-48EE"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnMissingFirstDash)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE BC8B-4058-9AA9-48EE5E003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnMissingSecondDash)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE-BC8B 4058-9AA9-48EE5E003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnMissingThirdDash)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE-BC8B-4058 9AA9-48EE5E003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnMissingLastDash)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE-BC8B-4058-9AA9 48EE5E003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnTooManyDashes)
|
||||
{
|
||||
CHECK(!guid_is_valid("4E67EBCE-BC8B-4058-9AA9-48EE5-003683"));
|
||||
}
|
||||
|
||||
TEST(GuidIsValid_ReturnsFalse_OnInvalidChar)
|
||||
{
|
||||
CHECK(!guid_is_valid("XE67EBCE-BC8B-4058-9AA9-48EE5X003683"));
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* \file path_tests.cpp
|
||||
* \brief Path handling automated tests.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
* \author Copyright (c) 2007-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
@ -115,6 +115,38 @@ SUITE(base)
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* path_relative() tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST(PathRelative_ReturnsDot_OnMatchingPaths)
|
||||
{
|
||||
char* result = path_relative("/a/b/c", "/a/b/c");
|
||||
CHECK_EQUAL(".", result);
|
||||
}
|
||||
|
||||
|
||||
TEST(PathRelative_ReturnsDoubleDot_OnChildToParent)
|
||||
{
|
||||
char* result = path_relative("/a/b/c", "/a/b");
|
||||
CHECK_EQUAL("..", result);
|
||||
}
|
||||
|
||||
|
||||
TEST(PathRelative_ReturnsDoubleDotPath_OnSiblingToSibling)
|
||||
{
|
||||
char* result = path_relative("/a/b/c", "/a/b/d");
|
||||
CHECK_EQUAL("../d", result);
|
||||
}
|
||||
|
||||
|
||||
TEST(PathRelative_ReturnsChildPath_OnParentToChild)
|
||||
{
|
||||
char* result = path_relative("/a/b/c", "/a/b/c/d");
|
||||
CHECK_EQUAL("d", result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* path_translate() tests
|
||||
**************************************************************************/
|
||||
|
@ -11,6 +11,28 @@
|
||||
#include "base/path.h"
|
||||
|
||||
|
||||
/**
|
||||
* Configure a new project object (solution, project). Initializes all list
|
||||
* fields and creates an initial configuration list.
|
||||
* \param L The Lua state.
|
||||
* \param fields The list of object fields.
|
||||
*/
|
||||
void engine_configure_project_object(lua_State* L, struct FieldInfo* fields)
|
||||
{
|
||||
struct FieldInfo* field;
|
||||
|
||||
/* set all list-type configuration values to empty tables */
|
||||
for (field = fields; field->name != NULL; ++field)
|
||||
{
|
||||
if (field->kind == ListField)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, field->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -101,6 +123,25 @@ int engine_get_active_object(lua_State* L, enum ObjectType type, int is_required
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the directory which contains the currently executing script. This is
|
||||
* used to locate resources specified in the script using relative paths.
|
||||
* \param L The Lua state.
|
||||
* \returns The directory containing the current script, as an absolute path.
|
||||
*/
|
||||
const char* engine_get_script_dir(lua_State* L)
|
||||
{
|
||||
const char* path;
|
||||
|
||||
lua_getglobal(L, FILE_KEY);
|
||||
path = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
path = path_directory(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remembers the object at the top of the stack as active for the given object type.
|
||||
* This function is used to indicate the current solution, project, etc.
|
||||
@ -143,20 +184,3 @@ void engine_set_script_file(lua_State* L, const char* filename)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the directory which contains the currently executing script. This is
|
||||
* used to locate resources specified in the script using relative paths.
|
||||
* \param L The Lua state.
|
||||
* \returns The directory containing the current script, as an absolute path.
|
||||
*/
|
||||
const char* engine_get_script_dir(lua_State* L)
|
||||
{
|
||||
const char* path;
|
||||
|
||||
lua_getglobal(L, FILE_KEY);
|
||||
path = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
path = path_directory(path);
|
||||
return path;
|
||||
}
|
||||
|
39
src/engine/fn_guid.c
Normal file
39
src/engine/fn_guid.c
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* \file fn_guid.c
|
||||
* \brief Specify a project GUID.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "internals.h"
|
||||
#include "base/guid.h"
|
||||
|
||||
|
||||
/**
|
||||
* Specify a project GUID, which is used by the Visual Studio actions to
|
||||
* identify the project in the solution.
|
||||
*/
|
||||
int fn_guid(lua_State* L)
|
||||
{
|
||||
const char* guid = luaL_optstring(L, 1, NULL);
|
||||
|
||||
/* retrieve the project being set */
|
||||
if (!engine_get_active_object(L, ProjectObject, REQUIRED))
|
||||
return 0;
|
||||
|
||||
/* if a value is provided, set it */
|
||||
if (guid != NULL)
|
||||
{
|
||||
if (!guid_is_valid(guid))
|
||||
{
|
||||
luaL_error(L, "invalid GUID");
|
||||
return 0;
|
||||
}
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setfield(L, -2, ProjectFieldInfo[ProjectGuid].name);
|
||||
}
|
||||
|
||||
/* return the current value */
|
||||
lua_getfield(L, -1, ProjectFieldInfo[ProjectGuid].name);
|
||||
return 1;
|
||||
}
|
72
src/engine/fn_project.c
Normal file
72
src/engine/fn_project.c
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* \file fn_project.c
|
||||
* \brief Create or select a project object.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "internals.h"
|
||||
#include "base/guid.h"
|
||||
|
||||
|
||||
/**
|
||||
* Create a new project object, or select an existing one.
|
||||
*/
|
||||
int fn_project(lua_State* L)
|
||||
{
|
||||
const char* name;
|
||||
|
||||
/* if there are no parameters, return the active project */
|
||||
if (lua_gettop(L) == 0)
|
||||
{
|
||||
engine_get_active_object(L, ProjectObject, OPTIONAL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get the active solution, which will contain this project */
|
||||
if (!engine_get_active_object(L, SolutionObject, REQUIRED))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = luaL_checkstring(L, 1);
|
||||
|
||||
/* get the projects list from the solution */
|
||||
lua_getfield(L, -1, PROJECTS_KEY);
|
||||
|
||||
/* check to see if a project with this name already exists */
|
||||
lua_getfield(L, -1, name);
|
||||
if (lua_isnil(L, -1))
|
||||
{
|
||||
/* project does not exists, create it */
|
||||
lua_newtable(L);
|
||||
|
||||
/* set the name */
|
||||
lua_pushvalue(L, 1);
|
||||
lua_setfield(L, -2, ProjectFieldInfo[ProjectName].name);
|
||||
|
||||
/* set the base directory */
|
||||
lua_pushstring(L, engine_get_script_dir(L));
|
||||
lua_setfield(L, -2, ProjectFieldInfo[ProjectBaseDirectory].name);
|
||||
|
||||
/* set a default GUID */
|
||||
lua_pushstring(L, guid_create());
|
||||
lua_setfield(L, -2, ProjectFieldInfo[ProjectGuid].name);
|
||||
|
||||
/* finish the configuration */
|
||||
engine_configure_project_object(L, ProjectFieldInfo);
|
||||
|
||||
/* add it to solution's list of projects, keyed by name */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -4, name);
|
||||
|
||||
/* also add with integer key */
|
||||
lua_pushvalue(L, -1);
|
||||
lua_rawseti(L, -4, luaL_getn(L, -4) + 1);
|
||||
}
|
||||
|
||||
/* activate and return the solution object */
|
||||
engine_set_active_object(L, ProjectObject);
|
||||
return 1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new solution object, or selects an existing one.
|
||||
* Create a new solution object, or select an existing one.
|
||||
*/
|
||||
int fn_solution(lua_State* L)
|
||||
{
|
||||
@ -34,11 +34,18 @@ int fn_solution(lua_State* L)
|
||||
|
||||
/* set the name */
|
||||
lua_pushstring(L, name);
|
||||
lua_setfield(L, -2, "name");
|
||||
lua_setfield(L, -2, SolutionFieldInfo[SolutionName].name);
|
||||
|
||||
/* set the base directory */
|
||||
lua_pushstring(L, engine_get_script_dir(L));
|
||||
lua_setfield(L, -2, "basedir");
|
||||
lua_setfield(L, -2, SolutionFieldInfo[SolutionBaseDirectory].name);
|
||||
|
||||
/* create an empty list of projects */
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, PROJECTS_KEY);
|
||||
|
||||
/* finish the configuration */
|
||||
engine_configure_project_object(L, SolutionFieldInfo);
|
||||
|
||||
/* add it to the master list of solutions, keyed by name */
|
||||
lua_pushvalue(L, -1);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define CONFIGURATION_KEY "configuration"
|
||||
#define FILE_KEY "_FILE"
|
||||
#define PROJECT_KEY "project"
|
||||
#define PROJECTS_KEY "projects"
|
||||
#define SESSION_KEY "_SESSION"
|
||||
#define SOLUTION_KEY "solution"
|
||||
#define SOLUTIONS_KEY "_SOLUTIONS"
|
||||
@ -41,6 +42,7 @@ int engine_get_active_object(lua_State* L, enum ObjectType type, int is_
|
||||
void engine_set_active_object(lua_State* L, enum ObjectType type);
|
||||
void engine_set_script_file(lua_State* L, const char* filename);
|
||||
const char* engine_get_script_dir(lua_State* L);
|
||||
void engine_configure_project_object(lua_State* L, struct FieldInfo* fields);
|
||||
|
||||
/* Internal session API */
|
||||
lua_State* session_get_lua_state(Session sess);
|
||||
@ -51,17 +53,21 @@ lua_State* session_get_lua_state(Session sess);
|
||||
struct UnloadFuncs
|
||||
{
|
||||
int (*unload_solution)(Session sess, lua_State* L, Solution sln);
|
||||
int (*unload_project)(Session sess, lua_State* L, Project prj);
|
||||
};
|
||||
|
||||
int unload_all(Session sess, lua_State* L, struct UnloadFuncs* funcs);
|
||||
int unload_solution(Session sess, lua_State* L, Solution sln);
|
||||
int unload_project(Session sess, lua_State* L, Project prj);
|
||||
|
||||
|
||||
/* Script function handlers */
|
||||
int fn_dofile(lua_State* L);
|
||||
int fn_error(lua_State* L);
|
||||
int fn_getcwd(lua_State* L);
|
||||
int fn_guid(lua_State* L);
|
||||
int fn_include(lua_State* L);
|
||||
int fn_project(lua_State* L);
|
||||
int fn_solution(lua_State* L);
|
||||
|
||||
|
||||
|
@ -18,7 +18,9 @@
|
||||
/** Functions to add to the global namespace */
|
||||
static const luaL_Reg funcs[] = {
|
||||
{ "dofile", fn_dofile },
|
||||
{ "guid", fn_guid },
|
||||
{ "include", fn_include },
|
||||
{ "project", fn_project },
|
||||
{ "solution", fn_solution },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
@ -350,6 +352,7 @@ int session_unload(Session sess)
|
||||
assert(sess);
|
||||
|
||||
funcs.unload_solution = unload_solution;
|
||||
funcs.unload_project = unload_project;
|
||||
result = unload_all(sess, sess->L, &funcs);
|
||||
return result;
|
||||
}
|
||||
|
88
src/engine/tests/fn_guid_tests.cpp
Normal file
88
src/engine/tests/fn_guid_tests.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* \file fn_guid_tests.cpp
|
||||
* \brief Automated tests for the guid() function.
|
||||
* \author Copyright (c) 2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "testing/testing.h"
|
||||
extern "C" {
|
||||
#include "engine/session.h"
|
||||
#include "base/guid.h"
|
||||
#include "base/error.h"
|
||||
}
|
||||
|
||||
struct FnGuid
|
||||
{
|
||||
Session sess;
|
||||
|
||||
FnGuid()
|
||||
{
|
||||
sess = session_create();
|
||||
}
|
||||
|
||||
~FnGuid()
|
||||
{
|
||||
session_destroy(sess);
|
||||
error_clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct FnGuid2 : FnGuid
|
||||
{
|
||||
FnGuid2()
|
||||
{
|
||||
session_run_string(sess,
|
||||
"solution 'MySolution';"
|
||||
"prj = project 'MyProject';");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SUITE(engine)
|
||||
{
|
||||
/**************************************************************************
|
||||
* Initial state tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST_FIXTURE(FnGuid, Guid_Exists_OnStartup)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (guid ~= nil)");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnGuid, Guid_RaisesError_OnNoProject)
|
||||
{
|
||||
const char* result = session_run_string(sess, "guid '0C202E43-B9AF-4972-822B-5A42F0BF008C'");
|
||||
CHECK_EQUAL("[string \"guid '0C202E43-B9AF-4972-822B-5A42F0BF008C'\"]:1: no active project", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnGuid2, Guid_ReturnsDefaultValue_OnNoValueSet)
|
||||
{
|
||||
const char* result = session_run_string(sess, "return guid()");
|
||||
CHECK(result != NULL && guid_is_valid(result));
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnGuid2, Guid_SetsField)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"guid '0C202E43-B9AF-4972-822B-5A42F0BF008C';"
|
||||
"return prj.guid");
|
||||
CHECK_EQUAL("0C202E43-B9AF-4972-822B-5A42F0BF008C", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnGuid2, Guid_ReturnsField_OnNoParams)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"prj.guid = '0C202E43-B9AF-4972-822B-5A42F0BF008C';"
|
||||
"return guid()");
|
||||
CHECK_EQUAL("0C202E43-B9AF-4972-822B-5A42F0BF008C", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnGuid2, Guid_RaisesError_OnInvalidGuid)
|
||||
{
|
||||
const char* result = session_run_string(sess, "guid '0C2XXXX-B9AF-4972-822B-5A42F0BF008C'");
|
||||
CHECK_EQUAL("[string \"guid '0C2XXXX-B9AF-4972-822B-5A42F0BF008C'\"]:1: invalid GUID", result);
|
||||
}
|
||||
}
|
145
src/engine/tests/fn_project_tests.cpp
Normal file
145
src/engine/tests/fn_project_tests.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* \file fn_project_tests.cpp
|
||||
* \brief Automated tests for the project() function.
|
||||
* \author Copyright (c) 2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
#include "testing/testing.h"
|
||||
extern "C" {
|
||||
#include "engine/session.h"
|
||||
#include "base/error.h"
|
||||
}
|
||||
|
||||
struct FnProject
|
||||
{
|
||||
Session sess;
|
||||
|
||||
FnProject()
|
||||
{
|
||||
sess = session_create();
|
||||
}
|
||||
|
||||
~FnProject()
|
||||
{
|
||||
session_destroy(sess);
|
||||
error_clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct FnProject2
|
||||
{
|
||||
Session sess;
|
||||
|
||||
FnProject2()
|
||||
{
|
||||
sess = session_create();
|
||||
session_run_string(sess,
|
||||
"sln = solution('MySolution');"
|
||||
"prj = project('MyProject')");
|
||||
}
|
||||
|
||||
~FnProject2()
|
||||
{
|
||||
session_destroy(sess);
|
||||
error_clear();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SUITE(engine)
|
||||
{
|
||||
/**************************************************************************
|
||||
* Initial state tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST_FIXTURE(FnProject, Project_Exists_OnStartup)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (project ~= nil)");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject, Project_ReturnsNil_OnNoActiveProject)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (project() == nil)");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Object creation tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST_FIXTURE(FnProject, Project_Fails_OnNoActiveSolution)
|
||||
{
|
||||
const char* result = session_run_string(sess, "project('MyProject')");
|
||||
CHECK_EQUAL("[string \"project('MyProject')\"]:1: no active solution", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_ReturnsNewObject_OnNewName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (prj ~= nil)");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_ReturnsObject_OnActiveProject)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (prj == project())");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_AddsToKeyList_OnNewName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (prj == sln.projects['MyProject']);");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_AddsToIndexList_OnNewName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return (prj == sln.projects[1]);");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_IncrementsTableSize_OnNewName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return #sln.projects");
|
||||
CHECK_EQUAL("1", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_ReturnsSameObject_OnExistingName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"prj1 = project('SecondProject');"
|
||||
"return (prj == project('MyProject'))");
|
||||
CHECK_EQUAL("true", result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Initial object state tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_SetsName)
|
||||
{
|
||||
const char* result = session_run_string(sess, "return prj.name");
|
||||
CHECK_EQUAL("MyProject", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_SetsBaseDir)
|
||||
{
|
||||
const char* result = session_run_string(sess, "return prj.basedir");
|
||||
CHECK_EQUAL("(string)", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnProject2, Project_SetsGuid)
|
||||
{
|
||||
const char* result = session_run_string(sess, "return prj.guid");
|
||||
CHECK(result != NULL && strlen(result) == 36);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \file fn_solution_tests.cpp
|
||||
* \brief Automated test for the solution() function.
|
||||
* \brief Automated tests for the solution() function.
|
||||
* \author Copyright (c) 2007-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
@ -117,6 +117,7 @@ SUITE(engine)
|
||||
/**************************************************************************
|
||||
* Initial object state tests
|
||||
**************************************************************************/
|
||||
|
||||
TEST_FIXTURE(FnSolution2, Solution_SetsName)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
@ -130,4 +131,11 @@ SUITE(engine)
|
||||
"return sln.basedir");
|
||||
CHECK_EQUAL("(string)", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FnSolution2, Solution_HasEmptyProjectsList)
|
||||
{
|
||||
const char* result = session_run_string(sess,
|
||||
"return #sln.projects");
|
||||
CHECK_EQUAL("0", result);
|
||||
}
|
||||
}
|
||||
|
64
src/engine/tests/unload_project_tests.cpp
Normal file
64
src/engine/tests/unload_project_tests.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* \file unload_project_tests.cpp
|
||||
* \brief Automated tests for project object 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 "engine/internals.h"
|
||||
}
|
||||
|
||||
|
||||
struct FxUnloadProject
|
||||
{
|
||||
Session sess;
|
||||
lua_State* L;
|
||||
Project prj;
|
||||
|
||||
FxUnloadProject()
|
||||
{
|
||||
sess = session_create();
|
||||
L = session_get_lua_state(sess);
|
||||
prj = project_create();
|
||||
|
||||
session_run_string(sess,
|
||||
"solution('MySolution');"
|
||||
"prj = project('MyProject');"
|
||||
" guid '0C202E43-B9AF-4972-822B-5A42F0BF008C';"
|
||||
"return prj");
|
||||
}
|
||||
|
||||
~FxUnloadProject()
|
||||
{
|
||||
project_destroy(prj);
|
||||
session_destroy(sess);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SUITE(unload)
|
||||
{
|
||||
TEST_FIXTURE(FxUnloadProject, UnloadProject_SetsName)
|
||||
{
|
||||
unload_project(sess, L, prj);
|
||||
const char* result = project_get_name(prj);
|
||||
CHECK_EQUAL("MyProject", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnloadProject, UnloadProject_SetsBaseDir)
|
||||
{
|
||||
unload_project(sess, L, prj);
|
||||
const char* result = project_get_base_dir(prj);
|
||||
CHECK_EQUAL("(string)", result);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnloadProject, UnloadProject_SetsGuid)
|
||||
{
|
||||
unload_project(sess, L, prj);
|
||||
const char* result = project_get_guid(prj);
|
||||
CHECK_EQUAL("0C202E43-B9AF-4972-822B-5A42F0BF008C", result);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* \file unload_solution_tests.cpp
|
||||
* \brief Automated test for solution object unloading from the script environment.
|
||||
* \brief Automated tests for solution object unloading from the script environment.
|
||||
* \author Copyright (c) 2007-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
|
@ -13,6 +13,7 @@ extern "C" {
|
||||
/* mock interface to object loaders */
|
||||
|
||||
static int num_solution_calls;
|
||||
static int num_project_calls;
|
||||
|
||||
static int stub_solution_func(Session sess, lua_State* L, Solution sln)
|
||||
{
|
||||
@ -28,6 +29,20 @@ static int stub_solution_fail_func(Session sess, lua_State* L, Solution sln)
|
||||
return !OKAY;
|
||||
}
|
||||
|
||||
static int stub_project_func(Session sess, lua_State* L, Project prj)
|
||||
{
|
||||
sess = NULL; L = NULL; prj = NULL;
|
||||
num_project_calls++;
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
static int stub_project_fail_func(Session sess, lua_State* L, Project prj)
|
||||
{
|
||||
sess = NULL; L = NULL; prj = NULL;
|
||||
num_project_calls++;
|
||||
return !OKAY;
|
||||
}
|
||||
|
||||
|
||||
struct FxUnload
|
||||
{
|
||||
@ -40,7 +55,9 @@ struct FxUnload
|
||||
sess = session_create();
|
||||
L = session_get_lua_state(sess);
|
||||
funcs.unload_solution = stub_solution_func;
|
||||
funcs.unload_project = stub_project_func;
|
||||
num_solution_calls = 0;
|
||||
num_project_calls = 0;
|
||||
}
|
||||
|
||||
~FxUnload()
|
||||
@ -56,6 +73,8 @@ struct FxUnload2 : FxUnload
|
||||
{
|
||||
session_run_string(sess,
|
||||
"solution 'MySolution';"
|
||||
" project 'MyProject';"
|
||||
" project 'MyProject2';"
|
||||
"solution 'MySolution2';");
|
||||
}
|
||||
|
||||
@ -98,7 +117,7 @@ SUITE(unload)
|
||||
CHECK(n == 2);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnload2, Unload_CallsSolutionFunc_OnEachSession)
|
||||
TEST_FIXTURE(FxUnload2, Unload_CallsSolutionFunc_OnEachSolution)
|
||||
{
|
||||
unload_all(sess, L, &funcs);
|
||||
CHECK(num_solution_calls == 2);
|
||||
@ -117,4 +136,38 @@ SUITE(unload)
|
||||
unload_all(sess, L, &funcs);
|
||||
CHECK(num_solution_calls == 1);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Project enumeration tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxUnload2, Unload_AddsProjects_OnNonEmptySession)
|
||||
{
|
||||
unload_all(sess, L, &funcs);
|
||||
Solution sln = session_get_solution(sess, 0);
|
||||
int n = solution_num_projects(sln);
|
||||
CHECK(n == 2);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnload2, Unload_CallsProjectFunc_OnEachProject)
|
||||
{
|
||||
unload_all(sess, L, &funcs);
|
||||
CHECK(num_project_calls == 2);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnload2, Unload_ReturnsNotOkay_OnProjectFailure)
|
||||
{
|
||||
funcs.unload_project = stub_project_fail_func;
|
||||
int result = unload_all(sess, L, &funcs);
|
||||
CHECK(result != OKAY);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxUnload2, Unload_AbortsProjectLoop_OnNotOkay)
|
||||
{
|
||||
funcs.unload_project = stub_project_fail_func;
|
||||
unload_all(sess, L, &funcs);
|
||||
CHECK(num_project_calls == 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,10 +37,34 @@ int unload_all(Session sess, lua_State* L, struct UnloadFuncs* funcs)
|
||||
|
||||
lua_rawgeti(L, -1, si);
|
||||
status = funcs->unload_solution(sess, L, sln);
|
||||
if (status == OKAY)
|
||||
{
|
||||
/* iterate over list of projects */
|
||||
int pi, pn;
|
||||
lua_getfield(L, -1, PROJECTS_KEY);
|
||||
pn = luaL_getn(L, -1);
|
||||
for (pi = 1; status == OKAY && pi <= pn; ++pi)
|
||||
{
|
||||
Project prj = project_create();
|
||||
solution_add_project(sln, prj);
|
||||
|
||||
lua_rawgeti(L, -1, pi);
|
||||
status = funcs->unload_project(sess, L, prj);
|
||||
|
||||
/* remove project object from stack */
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/* remove list of projects from stack */
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/* remove solution object from stack */
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/* remove list of solutions from stack */
|
||||
lua_pop(L, 1);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -60,7 +84,7 @@ int unload_solution(Session sess, lua_State* L, Solution sln)
|
||||
assert(L);
|
||||
assert(sln);
|
||||
|
||||
sess = 0;
|
||||
sess = 0; /* unused */
|
||||
|
||||
lua_getfield(L, -1, "name");
|
||||
value = lua_tostring(L, -1);
|
||||
@ -74,3 +98,39 @@ int unload_solution(Session sess, lua_State* L, Solution sln)
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unload information from the scripting environment for a particular project.
|
||||
* \param sess The session object which contains the scripted project objects.
|
||||
* \param L The Lua scripting engine state.
|
||||
* \param prj The project object to be populated.
|
||||
* \returns OKAY if successful.
|
||||
*/
|
||||
int unload_project(Session sess, lua_State* L, Project prj)
|
||||
{
|
||||
const char* value;
|
||||
|
||||
assert(sess);
|
||||
assert(L);
|
||||
assert(prj);
|
||||
|
||||
sess = 0; /* unused */
|
||||
|
||||
lua_getfield(L, -1, "name");
|
||||
value = lua_tostring(L, -1);
|
||||
project_set_name(prj, value);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "basedir");
|
||||
value = lua_tostring(L, -1);
|
||||
project_set_base_dir(prj, value);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, -1, "guid");
|
||||
value = lua_tostring(L, -1);
|
||||
project_set_guid(prj, value);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return OKAY;
|
||||
}
|
||||
|
@ -27,6 +27,13 @@
|
||||
int platform_create_dir(const char* path);
|
||||
|
||||
|
||||
/**
|
||||
* Create a GUID and copy it into the supplied buffer.
|
||||
* \param buffer The buffer to hold the new GUID; must hold at least 36 characters.
|
||||
*/
|
||||
void platform_create_guid(char* buffer);
|
||||
|
||||
|
||||
/**
|
||||
* Get the current working directory.
|
||||
* \param buffer A buffer to hold the directory.
|
||||
|
@ -25,6 +25,15 @@ int platform_create_dir(const char* path)
|
||||
}
|
||||
|
||||
|
||||
void platform_create_guid(char* buffer)
|
||||
{
|
||||
/* not sure how to get a UUID here, so I fake it */
|
||||
FILE* rnd = fopen("/dev/random", "rb");
|
||||
fread(buffer, 16, 1, rnd);
|
||||
fclose(rnd);
|
||||
}
|
||||
|
||||
|
||||
int platform_dir_get_current(char* buffer, int size)
|
||||
{
|
||||
char* result = getcwd(buffer, size);
|
||||
|
@ -18,6 +18,18 @@ int platform_create_dir(const char* path)
|
||||
}
|
||||
|
||||
|
||||
void platform_create_guid(char* buffer)
|
||||
{
|
||||
static int (__stdcall *CoCreateGuid)(char*) = NULL;
|
||||
if (CoCreateGuid == NULL)
|
||||
{
|
||||
HMODULE hOleDll = LoadLibrary("OLE32.DLL");
|
||||
CoCreateGuid = (int(__stdcall*)(char*))GetProcAddress(hOleDll, "CoCreateGuid");
|
||||
}
|
||||
CoCreateGuid(buffer);
|
||||
}
|
||||
|
||||
|
||||
int platform_dir_get_current(char* buffer, int size)
|
||||
{
|
||||
DWORD result = GetCurrentDirectory(size, buffer);
|
||||
|
205
src/project/project.c
Normal file
205
src/project/project.c
Normal file
@ -0,0 +1,205 @@
|
||||
/**
|
||||
* \file project.c
|
||||
* \brief The project class.
|
||||
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "premake.h"
|
||||
#include "project/project.h"
|
||||
#include "base/path.h"
|
||||
#include "base/strings.h"
|
||||
|
||||
|
||||
struct FieldInfo ProjectFieldInfo[] =
|
||||
{
|
||||
{ "basedir", StringField },
|
||||
{ "guid", StringField },
|
||||
{ "location", StringField },
|
||||
{ "name", StringField },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
DEFINE_CLASS(Project)
|
||||
{
|
||||
Fields fields;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create and initialize a new project object.
|
||||
* \returns A new project object.
|
||||
*/
|
||||
Project project_create()
|
||||
{
|
||||
Project prj = ALLOC_CLASS(Project);
|
||||
prj->fields = fields_create(ProjectFieldInfo);
|
||||
return prj;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroy a project object and release the associated memory.
|
||||
* \param prj The project object to destroy.
|
||||
*/
|
||||
void project_destroy(Project prj)
|
||||
{
|
||||
assert(prj);
|
||||
fields_destroy(prj->fields);
|
||||
free(prj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the base directory for the project; any properties containing relative
|
||||
* paths are relative to this location.
|
||||
* \param prj The project object to query.
|
||||
* \returns The base directory, or NULL if no directory has been set.
|
||||
*/
|
||||
const char* project_get_base_dir(Project prj)
|
||||
{
|
||||
return project_get_value(prj, ProjectBaseDirectory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the path to the project output file, using the provided file extension.
|
||||
* \param prj The project object to query.
|
||||
* \param basename The base filename; if NULL the project name will be used.
|
||||
* \param ext The file extension to be used on the filename; may be NULL.
|
||||
* \returns The path to the project file.
|
||||
*/
|
||||
const char* project_get_filename(Project prj, const char* basename, const char* ext)
|
||||
{
|
||||
const char* base_dir;
|
||||
const char* location;
|
||||
const char* directory;
|
||||
const char* result;
|
||||
|
||||
assert(prj);
|
||||
|
||||
if (!basename)
|
||||
{
|
||||
basename = project_get_name(prj);
|
||||
}
|
||||
|
||||
|
||||
if (!ext)
|
||||
{
|
||||
ext = "";
|
||||
}
|
||||
|
||||
base_dir = project_get_base_dir(prj);
|
||||
location = project_get_location(prj);
|
||||
directory = path_join(base_dir, location);
|
||||
|
||||
result = path_assemble(directory, basename, ext);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the GUID associated with a project.
|
||||
* \param prj The project to query.
|
||||
* \returns The GUID associated with the project, or NULL if the GUID has not been set.
|
||||
*/
|
||||
const char* project_get_guid(Project prj)
|
||||
{
|
||||
return project_get_value(prj, ProjectGuid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the output location (the relative path from the base directory to the
|
||||
* target output directory) for this project.
|
||||
* \param prj The project object to modify.
|
||||
* \returns The project output location, or NULL if no location has been set.
|
||||
*/
|
||||
const char* project_get_location(Project prj)
|
||||
{
|
||||
return project_get_value(prj, ProjectLocation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the project.
|
||||
* \returns The name, if set, NULL otherwise.
|
||||
*/
|
||||
const char* project_get_name(Project prj)
|
||||
{
|
||||
return project_get_value(prj, ProjectName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a string (single value) fields from a project, using the field indices.
|
||||
* \param prj The project object to query.
|
||||
* \param field The index of the field to query.
|
||||
* \returns The value of the field if set, of NULL.
|
||||
*/
|
||||
const char* project_get_value(Project prj, enum ProjectField field)
|
||||
{
|
||||
assert(prj);
|
||||
return fields_get_value(prj->fields, field);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the base directory of the project.
|
||||
* \param prj The project object to modify.
|
||||
* \param base_dir The new base directory.
|
||||
*/
|
||||
void project_set_base_dir(Project prj, const char* base_dir)
|
||||
{
|
||||
project_set_value(prj, ProjectBaseDirectory, base_dir);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the GUID associated with a project. The GUID is required by the Visual
|
||||
* Studio generators, and must be unique per project.
|
||||
* \param prj The project to modify.
|
||||
* \param guid The new project GUID.
|
||||
*/
|
||||
void project_set_guid(Project prj, const char* guid)
|
||||
{
|
||||
project_set_value(prj, ProjectGuid, guid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the output location (the relative path from the base directory to the
|
||||
* target output directory) for this project.
|
||||
* \param prj The project object to modify.
|
||||
* \param location The new output location.
|
||||
*/
|
||||
void project_set_location(Project prj, const char* location)
|
||||
{
|
||||
project_set_value(prj, ProjectLocation, location);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the project.
|
||||
* \param prj The project object.
|
||||
* \param name The new for the project.
|
||||
*/
|
||||
void project_set_name(Project prj, const char* name)
|
||||
{
|
||||
project_set_value(prj, ProjectName, name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a string (single value) field on a project, using the field indices.
|
||||
* \param prj The project object.
|
||||
* \param field The field to set.
|
||||
* \param value The new value for the field.
|
||||
*/
|
||||
void project_set_value(Project prj, enum ProjectField field, const char* value)
|
||||
{
|
||||
assert(prj);
|
||||
fields_set_value(prj->fields, field, value);
|
||||
}
|
@ -6,8 +6,41 @@
|
||||
#if !defined(PREMAKE_PROJECT_H)
|
||||
#define PREMAKE_PROJECT_H
|
||||
|
||||
#include "fields.h"
|
||||
|
||||
|
||||
/**
|
||||
* Project field index.
|
||||
* \note If you modify this list, you must also update SolutionFieldInfo[].
|
||||
*/
|
||||
enum ProjectField
|
||||
{
|
||||
ProjectBaseDirectory,
|
||||
ProjectGuid,
|
||||
ProjectLocation,
|
||||
ProjectName,
|
||||
NumProjectFields
|
||||
};
|
||||
|
||||
extern struct FieldInfo ProjectFieldInfo[];
|
||||
|
||||
|
||||
DECLARE_CLASS(Project)
|
||||
|
||||
int project_tests(void);
|
||||
Project project_create(void);
|
||||
void project_destroy(Project prj);
|
||||
|
||||
const char* project_get_base_dir(Project prj);
|
||||
const char* project_get_filename(Project prj, const char* basename, const char* ext);
|
||||
const char* project_get_guid(Project prj);
|
||||
const char* project_get_location(Project prj);
|
||||
const char* project_get_name(Project prj);
|
||||
const char* project_get_value(Project prj, enum ProjectField field);
|
||||
void project_set_base_dir(Project prj, const char* base_dir);
|
||||
void project_set_location(Project prj, const char* location);
|
||||
void project_set_guid(Project prj, const char* guid);
|
||||
void project_set_name(Project prj, const char* name);
|
||||
void project_set_value(Project prj, enum ProjectField field, const char* value);
|
||||
int project_tests(void);
|
||||
|
||||
#endif
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "premake.h"
|
||||
#include "project/solution.h"
|
||||
#include "base/array.h"
|
||||
#include "base/path.h"
|
||||
#include "base/strings.h"
|
||||
|
||||
@ -26,6 +27,7 @@ struct FieldInfo SolutionFieldInfo[] =
|
||||
DEFINE_CLASS(Solution)
|
||||
{
|
||||
Fields fields;
|
||||
Array projects;
|
||||
};
|
||||
|
||||
|
||||
@ -37,6 +39,7 @@ Solution solution_create()
|
||||
{
|
||||
Solution sln = ALLOC_CLASS(Solution);
|
||||
sln->fields = fields_create(SolutionFieldInfo);
|
||||
sln->projects = array_create();
|
||||
return sln;
|
||||
}
|
||||
|
||||
@ -47,12 +50,36 @@ Solution solution_create()
|
||||
*/
|
||||
void solution_destroy(Solution sln)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
assert(sln);
|
||||
fields_destroy(sln->fields);
|
||||
|
||||
n = solution_num_projects(sln);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
Project prj = solution_get_project(sln, i);
|
||||
project_destroy(prj);
|
||||
}
|
||||
array_destroy(sln->projects);
|
||||
|
||||
free(sln);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a project to a solution.
|
||||
* \param sln The solution to contain the project.
|
||||
* \param prj The project to add.
|
||||
*/
|
||||
void solution_add_project(Solution sln, Project prj)
|
||||
{
|
||||
assert(sln);
|
||||
assert(prj);
|
||||
array_add(sln->projects, prj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the base directory for the solution; any properties containing relative
|
||||
* paths are relative to this location.
|
||||
@ -122,6 +149,23 @@ const char* solution_get_name(Solution sln)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a project from the solution.
|
||||
* \param sln The solution to query.
|
||||
* \param index The index of the project to retreive.
|
||||
* \returns The project at the given index within the solution.
|
||||
*/
|
||||
Project solution_get_project(Solution sln, int index)
|
||||
{
|
||||
Project prj;
|
||||
|
||||
assert(sln);
|
||||
|
||||
prj = (Project)array_item(sln->projects, index);
|
||||
return prj;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a string (single value) fields from a solution, using the field indices.
|
||||
* \param sln The solution object to query.
|
||||
@ -135,6 +179,18 @@ const char* solution_get_value(Solution sln, enum SolutionField field)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of projects contained by this solution.
|
||||
* \param sln The solution to query.
|
||||
* \returns The number of projects contained by the solution.
|
||||
*/
|
||||
int solution_num_projects(Solution sln)
|
||||
{
|
||||
assert(sln);
|
||||
return array_size(sln->projects);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the base directory of the solution.
|
||||
* \param sln The solution object to modify.
|
||||
|
@ -7,10 +7,11 @@
|
||||
#define PREMAKE_SOLUTION_H
|
||||
|
||||
#include "fields.h"
|
||||
#include "project.h"
|
||||
|
||||
|
||||
/**
|
||||
* Solution value index.
|
||||
* Solution field index.
|
||||
* \note If you modify this list, you must also update SolutionFieldInfo[].
|
||||
*/
|
||||
enum SolutionField
|
||||
@ -29,11 +30,14 @@ DECLARE_CLASS(Solution)
|
||||
Solution solution_create(void);
|
||||
void solution_destroy(Solution sln);
|
||||
|
||||
void solution_add_project(Solution sln, Project prj);
|
||||
const char* solution_get_base_dir(Solution sln);
|
||||
const char* solution_get_filename(Solution sln, const char* basename, const char* ext);
|
||||
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_projects(Solution sln);
|
||||
void solution_set_base_dir(Solution sln, const char* base_dir);
|
||||
void solution_set_location(Solution sln, const char* location);
|
||||
void solution_set_name(Solution sln, const char* name);
|
||||
|
@ -21,3 +21,125 @@ int project_tests()
|
||||
if (status == OKAY) status = tests_run_suite("project");
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
struct FxProject
|
||||
{
|
||||
Project prj;
|
||||
|
||||
FxProject()
|
||||
{
|
||||
prj = project_create();
|
||||
}
|
||||
|
||||
~FxProject()
|
||||
{
|
||||
if (prj)
|
||||
project_destroy(prj);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
SUITE(project)
|
||||
{
|
||||
TEST_FIXTURE(FxProject, Create_ReturnsObject_OnSuccess)
|
||||
{
|
||||
CHECK(prj != NULL);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Name tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxProject, GetName_ReturnsNull_OnStartup)
|
||||
{
|
||||
const char* name = project_get_name(prj);
|
||||
CHECK(name == NULL);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxProject, SetName_CanRoundtrip)
|
||||
{
|
||||
project_set_name(prj, "MyProject");
|
||||
const char* name = project_get_name(prj);
|
||||
CHECK_EQUAL("MyProject", name);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Base directory tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxProject, GetBaseDir_ReturnsNull_OnStartup)
|
||||
{
|
||||
const char* result = project_get_base_dir(prj);
|
||||
CHECK(result == NULL);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxProject, SetBaseDir_CanRoundtrip)
|
||||
{
|
||||
project_set_base_dir(prj, "BaseDir");
|
||||
const char* result = project_get_base_dir(prj);
|
||||
CHECK_EQUAL("BaseDir", result);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* GUID testrs
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxProject, GetGuid_ReturnsNull_OnStartup)
|
||||
{
|
||||
const char* result = project_get_guid(prj);
|
||||
CHECK(result == NULL);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxProject, SetGuid_CanRoundtrip)
|
||||
{
|
||||
project_set_guid(prj, "AE2461B7-236F-4278-81D3-F0D476F9A4C0");
|
||||
const char* result = project_get_guid(prj);
|
||||
CHECK_EQUAL("AE2461B7-236F-4278-81D3-F0D476F9A4C0", result);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Location tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxProject, GetLocation_ReturnsNull_OnStartup)
|
||||
{
|
||||
const char* result = project_get_location(prj);
|
||||
CHECK(result == NULL);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxProject, SetLocation_CanRoundtrip)
|
||||
{
|
||||
project_set_location(prj, "Location");
|
||||
const char* result = project_get_location(prj);
|
||||
CHECK_EQUAL("Location", result);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Filename tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxProject, GetFilename_ReturnsFullPath_OnNoLocation)
|
||||
{
|
||||
project_set_name(prj, "MyProject");
|
||||
project_set_base_dir(prj, "/BaseDir");
|
||||
const char* filename = project_get_filename(prj, NULL, ".xyz");
|
||||
CHECK_EQUAL("/BaseDir/MyProject.xyz", filename);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxProject, GetFilename_ReturnsFullPath_OnLocation)
|
||||
{
|
||||
project_set_name(prj, "MyProject");
|
||||
project_set_base_dir(prj, "/BaseDir");
|
||||
project_set_location(prj, "Location");
|
||||
const char* filename = project_get_filename(prj, NULL, ".xyz");
|
||||
CHECK_EQUAL("/BaseDir/Location/MyProject.xyz", filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "testing/testing.h"
|
||||
extern "C" {
|
||||
#include "project/solution.h"
|
||||
#include "project/project.h"
|
||||
}
|
||||
|
||||
struct FxSolution
|
||||
@ -109,4 +110,31 @@ SUITE(project)
|
||||
const char* filename = solution_get_filename(sln, NULL, ".xyz");
|
||||
CHECK_EQUAL("/BaseDir/Location/MySolution.xyz", filename);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Project containment tests
|
||||
**********************************************************************/
|
||||
|
||||
TEST_FIXTURE(FxSolution, NumProjects_IsZero_OnStartup)
|
||||
{
|
||||
int result = solution_num_projects(sln);
|
||||
CHECK(result == 0);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxSolution, AddProject_IncrementsNumProjects)
|
||||
{
|
||||
Project prj = project_create();
|
||||
solution_add_project(sln, prj);
|
||||
int result = solution_num_projects(sln);
|
||||
CHECK(result == 1);
|
||||
}
|
||||
|
||||
TEST_FIXTURE(FxSolution, AddProject_CanRoundtrip)
|
||||
{
|
||||
Project prj = project_create();
|
||||
solution_add_project(sln, prj);
|
||||
Project result = solution_get_project(sln, 0);
|
||||
CHECK(prj == result);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user