From d5a4def451a496caed56e31ce1fbc461ae67192f Mon Sep 17 00:00:00 2001 From: starkos Date: Wed, 21 May 2008 21:03:46 +0000 Subject: [PATCH] Bug fixes and refactorings (r382:387) --- src/action/make/gmake.c | 9 ++++- src/action/make/make.c | 37 ------------------ src/action/make/make.h | 1 - src/action/make/make_project.c | 4 +- src/action/make/tests/gmake_project_tests.cpp | 4 +- src/action/make/tests/make_tests.cpp | 12 ------ src/action/vs200x/tests/vs200x_tests.cpp | 12 ------ src/action/vs200x/vs2002.c | 9 ++++- src/action/vs200x/vs2003.c | 9 ++++- src/action/vs200x/vs2005.c | 9 ++++- src/action/vs200x/vs2008.c | 9 ++++- src/action/vs200x/vs200x.c | 37 ------------------ src/action/vs200x/vs200x.h | 1 - src/platform/platform.c | 34 ++++++++++++++++ src/platform/platform.h | 39 ++++++++++++++++--- src/premake.c | 1 - src/project/project.c | 21 ++++++++++ src/project/project.h | 1 + src/project/tests/project_tests.cpp | 23 +++++++++++ src/session/session.c | 29 +++++++++++--- src/session/session.h | 13 ++++++- src/session/tests/session_tests.cpp | 23 +++++++++-- 22 files changed, 211 insertions(+), 126 deletions(-) create mode 100644 src/platform/platform.c diff --git a/src/action/make/gmake.c b/src/action/make/gmake.c index 76b433f6..46ecead5 100644 --- a/src/action/make/gmake.c +++ b/src/action/make/gmake.c @@ -12,6 +12,13 @@ #include "make_project.h" +/** The project features supported by this action */ +static SessionFeatures Features = +{ + { "c", "c++", NULL }, +}; + + /** The GNU make solution writing process, for session_enumerate_objects() */ static SessionSolutionCallback SolutionCallbacks[] = { @@ -70,7 +77,7 @@ static SessionProjectCallback ConfigCallbacks[] = int gmake_action(Session sess) { /* make sure I can support all of the features used in the session */ - if (make_validate_session(sess) != OKAY) + if (session_validate(sess, &Features) != OKAY) { return !OKAY; } diff --git a/src/action/make/make.c b/src/action/make/make.c index 3b9eb431..e728d4e2 100644 --- a/src/action/make/make.c +++ b/src/action/make/make.c @@ -128,40 +128,3 @@ const char* make_get_solution_makefile(Session sess, Solution sln) /* all good */ return my_path; } - - -/** - * Make sure all of the features described in the sesson are supported - * by the Make-based actions. - * \param sess The session to validate. - * \returns OKAY if the session can be supported. - */ -int make_validate_session(Session sess) -{ - int si, sn; - assert(sess); - - sn = session_num_solutions(sess); - for (si = 0; si < sn; ++si) - { - int pi, pn; - Solution sln = session_get_solution(sess, si); - - pn = solution_num_projects(sln); - for (pi = 0; pi < pn; ++pi) - { - const char* value; - Project prj = solution_get_project(sln, pi); - - /* check for a recognized language */ - value = project_get_language(prj); - if (!cstr_eq(value, "c") && !cstr_eq(value, "c++")) - { - error_set("%s is not currently supported for Make", value); - return !OKAY; - } - } - } - - return OKAY; -} diff --git a/src/action/make/make.h b/src/action/make/make.h index c821a588..dd83fd5b 100644 --- a/src/action/make/make.h +++ b/src/action/make/make.h @@ -11,6 +11,5 @@ const char* make_get_obj_filename(const char* filename); const char* make_get_project_makefile(Session sess, Project prj); const char* make_get_solution_makefile(Session sess, Solution sln); -int make_validate_session(Session sess); #endif diff --git a/src/action/make/make_project.c b/src/action/make/make_project.c index 01d23905..df8cbab0 100644 --- a/src/action/make/make_project.c +++ b/src/action/make/make_project.c @@ -140,9 +140,9 @@ int make_project_config_outdir(Session sess, Project prj, Stream strm) */ int make_project_config_outfile(Session sess, Project prj, Stream strm) { + const char* outfile = project_get_outfile(prj); UNUSED(sess); - UNUSED(prj); - return stream_writeline(strm, " OUTFILE := $(OUTDIR)/MyApp"); + return stream_writeline(strm, " OUTFILE := $(OUTDIR)/%s", outfile); } diff --git a/src/action/make/tests/gmake_project_tests.cpp b/src/action/make/tests/gmake_project_tests.cpp index 1cb85951..e14f3eb9 100644 --- a/src/action/make/tests/gmake_project_tests.cpp +++ b/src/action/make/tests/gmake_project_tests.cpp @@ -8,6 +8,7 @@ #include "action/tests/action_tests.h" extern "C" { #include "action/make/make_project.h" +#include "platform/platform.h" } SUITE(action) @@ -88,9 +89,10 @@ SUITE(action) TEST_FIXTURE(FxAction, MakeProject_Config_OutFile) { + platform_set(MacOSX); make_project_config_outfile(sess, prj, strm); CHECK_EQUAL( - " OUTFILE := $(OUTDIR)/MyApp\n", + " OUTFILE := $(OUTDIR)/MyProject\n", buffer); } diff --git a/src/action/make/tests/make_tests.cpp b/src/action/make/tests/make_tests.cpp index 59806746..10c6ac6d 100644 --- a/src/action/make/tests/make_tests.cpp +++ b/src/action/make/tests/make_tests.cpp @@ -95,16 +95,4 @@ SUITE(action) const char* result = make_get_project_makefile(sess, prj1); CHECK_EQUAL("./MyProject/MyProject1.make", result); } - - - /********************************************************************** - * Session validation tests - **********************************************************************/ - - TEST_FIXTURE(FxMake, MakeValidation_ReturnsNotOkay_OnUnknownLanguage) - { - project_set_language(prj1, "nonesuch"); - int result = make_validate_session(sess); - CHECK(result != OKAY); - } } diff --git a/src/action/vs200x/tests/vs200x_tests.cpp b/src/action/vs200x/tests/vs200x_tests.cpp index f6b40738..54e385b2 100644 --- a/src/action/vs200x/tests/vs200x_tests.cpp +++ b/src/action/vs200x/tests/vs200x_tests.cpp @@ -46,16 +46,4 @@ SUITE(action) const char* result = vs200x_project_file_extension(prj); CHECK_EQUAL(".vcproj", result); } - - - /********************************************************************** - * Session validation - **********************************************************************/ - - TEST_FIXTURE(FxAction, Vs200xValidation_ReturnsNotOkay_OnUnknownLanguage) - { - project_set_language(prj, "nonesuch"); - int result = vs200x_validate_session(sess); - CHECK(result != OKAY); - } } diff --git a/src/action/vs200x/vs2002.c b/src/action/vs200x/vs2002.c index c0bbcece..4bbb759e 100644 --- a/src/action/vs200x/vs2002.c +++ b/src/action/vs200x/vs2002.c @@ -12,6 +12,13 @@ #include "vs200x_project.h" +/** The project features supported by this action */ +static SessionFeatures Features = +{ + { "c", "c++", NULL }, +}; + + /** The VS2002 solution writing process, for session_enumerate_objects() */ static SessionSolutionCallback SolutionCallbacks[] = { @@ -67,7 +74,7 @@ static SessionProjectCallback ConfigCallbacks[] = int vs2002_action(Session sess) { /* make sure I can support all of the features used in the session */ - if (vs200x_validate_session(sess) != OKAY) + if (session_validate(sess, &Features) != OKAY) { return !OKAY; } diff --git a/src/action/vs200x/vs2003.c b/src/action/vs200x/vs2003.c index 0175fd09..655aa46c 100644 --- a/src/action/vs200x/vs2003.c +++ b/src/action/vs200x/vs2003.c @@ -12,6 +12,13 @@ #include "vs200x_project.h" +/** The project features supported by this action */ +static SessionFeatures Features = +{ + { "c", "c++", NULL }, +}; + + /** The VS2003 solution writing process, for session_enumerate_objects() */ static SessionSolutionCallback SolutionCallbacks[] = { @@ -67,7 +74,7 @@ static SessionProjectCallback ConfigCallbacks[] = int vs2003_action(Session sess) { /* make sure I can support all of the features used in the session */ - if (vs200x_validate_session(sess) != OKAY) + if (session_validate(sess, &Features) != OKAY) { return !OKAY; } diff --git a/src/action/vs200x/vs2005.c b/src/action/vs200x/vs2005.c index adfc5672..ab0a8314 100644 --- a/src/action/vs200x/vs2005.c +++ b/src/action/vs200x/vs2005.c @@ -12,6 +12,13 @@ #include "vs200x_project.h" +/** The project features supported by this action */ +static SessionFeatures Features = +{ + { "c", "c++", NULL }, +}; + + /** The VS2005 solution writing process, for session_enumerate_objects() */ static SessionSolutionCallback SolutionCallbacks[] = { @@ -74,7 +81,7 @@ static SessionProjectCallback ConfigCallbacks[] = int vs2005_action(Session sess) { /* make sure I can support all of the features used in the session */ - if (vs200x_validate_session(sess) != OKAY) + if (session_validate(sess, &Features) != OKAY) { return !OKAY; } diff --git a/src/action/vs200x/vs2008.c b/src/action/vs200x/vs2008.c index 6317a2a7..88cbe8d6 100644 --- a/src/action/vs200x/vs2008.c +++ b/src/action/vs200x/vs2008.c @@ -12,6 +12,13 @@ #include "vs200x_project.h" +/** The project features supported by this action */ +static SessionFeatures Features = +{ + { "c", "c++", NULL }, +}; + + /** The VS2008 solution writing process, for session_enumerate_objects() */ static SessionSolutionCallback SolutionCallbacks[] = { @@ -73,7 +80,7 @@ static SessionProjectCallback ConfigCallbacks[] = int vs2008_action(Session sess) { /* make sure I can support all of the features used in the session */ - if (vs200x_validate_session(sess) != OKAY) + if (session_validate(sess, &Features) != OKAY) { return !OKAY; } diff --git a/src/action/vs200x/vs200x.c b/src/action/vs200x/vs200x.c index 381674b0..2d19a0ba 100644 --- a/src/action/vs200x/vs200x.c +++ b/src/action/vs200x/vs200x.c @@ -161,40 +161,3 @@ const char* vs200x_true(Session sess) int version = vs200x_get_target_version(sess); return (version < 2005) ? "TRUE" : "true"; } - - -/** - * Make sure all of the features described in the sesson are supported - * by the Visual Studio actions. - * \param sess The session to validate. - * \returns OKAY if the session can be supported. - */ -int vs200x_validate_session(Session sess) -{ - int si, sn; - assert(sess); - - sn = session_num_solutions(sess); - for (si = 0; si < sn; ++si) - { - int pi, pn; - Solution sln = session_get_solution(sess, si); - - pn = solution_num_projects(sln); - for (pi = 0; pi < pn; ++pi) - { - const char* value; - Project prj = solution_get_project(sln, pi); - - /* check for a recognized language */ - value = project_get_language(prj); - if (!cstr_eq(value, "c") && !cstr_eq(value, "c++")) - { - error_set("%s is not currently supported for Visual Studio", value); - return !OKAY; - } - } - } - - return OKAY; -} diff --git a/src/action/vs200x/vs200x.h b/src/action/vs200x/vs200x.h index a9d0f791..ef3b39d1 100644 --- a/src/action/vs200x/vs200x.h +++ b/src/action/vs200x/vs200x.h @@ -15,7 +15,6 @@ int vs200x_get_target_version(Session sess); const char* vs200x_project_file_extension(Project prj); const char* vs200x_tool_guid(const char* language); const char* vs200x_true(Session sess); -int vs200x_validate_session(Session sess); #endif diff --git a/src/platform/platform.c b/src/platform/platform.c new file mode 100644 index 00000000..cf20a3a6 --- /dev/null +++ b/src/platform/platform.c @@ -0,0 +1,34 @@ +/** + * \file platform.c + * \brief Platform abstraction API. + * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project + */ + +#include "premake.h" +#include "platform.h" + +static enum Platform CurrentPlatform = Unknown; + + +enum Platform platform_get() +{ + if (CurrentPlatform == Unknown) + { +#if defined(PLATFORM_BSD) + CurrentPlatform = BSD; +#elif defined(PLATFORM_LINUX) + CurrentPlatform = Linux; +#elif defined(PLATFORM_MACOSX) + CurrentPlatform = MacOSX; +#else + CurrentPlatform = Windows; +#endif + } + return CurrentPlatform; +} + + +void platform_set(enum Platform id) +{ + CurrentPlatform = id; +} diff --git a/src/platform/platform.h b/src/platform/platform.h index 450bc63b..88c461d5 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -7,16 +7,29 @@ #define PREMAKE_PLATFORM_H -/* Determine the current OS. I'm not sure how to reliably detect Windows - * but since it is the most common I use it as the default */ +/** + * The currently support platforms. If you add to this list be sure to + * also update the platform detection logic below, and the platform + * identifier initialization in platform.c. + */ +enum Platform +{ + Unknown, + BSD, + Linux, + MacOSX, + Windows +}; + + #if defined(__linux__) -#define PLATFORM_LINUX 1 +#define PLATFORM_LINUX (1) #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) -#define PLATFORM_BSD 1 +#define PLATFORM_BSD (1) #elif defined(__APPLE__) && defined(__MACH__) -#define PLATFORM_MACOSX 1 +#define PLATFORM_MACOSX (1) #else -#define PLATFORM_WINDOWS 1 +#define PLATFORM_WINDOWS (1) #endif @@ -51,4 +64,18 @@ int platform_dir_get_current(char* buffer, int size); int platform_dir_set_current(const char* path); +/** + * Retrieve the current platform identifier. + */ +enum Platform platform_get(void); + + +/** + * Set the platform identification string, forcing a platform-specific + * behavior regardless of the actual current platform. + * \param id One of the platform identifiers. + */ +void platform_set(enum Platform id); + + #endif diff --git a/src/premake.c b/src/premake.c index ce48b175..cdecbd25 100644 --- a/src/premake.c +++ b/src/premake.c @@ -18,7 +18,6 @@ static HostExecutionStep Steps[] = host_parse_argv, /* process the command line arguments */ host_run_script, /* run the main script (i.e. premake4.lua) */ session_unload, /* unload the objects built by the script into more accessible C data structures */ - session_validate, /* make sure that all required objects and values have been defined by the script */ host_show_help, /* show help and version messages as appropriate; may end processing here */ host_run_action, /* run the action specified on the command line */ NULL /* all done! */ diff --git a/src/project/project.c b/src/project/project.c index b6a03fd0..30c9a388 100644 --- a/src/project/project.c +++ b/src/project/project.c @@ -6,12 +6,15 @@ #include #include +#include #include "premake.h" #include "project/project.h" +#include "base/buffers.h" #include "base/cstr.h" #include "base/guid.h" #include "base/path.h" #include "base/strings.h" +#include "platform/platform.h" struct FieldInfo ProjectFieldInfo[] = @@ -172,6 +175,24 @@ const char* project_get_name(Project prj) } +/** + * Retrieve the output filename for this project, taking into account platform-specific + * naming conventions. For instance, for a project named "MyProject" this function would + * return "MyProject.exe" on Windows. No path information is included, use the function + * project_get_outdir() for that. + */ +const char* project_get_outfile(Project prj) +{ + char* buffer = buffers_next(); + strcpy(buffer, project_get_name(prj)); + if (platform_get() == Windows) + { + strcat(buffer, ".exe"); + } + return buffer; +} + + /** * Retrieve a string (single value) fields from a project, using the field indices. * \param prj The project object to query. diff --git a/src/project/project.h b/src/project/project.h index b037fc01..736c914a 100644 --- a/src/project/project.h +++ b/src/project/project.h @@ -40,6 +40,7 @@ const char* project_get_guid(Project prj); const char* project_get_language(Project prj); const char* project_get_location(Project prj); 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); void project_set_base_dir(Project prj, const char* base_dir); diff --git a/src/project/tests/project_tests.cpp b/src/project/tests/project_tests.cpp index 29dce461..d31f279a 100644 --- a/src/project/tests/project_tests.cpp +++ b/src/project/tests/project_tests.cpp @@ -8,6 +8,7 @@ #include "testing/testing.h" extern "C" { #include "project/project.h" +#include "platform/platform.h" } @@ -176,6 +177,28 @@ SUITE(project) const char* filename = project_get_filename(prj, NULL, ".xyz"); CHECK_EQUAL("/BaseDir/Location/MyProject.xyz", filename); } + + + + /********************************************************************** + * Output file tests + **********************************************************************/ + + TEST_FIXTURE(FxProject, GetOutFile_ReturnsProjectName_OnNoTargetAndNotWindows) + { + platform_set(MacOSX); + project_set_name(prj, "MyProject"); + const char* result = project_get_outfile(prj); + CHECK_EQUAL("MyProject", result); + } + + TEST_FIXTURE(FxProject, GetOutFile_AddsExe_OnNoTargetAndWindows) + { + platform_set(Windows); + project_set_name(prj, "MyProject"); + const char* result = project_get_outfile(prj); + CHECK_EQUAL("MyProject.exe", result); + } } diff --git a/src/session/session.c b/src/session/session.c index 2685add4..b21c0326 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -305,14 +305,16 @@ int session_unload(Session sess) /** * Make sure that all required objects and values have been defined by the * project script. - * \param sess The session to validate. + * \param sess The session to validate. + * \param features The features (language, kind, etc.) supported by the current action. * \returns OKAY if the session is valid. */ -int session_validate(Session sess) +int session_validate(Session sess, SessionFeatures* features) { int si, sn; assert(sess); + assert(features); sn = session_num_solutions(sess); for (si = 0; si < sn; ++si) @@ -330,14 +332,29 @@ int session_validate(Session sess) for (pi = 0; pi < pn; ++pi) { - const char* value; + int i; + Project prj = solution_get_project(sln, pi); + const char* prj_name = project_get_name(prj); + const char* prj_lang = project_get_language(prj); /* every project must have a language defined */ - value = project_get_language(prj); - if (value == NULL) + if (prj_lang == NULL) { - error_set("no language defined for project '%s'", project_get_name(prj)); + error_set("no language defined for project '%s'", prj_name); + return !OKAY; + } + + /* action must support the language */ + for (i = 0; features->languages[i] != NULL; ++i) + { + if (cstr_eq(prj_lang, features->languages[i])) + break; + } + + if (features->languages[i] == NULL) + { + error_set("%s language projects are not supported by this action", prj_lang); return !OKAY; } } diff --git a/src/session/session.h b/src/session/session.h index 32a1fb1b..d8bf62ec 100644 --- a/src/session/session.h +++ b/src/session/session.h @@ -64,6 +64,17 @@ typedef struct struct_SessionAction } SessionAction; +/** + * Describe the features (languages, project kinds, etc.) supported by an action. Used by + * session_validate() to ensure that action handler functions only get called with data + * that they can handle. + */ +typedef struct struct_SessionFeatures +{ + const char* languages[64]; +} SessionFeatures; + + Session session_create(void); void session_destroy(Session sess); void session_add_solution(Session sess, Solution sln); @@ -79,7 +90,7 @@ void session_set_action(Session sess, const char* action); void session_set_active_stream(Session sess, Stream strm); int session_tests(void); int session_unload(Session sess); -int session_validate(Session sess); +int session_validate(Session sess, SessionFeatures* features); #endif /** @} */ diff --git a/src/session/tests/session_tests.cpp b/src/session/tests/session_tests.cpp index 26bea76e..ab6a7d9d 100644 --- a/src/session/tests/session_tests.cpp +++ b/src/session/tests/session_tests.cpp @@ -36,6 +36,11 @@ int session_tests() #define FAIL_SLN_PARAM (1) #define FAIL_PRJ_PARAM (2) +static SessionFeatures features = { + { "c", "c++", NULL }, +}; + + static int num_solution_calls; static int num_project_calls; static int num_config_calls; @@ -349,7 +354,7 @@ SUITE(session) TEST_FIXTURE(FxSession, Validate_ReturnsOkay_OnNoSolutions) { - int result = session_validate(sess); + int result = session_validate(sess, &features); CHECK(result == OKAY); } @@ -358,14 +363,14 @@ SUITE(session) AddSolution(); AddProject(); project_set_language(prj, "c++"); - int result = session_validate(sess); + int result = session_validate(sess, &features); CHECK(result == OKAY); } TEST_FIXTURE(FxSession, Validate_NotOkay_OnEmptySolution) { AddSolution(); - int result = session_validate(sess); + int result = session_validate(sess, &features); CHECK(result != OKAY); CHECK_EQUAL("no projects defined for solution 'MySolution'", error_get()); } @@ -374,9 +379,19 @@ SUITE(session) { AddSolution(); AddProject(); - int result = session_validate(sess); + int result = session_validate(sess, &features); CHECK(result != OKAY); CHECK_EQUAL("no language defined for project 'MyProject'", error_get()); } + + TEST_FIXTURE(FxSession, Validate_NotOkay_OnUnsupportedLanguage) + { + AddSolution(); + AddProject(); + project_set_language(prj, "nonesuch"); + int result = session_validate(sess, &features); + CHECK(result != OKAY); + CHECK_EQUAL("nonesuch language projects are not supported by this action", error_get()); + } }