Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/premake-4.x-stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/actions')
-rw-r--r--src/actions/actions.c20
-rw-r--r--src/actions/actions.h31
-rw-r--r--src/actions/make/gmake.c88
-rw-r--r--src/actions/make/gmake_project.c49
-rw-r--r--src/actions/make/gmake_solution.c19
-rw-r--r--src/actions/make/make.c153
-rw-r--r--src/actions/make/make.h16
-rw-r--r--src/actions/make/make_project.c329
-rw-r--r--src/actions/make/make_project.h35
-rw-r--r--src/actions/make/make_solution.c251
-rw-r--r--src/actions/make/make_solution.h19
-rw-r--r--src/actions/make/tests/make_config_tests.cpp142
-rw-r--r--src/actions/make/tests/make_project_tests.cpp186
-rw-r--r--src/actions/make/tests/make_solution_tests.cpp122
-rw-r--r--src/actions/make/tests/make_tests.cpp98
-rw-r--r--src/actions/support/sourcetree.c108
-rw-r--r--src/actions/support/sourcetree.h38
-rw-r--r--src/actions/tests/action_tests.h83
-rw-r--r--src/actions/vs200x/tests/vs2002_solution_tests.cpp108
-rw-r--r--src/actions/vs200x/tests/vs2003_solution_tests.cpp45
-rw-r--r--src/actions/vs200x/tests/vs2005_solution_tests.cpp80
-rw-r--r--src/actions/vs200x/tests/vs2008_solution_tests.cpp30
-rw-r--r--src/actions/vs200x/tests/vs200x_compiler_tests.cpp102
-rw-r--r--src/actions/vs200x/tests/vs200x_config_tests.cpp67
-rw-r--r--src/actions/vs200x/tests/vs200x_linker_tests.cpp80
-rw-r--r--src/actions/vs200x/tests/vs200x_project_tests.cpp467
-rw-r--r--src/actions/vs200x/tests/vs200x_tests.cpp56
-rw-r--r--src/actions/vs200x/tests/vs200x_xml_tests.cpp120
-rw-r--r--src/actions/vs200x/vs2002.c85
-rw-r--r--src/actions/vs200x/vs2002_solution.c169
-rw-r--r--src/actions/vs200x/vs2003.c84
-rw-r--r--src/actions/vs200x/vs2003_solution.c55
-rw-r--r--src/actions/vs200x/vs2005.c92
-rw-r--r--src/actions/vs200x/vs2005_solution.c110
-rw-r--r--src/actions/vs200x/vs2008.c91
-rw-r--r--src/actions/vs200x/vs2008_solution.c29
-rw-r--r--src/actions/vs200x/vs200x.c190
-rw-r--r--src/actions/vs200x/vs200x.h21
-rw-r--r--src/actions/vs200x/vs200x_config.c64
-rw-r--r--src/actions/vs200x/vs200x_config.h17
-rw-r--r--src/actions/vs200x/vs200x_project.c475
-rw-r--r--src/actions/vs200x/vs200x_project.h41
-rw-r--r--src/actions/vs200x/vs200x_solution.c33
-rw-r--r--src/actions/vs200x/vs200x_solution.h30
44 files changed, 4528 insertions, 0 deletions
diff --git a/src/actions/actions.c b/src/actions/actions.c
new file mode 100644
index 0000000..78b0d67
--- /dev/null
+++ b/src/actions/actions.c
@@ -0,0 +1,20 @@
+/**
+ * \file actions.c
+ * \brief Built-in engine actions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <string.h>
+#include "premake.h"
+#include "actions/actions.h"
+
+
+SessionAction Actions[] =
+{
+ { "gmake", "GNU Makefiles for POSIX, MinGW, and Cygwin", gmake_action },
+ { "vs2002", "Microsoft Visual Studio 2002", vs2002_action },
+ { "vs2003", "Microsoft Visual Studio 2003", vs2003_action },
+ { "vs2005", "Microsoft Visual Studio 2005 (includes Express editions)", vs2005_action },
+ { "vs2008", "Microsoft Visual Studio 2008 (includes Express editions)", vs2008_action },
+ { 0, 0, 0 }
+};
diff --git a/src/actions/actions.h b/src/actions/actions.h
new file mode 100644
index 0000000..5bdc6a5
--- /dev/null
+++ b/src/actions/actions.h
@@ -0,0 +1,31 @@
+/**
+ * \file actions.h
+ * \brief Built-in engine actions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ *
+ * \defgroup action Actions
+ *
+ * The actions component contains the implementation of all of the built-in
+ * Premake actions, along with a few common support functions.
+ *
+ * @{
+ */
+#if !defined(PREMAKE_ACTIONS_H)
+#define PREMAKE_ACTIONS_H
+
+#include "session/session.h"
+
+
+int gmake_action (Session sess);
+int vs2002_action(Session sess);
+int vs2003_action(Session sess);
+int vs2005_action(Session sess);
+int vs2008_action(Session sess);
+
+
+/* the list of built-in Premake actions */
+extern SessionAction Actions[];
+
+
+#endif
+/** @} */
diff --git a/src/actions/make/gmake.c b/src/actions/make/gmake.c
new file mode 100644
index 0000000..073cb5e
--- /dev/null
+++ b/src/actions/make/gmake.c
@@ -0,0 +1,88 @@
+/**
+ * \file gmake.c
+ * \brief GNU makefile generation action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/actions.h"
+#include "make.h"
+#include "make_solution.h"
+#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[] =
+{
+ make_solution_create,
+ make_solution_signature,
+ make_solution_default_config,
+ make_solution_phony_rule,
+ make_solution_all_rule,
+ make_solution_projects,
+ make_solution_clean_rule,
+ NULL
+};
+
+/** The GNU make project writing process, for session_enumerate_objects() */
+static SessionProjectCallback ProjectCallbacks[] =
+{
+ make_project_create,
+ make_project_signature,
+ session_enumerate_configurations,
+ make_project_objects,
+ make_project_resources,
+ gmake_project_shell_detect,
+ make_project_phony_rule,
+ make_project_target,
+ make_project_mkdir_rules,
+ make_project_clean_rules,
+ make_project_source_rules,
+ make_project_include_dependencies,
+ NULL
+};
+
+
+/** The GNU make configuration writing process, for session_enumerate_configurations() */
+static SessionProjectCallback ConfigCallbacks[] =
+{
+ make_project_config_conditional,
+ make_project_config_outdir,
+ make_project_config_outfile,
+ make_project_config_objdir,
+ make_project_config_cppflags,
+ make_project_config_cflags,
+ make_project_config_cxxflags,
+ make_project_config_ldflags,
+ make_project_config_lddeps,
+ make_project_config_resflags,
+ make_project_config_end,
+ NULL
+};
+
+
+/**
+ * The GNU make action handler.
+ * \param sess The active session object.
+ * \returns OKAY if successful.
+ */
+int gmake_action(Session sess)
+{
+ /* make sure I can support all of the features used in the session */
+ if (session_validate(sess, &Features) != OKAY)
+ {
+ return !OKAY;
+ }
+
+ stream_writeline(Console, "Generating project files for GNU make...");
+ return session_enumerate_objects(sess, SolutionCallbacks, ProjectCallbacks, ConfigCallbacks);
+}
+
diff --git a/src/actions/make/gmake_project.c b/src/actions/make/gmake_project.c
new file mode 100644
index 0000000..3788e2d
--- /dev/null
+++ b/src/actions/make/gmake_project.c
@@ -0,0 +1,49 @@
+/**
+ * \file gmake_project.c
+ * \brief GNU makefile project generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "make_project.h"
+
+
+/**
+ * Write the shell detection block, which is used while building on Windows in
+ * order to detect the enclosing shell type: MS-DOS, Cygwin, or MinGW. The shell
+ * determines how directories and files should be created and removed.
+ *
+ * While the detection in important only on Windows, I write for all platforms.
+ * This simplifies the code generation, and makes portable makefiles possible
+ * (even though most will have platform-specific bits in them).
+ */
+int gmake_project_shell_detect(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+
+ UNUSED(sess);
+ UNUSED(prj);
+
+ z |= stream_writeline(strm, "SHELLTYPE := msdos");
+ z |= stream_writeline(strm, "ifeq (,$(ComSpec)$(COMSPEC))");
+ z |= stream_writeline(strm, " SHELLTYPE := posix");
+ z |= stream_writeline(strm, "endif");
+ z |= stream_writeline(strm, "ifeq (/bin,$(findstring /bin,$(SHELL)))");
+ z |= stream_writeline(strm, " SHELLTYPE := posix");
+ z |= stream_writeline(strm, "endif");
+ z |= stream_writeline(strm, "");
+ z |= stream_writeline(strm, "ifeq (posix,$(SHELLTYPE))");
+ z |= stream_writeline(strm, " MKDIR := mkdir -p");
+ z |= stream_writeline(strm, " PATHSEP := /");
+ z |= stream_writeline(strm, "else");
+ z |= stream_writeline(strm, " MKDIR := mkdir");
+ z |= stream_writeline(strm, " PATHSEP := \\\\");
+ z |= stream_writeline(strm, "endif");
+ z |= stream_writeline(strm, "");
+ z |= stream_writeline(strm, "SYS_OUTDIR := $(subst /,$(PATHSEP),$(OUTDIR))");
+ z |= stream_writeline(strm, "SYS_OUTFILE := $(subst /,$(PATHSEP),$(OUTFILE))");
+ z |= stream_writeline(strm, "SYS_OBJDIR := $(subst /,$(PATHSEP),$(OBJDIR))");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
diff --git a/src/actions/make/gmake_solution.c b/src/actions/make/gmake_solution.c
new file mode 100644
index 0000000..5351441
--- /dev/null
+++ b/src/actions/make/gmake_solution.c
@@ -0,0 +1,19 @@
+/**
+ * \file gmake_solution.c
+ * \brief GNU makefile solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "premake.h"
+#include "make.h"
+#include "make_solution.h"
+#include "base/buffers.h"
+#include "base/cstr.h"
+#include "base/path.h"
+#include "base/strings.h"
+
+
+
diff --git a/src/actions/make/make.c b/src/actions/make/make.c
new file mode 100644
index 0000000..e2a1d7f
--- /dev/null
+++ b/src/actions/make/make.c
@@ -0,0 +1,153 @@
+/**
+ * \file make.c
+ * \brief Support functions for the makefile action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "make.h"
+#include "base/cstr.h"
+#include "base/error.h"
+#include "base/path.h"
+
+
+/**
+ * Given a source file filename, returns the name of the corresponding .o file.
+ * \param filename The source code filename.
+ * \returns The filename of the .o file.
+ */
+const char* make_get_obj_filename(const char* filename)
+{
+ const char* basename = path_basename(filename);
+ const char* obj_name = cstr_format("$(OBJDIR)/%s.o", basename);
+ return obj_name;
+}
+
+
+/**
+ * Get the name of the project makefile for a particular project.
+ * \param sess The current execution session context.
+ * \param prj The project being requested.
+ * \returns If this project is the only object which will generate output to
+ * its target location, then this function will return "Makefile" as
+ * the filename. If any other object shares this output location, it
+ * will return "ProjectName.make" instead, so that both objects may
+ * coexist in the same directory.
+ */
+const char* make_get_project_makefile(Session sess, Project prj)
+{
+ const char* my_path;
+ const char* their_path;
+ int si, sn;
+
+ assert(sess);
+ assert(prj);
+
+ /* get the full makefile path for this project */
+ my_path = project_get_filename(prj, "Makefile", NULL);
+
+ /* see if any other solution wants to use this same path */
+ sn = session_num_solutions(sess);
+ for (si = 0; si < sn; ++si)
+ {
+ int pi, pn;
+
+ Solution sln2 = session_get_solution(sess, si);
+ their_path = solution_get_filename(sln2, "Makefile", NULL);
+ if (cstr_eq(my_path, their_path))
+ {
+ /* conflict; use the alternate name */
+ my_path = project_get_filename(prj, NULL, ".make");
+ return my_path;
+ }
+
+ /* check any projects contained by this solution */
+ pn = solution_num_projects(sln2);
+ for (pi = 0; pi < pn; ++pi)
+ {
+ Project prj2 = solution_get_project(sln2, pi);
+ if (prj != prj2)
+ {
+ their_path = project_get_filename(prj2, "Makefile", NULL);
+ if (cstr_eq(my_path, their_path))
+ {
+ /* conflict; use the alternate name */
+ my_path = project_get_filename(prj, NULL, ".make");
+ return my_path;
+ }
+ }
+ }
+ }
+
+ /* all good */
+ return my_path;
+}
+
+
+/**
+ * Build a list of project names contained by the solution.
+ * \param sln The solution to query.
+ * \returns A list of project names. The caller owns this list and must destroy it when done.
+ */
+Strings make_get_project_names(Solution sln)
+{
+ Strings result;
+ int i, n;
+
+ result = strings_create();
+ n = solution_num_projects(sln);
+ for (i = 0; i < n; ++i)
+ {
+ Project prj = solution_get_project(sln, i);
+ const char* name = project_get_name(prj);
+ strings_add(result, name);
+ }
+
+ return result;
+}
+
+
+/**
+ * Get the name of the solution makefile for a particular solution.
+ * \param sess The current execution session context.
+ * \param sln The solution being requested.
+ * \returns If this solution is the only object which will generate output to
+ * its target location, then this function will return "Makefile" as
+ * the filename. If any other solution shares this output location, it
+ * will return "SolutionName.make" instead, so that both objects may
+ * coexist in the same directory.
+ */
+const char* make_get_solution_makefile(Session sess, Solution sln)
+{
+ const char* my_path;
+ const char* their_path;
+ int i, n;
+
+ assert(sess);
+ assert(sln);
+
+ /* get the full makefile path for this solution */
+ my_path = solution_get_filename(sln, "Makefile", NULL);
+
+ /* see if any other solution wants to use this same path */
+ n = session_num_solutions(sess);
+ for (i = 0; i < n; ++i)
+ {
+ Solution them = session_get_solution(sess, i);
+ if (them != sln)
+ {
+ their_path = solution_get_filename(them, "Makefile", NULL);
+ if (cstr_eq(my_path, their_path))
+ {
+ /* conflict; use the alternate name */
+ my_path = solution_get_filename(sln, NULL, ".make");
+ return my_path;
+ }
+ }
+ }
+
+ /* all good */
+ return my_path;
+}
diff --git a/src/actions/make/make.h b/src/actions/make/make.h
new file mode 100644
index 0000000..4ac8e43
--- /dev/null
+++ b/src/actions/make/make.h
@@ -0,0 +1,16 @@
+/**
+ * \file make.h
+ * \brief Support functions for the makefile action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_MAKE_H)
+#define PREMAKE_MAKE_H
+
+#include "session/session.h"
+
+const char* make_get_obj_filename(const char* filename);
+const char* make_get_project_makefile(Session sess, Project prj);
+Strings make_get_project_names(Solution sln);
+const char* make_get_solution_makefile(Session sess, Solution sln);
+
+#endif
diff --git a/src/actions/make/make_project.c b/src/actions/make/make_project.c
new file mode 100644
index 0000000..8e1298b
--- /dev/null
+++ b/src/actions/make/make_project.c
@@ -0,0 +1,329 @@
+/**
+ * \file make_project.c
+ * \brief Makefile project generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/make/make.h"
+#include "actions/make/make_project.h"
+#include "base/error.h"
+#include "base/path.h"
+
+
+/**
+ * Write the rules to clean up output files on a `make clean`.
+ */
+int make_project_clean_rules(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ UNUSED(sess);
+ z |= stream_writeline(strm, "clean:");
+ z |= stream_writeline(strm, "\t@echo Cleaning %s", project_get_name(prj));
+ z |= stream_writeline(strm, "ifeq (posix, $(SHELLTYPE))");
+ z |= stream_writeline(strm, "\t@rm -f $(SYS_OUTFILE)");
+ z |= stream_writeline(strm, "\t@rm -rf $(SYS_OBJDIR)");
+ z |= stream_writeline(strm, "else");
+ z |= stream_writeline(strm, "\t@if exist $(SYS_OUTFILE) del $(SYS_OUTFILE)");
+ z |= stream_writeline(strm, "\t@if exist $(SYS_OBJDIR) rmdir /s /q $(SYS_OBJDIR)");
+ z |= stream_writeline(strm, "endif");
+ z |= stream_writeline(strm, "");
+ return OKAY;
+}
+
+
+/**
+ * Write the opening conditional for a configuration block.
+ */
+int make_project_config_conditional(Session sess, Project prj, Stream strm)
+{
+ const char* cfg_name = project_get_configuration_filter(prj);
+ UNUSED(sess);
+ return stream_writeline(strm, "ifeq ($(CONFIG),%s)", cfg_name);
+}
+
+
+/**
+ * Write the CFLAGS configuration variable.
+ */
+int make_project_config_cflags(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)");
+}
+
+
+/**
+ * Write the CPPFLAGS configuration variable.
+ */
+int make_project_config_cppflags(Session sess, Project prj, Stream strm)
+{
+ Strings values;
+ int z = OKAY;
+ UNUSED(sess);
+
+ z |= stream_write(strm, " CPPFLAGS += -MMD");
+
+ values = project_get_config_values(prj, BlockDefines);
+ z |= stream_write_strings(strm, values, "", " -D \"", "\"", "", "", NULL);
+
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the CXXFLAGS configuration variable.
+ */
+int make_project_config_cxxflags(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " CXXFLAGS += $(CFLAGS)");
+}
+
+
+/**
+ * Write the opening conditional for a configuration block.
+ */
+int make_project_config_end(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(prj);
+ z = stream_writeline(strm, "endif");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the LDDEPS configuration variable.
+ */
+int make_project_config_lddeps(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " LDDEPS :=");
+}
+
+
+/**
+ * Write the LDFLAGS configuration variable.
+ */
+int make_project_config_ldflags(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " LDFLAGS +=");
+}
+
+
+/**
+ * Write the OBJDIR configuration variable.
+ */
+int make_project_config_objdir(Session sess, Project prj, Stream strm)
+{
+ const char* cfg_name = project_get_configuration_filter(prj);
+ UNUSED(sess);
+ return stream_writeline(strm, " OBJDIR := obj/%s", cfg_name);
+}
+
+
+/**
+ * Write the OUTDIR configuration variable.
+ */
+int make_project_config_outdir(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " OUTDIR := .");
+}
+
+
+/**
+ * Write the OUTFILE configuration variable.
+ */
+int make_project_config_outfile(Session sess, Project prj, Stream strm)
+{
+ const char* outfile = project_get_outfile(prj);
+ UNUSED(sess);
+ return stream_writeline(strm, " OUTFILE := $(OUTDIR)/%s", outfile);
+}
+
+
+/**
+ * Write the RESFLAGS configuration variable.
+ */
+int make_project_config_resflags(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, " RESFLAGS +=");
+}
+
+
+/**
+ * Create a new output stream for a project , and make it active for subsequent writes.
+ */
+int make_project_create(Session sess, Project prj, Stream strm)
+{
+ /* create the makefile */
+ const char* filename = make_get_project_makefile(sess, prj);
+ strm = stream_create_file(filename);
+ if (!strm)
+ {
+ return !OKAY;
+ }
+
+ /* make the stream active for the functions that come after */
+ session_set_active_stream(sess, strm);
+ return OKAY;
+}
+
+
+/**
+ * Include the auto-generated dependencies into the project makefile.
+ */
+int make_project_include_dependencies(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, "-include $(OBJECTS:%%.o=%%.d)");
+}
+
+
+/**
+ * Write the rules to create the output and object directories.
+ */
+int make_project_mkdir_rules(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ UNUSED(sess);
+ UNUSED(prj);
+ z |= stream_writeline(strm, "$(OUTDIR):");
+ z |= stream_writeline(strm, "\t@echo Creating $(OUTDIR)");
+ z |= stream_writeline(strm, "\t@$(MKDIR) $(SYS_OUTDIR)");
+ z |= stream_writeline(strm, "");
+ z |= stream_writeline(strm, "$(OBJDIR):");
+ z |= stream_writeline(strm, "\t@echo Creating $(OBJDIR)");
+ z |= stream_writeline(strm, "\t@$(MKDIR) $(SYS_OBJDIR)");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the OBJECTS project variable.
+ */
+int make_project_objects(Session sess, Project prj, Stream strm)
+{
+ Strings files;
+ int i, n, z;
+ UNUSED(sess);
+
+ z = stream_writeline(strm, "OBJECTS := \\");
+
+ files = project_get_files(prj);
+ n = strings_size(files);
+ for (i = 0; i < n; ++i)
+ {
+ const char* filename = strings_item(files, i);
+ if (path_is_cpp_source(filename))
+ {
+ const char* obj_name = make_get_obj_filename(filename);
+ z |= stream_writeline(strm, "\t%s \\", obj_name);
+ }
+ }
+
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the .PHONY rule for a project.
+ */
+int make_project_phony_rule(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(prj);
+ z = stream_writeline(strm, ".PHONY: clean");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the RESOURCES project variable.
+ */
+int make_project_resources(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(prj);
+ z = stream_writeline(strm, "RESOURCES := \\");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the project makefile signature.
+ */
+int make_project_signature(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(prj);
+ z = stream_writeline(strm, "# GNU Makefile autogenerated by Premake");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write makefile rules for each source code file.
+ */
+int make_project_source_rules(Session sess, Project prj, Stream strm)
+{
+ Strings files;
+ int i, n, z = OKAY;
+ UNUSED(sess);
+
+ files = project_get_files(prj);
+ n = strings_size(files);
+ for (i = 0; i < n; ++i)
+ {
+ const char* filename = strings_item(files, i);
+ if (path_is_cpp_source(filename))
+ {
+ const char* obj_name = make_get_obj_filename(filename);
+ z |= stream_writeline(strm, "%s: %s", obj_name, filename);
+ z |= stream_writeline(strm, "\t@echo $(notdir $<)");
+ z |= stream_writeline(strm, "\t@$(CXX) $(CXXFLAGS) -o $@ -c $<");
+ z |= stream_writeline(strm, "");
+ }
+ }
+
+ return z;
+}
+
+
+/**
+ * Write the project output target rule.
+ */
+int make_project_target(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ UNUSED(sess);
+ z |= stream_writeline(strm, "$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)");
+ z |= stream_writeline(strm, "\t@echo Linking %s", project_get_name(prj));
+ z |= stream_writeline(strm, "\t@$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)");
+ z |= stream_writeline(strm, "");
+ return z;
+}
diff --git a/src/actions/make/make_project.h b/src/actions/make/make_project.h
new file mode 100644
index 0000000..e8a3ef8
--- /dev/null
+++ b/src/actions/make/make_project.h
@@ -0,0 +1,35 @@
+/**
+ * \file make_project.h
+ * \brief Makefile project generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_MAKE_PROJECT_H)
+#define PREMAKE_MAKE_PROJECT_H
+
+#include "session/session.h"
+
+int gmake_project_shell_detect(Session sess, Project prj, Stream strm);
+
+int make_project_clean_rules(Session sess, Project prj, Stream strm);
+int make_project_config_conditional(Session sess, Project prj, Stream strm);
+int make_project_config_cflags(Session sess, Project prj, Stream strm);
+int make_project_config_cppflags(Session sess, Project prj, Stream strm);
+int make_project_config_cxxflags(Session sess, Project prj, Stream strm);
+int make_project_config_end(Session sess, Project prj, Stream strm);
+int make_project_config_lddeps(Session sess, Project prj, Stream strm);
+int make_project_config_ldflags(Session sess, Project prj, Stream strm);
+int make_project_config_objdir(Session sess, Project prj, Stream strm);
+int make_project_config_outdir(Session sess, Project prj, Stream strm);
+int make_project_config_outfile(Session sess, Project prj, Stream strm);
+int make_project_config_resflags(Session sess, Project prj, Stream strm);
+int make_project_create(Session sess, Project prj, Stream strm);
+int make_project_include_dependencies(Session sess, Project prj, Stream strm);
+int make_project_mkdir_rules(Session sess, Project prj, Stream strm);
+int make_project_objects(Session sess, Project prj, Stream strm);
+int make_project_phony_rule(Session sess, Project prj, Stream strm);
+int make_project_resources(Session sess, Project prj, Stream strm);
+int make_project_signature(Session sess, Project prj, Stream strm);
+int make_project_source_rules(Session sess, Project prj, Stream strm);
+int make_project_target(Session sess, Project prj, Stream strm);
+
+#endif
diff --git a/src/actions/make/make_solution.c b/src/actions/make/make_solution.c
new file mode 100644
index 0000000..2516453
--- /dev/null
+++ b/src/actions/make/make_solution.c
@@ -0,0 +1,251 @@
+/**
+ * \file make_solution.c
+ * \brief Makefile solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "premake.h"
+#include "actions/make/make.h"
+#include "actions/make/make_solution.h"
+#include "base/buffers.h"
+#include "base/cstr.h"
+#include "base/error.h"
+#include "base/path.h"
+
+
+static const char* make_solution_project_rule(Session sess, Solution sln, Project prj);
+
+
+/**
+ * Write the GNU solution makefile clean rules.
+ * \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 make_solution_clean_rule(Session sess, Solution sln, Stream strm)
+{
+ int i, n, z;
+
+ assert(sess);
+ assert(sln);
+ assert(strm);
+
+ z = stream_writeline(strm, "clean:");
+ n = solution_num_projects(sln);
+ for (i = 0; i < n; ++i)
+ {
+ Project prj = solution_get_project(sln, i);
+ const char* rule = make_solution_project_rule(sess, sln, prj);
+ z |= stream_writeline(strm, "%s clean", rule);
+ }
+
+ return z;
+}
+
+
+/**
+ * Write the makefile "all" rule.
+ * \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 make_solution_all_rule(Session sess, Solution sln, Stream strm)
+{
+ Strings prj_names;
+ int z;
+
+ UNUSED(sess);
+ assert(sln);
+ assert(strm);
+
+ prj_names = make_get_project_names(sln);
+ z = stream_writeline_strings(strm, prj_names, "all:", " ", "", "");
+ z |= stream_writeline(strm, "");
+ strings_destroy(prj_names);
+ return z;
+}
+
+
+/**
+ * Create a new output stream for a solution, and make it active for subsequent writes.
+ * \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 make_solution_create(Session sess, Solution sln, Stream strm)
+{
+ /* create the makefile */
+ const char* filename = make_get_solution_makefile(sess, sln);
+ strm = stream_create_file(filename);
+ if (!strm)
+ {
+ return !OKAY;
+ }
+
+ /* make the stream active for the functions that come after */
+ session_set_active_stream(sess, strm);
+ return OKAY;
+}
+
+
+/**
+ * Write makefile rules to set a default build configuration.
+ * \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 make_solution_default_config(Session sess, Solution sln, Stream strm)
+{
+ const char* default_config_name;
+ int z;
+
+ UNUSED(sess);
+ assert(sln);
+ assert(strm);
+
+ 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");
+ z |= stream_writeline(strm, "export CONFIG");
+ z |= stream_writeline(strm, "");
+ return z;
+}
+
+
+/**
+ * Write the makefile .PHONY rule.
+ * \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 make_solution_phony_rule(Session sess, Solution sln, Stream strm)
+{
+ Strings prj_names;
+ int z;
+
+ UNUSED(sess);
+ assert(sln);
+ assert(strm);
+
+ prj_names = make_get_project_names(sln);
+ z = stream_writeline_strings(strm, prj_names, ".PHONY: all clean", " ", "", "");
+ z |= stream_writeline(strm, "");
+ strings_destroy(prj_names);
+ return z;
+}
+
+
+
+/**
+ * Build the makefile rule to call an individual project.
+ * \param sess The current session context.
+ * \param sln The solution containing the project.
+ * \param prj The project to be built.
+ * \returns The makefile rule to trigger the project build.
+ */
+const char* make_solution_project_rule(Session sess, Solution sln, Project prj)
+{
+ char* buffer = buffers_next();
+
+ /* project file paths are specified relative to the solution */
+ const char* sln_path = path_directory(solution_get_filename(sln, NULL, NULL));
+
+ const char* prj_file = make_get_project_makefile(sess, prj);
+ const char* prj_file_dir = path_directory(prj_file);
+ const char* prj_file_name = path_filename(prj_file);
+ prj_file_dir = path_relative(sln_path, prj_file_dir);
+
+ strcpy(buffer, "\t@$(MAKE)");
+ if (!cstr_eq(".", prj_file_dir))
+ {
+ strcat(buffer, " --no-print-directory -C ");
+ strcat(buffer, prj_file_dir);
+ }
+ if (!cstr_eq("Makefile", prj_file_name))
+ {
+ strcat(buffer, " -f ");
+ strcat(buffer, prj_file_name);
+ }
+
+ return buffer;
+}
+
+
+/**
+ * Write the solution makefile project entries.
+ * \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 make_solution_projects(Session sess, Solution sln, Stream strm)
+{
+ int i, n, z = OKAY;
+
+ assert(sess);
+ assert(sln);
+ assert(strm);
+
+ 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* rule = make_solution_project_rule(sess, sln, prj);
+
+ z |= stream_writeline(strm, "%s:", prj_name);
+ z |= stream_writeline(strm, "\t@echo ==== Building %s ====", prj_name);
+ z |= stream_writeline(strm, rule);
+ z |= stream_writeline(strm, "");
+ }
+
+ return z;
+}
+
+
+/**
+ * Write the makefile solution file signature block.
+ * \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 make_solution_signature(Session sess, Solution sln, Stream strm)
+{
+ const char* file_type;
+ Strings config_names;
+ int z;
+
+ assert(sess);
+ assert(sln);
+ assert(strm);
+
+ if (cstr_eq(session_get_action(sess), "gmake"))
+ {
+ file_type = "GNU Make";
+ }
+ else
+ {
+ file_type = "(unknown)";
+ assert(0);
+ }
+
+ z = stream_writeline(strm, "# %s makefile autogenerated by Premake", file_type);
+ z |= stream_writeline(strm, "# Usage: make [ CONFIG=config_name ]");
+ z |= stream_writeline(strm, "# Where {config_name} is one of:");
+
+ config_names = solution_get_configs(sln);
+ z |= stream_writeline_strings(strm, config_names, "# ", " ", "", ",");
+ z |= stream_writeline(strm, "");
+
+ return z;
+}
diff --git a/src/actions/make/make_solution.h b/src/actions/make/make_solution.h
new file mode 100644
index 0000000..0ff86cd
--- /dev/null
+++ b/src/actions/make/make_solution.h
@@ -0,0 +1,19 @@
+/**
+ * \file make_solution.h
+ * \brief Makefile solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_MAKE_SOLUTION_H)
+#define PREMAKE_MAKE_SOLUTION_H
+
+#include "session/session.h"
+
+int make_solution_clean_rule(Session sess, Solution sln, Stream strm);
+int make_solution_all_rule(Session sess, Solution sln, Stream strm);
+int make_solution_create(Session sess, Solution sln, Stream strm);
+int make_solution_default_config(Session sess, Solution sln, Stream strm);
+int make_solution_phony_rule(Session sess, Solution sln, Stream strm);
+int make_solution_projects(Session sess, Solution sln, Stream strm);
+int make_solution_signature(Session sess, Solution sln, Stream strm);
+
+#endif
diff --git a/src/actions/make/tests/make_config_tests.cpp b/src/actions/make/tests/make_config_tests.cpp
new file mode 100644
index 0000000..5c8ae6b
--- /dev/null
+++ b/src/actions/make/tests/make_config_tests.cpp
@@ -0,0 +1,142 @@
+/**
+ * \file make_config_tests.cpp
+ * \brief Automated tests for makefile configuration block processing.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/make/make_project.h"
+#include "platform/platform.h"
+}
+
+SUITE(action)
+{
+ /**********************************************************************
+ * CPPFLAGS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeCppFlags_Defaults)
+ {
+ make_project_config_cppflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " CPPFLAGS += -MMD\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, MakeCppFlags_WithDefines)
+ {
+ char* defines[] = { "DEFINE0", "DEFINE1", NULL};
+ SetConfigField(prj, BlockDefines, defines);
+ make_project_config_cppflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " CPPFLAGS += -MMD -D \"DEFINE0\" -D \"DEFINE1\"\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * CFLAGS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_CFlags)
+ {
+ make_project_config_cflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * CXXFLAGS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_CxxFlags)
+ {
+ make_project_config_cxxflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " CXXFLAGS += $(CFLAGS)\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * LDDEPS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_LdDeps)
+ {
+ make_project_config_lddeps(sess, prj, strm);
+ CHECK_EQUAL(
+ " LDDEPS :=\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * LDFLAGS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_LdFlags)
+ {
+ make_project_config_ldflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " LDFLAGS +=\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * OBJDIR tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_ObjDir)
+ {
+ make_project_config_objdir(sess, prj, strm);
+ CHECK_EQUAL(
+ " OBJDIR := obj/Debug\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * OUTFILE tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_OutFile)
+ {
+ platform_set(MacOSX);
+ make_project_config_outfile(sess, prj, strm);
+ CHECK_EQUAL(
+ " OUTFILE := $(OUTDIR)/MyProject\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * OUTDIR tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_OutDir)
+ {
+ make_project_config_outdir(sess, prj, strm);
+ CHECK_EQUAL(
+ " OUTDIR := .\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * RESFLAGS tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_ResFlags)
+ {
+ make_project_config_resflags(sess, prj, strm);
+ CHECK_EQUAL(
+ " RESFLAGS +=\n",
+ buffer);
+ }
+}
diff --git a/src/actions/make/tests/make_project_tests.cpp b/src/actions/make/tests/make_project_tests.cpp
new file mode 100644
index 0000000..2ca0319
--- /dev/null
+++ b/src/actions/make/tests/make_project_tests.cpp
@@ -0,0 +1,186 @@
+/**
+ * \file make_project_tests.cpp
+ * \brief Automated tests for GNU makefile project processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/make/make_project.h"
+#include "platform/platform.h"
+}
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_SignatureIsCorrect_OnGmake)
+ {
+ session_set_action(sess, "gmake");
+ make_project_signature(sess, prj, strm);
+ CHECK_EQUAL(
+ "# GNU Makefile autogenerated by Premake\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Config block conditional tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_Conditional)
+ {
+ make_project_config_conditional(sess, prj, strm);
+ CHECK_EQUAL(
+ "ifeq ($(CONFIG),Debug)\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, MakeProject_Config_End)
+ {
+ make_project_config_end(sess, prj, strm);
+ CHECK_EQUAL(
+ "endif\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Object file list tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Objects_ConvertsFileExtension)
+ {
+ char* files[] = { "Hello.cpp", "Goodbye.cpp", NULL };
+ SetField(prj, ProjectFiles, files);
+ make_project_objects(sess, prj, strm);
+ CHECK_EQUAL(
+ "OBJECTS := \\\n"
+ "\t$(OBJDIR)/Hello.o \\\n"
+ "\t$(OBJDIR)/Goodbye.o \\\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Resource file list tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_Resources)
+ {
+ make_project_resources(sess, prj, strm);
+ CHECK_EQUAL(
+ "RESOURCES := \\\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * .PHONY rule tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_PhonyRule)
+ {
+ make_project_phony_rule(sess, prj, strm);
+ CHECK_EQUAL(
+ ".PHONY: clean\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Output target tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_OutputTarget)
+ {
+ make_project_target(sess, prj, strm);
+ CHECK_EQUAL(
+ "$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
+ "\t@echo Linking MyProject\n"
+ "\t@$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Directory creation rules
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_MkdirRules)
+ {
+ make_project_mkdir_rules(sess, prj, strm);
+ CHECK_EQUAL(
+ "$(OUTDIR):\n"
+ "\t@echo Creating $(OUTDIR)\n"
+ "\t@$(MKDIR) $(SYS_OUTDIR)\n"
+ "\n"
+ "$(OBJDIR):\n"
+ "\t@echo Creating $(OBJDIR)\n"
+ "\t@$(MKDIR) $(SYS_OBJDIR)\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Clean rules
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_CleanRules)
+ {
+ make_project_clean_rules(sess, prj, strm);
+ CHECK_EQUAL(
+ "clean:\n"
+ "\t@echo Cleaning MyProject\n"
+ "ifeq (posix, $(SHELLTYPE))\n"
+ "\t@rm -f $(SYS_OUTFILE)\n"
+ "\t@rm -rf $(SYS_OBJDIR)\n"
+ "else\n"
+ "\t@if exist $(SYS_OUTFILE) del $(SYS_OUTFILE)\n"
+ "\t@if exist $(SYS_OBJDIR) rmdir /s /q $(SYS_OBJDIR)\n"
+ "endif\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Source rule tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_SourceRules)
+ {
+ char* files[] = { "Hello.cpp", NULL };
+ SetField(prj, ProjectFiles, files);
+ make_project_source_rules(sess, prj, strm);
+ CHECK_EQUAL(
+ "$(OBJDIR)/Hello.o: Hello.cpp\n"
+ "\t@echo $(notdir $<)\n"
+ "\t@$(CXX) $(CXXFLAGS) -o $@ -c $<\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * File dependency generation tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeProject_IncludeDependencies)
+ {
+ make_project_include_dependencies(sess, prj, strm);
+ CHECK_EQUAL(
+ "-include $(OBJECTS:%.o=%.d)\n",
+ buffer);
+ }
+}
diff --git a/src/actions/make/tests/make_solution_tests.cpp b/src/actions/make/tests/make_solution_tests.cpp
new file mode 100644
index 0000000..896a8e5
--- /dev/null
+++ b/src/actions/make/tests/make_solution_tests.cpp
@@ -0,0 +1,122 @@
+/**
+ * \file make_solution_tests.cpp
+ * \brief Automated tests for makefile "solution" processing.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/make/make_solution.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeSolution_SignatureIsCorrect_OnGmake)
+ {
+ session_set_action(sess, "gmake");
+ make_solution_signature(sess, sln, strm);
+ CHECK_EQUAL(
+ "# GNU Make makefile autogenerated by Premake\n"
+ "# Usage: make [ CONFIG=config_name ]\n"
+ "# Where {config_name} is one of:\n"
+ "# Debug, Release\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Default configuration tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeSolution_DefaultConfigIsCorrect)
+ {
+ make_solution_default_config(sess, sln, strm);
+ CHECK_EQUAL(
+ "ifndef CONFIG\n"
+ " CONFIG=Debug\n"
+ "endif\n"
+ "export CONFIG\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Phony rule tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeSolution_PhonyRuleIsCorrect)
+ {
+ make_solution_phony_rule(sess, sln, strm);
+ CHECK_EQUAL(
+ ".PHONY: all clean MyProject\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * All rule tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, MakeSolution_AllRuleIsCorrect)
+ {
+ make_solution_all_rule(sess, sln, strm);
+ CHECK_EQUAL(
+ "all: MyProject\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project entry tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Make_ProjectEntry_InSameDirectory)
+ {
+ project_set_location(prj, "");
+ make_solution_projects(sess, sln, strm);
+ CHECK_EQUAL(
+ "MyProject:\n"
+ "\t@echo ==== Building MyProject ====\n"
+ "\t@$(MAKE) -f MyProject.make\n"
+ "\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Make_ProjectEntry_InDifferentDirectory)
+ {
+ project_set_location(prj, "MyProject");
+ make_solution_projects(sess, sln, strm);
+ CHECK_EQUAL(
+ "MyProject:\n"
+ "\t@echo ==== Building MyProject ====\n"
+ "\t@$(MAKE) --no-print-directory -C MyProject\n"
+ "\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Clean rule tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Gmake_CleanRule_IsCorrect)
+ {
+ project_set_location(prj, "");
+ make_solution_clean_rule(sess, sln, strm);
+ CHECK_EQUAL(
+ "clean:\n"
+ "\t@$(MAKE) -f MyProject.make clean\n",
+ buffer);
+ }
+
+}
diff --git a/src/actions/make/tests/make_tests.cpp b/src/actions/make/tests/make_tests.cpp
new file mode 100644
index 0000000..db4fe87
--- /dev/null
+++ b/src/actions/make/tests/make_tests.cpp
@@ -0,0 +1,98 @@
+/**
+ * \file make_tests.cpp
+ * \brief Automated tests for the makefile generator support functions.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "testing/testing.h"
+extern "C" {
+#include "actions/make/make.h"
+#include "base/error.h"
+}
+
+
+struct FxMake
+{
+ Session sess;
+ Solution sln1;
+ Solution sln2;
+ Project prj1;
+ Project prj2;
+
+ FxMake()
+ {
+ sess = session_create();
+ sln1 = AddSolution("MySolution1");
+ sln2 = AddSolution("MySolution2");
+ prj1 = AddProject("MyProject1");
+ prj2 = AddProject("MyProject2");
+ }
+
+ ~FxMake()
+ {
+ session_destroy(sess);
+ error_clear();
+ }
+
+ Solution AddSolution(const char* name)
+ {
+ Solution sln = solution_create();
+ session_add_solution(sess, sln);
+ solution_set_name(sln, name);
+ solution_set_base_dir(sln, ".");
+ return sln;
+ }
+
+ Project AddProject(const char* name)
+ {
+ Project prj = project_create();
+ solution_add_project(sln1, prj);
+ project_set_name(prj, name);
+ project_set_base_dir(prj, ".");
+ return prj;
+ }
+};
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Makefile naming tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxMake, GetSolutionMakefile_ReturnsMakefile_OnUniqueLocation)
+ {
+ solution_set_location(sln1, "MySolution");
+ const char* result = make_get_solution_makefile(sess, sln1);
+ CHECK_EQUAL("./MySolution/Makefile", result);
+ }
+
+ TEST_FIXTURE(FxMake, GetSolutionMakefile_ReturnsDotMake_OnSharedLocation)
+ {
+ const char* result = make_get_solution_makefile(sess, sln1);
+ CHECK_EQUAL("./MySolution1.make", result);
+ }
+
+ TEST_FIXTURE(FxMake, GetProjectMakefile_ReturnsMakefile_OnUniqueLocation)
+ {
+ project_set_location(prj1, "MyProject");
+ const char* result = make_get_project_makefile(sess, prj1);
+ CHECK_EQUAL("./MyProject/Makefile", result);
+ }
+
+ TEST_FIXTURE(FxMake, GetProjectMakefile_ReturnsDotMake_OnSharedWithSolution)
+ {
+ project_set_location(prj2, "MyProject");
+ const char* result = make_get_project_makefile(sess, prj1);
+ CHECK_EQUAL("./MyProject1.make", result);
+ }
+
+ TEST_FIXTURE(FxMake, GetProjectMakefile_ReturnsDotMake_OnSharedWithProject)
+ {
+ project_set_location(prj1, "MyProject");
+ project_set_location(prj2, "MyProject");
+ const char* result = make_get_project_makefile(sess, prj1);
+ CHECK_EQUAL("./MyProject/MyProject1.make", result);
+ }
+}
diff --git a/src/actions/support/sourcetree.c b/src/actions/support/sourcetree.c
new file mode 100644
index 0000000..7659dcf
--- /dev/null
+++ b/src/actions/support/sourcetree.c
@@ -0,0 +1,108 @@
+/**
+ * \file sourcetree.h
+ * \brief Source code tree enumerator.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <string.h>
+#include "premake.h"
+#include "sourcetree.h"
+#include "base/buffers.h"
+#include "base/cstr.h"
+#include "base/string.h"
+
+
+static int sourcetree_do(Session sess, Project prj, Stream strm, SourceTreeCallback handler, const char* group);
+
+
+/**
+ * Walk a list of source files and pass them off, in nesting order, to
+ * the specified callback. Handles the grouping of related files info
+ * groups (by directory currently).
+ * \param sess The current execution session context.
+ * \param prj The project containing the files to enumerate.
+ * \param strm The active output stream.
+ * \param handler The per-file handler function.
+ * \returns OKAY on success.
+ */
+int sourcetree_walk(Session sess, Project prj, Stream strm, SourceTreeCallback handler)
+{
+ return sourcetree_do(sess, prj, strm, handler, "");
+}
+
+
+static int sourcetree_do(Session sess, Project prj, Stream strm, SourceTreeCallback handler, const char* group)
+{
+ int i, n;
+ unsigned group_len;
+ Strings files;
+ char* buffer;
+
+ group_len = strlen(group);
+
+ /* open an enclosing group */
+ buffer = buffers_next();
+ strcpy(buffer, group);
+ cstr_trim(buffer, '/');
+ handler(sess, prj, strm, buffer, GroupStart);
+
+ /* scan all files in this group and process any subdirectories (subgroups) */
+ files = project_get_files(prj);
+ n = strings_size(files);
+ for (i = 0; i < n; ++i)
+ {
+ const char* filename = strings_item(files, i);
+
+ /* is this file in the group that I am currently processing? */
+ if (cstr_starts_with(filename, group))
+ {
+ /* see if this file contains an additional directory level (a new group) */
+ const char* ptr = strchr(filename + group_len, '/');
+ if (ptr)
+ {
+ int j;
+
+ /* pull out the name of this new group */
+ size_t len = ptr - filename + 1;
+ buffer = buffers_next();
+ strncpy(buffer, filename, len);
+ buffer[len] = '\0';
+
+ /* have I processed this subdirectory already? See if it appears earlier in the list */
+ for (j = 0; j < i; ++j)
+ {
+ if (cstr_starts_with(strings_item(files, j), buffer))
+ break;
+ }
+
+ if (i == j)
+ {
+ /* a new group, process it now */
+ String new_group = string_create(buffer);
+ int z = sourcetree_do(sess, prj, strm, handler, string_cstr(new_group));
+ string_destroy(new_group);
+ if (z != OKAY) return !OKAY;
+ }
+ }
+ }
+ }
+
+ /* now process all files that belong to this current group (and not a subgroup) */
+ for (i = 0; i < n; ++i)
+ {
+ const char* filename = strings_item(files, i);
+ if (cstr_starts_with(filename, group) && strchr(filename + group_len, '/') == NULL)
+ {
+ if (handler(sess, prj, strm, filename, SourceFile) != OKAY)
+ return !OKAY;
+ }
+ }
+
+ /* close the group */
+ buffer = buffers_next();
+ strcpy(buffer, group);
+ cstr_trim(buffer, '/');
+ handler(sess, prj, strm, buffer, GroupEnd);
+ return OKAY;
+}
+
diff --git a/src/actions/support/sourcetree.h b/src/actions/support/sourcetree.h
new file mode 100644
index 0000000..f39224f
--- /dev/null
+++ b/src/actions/support/sourcetree.h
@@ -0,0 +1,38 @@
+/**
+ * \file sourcetree.h
+ * \brief Source code tree enumerator.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_SOURCETREE_H)
+#define PREMAKE_SOURCETREE_H
+
+#include "session/session.h"
+
+
+/**
+ * State values for the source tree enumeration functions.
+ */
+enum SourceTreeState
+{
+ GroupStart,
+ GroupEnd,
+ SourceFile
+};
+
+
+/**
+ * Per-file callback signature for action_source_tree.
+ * \param sess The current execution state context.
+ * \param prj The current project; contains the file being enumerated.
+ * \param strm The active output stream; for writing the file markup.
+ * \param filename The name of the file to process.
+ * \param state One of the ActionSourceStates, enabling file grouping.
+ * \returns OKAY if successful.
+ */
+typedef int (*SourceTreeCallback)(Session sess, Project prj, Stream strm, const char* filename, int state);
+
+
+int sourcetree_walk(Session sess, Project prj, Stream strm, SourceTreeCallback handler);
+
+
+#endif
diff --git a/src/actions/tests/action_tests.h b/src/actions/tests/action_tests.h
new file mode 100644
index 0000000..71c53b8
--- /dev/null
+++ b/src/actions/tests/action_tests.h
@@ -0,0 +1,83 @@
+/**
+ * \file action_tests.h
+ * \brief Common test fixtures for all action tests.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "testing/testing.h"
+extern "C" {
+#include "session/session.h"
+#include "project/project.h"
+}
+
+struct FxAction
+{
+ Session sess;
+ Stream strm;
+ Solution sln;
+ Filter flt;
+ Project prj;
+ char buffer[8192];
+
+ FxAction()
+ {
+ sess = session_create();
+
+ strm = stream_create_null();
+ stream_set_buffer(strm, buffer);
+ session_set_active_stream(sess, strm);
+
+ sln = solution_create();
+ session_add_solution(sess, sln);
+ solution_set_name(sln, "MySolution");
+ solution_set_base_dir(sln, "/Root");
+ solution_add_config(sln, "Debug");
+ solution_add_config(sln, "Release");
+
+ prj = project_create();
+ solution_add_project(sln, prj);
+ project_set_name(prj, "MyProject");
+ project_set_base_dir(prj, "/Root");
+ project_set_location(prj, "ProjectFolder");
+ project_set_guid(prj, "AE2461B7-236F-4278-81D3-F0D476F9A4C0");
+ project_set_language(prj, "c++");
+
+ flt = filter_create();
+ filter_set_value(flt, FilterConfig, "Debug");
+ project_set_filter(prj, flt);
+ }
+
+ ~FxAction()
+ {
+ stream_destroy(strm);
+ session_destroy(sess);
+ filter_destroy(flt);
+ }
+
+
+ void SetField(Project prj, enum ProjectField index, char** values)
+ {
+ Strings strs = strings_create();
+ for (char** value = values; (*value) != NULL; ++value)
+ {
+ strings_add(strs, *value);
+ }
+
+ project_set_values(prj, index, strs);
+ }
+
+ void SetConfigField(Project prj, enum BlockField index, char** values)
+ {
+ Strings strs = strings_create();
+ for (char** value = values; (*value) != NULL; ++value)
+ {
+ strings_add(strs, *value);
+ }
+
+ Block blk = block_create();
+ block_set_values(blk, index, strs);
+
+ Blocks blks = project_get_blocks(prj);
+ blocks_add(blks, blk);
+ }
+};
diff --git a/src/actions/vs200x/tests/vs2002_solution_tests.cpp b/src/actions/vs200x/tests/vs2002_solution_tests.cpp
new file mode 100644
index 0000000..1605ef9
--- /dev/null
+++ b/src/actions/vs200x/tests/vs2002_solution_tests.cpp
@@ -0,0 +1,108 @@
+/**
+ * \file vs2002_solution_tests.cpp
+ * \brief Automated tests for VS2002 solution processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_solution.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_Signature_IsCorrect)
+ {
+ vs2002_solution_signature(sess, sln, strm);
+ CHECK_EQUAL(
+ "Microsoft Visual Studio Solution File, Format Version 7.00\r\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project entry tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_ProjectEntry_UsesRelativePath)
+ {
+ vs2002_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);
+ }
+
+
+ /**********************************************************************
+ * Solution configuration tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_SolutionConfiguration_IsCorrect)
+ {
+ vs2002_solution_configuration(sess, sln, strm);
+ CHECK_EQUAL(
+ "Global\n"
+ "\tGlobalSection(SolutionConfiguration) = preSolution\n"
+ "\t\tConfigName.0 = Debug\n"
+ "\t\tConfigName.1 = Release\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project dependencies tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_ProjectDependencies_IsCorrect)
+ {
+ vs2002_solution_dependencies(sess, sln, strm);
+ CHECK_EQUAL(
+ "\tGlobalSection(ProjectDependencies) = postSolution\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project configuration tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_ProjectConfiguration_IsCorrect)
+ {
+ vs2002_solution_project_configuration(sess, sln, strm);
+ CHECK_EQUAL(
+ "\tGlobalSection(ProjectConfiguration) = postSolution\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug.ActiveCfg = Debug|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug.Build.0 = Debug|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release.ActiveCfg = Release|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release.Build.0 = Release|Win32\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Solution extensibility tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2002_Extensibility_IsCorrect)
+ {
+ vs2002_solution_extensibility(sess, sln, strm);
+ CHECK_EQUAL(
+ "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
+ "\tEndGlobalSection\n"
+ "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
+ "\tEndGlobalSection\n"
+ "EndGlobal\n",
+ buffer);
+ }
+
+}
diff --git a/src/actions/vs200x/tests/vs2003_solution_tests.cpp b/src/actions/vs200x/tests/vs2003_solution_tests.cpp
new file mode 100644
index 0000000..8ee8614
--- /dev/null
+++ b/src/actions/vs200x/tests/vs2003_solution_tests.cpp
@@ -0,0 +1,45 @@
+/**
+ * \file vs2003_solution_tests.cpp
+ * \brief Automated tests for VS2003 solution processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_solution.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2003_Signature_IsCorrect)
+ {
+ vs2003_solution_signature(sess, sln, strm);
+ CHECK_EQUAL(
+ "Microsoft Visual Studio Solution File, Format Version 8.00\r\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Solution configuration tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2003_SolutionConfiguration_IsCorrect)
+ {
+ vs2003_solution_configuration(sess, sln, strm);
+ CHECK_EQUAL(
+ "Global\n"
+ "\tGlobalSection(SolutionConfiguration) = preSolution\n"
+ "\t\tDebug = Debug\n"
+ "\t\tRelease = Release\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+}
diff --git a/src/actions/vs200x/tests/vs2005_solution_tests.cpp b/src/actions/vs200x/tests/vs2005_solution_tests.cpp
new file mode 100644
index 0000000..e50edcb
--- /dev/null
+++ b/src/actions/vs200x/tests/vs2005_solution_tests.cpp
@@ -0,0 +1,80 @@
+/**
+ * \file vs2005_solution_tests.cpp
+ * \brief Automated tests for VS2005 solution processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_solution.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2005_Signature_IsCorrect)
+ {
+ vs2005_solution_signature(sess, sln, strm);
+ CHECK_EQUAL(
+ "\357\273\277\r\n"
+ "Microsoft Visual Studio Solution File, Format Version 9.00\r\n"
+ "# Visual Studio 2005\r\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Solution Configuration Platforms tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Platforms_IsCorrect)
+ {
+ vs2005_solution_platforms(sess, sln, strm);
+ CHECK_EQUAL(
+ "Global\n"
+ "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"
+ "\t\tDebug|Win32 = Debug|Win32\n"
+ "\t\tRelease|Win32 = Release|Win32\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project Configuration Platforms tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, ProjectPlatforms_IsCorrect)
+ {
+ vs2005_solution_project_platforms(sess, sln, strm);
+ CHECK_EQUAL(
+ "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug|Win32.ActiveCfg = Debug|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug|Win32.Build.0 = Debug|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release|Win32.ActiveCfg = Release|Win32\n"
+ "\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release|Win32.Build.0 = Release|Win32\n"
+ "\tEndGlobalSection\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Solution Project tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Properties_IsCorrect)
+ {
+ vs2005_solution_properties(sess, sln, strm);
+ CHECK_EQUAL(
+ "\tGlobalSection(SolutionProperties) = preSolution\n"
+ "\t\tHideSolutionNode = FALSE\n"
+ "\tEndGlobalSection\n"
+ "EndGlobal\n",
+ buffer);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs2008_solution_tests.cpp b/src/actions/vs200x/tests/vs2008_solution_tests.cpp
new file mode 100644
index 0000000..7495b97
--- /dev/null
+++ b/src/actions/vs200x/tests/vs2008_solution_tests.cpp
@@ -0,0 +1,30 @@
+/**
+ * \file vs2008_solution_tests.cpp
+ * \brief Automated tests for VS2008 solution processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_solution.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Signature tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs2008_Signature_IsCorrect)
+ {
+ vs2008_solution_signature(sess, sln, strm);
+ CHECK_EQUAL(
+ "\357\273\277\r\n"
+ "Microsoft Visual Studio Solution File, Format Version 10.00\r\n"
+ "# Visual Studio 2008\r\n",
+ buffer);
+ }
+
+}
diff --git a/src/actions/vs200x/tests/vs200x_compiler_tests.cpp b/src/actions/vs200x/tests/vs200x_compiler_tests.cpp
new file mode 100644
index 0000000..167ad30
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_compiler_tests.cpp
@@ -0,0 +1,102 @@
+/**
+ * \file vs200x_compiler_tests.cpp
+ * \brief Automated tests for VS200x compiler block processing.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_project.h"
+}
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Default settings
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VCCLCompilerTool_Defaults_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_cl_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCCLCompilerTool\"\n"
+ "\t\t\t\tOptimization=\"0\"\n"
+ "\t\t\t\tMinimalRebuild=\"TRUE\"\n"
+ "\t\t\t\tBasicRuntimeChecks=\"3\"\n"
+ "\t\t\t\tRuntimeLibrary=\"3\"\n"
+ "\t\t\t\tRuntimeTypeInfo=\"TRUE\"\n"
+ "\t\t\t\tUsePrecompiledHeader=\"2\"\n"
+ "\t\t\t\tWarningLevel=\"3\"\n"
+ "\t\t\t\tDetect64BitPortabilityProblems=\"TRUE\"\n"
+ "\t\t\t\tDebugInformationFormat=\"4\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VCCLCompilerTool_Defaults_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_project_vc_cl_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCCLCompilerTool\"\n"
+ "\t\t\t\tOptimization=\"0\"\n"
+ "\t\t\t\tMinimalRebuild=\"true\"\n"
+ "\t\t\t\tBasicRuntimeChecks=\"3\"\n"
+ "\t\t\t\tRuntimeLibrary=\"3\"\n"
+ "\t\t\t\tUsePrecompiledHeader=\"0\"\n"
+ "\t\t\t\tWarningLevel=\"3\"\n"
+ "\t\t\t\tDetect64BitPortabilityProblems=\"true\"\n"
+ "\t\t\t\tDebugInformationFormat=\"4\"\n"
+ "\t\t\t/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VCCLCompilerTool_Defaults_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_project_vc_cl_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCCLCompilerTool\"\n"
+ "\t\t\t\tOptimization=\"0\"\n"
+ "\t\t\t\tMinimalRebuild=\"true\"\n"
+ "\t\t\t\tBasicRuntimeChecks=\"3\"\n"
+ "\t\t\t\tRuntimeLibrary=\"3\"\n"
+ "\t\t\t\tUsePrecompiledHeader=\"0\"\n"
+ "\t\t\t\tWarningLevel=\"3\"\n"
+ "\t\t\t\tDebugInformationFormat=\"4\"\n"
+ "\t\t\t/>\n",
+ buffer);
+ }
+
+
+
+ /**********************************************************************
+ * Defines tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VCCLCompilerTool_WithDefines)
+ {
+ session_set_action(sess, "vs2002");
+ char* defines[] = { "DEFINE0", "DEFINE1", NULL };
+ SetConfigField(prj, BlockDefines, defines);
+ vs200x_project_vc_cl_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCCLCompilerTool\"\n"
+ "\t\t\t\tOptimization=\"0\"\n"
+ "\t\t\t\tPreprocessorDefinitions=\"DEFINE0;DEFINE1\"\n"
+ "\t\t\t\tMinimalRebuild=\"TRUE\"\n"
+ "\t\t\t\tBasicRuntimeChecks=\"3\"\n"
+ "\t\t\t\tRuntimeLibrary=\"3\"\n"
+ "\t\t\t\tRuntimeTypeInfo=\"TRUE\"\n"
+ "\t\t\t\tUsePrecompiledHeader=\"2\"\n"
+ "\t\t\t\tWarningLevel=\"3\"\n"
+ "\t\t\t\tDetect64BitPortabilityProblems=\"TRUE\"\n"
+ "\t\t\t\tDebugInformationFormat=\"4\"/>\n",
+ buffer);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs200x_config_tests.cpp b/src/actions/vs200x/tests/vs200x_config_tests.cpp
new file mode 100644
index 0000000..7a8fbe9
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_config_tests.cpp
@@ -0,0 +1,67 @@
+/**
+ * \file vs200x_config_tests.cpp
+ * \brief Automated tests for VS200x configuration settings processing.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_config.h"
+}
+
+SUITE(action)
+{
+ /*************************************************************************
+ * Character set tests
+ *************************************************************************/
+
+ TEST_FIXTURE(FxAction, VsCharacterSet_Defaults_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_config_character_set(sess, strm);
+ CHECK_EQUAL("\n\t\t\tCharacterSet=\"2\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsCharacterSet_Defaults_OnVs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_config_character_set(sess, strm);
+ CHECK_EQUAL("\n\t\t\tCharacterSet=\"2\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsCharacterSet_Defaults_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_config_character_set(sess, strm);
+ CHECK_EQUAL("\n\t\t\tCharacterSet=\"1\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsCharacterSet_Defaults_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_config_character_set(sess, strm);
+ CHECK_EQUAL("\n\t\t\tCharacterSet=\"1\"", buffer);
+ }
+
+
+ /*************************************************************************
+ * Defines tests
+ *************************************************************************/
+
+ TEST_FIXTURE(FxAction, VsDefines_Empty_OnNoSymbols)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_config_defines(sess, strm, prj);
+ CHECK_EQUAL("", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsDefines_SemiSplitList)
+ {
+ session_set_action(sess, "vs2002");
+ char* values[] = { "DEFINE0", "DEFINE1", "DEFINE2", NULL };
+ SetConfigField(prj, BlockDefines, values);
+ vs200x_config_defines(sess, strm, prj);
+ CHECK_EQUAL("\n\t\t\t\tPreprocessorDefinitions=\"DEFINE0;DEFINE1;DEFINE2\"", buffer);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs200x_linker_tests.cpp b/src/actions/vs200x/tests/vs200x_linker_tests.cpp
new file mode 100644
index 0000000..10b8e01
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_linker_tests.cpp
@@ -0,0 +1,80 @@
+/**
+ * \file vs200x_linker_tests.cpp
+ * \brief Automated tests for VS200x linker block processing.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_project.h"
+}
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Default settings
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VCLinkerTool_Defaults_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_linker_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCLinkerTool\"\n"
+ "\t\t\t\tLinkIncremental=\"2\"\n"
+ "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"
+ "\t\t\t\tSubSystem=\"1\"\n"
+ "\t\t\t\tEntryPointSymbol=\"mainCRTStartup\"\n"
+ "\t\t\t\tTargetMachine=\"1\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VCLinkerTool_Defaults_OnVs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_project_vc_linker_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCLinkerTool\"\n"
+ "\t\t\t\tLinkIncremental=\"2\"\n"
+ "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"
+ "\t\t\t\tSubSystem=\"1\"\n"
+ "\t\t\t\tEntryPointSymbol=\"mainCRTStartup\"\n"
+ "\t\t\t\tTargetMachine=\"1\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VCLinkerTool_Defaults_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_project_vc_linker_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCLinkerTool\"\n"
+ "\t\t\t\tLinkIncremental=\"2\"\n"
+ "\t\t\t\tGenerateDebugInformation=\"true\"\n"
+ "\t\t\t\tSubSystem=\"1\"\n"
+ "\t\t\t\tEntryPointSymbol=\"mainCRTStartup\"\n"
+ "\t\t\t\tTargetMachine=\"1\"\n"
+ "\t\t\t/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VCLinkerTool_Defaults_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_project_vc_linker_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCLinkerTool\"\n"
+ "\t\t\t\tLinkIncremental=\"2\"\n"
+ "\t\t\t\tGenerateDebugInformation=\"true\"\n"
+ "\t\t\t\tSubSystem=\"1\"\n"
+ "\t\t\t\tEntryPointSymbol=\"mainCRTStartup\"\n"
+ "\t\t\t\tTargetMachine=\"1\"\n"
+ "\t\t\t/>\n",
+ buffer);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs200x_project_tests.cpp b/src/actions/vs200x/tests/vs200x_project_tests.cpp
new file mode 100644
index 0000000..ff14eb9
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_project_tests.cpp
@@ -0,0 +1,467 @@
+/**
+ * \file vs200x_project_tests.cpp
+ * \brief Automated tests for Visual Studio project processing.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x_project.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Encoding tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_Encoding)
+ {
+ vs200x_project_encoding(sess, prj, strm);
+ CHECK_EQUAL(
+ "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Project element tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VsProject_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_element(sess, prj, strm);
+ CHECK_EQUAL(
+ "<VisualStudioProject\n"
+ "\tProjectType=\"Visual C++\"\n"
+ "\tVersion=\"7.00\"\n"
+ "\tName=\"MyProject\"\n"
+ "\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
+ "\tKeyword=\"Win32Proj\">\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsProject_OnVs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_project_element(sess, prj, strm);
+ CHECK_EQUAL(
+ "<VisualStudioProject\n"
+ "\tProjectType=\"Visual C++\"\n"
+ "\tVersion=\"7.10\"\n"
+ "\tName=\"MyProject\"\n"
+ "\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
+ "\tKeyword=\"Win32Proj\">\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsProject_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_project_element(sess, prj, strm);
+ CHECK_EQUAL(
+ "<VisualStudioProject\n"
+ "\tProjectType=\"Visual C++\"\n"
+ "\tVersion=\"8.00\"\n"
+ "\tName=\"MyProject\"\n"
+ "\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
+ "\tRootNamespace=\"MyProject\"\n"
+ "\tKeyword=\"Win32Proj\"\n"
+ "\t>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsProject_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_project_element(sess, prj, strm);
+ CHECK_EQUAL(
+ "<VisualStudioProject\n"
+ "\tProjectType=\"Visual C++\"\n"
+ "\tVersion=\"9.00\"\n"
+ "\tName=\"MyProject\"\n"
+ "\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
+ "\tRootNamespace=\"MyProject\"\n"
+ "\tKeyword=\"Win32Proj\"\n"
+ "\tTargetFrameworkVersion=\"196613\"\n"
+ "\t>\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Platforms tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_Platforms)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_platforms(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Platforms>\n"
+ "\t\t<Platform\n"
+ "\t\t\tName=\"Win32\"/>\n"
+ "\t</Platforms>\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Tool files tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VsToolFiles_Defaults_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_tool_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Configurations>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsToolFiles_Defaults_OnVs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_project_tool_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Configurations>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsToolFiles_Defaults_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_project_tool_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<ToolFiles>\n"
+ "\t</ToolFiles>\n"
+ "\t<Configurations>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsToolFiles_Defaults_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_project_tool_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<ToolFiles>\n"
+ "\t</ToolFiles>\n"
+ "\t<Configurations>\n",
+ buffer);
+ }
+
+
+
+ /**********************************************************************
+ * Configuration element tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_Configuration)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_config_element(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t<Configuration\n"
+ "\t\t\tName=\"Debug|Win32\"\n"
+ "\t\t\tOutputDirectory=\"$(SolutionDir)$(ConfigurationName)\"\n"
+ "\t\t\tIntermediateDirectory=\"$(ConfigurationName)\"\n"
+ "\t\t\tConfigurationType=\"1\"\n"
+ "\t\t\tCharacterSet=\"2\">\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Tool element tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_VCALinkTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_alink_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCALinkTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCAppVerifierTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_app_verifier_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCAppVerifierTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCBscMakeTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_bsc_make_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCBscMakeTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCCustomBuildTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_custom_build_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCCustomBuildTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCFxCopTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_fx_cop_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCFxCopTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCManagedResourceCompilerTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_managed_resource_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCManagedResourceCompilerTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCManifestTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_manifest_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCManifestTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCMIDLTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_midl_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCMIDLTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCPreBuildEventTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_pre_build_event_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCPreBuildEventTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCPreLinkEventTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_pre_link_event_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCPreLinkEventTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCPostBuildEventTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_post_build_event_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCPostBuildEventTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCResourceCompilerTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_resource_compiler_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCResourceCompilerTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCWebDeploymentTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_web_deployment_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCWebDeploymentTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCWebServiceProxyGeneratorTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_web_service_proxy_generator_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCXDCMakeTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_xdc_make_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCXDCMakeTool\"/>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_VCXMLDataGeneratorTool)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_vc_xml_data_generator_tool(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t\t\t<Tool\n"
+ "\t\t\t\tName=\"VCXMLDataGeneratorTool\"/>\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * References section tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, VsReferences_Defaults_OnVs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_references(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t</Configurations>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsReferences_Defaults_OnVs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_project_references(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t</Configurations>\n"
+ "\t<References>\n"
+ "\t</References>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsReferences_Defaults_OnVs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_project_references(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t</Configurations>\n"
+ "\t<References>\n"
+ "\t</References>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, VsReferences_Defaults_OnVs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_project_references(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t</Configurations>\n"
+ "\t<References>\n"
+ "\t</References>\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Files section tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_Files_OnNoFiles)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Files>\n"
+ "\t</Files>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_Files_OnSingleCppFile)
+ {
+ session_set_action(sess, "vs2002");
+ char* values[] = { "Hello.cpp", 0 };
+ SetField(prj, ProjectFiles, values);
+ vs200x_project_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Files>\n"
+ "\t\t<File\n"
+ "\t\t\tRelativePath=\".\\Hello.cpp\">\n"
+ "\t\t</File>\n"
+ "\t</Files>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_Files_OnUpperDirectory)
+ {
+ session_set_action(sess, "vs2002");
+ char* values[] = { "../../Hello.cpp", 0 };
+ SetField(prj, ProjectFiles, values);
+ vs200x_project_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Files>\n"
+ "\t\t<File\n"
+ "\t\t\tRelativePath=\"..\\..\\Hello.cpp\">\n"
+ "\t\t</File>\n"
+ "\t</Files>\n",
+ buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Vs200x_Files_OnGroupedCppFile)
+ {
+ session_set_action(sess, "vs2002");
+ char* values[] = { "Src/Hello.cpp", 0 };
+ SetField(prj, ProjectFiles, values);
+ vs200x_project_files(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Files>\n"
+ "\t\t<Filter\n"
+ "\t\t\tName=\"Src\"\n"
+ "\t\t\tFilter=\"\">\n"
+ "\t\t\t<File\n"
+ "\t\t\t\tRelativePath=\".\\Src\\Hello.cpp\">\n"
+ "\t\t\t</File>\n"
+ "\t\t</Filter>\n"
+ "\t</Files>\n",
+ buffer);
+ }
+
+
+ /**********************************************************************
+ * Globals section tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Vs200x_Globals)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_project_globals(sess, prj, strm);
+ CHECK_EQUAL(
+ "\t<Globals>\n"
+ "\t</Globals>\n"
+ "</VisualStudioProject>\n",
+ buffer);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs200x_tests.cpp b/src/actions/vs200x/tests/vs200x_tests.cpp
new file mode 100644
index 0000000..a41a071
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_tests.cpp
@@ -0,0 +1,56 @@
+/**
+ * \file vs200x_tests.cpp
+ * \brief Automated tests for VS200x support functions.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Language GUID tests
+ **********************************************************************/
+
+ TEST(ToolGuid_ReturnsCorrectGUID_OnC)
+ {
+ const char* result = vs200x_tool_guid("c");
+ CHECK_EQUAL("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942", result);
+ }
+
+ TEST(ToolGuid_ReturnsCorrectGUID_OnCpp)
+ {
+ const char* result = vs200x_tool_guid("c++");
+ CHECK_EQUAL("8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942", result);
+ }
+
+ TEST(ToolGuid_ReturnsCorrectGUID_OnCSharp)
+ {
+ const char* result = vs200x_tool_guid("c#");
+ CHECK_EQUAL("FAE04EC0-301F-11D3-BF4B-00C04F79EFBC", result);
+ }
+
+
+ /**********************************************************************
+ * Language file extensions
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, ProjectExtension_IsVcproj_ForC)
+ {
+ project_set_language(prj, "c");
+ const char* result = vs200x_project_file_extension(prj);
+ CHECK_EQUAL(".vcproj", result);
+ }
+
+ TEST_FIXTURE(FxAction, ProjectExtension_IsVcproj_ForCpp)
+ {
+ project_set_language(prj, "c++");
+ const char* result = vs200x_project_file_extension(prj);
+ CHECK_EQUAL(".vcproj", result);
+ }
+}
diff --git a/src/actions/vs200x/tests/vs200x_xml_tests.cpp b/src/actions/vs200x/tests/vs200x_xml_tests.cpp
new file mode 100644
index 0000000..9616b99
--- /dev/null
+++ b/src/actions/vs200x/tests/vs200x_xml_tests.cpp
@@ -0,0 +1,120 @@
+/**
+ * \file vs200x_xml_tests.cpp
+ * \brief Automated tests for Visual Studio XML output functions.
+ * \author Copyright (c) 2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "actions/tests/action_tests.h"
+extern "C" {
+#include "actions/vs200x/vs200x.h"
+}
+
+
+SUITE(action)
+{
+ /**********************************************************************
+ * Element end tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, ElementEnd_SlashBracket_Vs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_element_end(sess, strm, 0, "/>");
+ CHECK_EQUAL("/>\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_SlashBracket_Vs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_element_end(sess, strm, 0, "/>");
+ CHECK_EQUAL("/>\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_SlashBracket_Vs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_element_end(sess, strm, 0, "/>");
+ CHECK_EQUAL("\n/>\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_SlashBracket_Vs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_element_end(sess, strm, 0, "/>");
+ CHECK_EQUAL("\n/>\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_Bracket_Vs2002)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_element_end(sess, strm, 0, ">");
+ CHECK_EQUAL(">\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_Bracket_Vs2003)
+ {
+ session_set_action(sess, "vs2003");
+ vs200x_element_end(sess, strm, 0, ">");
+ CHECK_EQUAL(">\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_Bracket_Vs2005)
+ {
+ session_set_action(sess, "vs2005");
+ vs200x_element_end(sess, strm, 0, ">");
+ CHECK_EQUAL("\n\t>\n", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, ElementEnd_Bracket_Vs2008)
+ {
+ session_set_action(sess, "vs2008");
+ vs200x_element_end(sess, strm, 0, ">");
+ CHECK_EQUAL("\n\t>\n", buffer);
+ }
+
+
+ /**********************************************************************
+ * Attribute tests
+ **********************************************************************/
+
+ TEST_FIXTURE(FxAction, Attribute_OnLevel0)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_attribute(strm, 0, "ProjectType", "Visual C++");
+ CHECK_EQUAL("\nProjectType=\"Visual C++\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Attribute_OnLevel3)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_attribute(strm, 3, "ProjectType", "Visual C++");
+ CHECK_EQUAL("\n\t\t\tProjectType=\"Visual C++\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, Attribute_IsEscaped)
+ {
+ session_set_action(sess, "vs2002");
+ vs200x_attribute(strm, 1, "PreprocessorSymbols", "DEBUG;MSG=\"Hello\";TRACE");
+ CHECK_EQUAL("\n\tPreprocessorSymbols=\"DEBUG;MSG=&quot;Hello&quot;;TRACE\"", buffer);
+ }
+
+ TEST_FIXTURE(FxAction, AttributeList_OnLevel0)
+ {
+ const char* values[] = { "VALUE0", "VALUE1", "VALUE2", NULL };
+ Strings strs = strings_create_from_array(values);
+ vs200x_list_attribute(strm, 0, "Values", strs);
+ CHECK_EQUAL("\nValues=\"VALUE0;VALUE1;VALUE2\"", buffer);
+ strings_destroy(strs);
+ }
+
+ TEST_FIXTURE(FxAction, AttributeList_IsEscaped)
+ {
+ const char* values[] = { "VALUE0", "VALUE1=\"Hello\"", "VALUE2", NULL };
+ Strings strs = strings_create_from_array(values);
+ vs200x_list_attribute(strm, 0, "Values", strs);
+ CHECK_EQUAL("\nValues=\"VALUE0;VALUE1=&quot;Hello&quot;;VALUE2\"", buffer);
+ strings_destroy(strs);
+ }
+
+}
diff --git a/src/actions/vs200x/vs2002.c b/src/actions/vs200x/vs2002.c
new file mode 100644
index 0000000..8abc23b
--- /dev/null
+++ b/src/actions/vs200x/vs2002.c
@@ -0,0 +1,85 @@
+/**
+ * \file vs2002.c
+ * \brief Visual Studio 2002 project file generation action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/actions.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+#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[] =
+{
+ vs200x_solution_create,
+ vs2002_solution_signature,
+ vs2002_solution_projects,
+ vs2002_solution_configuration,
+ vs2002_solution_dependencies,
+ vs2002_solution_project_configuration,
+ vs2002_solution_extensibility,
+ NULL
+};
+
+/** The VS2002 project writing process, for session_enumerate_objects() */
+static SessionProjectCallback ProjectCallbacks[] =
+{
+ vs200x_project_create,
+ vs200x_project_encoding,
+ vs200x_project_element,
+ vs200x_project_platforms,
+ vs200x_project_tool_files,
+ session_enumerate_configurations,
+ vs200x_project_references,
+ vs200x_project_files,
+ vs200x_project_globals,
+ NULL
+};
+
+/** The VS2002 configuration writing process, for session_enumerate_configurations() */
+static SessionProjectCallback ConfigCallbacks[] =
+{
+ vs200x_project_config_element,
+ vs200x_project_vc_cl_compiler_tool,
+ vs200x_project_vc_custom_build_tool,
+ vs200x_project_vc_linker_tool,
+ vs200x_project_vc_midl_tool,
+ vs200x_project_vc_post_build_event_tool,
+ vs200x_project_vc_pre_build_event_tool,
+ vs200x_project_vc_pre_link_event_tool,
+ vs200x_project_vc_resource_compiler_tool,
+ vs200x_project_vc_web_service_proxy_generator_tool,
+ vs200x_project_vc_web_deployment_tool,
+ vs200x_project_config_end,
+ NULL
+};
+
+
+/**
+ * The Visual Studio 2002 action handler.
+ * \param sess The active session object.
+ * \returns OKAY if successful.
+ */
+int vs2002_action(Session sess)
+{
+ /* make sure I can support all of the features used in the session */
+ if (session_validate(sess, &Features) != OKAY)
+ {
+ return !OKAY;
+ }
+
+ stream_writeline(Console, "Generating project files for Visual Studio 2002...");
+ return session_enumerate_objects(sess, SolutionCallbacks, ProjectCallbacks, ConfigCallbacks);
+}
+
diff --git a/src/actions/vs200x/vs2002_solution.c b/src/actions/vs200x/vs2002_solution.c
new file mode 100644
index 0000000..7274eb7
--- /dev/null
+++ b/src/actions/vs200x/vs2002_solution.c
@@ -0,0 +1,169 @@
+/**
+ * \file vs2002_solution.c
+ * \brief Visual Studio 2002 solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+#include "vs200x_project.h"
+#include "base/path.h"
+
+
+/**
+ * Create the Visual Studio 2002 solution configuration block.
+ * \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 vs2002_solution_configuration(Session sess, Solution sln, Stream strm)
+{
+ int i, n, z;
+ UNUSED(sess);
+
+ z = stream_writeline(strm, "Global");
+ z |= stream_writeline(strm, "\tGlobalSection(SolutionConfiguration) = preSolution");
+
+ n = solution_num_configs(sln);
+ for (i = 0; i < n; ++i)
+ {
+ const char* config_name = solution_get_config(sln, i);
+ z |= stream_writeline(strm, "\t\tConfigName.%d = %s", i, config_name);
+ }
+
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * Create the Visual Studio 2002 project dependencies block.
+ * \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 vs2002_solution_dependencies(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ z = stream_writeline(strm, "\tGlobalSection(ProjectDependencies) = postSolution");
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * Write out the Visual Studio 2002 solution extensibility block.
+ * \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 vs2002_solution_extensibility(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ z = stream_writeline(strm, "\tGlobalSection(ExtensibilityGlobals) = postSolution");
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ z |= stream_writeline(strm, "\tGlobalSection(ExtensibilityAddIns) = postSolution");
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ z |= stream_writeline(strm, "EndGlobal");
+ return z;
+}
+
+
+/**
+ * Write out the Visual Studio 2002 project configurations block.
+ * \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 vs2002_solution_project_configuration(Session sess, Solution sln, Stream strm)
+{
+ int pi, pn, z;
+ UNUSED(sess);
+ z = stream_writeline(strm, "\tGlobalSection(ProjectConfiguration) = postSolution");
+ pn = solution_num_projects(sln);
+ for (pi = 0; pi < pn; ++pi)
+ {
+ int ci, cn;
+ Project prj = solution_get_project(sln, pi);
+ const char* prj_id = project_get_guid(prj);
+
+ cn = solution_num_configs(sln);
+ for (ci = 0; ci < cn; ++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);
+ }
+ }
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * 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 vs2002_solution_projects(Session sess, Solution sln, Stream strm)
+{
+ const char* sln_path;
+ int i, n, z = OKAY;
+
+ UNUSED(sess);
+
+ /* 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_lang = project_get_language(prj);
+ const char* prj_ext = vs200x_project_file_extension(prj);
+ const char* prj_file = project_get_filename(prj, prj_name, prj_ext);
+ const char* tool_id = vs200x_tool_guid(prj_lang);
+
+ /* convert absolute project file name to be relative to solution */
+ prj_file = path_relative(sln_path, prj_file);
+ prj_file = path_translate(prj_file, "\\");
+
+ z |= stream_writeline(strm, "Project(\"{%s}\") = \"%s\", \"%s\", \"{%s}\"", tool_id, prj_name, prj_file, prj_id);
+ z |= stream_writeline(strm, "EndProject");
+ }
+
+ return z;
+}
+
+
+/**
+ * Write the Visual Studio 2002 solution file signature.
+ * \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 vs2002_solution_signature(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ stream_set_newline(strm, "\r\n");
+ z = stream_writeline(strm, "Microsoft Visual Studio Solution File, Format Version 7.00");
+ return z;
+}
diff --git a/src/actions/vs200x/vs2003.c b/src/actions/vs200x/vs2003.c
new file mode 100644
index 0000000..db83666
--- /dev/null
+++ b/src/actions/vs200x/vs2003.c
@@ -0,0 +1,84 @@
+/**
+ * \file vs2003.c
+ * \brief Visual Studio 2003 project file generation action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/actions.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+#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[] =
+{
+ vs200x_solution_create,
+ vs2003_solution_signature,
+ vs2002_solution_projects,
+ vs2003_solution_configuration,
+ vs2002_solution_project_configuration,
+ vs2002_solution_extensibility,
+ NULL
+};
+
+/** The VS2003 project writing process, for session_enumerate_objects() */
+static SessionProjectCallback ProjectCallbacks[] =
+{
+ vs200x_project_create,
+ vs200x_project_encoding,
+ vs200x_project_element,
+ vs200x_project_platforms,
+ vs200x_project_tool_files,
+ session_enumerate_configurations,
+ vs200x_project_references,
+ vs200x_project_files,
+ vs200x_project_globals,
+ NULL
+};
+
+/** The VS2003 configuration writing process, for session_enumerate_configurations() */
+static SessionProjectCallback ConfigCallbacks[] =
+{
+ vs200x_project_config_element,
+ vs200x_project_vc_cl_compiler_tool,
+ vs200x_project_vc_custom_build_tool,
+ vs200x_project_vc_linker_tool,
+ vs200x_project_vc_midl_tool,
+ vs200x_project_vc_post_build_event_tool,
+ vs200x_project_vc_pre_build_event_tool,
+ vs200x_project_vc_pre_link_event_tool,
+ vs200x_project_vc_resource_compiler_tool,
+ vs200x_project_vc_web_service_proxy_generator_tool,
+ vs200x_project_vc_xml_data_generator_tool,
+ vs200x_project_vc_web_deployment_tool,
+ vs200x_project_config_end,
+ NULL
+};
+
+
+/**
+ * The Visual Studio 2003 action handler.
+ * \param sess The active session object.
+ * \returns OKAY if successful.
+ */
+int vs2003_action(Session sess)
+{
+ /* make sure I can support all of the features used in the session */
+ if (session_validate(sess, &Features) != OKAY)
+ {
+ return !OKAY;
+ }
+
+ stream_writeline(Console, "Generating project files for Visual Studio 2003...");
+ return session_enumerate_objects(sess, SolutionCallbacks, ProjectCallbacks, ConfigCallbacks);
+}
diff --git a/src/actions/vs200x/vs2003_solution.c b/src/actions/vs200x/vs2003_solution.c
new file mode 100644
index 0000000..1c1517c
--- /dev/null
+++ b/src/actions/vs200x/vs2003_solution.c
@@ -0,0 +1,55 @@
+/**
+ * \file vs2003_solution.c
+ * \brief Visual Studio 2003 solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "vs200x_solution.h"
+
+
+/**
+ * Create the Visual Studio 2003 solution configuration block.
+ * \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 vs2003_solution_configuration(Session sess, Solution sln, Stream strm)
+{
+ int i, n, z;
+ UNUSED(sess);
+
+ z = stream_writeline(strm, "Global");
+ z |= stream_writeline(strm, "\tGlobalSection(SolutionConfiguration) = preSolution");
+
+ n = solution_num_configs(sln);
+ for (i = 0; i < n; ++i)
+ {
+ const char* config_name = solution_get_config(sln, i);
+ z |= stream_writeline(strm, "\t\t%s = %s", config_name, config_name);
+ }
+
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * Write the Visual Studio 2003 solution file signature.
+ * \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 vs2003_solution_signature(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ stream_set_newline(strm, "\r\n");
+ z = stream_writeline(strm, "Microsoft Visual Studio Solution File, Format Version 8.00");
+ return z;
+}
diff --git a/src/actions/vs200x/vs2005.c b/src/actions/vs200x/vs2005.c
new file mode 100644
index 0000000..47e835c
--- /dev/null
+++ b/src/actions/vs200x/vs2005.c
@@ -0,0 +1,92 @@
+/**
+ * \file vs2005.c
+ * \brief Visual Studio 2005 project file generation action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/actions.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+#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[] =
+{
+ vs200x_solution_create,
+ vs2005_solution_signature,
+ vs2002_solution_projects,
+ vs2005_solution_platforms,
+ vs2005_solution_project_platforms,
+ vs2005_solution_properties,
+ NULL
+};
+
+/** The VS2005 project writing process, for session_enumerate_objects() */
+static SessionProjectCallback ProjectCallbacks[] =
+{
+ vs200x_project_create,
+ vs200x_project_encoding,
+ vs200x_project_element,
+ vs200x_project_platforms,
+ vs200x_project_tool_files,
+ session_enumerate_configurations,
+ vs200x_project_references,
+ vs200x_project_files,
+ vs200x_project_globals,
+ NULL
+};
+
+/** The VS2005 configuration writing process, for session_enumerate_configurations() */
+static SessionProjectCallback ConfigCallbacks[] =
+{
+ vs200x_project_config_element,
+ vs200x_project_vc_pre_build_event_tool,
+ vs200x_project_vc_custom_build_tool,
+ vs200x_project_vc_xml_data_generator_tool,
+ vs200x_project_vc_web_service_proxy_generator_tool,
+ vs200x_project_vc_midl_tool,
+ vs200x_project_vc_cl_compiler_tool,
+ vs200x_project_vc_managed_resource_compiler_tool,
+ vs200x_project_vc_resource_compiler_tool,
+ vs200x_project_vc_pre_link_event_tool,
+ vs200x_project_vc_linker_tool,
+ vs200x_project_vc_alink_tool,
+ vs200x_project_vc_manifest_tool,
+ vs200x_project_vc_xdc_make_tool,
+ vs200x_project_vc_bsc_make_tool,
+ vs200x_project_vc_fx_cop_tool,
+ vs200x_project_vc_app_verifier_tool,
+ vs200x_project_vc_web_deployment_tool,
+ vs200x_project_vc_post_build_event_tool,
+ vs200x_project_config_end,
+ NULL
+};
+
+
+/**
+ * The Visual Studio 2005 action handler.
+ * \param sess The active session object.
+ * \returns OKAY if successful.
+ */
+int vs2005_action(Session sess)
+{
+ /* make sure I can support all of the features used in the session */
+ if (session_validate(sess, &Features) != OKAY)
+ {
+ return !OKAY;
+ }
+
+ stream_writeline(Console, "Generating project files for Visual Studio 2005...");
+ return session_enumerate_objects(sess, SolutionCallbacks, ProjectCallbacks, ConfigCallbacks);
+}
+
diff --git a/src/actions/vs200x/vs2005_solution.c b/src/actions/vs200x/vs2005_solution.c
new file mode 100644
index 0000000..6f589ea
--- /dev/null
+++ b/src/actions/vs200x/vs2005_solution.c
@@ -0,0 +1,110 @@
+/**
+ * \file vs2005_solution.c
+ * \brief Visual Studio 2005 solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "vs200x_solution.h"
+
+
+/**
+ * Write out the Visual Studio solution-level platform configuration block.
+ * \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 vs2005_solution_platforms(Session sess, Solution sln, Stream strm)
+{
+ int i, n, z;
+ UNUSED(sess);
+
+ z = stream_writeline(strm, "Global");
+ z |= stream_writeline(strm, "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution");
+
+ n = solution_num_configs(sln);
+ for (i = 0; i < n; ++i)
+ {
+ const char* config_name = solution_get_config(sln, i);
+ z |= stream_writeline(strm, "\t\t%s|Win32 = %s|Win32", config_name, config_name);
+ }
+
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * Write out the Visual Studio 2005 project-level platform configurations block.
+ * \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 vs2005_solution_project_platforms(Session sess, Solution sln, Stream strm)
+{
+ int pi, pn, z;
+ UNUSED(sess);
+ z = stream_writeline(strm, "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution");
+ pn = solution_num_projects(sln);
+ for (pi = 0; pi < pn; ++pi)
+ {
+ int ci, cn;
+ Project prj = solution_get_project(sln, pi);
+ const char* prj_id = project_get_guid(prj);
+
+ cn = solution_num_configs(sln);
+ for (ci = 0; ci < cn; ++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);
+ }
+ }
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ return z;
+}
+
+
+/**
+ * Write out the Visual Studio 2005 solution properties block.
+ * \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 vs2005_solution_properties(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ z = stream_writeline(strm, "\tGlobalSection(SolutionProperties) = preSolution");
+ z |= stream_writeline(strm, "\t\tHideSolutionNode = FALSE");
+ z |= stream_writeline(strm, "\tEndGlobalSection");
+ z |= stream_writeline(strm, "EndGlobal");
+ return z;
+}
+
+
+/**
+ * Write the Visual Studio 2005 solution file signature.
+ * \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 vs2005_solution_signature(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ stream_set_newline(strm, "\r\n");
+ z = stream_write_unicode_marker(strm);
+ z |= stream_writeline(strm, "");
+ z |= stream_writeline(strm, "Microsoft Visual Studio Solution File, Format Version 9.00");
+ z |= stream_writeline(strm, "# Visual Studio 2005");
+ return z;
+}
diff --git a/src/actions/vs200x/vs2008.c b/src/actions/vs200x/vs2008.c
new file mode 100644
index 0000000..9af42ad
--- /dev/null
+++ b/src/actions/vs200x/vs2008.c
@@ -0,0 +1,91 @@
+/**
+ * \file vs2008.c
+ * \brief Visual Studio 2008 project file generation action.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "actions/actions.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+#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[] =
+{
+ vs200x_solution_create,
+ vs2008_solution_signature,
+ vs2002_solution_projects,
+ vs2005_solution_platforms,
+ vs2005_solution_project_platforms,
+ vs2005_solution_properties,
+ NULL
+};
+
+/** The VS2008 project writing process, for session_enumerate_objects() */
+static SessionProjectCallback ProjectCallbacks[] =
+{
+ vs200x_project_create,
+ vs200x_project_encoding,
+ vs200x_project_element,
+ vs200x_project_platforms,
+ vs200x_project_tool_files,
+ session_enumerate_configurations,
+ vs200x_project_references,
+ vs200x_project_files,
+ vs200x_project_globals,
+ NULL
+};
+
+/** The VS2008 configuration writing process, for session_enumerate_configurations() */
+static SessionProjectCallback ConfigCallbacks[] =
+{
+ vs200x_project_config_element,
+ vs200x_project_vc_pre_build_event_tool,
+ vs200x_project_vc_custom_build_tool,
+ vs200x_project_vc_xml_data_generator_tool,
+ vs200x_project_vc_web_service_proxy_generator_tool,
+ vs200x_project_vc_midl_tool,
+ vs200x_project_vc_cl_compiler_tool,
+ vs200x_project_vc_managed_resource_compiler_tool,
+ vs200x_project_vc_resource_compiler_tool,
+ vs200x_project_vc_pre_link_event_tool,
+ vs200x_project_vc_linker_tool,
+ vs200x_project_vc_alink_tool,
+ vs200x_project_vc_manifest_tool,
+ vs200x_project_vc_xdc_make_tool,
+ vs200x_project_vc_bsc_make_tool,
+ vs200x_project_vc_fx_cop_tool,
+ vs200x_project_vc_app_verifier_tool,
+ vs200x_project_vc_post_build_event_tool,
+ vs200x_project_config_end,
+ NULL
+};
+
+
+/**
+ * The Visual Studio 2008 action handler.
+ * \param sess The active session object.
+ * \returns OKAY if successful.
+ */
+int vs2008_action(Session sess)
+{
+ /* make sure I can support all of the features used in the session */
+ if (session_validate(sess, &Features) != OKAY)
+ {
+ return !OKAY;
+ }
+
+ stream_writeline(Console, "Generating project files for Visual Studio 2008...");
+ return session_enumerate_objects(sess, SolutionCallbacks, ProjectCallbacks, ConfigCallbacks);
+}
+
diff --git a/src/actions/vs200x/vs2008_solution.c b/src/actions/vs200x/vs2008_solution.c
new file mode 100644
index 0000000..856bd51
--- /dev/null
+++ b/src/actions/vs200x/vs2008_solution.c
@@ -0,0 +1,29 @@
+/**
+ * \file vs2008_solution.c
+ * \brief Visual Studio 2008 solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "vs200x_solution.h"
+
+
+/**
+ * Write the Visual Studio 2008 solution file signature.
+ * \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 vs2008_solution_signature(Session sess, Solution sln, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(sln);
+ stream_set_newline(strm, "\r\n");
+ z = stream_write_unicode_marker(strm);
+ z |= stream_writeline(strm, "");
+ z |= stream_writeline(strm, "Microsoft Visual Studio Solution File, Format Version 10.00");
+ z |= stream_writeline(strm, "# Visual Studio 2008");
+ return z;
+}
diff --git a/src/actions/vs200x/vs200x.c b/src/actions/vs200x/vs200x.c
new file mode 100644
index 0000000..91b4cfb
--- /dev/null
+++ b/src/actions/vs200x/vs200x.c
@@ -0,0 +1,190 @@
+/**
+ * \file vs200x.c
+ * \brief General purpose Visual Studio support functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "premake.h"
+#include "vs200x.h"
+#include "base/buffers.h"
+#include "base/cstr.h"
+#include "base/error.h"
+
+
+/**
+ * Write an XML attribute, adjusting for the differing Visual Studio formats.
+ * \param strm The output stream, the attribute will be written here.
+ * \param indent_size How far to indent (with tabs) the attribute.
+ * \param name The attribute name.
+ * \param value The attribute value; may contain printf-style formatting codes.
+ * \returns OKAY if successful.
+ */
+int vs200x_attribute(Stream strm, int indent_size, const char* name, const char* value, ...)
+{
+ va_list args;
+ char* buffer;
+ int z = OKAY;
+
+ z |= stream_writeline(strm, "");
+ z |= stream_write_n(strm, "\t", indent_size);
+ z |= stream_write(strm, "%s=\"", name);
+
+ buffer = buffers_next();
+ va_start(args, value);
+ vsprintf(buffer, value, args);
+ z |= stream_write_escaped(strm, buffer);
+ va_end(args);
+
+ z |= stream_write(strm, "\"");
+ return z;
+}
+
+
+/**
+ * Write an XML attribute containing a list of values, adjusting for the differing Visual Studio formats.
+ * \param strm The output stream, the attribute will be written here.
+ * \param indent_size How far to indent (with tabs) the attribute.
+ * \param name The attribute name.
+ * \param values The attribute list value.
+ * \returns OKAY if successful.
+ */
+int vs200x_list_attribute(Stream strm, int indent_size, const char* name, Strings values)
+{
+ int z = OKAY;
+
+ z |= stream_writeline(strm, "");
+ z |= stream_write_n(strm, "\t", indent_size);
+ z |= stream_write(strm, "%s=", name);
+ z |= stream_write_strings(strm, values, "\"", "", "", ";", "\"", stream_write_escaped);
+ return z;
+}
+
+
+/**
+ * Write the ending part of an XML tag, adjust for the differing Visual Studio formats.
+ * \param sess The current execution session.
+ * \param strm The output stream.
+ * \param level The XML element nesting level.
+ * \param markup The end tag markup.
+ * \returns OKAY if successful.
+ */
+int vs200x_element_end(Session sess, Stream strm, int level, const char* markup)
+{
+ int z;
+ int version = vs200x_get_target_version(sess);
+ if (version >= 2005)
+ {
+ z = stream_writeline(strm, "");
+ if (markup[0] == '>')
+ {
+ level++;
+ }
+ z |= stream_write_n(strm, "\t", level);
+ z |= stream_writeline(strm, "%s", markup);
+ }
+ else
+ {
+ z = stream_writeline(strm, markup);
+ }
+ return z;
+}
+
+
+/**
+ * Return the Visual Studio version appropriate version of the string for a false
+ * value. Before 2005 this was "FALSE", after it is "false".
+ */
+const char* vs200x_false(Session sess)
+{
+ int version = vs200x_get_target_version(sess);
+ return (version < 2005) ? "FALSE" : "false";
+}
+
+
+/**
+ * Converts the session action string to a Visual Studio version number.
+ * \param sess The current execution session.
+ * \returns The Visual Studio version number corresponding to the current action.
+ */
+int vs200x_get_target_version(Session sess)
+{
+ const char* action = session_get_action(sess);
+ if (cstr_eq(action, "vs2002"))
+ {
+ return 2002;
+ }
+ else if (cstr_eq(action, "vs2003"))
+ {
+ return 2003;
+ }
+ else if (cstr_eq(action, "vs2005"))
+ {
+ return 2005;
+ }
+ else if (cstr_eq(action, "vs2008"))
+ {
+ return 2008;
+ }
+ else
+ {
+ assert(0);
+ return 0;
+ }
+}
+
+
+/**
+ * Return the appropriate file extension for a particular project.
+ * \param prj The project object.
+ * \returns The appropriate project file extension, based on the project settings.
+ */
+const char* vs200x_project_file_extension(Project prj)
+{
+ const char* language = project_get_language(prj);
+ if (cstr_eq(language, "c") || cstr_eq(language, "c++"))
+ {
+ return ".vcproj";
+ }
+ else
+ {
+ error_set("unsupported language '%s'", language);
+ return NULL;
+ }
+}
+
+
+/**
+ * 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_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;
+ }
+}
+
+
+/**
+ * Return the Visual Studio version appropriate version of the string for a true
+ * value. Before 2005 this was "TRUE", after it is "true".
+ */
+const char* vs200x_true(Session sess)
+{
+ int version = vs200x_get_target_version(sess);
+ return (version < 2005) ? "TRUE" : "true";
+}
diff --git a/src/actions/vs200x/vs200x.h b/src/actions/vs200x/vs200x.h
new file mode 100644
index 0000000..b99c2f5
--- /dev/null
+++ b/src/actions/vs200x/vs200x.h
@@ -0,0 +1,21 @@
+/**
+ * \file vs200x.h
+ * \brief General purpose Visual Studio support functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_VS200X_H)
+#define PREMAKE_VS200X_H
+
+#include "session/session.h"
+
+int vs200x_attribute(Stream strm, int indent_size, const char* name, const char* value, ...);
+int vs200x_list_attribute(Stream strm, int indent_size, const char* name, Strings values);
+int vs200x_element_end(Session sess, Stream strm, int level, const char* markup);
+const char* vs200x_false(Session sess);
+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);
+
+#endif
+
diff --git a/src/actions/vs200x/vs200x_config.c b/src/actions/vs200x/vs200x_config.c
new file mode 100644
index 0000000..3e94305
--- /dev/null
+++ b/src/actions/vs200x/vs200x_config.c
@@ -0,0 +1,64 @@
+/**
+ * \file vs200x_config.c
+ * \brief Visual Studio 200x configuration generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include "premake.h"
+#include "vs200x.h"
+#include "vs200x_config.h"
+
+
+int vs200x_config_character_set(Session sess, Stream strm)
+{
+ int version = vs200x_get_target_version(sess);
+ return vs200x_attribute(strm, 3, "CharacterSet", version > 2003 ? "1" : "2");
+}
+
+
+/**
+ * Write out the list of preprocessor symbols as defined by the configuration.
+ * This entry is only written if there are values to write.
+ */
+int vs200x_config_defines(Session sess, Stream strm, Project prj)
+{
+ Strings values = project_get_config_values(prj, BlockDefines);
+ UNUSED(sess);
+ if (strings_size(values) > 0)
+ {
+ return vs200x_list_attribute(strm, 4, "PreprocessorDefinitions", values);
+ }
+ return OKAY;
+}
+
+
+int vs200x_config_detect_64bit_portability(Session sess, Stream strm, Project prj)
+{
+ int version = vs200x_get_target_version(sess);
+ UNUSED(prj);
+ if (version < 2008)
+ {
+ return vs200x_attribute(strm, 4, "Detect64BitPortabilityProblems", vs200x_true(sess));
+ }
+ return OKAY;
+}
+
+
+int vs200x_config_runtime_type_info(Session sess, Stream strm, Project prj)
+{
+ int version = vs200x_get_target_version(sess);
+ UNUSED(prj);
+ if (version < 2005)
+ {
+ return vs200x_attribute(strm, 4, "RuntimeTypeInfo", vs200x_true(sess));
+ }
+ return OKAY;
+}
+
+
+int vs200x_config_use_precompiled_header(Session sess, Stream strm, Project prj)
+{
+ int version = vs200x_get_target_version(sess);
+ UNUSED(prj);
+ return vs200x_attribute(strm, 4, "UsePrecompiledHeader", (version > 2003) ? "0" : "2");
+}
diff --git a/src/actions/vs200x/vs200x_config.h b/src/actions/vs200x/vs200x_config.h
new file mode 100644
index 0000000..53172e9
--- /dev/null
+++ b/src/actions/vs200x/vs200x_config.h
@@ -0,0 +1,17 @@
+/**
+ * \file vs200x_config.h
+ * \brief Visual Studio 200x configuration generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_VS200X_CONFIG_H)
+#define PREMAKE_VS200X_CONFIG_H
+
+#include "session/session.h"
+
+int vs200x_config_character_set(Session sess, Stream strm);
+int vs200x_config_defines(Session sess, Stream strm, Project prj);
+int vs200x_config_detect_64bit_portability(Session sess, Stream strm, Project prj);
+int vs200x_config_runtime_type_info(Session sess, Stream strm, Project prj);
+int vs200x_config_use_precompiled_header(Session sess, Stream strm, Project prj);
+
+#endif
diff --git a/src/actions/vs200x/vs200x_project.c b/src/actions/vs200x/vs200x_project.c
new file mode 100644
index 0000000..0c48255
--- /dev/null
+++ b/src/actions/vs200x/vs200x_project.c
@@ -0,0 +1,475 @@
+/**
+ * \file vs200x_project.c
+ * \brief Visual Studio multiple-version project generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "premake.h"
+#include "vs200x.h"
+#include "vs200x_project.h"
+#include "vs200x_config.h"
+#include "actions/support/sourcetree.h"
+#include "base/cstr.h"
+#include "base/path.h"
+
+
+/**
+ * Write the opening [Configuration] element and attributes.
+ */
+int vs200x_project_config_element(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ const char* cfg_name = project_get_configuration_filter(prj);
+ z |= stream_write(strm, "\t\t<Configuration");
+ z |= vs200x_attribute(strm, 3, "Name", "%s|Win32", cfg_name);
+ z |= vs200x_attribute(strm, 3, "OutputDirectory", "$(SolutionDir)$(ConfigurationName)");
+ z |= vs200x_attribute(strm, 3, "IntermediateDirectory", "$(ConfigurationName)");
+ z |= vs200x_attribute(strm, 3, "ConfigurationType", "1");
+ z |= vs200x_config_character_set(sess, strm);
+ z |= vs200x_element_end(sess, strm, 2, ">");
+ return z;
+}
+
+
+/**
+ * Write the closing [Configuration] element.
+ */
+int vs200x_project_config_end(Session sess, Project prj, Stream strm)
+{
+ UNUSED(sess);
+ UNUSED(prj);
+ return stream_writeline(strm, "\t\t</Configuration>");
+}
+
+
+/**
+ * Create a new output stream for a project, and make it active for subsequent writes.
+ */
+int vs200x_project_create(Session sess, Project prj, Stream strm)
+{
+ /* create the project file */
+ const char* extension = vs200x_project_file_extension(prj);
+ const char* filename = project_get_filename(prj, NULL, extension);
+ strm = stream_create_file(filename);
+ if (!strm)
+ {
+ return !OKAY;
+ }
+
+ /* make the stream active for the functions that come after */
+ session_set_active_stream(sess, strm);
+ return OKAY;
+}
+
+
+/**
+ * Write the root [VisualStudioProject] element and attributes.
+ */
+int vs200x_project_element(Session sess, Project prj, Stream strm)
+{
+ int version, z;
+ const char* prj_ver;
+ const char* prj_name = project_get_name(prj);
+ const char* prj_guid = project_get_guid(prj);
+
+ version = vs200x_get_target_version(sess);
+ switch (version)
+ {
+ default:
+ prj_ver = "7.00"; break;
+ case 2003:
+ prj_ver = "7.10"; break;
+ case 2005:
+ prj_ver = "8.00"; break;
+ case 2008:
+ prj_ver = "9.00"; break;
+ }
+
+ z = stream_write(strm, "<VisualStudioProject");
+ z |= vs200x_attribute(strm, 1, "ProjectType", "Visual C++");
+ z |= vs200x_attribute(strm, 1, "Version", prj_ver);
+ z |= vs200x_attribute(strm, 1, "Name", prj_name);
+ z |= vs200x_attribute(strm, 1, "ProjectGUID", "{%s}", prj_guid);
+ if (version > 2003)
+ {
+ z |= vs200x_attribute(strm, 1, "RootNamespace", prj_name);
+ }
+ z |= vs200x_attribute(strm, 1, "Keyword", "Win32Proj");
+ if (version > 2005)
+ {
+ z |= vs200x_attribute(strm, 1, "TargetFrameworkVersion", "196613");
+ }
+ z |= vs200x_element_end(sess, strm, 0, ">");
+ return z;
+}
+
+
+/**
+ * Write the file encoding at the start of the project file.
+ */
+int vs200x_project_encoding(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(sess);
+ UNUSED(prj);
+
+ stream_set_newline(strm, "\r\n");
+ z = stream_writeline(strm, "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>");
+ return z;
+}
+
+
+/**
+ * Write an individual file entry to the project file; callback for sourcetree_walk().
+ * \param sess The current execution session context.
+ * \param prj The current project; contains the file being enumerated.
+ * \param strm The active output stream; for writing the file markup.
+ * \param filename The name of the file to process.
+ * \param state One of the ActionSourceStates, enabling file grouping.
+ * \returns OKAY if successful.
+ */
+int vs200x_project_file(Session sess, Project prj, Stream strm, const char* filename, int state)
+{
+ const char* name;
+ const char* ptr;
+ int depth, z = OKAY;
+
+ /* figure out the grouping depth, skipping over any leading dot directories */
+ depth = 2;
+
+ ptr = filename;
+ while (cstr_starts_with(ptr, "../"))
+ {
+ ptr += 3;
+ }
+
+ ptr = strchr(ptr, '/');
+ while (ptr != NULL)
+ {
+ depth++;
+ ptr = strchr(ptr + 1, '/');
+ }
+
+ /* group name is just the last bit of the path */
+ name = path_filename(filename);
+
+ /* use the Windows path separator */
+ filename = path_translate(filename, "\\");
+
+ switch (state)
+ {
+ case GroupStart:
+ if (strlen(filename) > 0 && !cstr_eq(name, ".."))
+ {
+ z |= stream_write_n(strm, "\t", depth);
+ z |= stream_write(strm, "<Filter");
+ z |= vs200x_attribute(strm, depth + 1, "Name", name);
+ z |= vs200x_attribute(strm, depth + 1, "Filter", "");
+ z |= vs200x_element_end(sess, strm, depth, ">");
+ }
+ break;
+
+ case GroupEnd:
+ if (strlen(filename) > 0 && !cstr_eq(name, ".."))
+ {
+ z |= stream_write_n(strm, "\t", depth);
+ z |= stream_writeline(strm, "</Filter>");
+ }
+ break;
+
+ case SourceFile:
+ z |= stream_write_n(strm, "\t", depth);
+ z |= stream_write(strm, "<File");
+ ptr = (filename[0] == '.') ? "" : ".\\";
+ z |= vs200x_attribute(strm, depth + 1, "RelativePath", "%s%s", ptr, filename);
+ z |= vs200x_element_end(sess, strm, depth, ">");
+ z |= stream_write_n(strm, "\t", depth);
+ z |= stream_writeline(strm, "</File>");
+ break;
+ }
+
+ UNUSED(prj);
+ return z;
+}
+
+
+/**
+ * Write out the [Files] element.
+ */
+int vs200x_project_files(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ z |= stream_writeline(strm, "\t<Files>");
+ z |= sourcetree_walk(sess, prj, strm, vs200x_project_file);
+ z |= stream_writeline(strm, "\t</Files>");
+ return z;
+}
+
+
+/**
+ * Write out the [Globals] element.
+ */
+int vs200x_project_globals(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ UNUSED(sess);
+ UNUSED(prj);
+ z |= stream_writeline(strm, "\t<Globals>");
+ z |= stream_writeline(strm, "\t</Globals>");
+ z |= stream_writeline(strm, "</VisualStudioProject>");
+ return z;
+}
+
+
+/**
+ * Write out the platforms section of a project file.
+ */
+int vs200x_project_platforms(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ UNUSED(prj);
+ z |= stream_writeline(strm, "\t<Platforms>");
+ z |= stream_write(strm, "\t\t<Platform");
+ z |= vs200x_attribute(strm, 3, "Name", "Win32");
+ z |= vs200x_element_end(sess, strm, 2, "/>");
+ z |= stream_writeline(strm, "\t</Platforms>");
+ return OKAY;
+}
+
+
+/**
+ * Write out the [References] element and attributes.
+ */
+int vs200x_project_references(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(prj);
+ z = stream_writeline(strm, "\t</Configurations>");
+ if (vs200x_get_target_version(sess) > 2002)
+ {
+ z |= stream_writeline(strm, "\t<References>");
+ z |= stream_writeline(strm, "\t</References>");
+ }
+ return z;
+}
+
+
+/**
+ * Write out the [ToolFiles] section of a Visual Studio project.
+ */
+int vs200x_project_tool_files(Session sess, Project prj, Stream strm)
+{
+ int version, z = OKAY;
+ UNUSED(prj);
+
+ version = vs200x_get_target_version(sess);
+ if (version > 2003)
+ {
+ z |= stream_writeline(strm, "\t<ToolFiles>");
+ z |= stream_writeline(strm, "\t</ToolFiles>");
+ }
+ z |= stream_writeline(strm, "\t<Configurations>");
+ return z;
+}
+
+
+/**
+ * Common function to write an empty [Tool] element.
+ */
+static int vs200x_project_vc_empty_tool(Session sess, Project prj, Stream strm, const char* name)
+{
+ int z;
+ UNUSED(prj);
+ z = stream_write(strm, "\t\t\t<Tool");
+ z |= vs200x_attribute(strm, 4, "Name", name);
+ z |= vs200x_element_end(sess, strm, 3, "/>");
+ return z;
+}
+
+
+/**
+ * Write the VCALinkTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_alink_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCALinkTool");
+}
+
+
+/**
+ * Write the VCAppVerifierTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_app_verifier_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCAppVerifierTool");
+}
+
+
+/**
+ * Write the VCBscMakeTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_bsc_make_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCBscMakeTool");
+}
+
+
+/**
+ * Write the VCCLCompilerTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_cl_compiler_tool(Session sess, Project prj, Stream strm)
+{
+ int z = OKAY;
+ z |= stream_write(strm, "\t\t\t<Tool");
+ z |= vs200x_attribute(strm, 4, "Name", "VCCLCompilerTool");
+ z |= vs200x_attribute(strm, 4, "Optimization", "0");
+ z |= vs200x_config_defines(sess, strm, prj);
+ z |= vs200x_attribute(strm, 4, "MinimalRebuild", vs200x_true(sess));
+ z |= vs200x_attribute(strm, 4, "BasicRuntimeChecks", "3");
+ z |= vs200x_attribute(strm, 4, "RuntimeLibrary", "3");
+ z |= vs200x_config_runtime_type_info(sess, strm, prj);
+ z |= vs200x_config_use_precompiled_header(sess, strm, prj);
+ z |= vs200x_attribute(strm, 4, "WarningLevel", "3");
+ z |= vs200x_config_detect_64bit_portability(sess, strm, prj);
+ z |= vs200x_attribute(strm, 4, "DebugInformationFormat", "4");
+ z |= vs200x_element_end(sess, strm, 3, "/>");
+ return z;
+}
+
+
+/**
+ * Write the VCCustomBuildTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_custom_build_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCCustomBuildTool");
+}
+
+
+/**
+ * Write the VCFxCopTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_fx_cop_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCFxCopTool");
+}
+
+
+/**
+ * Write the VCLinkerTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_linker_tool(Session sess, Project prj, Stream strm)
+{
+ int z;
+ UNUSED(prj);
+ z = stream_write(strm, "\t\t\t<Tool");
+ z |= vs200x_attribute(strm, 4, "Name", "VCLinkerTool");
+ z |= vs200x_attribute(strm, 4, "LinkIncremental", "2");
+ z |= vs200x_attribute(strm, 4, "GenerateDebugInformation", vs200x_true(sess));
+ z |= vs200x_attribute(strm, 4, "SubSystem", "1");
+ z |= vs200x_attribute(strm, 4, "EntryPointSymbol", "mainCRTStartup");
+ z |= vs200x_attribute(strm, 4, "TargetMachine", "1");
+ z |= vs200x_element_end(sess, strm, 3, "/>");
+ return z;
+}
+
+
+/**
+ * Write the VCManagedResourceCompilerTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_managed_resource_compiler_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCManagedResourceCompilerTool");
+}
+
+
+/**
+ * Write the VCManifestTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_manifest_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCManifestTool");
+}
+
+
+/**
+ * Write the VCMIDLTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_midl_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCMIDLTool");
+}
+
+
+/**
+ * Write the VCPreBuildEventTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_pre_build_event_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCPreBuildEventTool");
+}
+
+
+/**
+ * Write the VCPreLinkEventTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_pre_link_event_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCPreLinkEventTool");
+}
+
+
+/**
+ * Write the VCPostBuildEventTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_post_build_event_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCPostBuildEventTool");
+}
+
+
+/**
+ * Write the VCResourceCompiler [Tool] element and attributes.
+ */
+int vs200x_project_vc_resource_compiler_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCResourceCompilerTool");
+}
+
+
+/**
+ * Write the VCWebDeploymentTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_web_deployment_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCWebDeploymentTool");
+}
+
+
+/**
+ * Write the VCWebServiceProxyGeneratorTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_web_service_proxy_generator_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCWebServiceProxyGeneratorTool");
+}
+
+
+/**
+ * Write the VCXDCMakeTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_xdc_make_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCXDCMakeTool");
+}
+
+
+/**
+ * Write the VCXMLDataGeneratorTool [Tool] element and attributes.
+ */
+int vs200x_project_vc_xml_data_generator_tool(Session sess, Project prj, Stream strm)
+{
+ return vs200x_project_vc_empty_tool(sess, prj, strm, "VCXMLDataGeneratorTool");
+}
diff --git a/src/actions/vs200x/vs200x_project.h b/src/actions/vs200x/vs200x_project.h
new file mode 100644
index 0000000..a4950f9
--- /dev/null
+++ b/src/actions/vs200x/vs200x_project.h
@@ -0,0 +1,41 @@
+/**
+ * \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 "session/session.h"
+
+int vs200x_project_config_element(Session sess, Project prj, Stream strm);
+int vs200x_project_config_end(Session sess, Project prj, Stream strm);
+int vs200x_project_create(Session sess, Project prj, Stream strm);
+int vs200x_project_element(Session sess, Project prj, Stream strm);
+int vs200x_project_encoding(Session sess, Project prj, Stream strm);
+int vs200x_project_file(Session sess, Project prj, Stream strm, const char* filename, int state);
+int vs200x_project_files(Session sess, Project prj, Stream strm);
+int vs200x_project_globals(Session sess, Project prj, Stream strm);
+int vs200x_project_platforms(Session sess, Project prj, Stream strm);
+int vs200x_project_references(Session sess, Project prj, Stream strm);
+int vs200x_project_tool_files(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_alink_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_app_verifier_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_bsc_make_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_cl_compiler_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_custom_build_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_fx_cop_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_midl_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_linker_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_managed_resource_compiler_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_manifest_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_pre_build_event_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_pre_link_event_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_post_build_event_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_resource_compiler_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_web_deployment_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_web_service_proxy_generator_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_xdc_make_tool(Session sess, Project prj, Stream strm);
+int vs200x_project_vc_xml_data_generator_tool(Session sess, Project prj, Stream strm);
+
+#endif
diff --git a/src/actions/vs200x/vs200x_solution.c b/src/actions/vs200x/vs200x_solution.c
new file mode 100644
index 0000000..6578bd4
--- /dev/null
+++ b/src/actions/vs200x/vs200x_solution.c
@@ -0,0 +1,33 @@
+/**
+ * \file vs200x_solution.c
+ * \brief Visual Studio multiple-version solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+
+#include <stdlib.h>
+#include "premake.h"
+#include "vs200x.h"
+#include "vs200x_solution.h"
+
+
+/**
+ * Create a new output stream for a solution, and make it active for subsequent writes.
+ * \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_create(Session sess, Solution sln, Stream strm)
+{
+ /* create the solution file */
+ const char* filename = solution_get_filename(sln, NULL, ".sln");
+ strm = stream_create_file(filename);
+ if (!strm)
+ {
+ return !OKAY;
+ }
+
+ /* make the stream active for the functions that come after */
+ session_set_active_stream(sess, strm);
+ return OKAY;
+}
diff --git a/src/actions/vs200x/vs200x_solution.h b/src/actions/vs200x/vs200x_solution.h
new file mode 100644
index 0000000..18683c4
--- /dev/null
+++ b/src/actions/vs200x/vs200x_solution.h
@@ -0,0 +1,30 @@
+/**
+ * \file vs200x_solution.h
+ * \brief Visual Studio 200x solution generation functions.
+ * \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
+ */
+#if !defined(PREMAKE_VS200X_SOLUTION_H)
+#define PREMAKE_VS200X_SOLUTION_H
+
+#include "session/session.h"
+
+int vs2002_solution_configuration(Session sess, Solution sln, Stream strm);
+int vs2002_solution_dependencies(Session sess, Solution sln, Stream strm);
+int vs2002_solution_extensibility(Session sess, Solution sln, Stream strm);
+int vs2002_solution_project_configuration(Session sess, Solution sln, Stream strm);
+int vs2002_solution_projects(Session sess, Solution sln, Stream strm);
+int vs2002_solution_signature(Session sess, Solution sln, Stream strm);
+
+int vs2003_solution_configuration(Session sess, Solution sln, Stream strm);
+int vs2003_solution_signature(Session sess, Solution sln, Stream strm);
+
+int vs2005_solution_platforms(Session sess, Solution sln, Stream strm);
+int vs2005_solution_project_platforms(Session sess, Solution sln, Stream strm);
+int vs2005_solution_properties(Session sess, Solution sln, Stream strm);
+int vs2005_solution_signature(Session sess, Solution sln, Stream strm);
+
+int vs2008_solution_signature(Session sess, Solution sln, Stream strm);
+
+int vs200x_solution_create(Session sess, Solution sln, Stream strm);
+
+#endif