Added handling of spaces to solution, project, configuration, and file names (r461:463)

This commit is contained in:
starkos 2008-07-31 13:07:01 +00:00
parent 21882c1218
commit e6b1bc0863
19 changed files with 135 additions and 96 deletions

View File

@ -1,19 +0,0 @@
/**
* \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"

View File

@ -8,11 +8,37 @@
#include <stdlib.h>
#include "premake.h"
#include "make.h"
#include "base/buffers.h"
#include "base/cstr.h"
#include "base/error.h"
#include "base/path.h"
/**
* Escapes spaces in a string value, so it can be safely written to the makefile.
* \param value The string value to escape.
* \returns The same string value, with spaces escaped.
*/
const char* make_escape(const char* value)
{
char* buffer = buffers_next();
const char* src = value;
char* dst = buffer;
while (*src != '\0')
{
if (*src == ' ')
{
*(dst++) = '\\';
}
*(dst++) = *(src++);
}
*dst = '\0';
return buffer;
}
/**
* Given a source file filename, returns the name of the corresponding .o file.
* \param filename The source code filename.
@ -151,3 +177,16 @@ const char* make_get_solution_makefile(Session sess, Solution sln)
/* all good */
return my_path;
}
/**
* Write a string value to a stream, escape any space characters it contains.
* \param strm The output stream.
* \param value The string value to escape.
* \returns OKAY if successful.
*/
int make_write_escaped(Stream strm, const char* value)
{
const char* escaped = make_escape(value);
return stream_write(strm, escaped);
}

View File

@ -8,9 +8,11 @@
#include "session/session.h"
const char* make_escape(const char* value);
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);
int make_write_escaped(Stream strm, const char* value);
#endif

View File

@ -129,7 +129,7 @@ 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);
return stream_writeline(strm, " OBJDIR := obj/%s", make_escape(cfg_name));
}
@ -151,7 +151,7 @@ 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);
return stream_writeline(strm, " OUTFILE := $(OUTDIR)/%s", make_escape(outfile));
}
@ -235,7 +235,7 @@ int make_project_objects(Session sess, Project prj, Stream strm)
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, "\t%s \\", make_escape(obj_name));
}
}
@ -299,7 +299,7 @@ int make_project_source_rules(Session sess, Project prj, Stream strm)
n = strings_size(files);
for (i = 0; i < n; ++i)
{
const char* filename = strings_item(files, i);
const char* filename = make_escape(strings_item(files, i));
if (path_is_cpp_source(filename))
{
const char* obj_name = make_get_obj_filename(filename);

View File

@ -64,7 +64,7 @@ int make_solution_all_rule(Session sess, Solution sln, Stream strm)
assert(strm);
prj_names = make_get_project_names(sln);
z = stream_writeline_strings(strm, prj_names, "all:", " ", "", "");
z = stream_writeline_strings(strm, prj_names, "all:", " ", "", "", "", make_write_escaped);
z |= stream_writeline(strm, "");
strings_destroy(prj_names);
return z;
@ -137,7 +137,7 @@ int make_solution_phony_rule(Session sess, Solution sln, Stream strm)
assert(strm);
prj_names = make_get_project_names(sln);
z = stream_writeline_strings(strm, prj_names, ".PHONY: all clean", " ", "", "");
z = stream_writeline_strings(strm, prj_names, ".PHONY: all clean", " ", "", "", "", make_write_escaped);
z |= stream_writeline(strm, "");
strings_destroy(prj_names);
return z;
@ -159,7 +159,7 @@ const char* make_solution_project_rule(Session sess, Solution sln, Project prj)
/* 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 = 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);
@ -168,12 +168,12 @@ const char* make_solution_project_rule(Session sess, Solution sln, Project prj)
if (!cstr_eq(".", prj_file_dir))
{
strcat(buffer, " --no-print-directory -C ");
strcat(buffer, prj_file_dir);
strcat(buffer, make_escape(prj_file_dir));
}
if (!cstr_eq("Makefile", prj_file_name))
{
strcat(buffer, " -f ");
strcat(buffer, prj_file_name);
strcat(buffer, make_escape(prj_file_name));
}
return buffer;
@ -202,7 +202,7 @@ int make_solution_projects(Session sess, Solution sln, Stream strm)
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, "%s:", make_escape(prj_name));
z |= stream_writeline(strm, "\t@echo ==== Building %s ====", prj_name);
z |= stream_writeline(strm, rule);
z |= stream_writeline(strm, "");
@ -244,7 +244,7 @@ int make_solution_signature(Session sess, Solution sln, Stream strm)
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_strings(strm, config_names, "# ", " ", "", ",", "", NULL);
z |= stream_writeline(strm, "");
return z;

View File

@ -96,7 +96,7 @@ SUITE(action)
{
make_project_config_objdir(sess, prj, strm);
CHECK_EQUAL(
" OBJDIR := obj/Debug\n",
" OBJDIR := obj/Debug\\ DLL\n",
buffer);
}
@ -110,7 +110,7 @@ SUITE(action)
platform_set(MacOSX);
make_project_config_outfile(sess, prj, strm);
CHECK_EQUAL(
" OUTFILE := $(OUTDIR)/MyProject\n",
" OUTFILE := $(OUTDIR)/My\\ Project\n",
buffer);
}

View File

@ -36,7 +36,7 @@ SUITE(action)
{
make_project_config_conditional(sess, prj, strm);
CHECK_EQUAL(
"ifeq ($(CONFIG),Debug)\n",
"ifeq ($(CONFIG),Debug DLL)\n",
buffer);
}
@ -56,13 +56,13 @@ SUITE(action)
TEST_FIXTURE(FxAction, MakeProject_Objects_ConvertsFileExtension)
{
char* files[] = { "Hello.cpp", "Goodbye.cpp", NULL };
char* files[] = { "Hello.cpp", "Good Bye.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"
"\t$(OBJDIR)/Good\\ Bye.o \\\n"
"\n",
buffer);
}
@ -105,7 +105,7 @@ SUITE(action)
make_project_target(sess, prj, strm);
CHECK_EQUAL(
"$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
"\t@echo Linking MyProject\n"
"\t@echo Linking My Project\n"
"\t@$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)\n"
"\n",
buffer);
@ -141,7 +141,7 @@ SUITE(action)
make_project_clean_rules(sess, prj, strm);
CHECK_EQUAL(
"clean:\n"
"\t@echo Cleaning MyProject\n"
"\t@echo Cleaning My Project\n"
"ifeq (posix, $(SHELLTYPE))\n"
"\t@rm -f $(SYS_OUTFILE)\n"
"\t@rm -rf $(SYS_OBJDIR)\n"
@ -160,11 +160,11 @@ SUITE(action)
TEST_FIXTURE(FxAction, MakeProject_SourceRules)
{
char* files[] = { "Hello.cpp", NULL };
char* files[] = { "Good Bye.cpp", NULL };
SetField(prj, ProjectFiles, files);
make_project_source_rules(sess, prj, strm);
CHECK_EQUAL(
"$(OBJDIR)/Hello.o: Hello.cpp\n"
"$(OBJDIR)/Good\\ Bye.o: Good\\ Bye.cpp\n"
"\t@echo $(notdir $<)\n"
"\t@$(CXX) $(CXXFLAGS) -o $@ -c $<\n"
"\n",

View File

@ -25,7 +25,7 @@ SUITE(action)
"# GNU Make makefile autogenerated by Premake\n"
"# Usage: make [ CONFIG=config_name ]\n"
"# Where {config_name} is one of:\n"
"# Debug, Release\n"
"# Debug DLL, Release DLL\n"
"\n",
buffer);
}
@ -40,7 +40,7 @@ SUITE(action)
make_solution_default_config(sess, sln, strm);
CHECK_EQUAL(
"ifndef CONFIG\n"
" CONFIG=Debug\n"
" CONFIG=Debug DLL\n"
"endif\n"
"export CONFIG\n"
"\n",
@ -56,7 +56,7 @@ SUITE(action)
{
make_solution_phony_rule(sess, sln, strm);
CHECK_EQUAL(
".PHONY: all clean MyProject\n"
".PHONY: all clean My\\ Project\n"
"\n",
buffer);
}
@ -70,7 +70,7 @@ SUITE(action)
{
make_solution_all_rule(sess, sln, strm);
CHECK_EQUAL(
"all: MyProject\n"
"all: My\\ Project\n"
"\n",
buffer);
}
@ -85,21 +85,21 @@ SUITE(action)
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"
"My\\ Project:\n"
"\t@echo ==== Building My Project ====\n"
"\t@$(MAKE) -f My\\ Project.make\n"
"\n",
buffer);
}
TEST_FIXTURE(FxAction, Make_ProjectEntry_InDifferentDirectory)
{
project_set_location(prj, "MyProject");
project_set_location(prj, "My Project");
make_solution_projects(sess, sln, strm);
CHECK_EQUAL(
"MyProject:\n"
"\t@echo ==== Building MyProject ====\n"
"\t@$(MAKE) --no-print-directory -C MyProject\n"
"My\\ Project:\n"
"\t@echo ==== Building My Project ====\n"
"\t@$(MAKE) --no-print-directory -C My\\ Project\n"
"\n",
buffer);
}
@ -115,7 +115,7 @@ SUITE(action)
make_solution_clean_rule(sess, sln, strm);
CHECK_EQUAL(
"clean:\n"
"\t@$(MAKE) -f MyProject.make clean\n",
"\t@$(MAKE) -f My\\ Project.make clean\n",
buffer);
}

View File

@ -29,21 +29,21 @@ struct FxAction
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");
solution_set_name(sln, "My Solution");
solution_set_base_dir(sln, "Root Folder");
solution_add_config(sln, "Debug DLL");
solution_add_config(sln, "Release DLL");
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_name(prj, "My Project");
project_set_base_dir(prj, "Root Folder");
project_set_location(prj, "Project Folder");
project_set_guid(prj, "AE2461B7-236F-4278-81D3-F0D476F9A4C0");
project_set_language(prj, "c++");
flt = session_get_filter(sess);
filter_set_value(flt, FilterConfig, "Debug");
filter_set_value(flt, FilterConfig, "Debug DLL");
project_set_filter(prj, flt);
}

View File

@ -34,7 +34,7 @@ SUITE(action)
{
vs2002_solution_projects(sess, sln, strm);
CHECK_EQUAL(
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"ProjectFolder\\MyProject.vcproj\", \"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"My Project\", \"Project Folder\\My Project.vcproj\", \"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"EndProject\n",
buffer);
}
@ -50,8 +50,8 @@ SUITE(action)
CHECK_EQUAL(
"Global\n"
"\tGlobalSection(SolutionConfiguration) = preSolution\n"
"\t\tConfigName.0 = Debug\n"
"\t\tConfigName.1 = Release\n"
"\t\tConfigName.0 = Debug DLL\n"
"\t\tConfigName.1 = Release DLL\n"
"\tEndGlobalSection\n",
buffer);
}
@ -80,10 +80,10 @@ SUITE(action)
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"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug DLL.ActiveCfg = Debug DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug DLL.Build.0 = Debug DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release DLL.ActiveCfg = Release DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release DLL.Build.0 = Release DLL|Win32\n"
"\tEndGlobalSection\n",
buffer);
}

View File

@ -36,8 +36,8 @@ SUITE(action)
CHECK_EQUAL(
"Global\n"
"\tGlobalSection(SolutionConfiguration) = preSolution\n"
"\t\tDebug = Debug\n"
"\t\tRelease = Release\n"
"\t\tDebug DLL = Debug DLL\n"
"\t\tRelease DLL = Release DLL\n"
"\tEndGlobalSection\n",
buffer);
}

View File

@ -38,8 +38,8 @@ SUITE(action)
CHECK_EQUAL(
"Global\n"
"\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"
"\t\tDebug|Win32 = Debug|Win32\n"
"\t\tRelease|Win32 = Release|Win32\n"
"\t\tDebug DLL|Win32 = Debug DLL|Win32\n"
"\t\tRelease DLL|Win32 = Release DLL|Win32\n"
"\tEndGlobalSection\n",
buffer);
}
@ -54,10 +54,10 @@ SUITE(action)
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"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug DLL|Win32.ActiveCfg = Debug DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Debug DLL|Win32.Build.0 = Debug DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release DLL|Win32.ActiveCfg = Release DLL|Win32\n"
"\t\t{AE2461B7-236F-4278-81D3-F0D476F9A4C0}.Release DLL|Win32.Build.0 = Release DLL|Win32\n"
"\tEndGlobalSection\n",
buffer);
}

View File

@ -38,7 +38,7 @@ SUITE(action)
"<VisualStudioProject\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"7.00\"\n"
"\tName=\"MyProject\"\n"
"\tName=\"My Project\"\n"
"\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"\tKeyword=\"Win32Proj\">\n",
buffer);
@ -52,7 +52,7 @@ SUITE(action)
"<VisualStudioProject\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"7.10\"\n"
"\tName=\"MyProject\"\n"
"\tName=\"My Project\"\n"
"\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"\tKeyword=\"Win32Proj\">\n",
buffer);
@ -66,7 +66,7 @@ SUITE(action)
"<VisualStudioProject\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"8.00\"\n"
"\tName=\"MyProject\"\n"
"\tName=\"My Project\"\n"
"\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"\tRootNamespace=\"MyProject\"\n"
"\tKeyword=\"Win32Proj\"\n"
@ -82,7 +82,7 @@ SUITE(action)
"<VisualStudioProject\n"
"\tProjectType=\"Visual C++\"\n"
"\tVersion=\"9.00\"\n"
"\tName=\"MyProject\"\n"
"\tName=\"My Project\"\n"
"\tProjectGUID=\"{AE2461B7-236F-4278-81D3-F0D476F9A4C0}\"\n"
"\tRootNamespace=\"MyProject\"\n"
"\tKeyword=\"Win32Proj\"\n"
@ -165,7 +165,7 @@ SUITE(action)
vs200x_project_config_element(sess, prj, strm);
CHECK_EQUAL(
"\t\t<Configuration\n"
"\t\t\tName=\"Debug|Win32\"\n"
"\t\t\tName=\"Debug DLL|Win32\"\n"
"\t\t\tOutputDirectory=\"$(SolutionDir)$(ConfigurationName)\"\n"
"\t\t\tIntermediateDirectory=\"$(ConfigurationName)\"\n"
"\t\t\tConfigurationType=\"1\"\n"

View File

@ -94,7 +94,7 @@ int vs200x_project_element(Session sess, Project prj, Stream strm)
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, "RootNamespace", cstr_to_identifier(prj_name));
}
z |= vs200x_attribute(strm, 1, "Keyword", "Win32Proj");
if (version > 2005)

View File

@ -127,6 +127,31 @@ int cstr_starts_with(const char* str, const char* expected)
}
/**
* Removes spaces any other special characters from a string, converting it
* into a C/C++/C# safe identifier.
* \param str The string to process.
* \returns An identifier-safe string.
*/
char* cstr_to_identifier(const char* str)
{
char* buffer = buffers_next();
char* dst = buffer;
while (*str != '\0')
{
if (isalnum(*str) || *str == '_')
{
*(dst++) = *str;
}
str++;
}
*dst = '\0';
return buffer;
}
/**
* Remove a character from the end of a string, if present.
* \param str The string to trim.

View File

@ -19,6 +19,7 @@ int cstr_eq(const char* str, const char* expected);
int cstr_eqi(const char* str, const char* expected);
char* cstr_format(const char* format, ...);
int cstr_starts_with(const char* str, const char* expected);
char* cstr_to_identifier(const char* str);
void cstr_trim(char* str, char ch);
#endif

View File

@ -180,24 +180,14 @@ int stream_write_strings(Stream strm, Strings strs, const char* start, const cha
* \param postfix A postfix string, to be written after each item.
* \param infix An infix strings, to write between items, after the
* previous postfix string and before the next prefix.
* \param end The end string, always written last, even if there are no items in the list.
* \param writer A callback function to handle output of each list item.
* \returns OKAY if successful.
*/
int stream_writeline_strings(Stream strm, Strings strs, const char* start, const char* prefix, const char* postfix, const char* infix)
int stream_writeline_strings(Stream strm, Strings strs, const char* start, const char* prefix, const char* postfix, const char* infix, const char* end, StreamWriterFunc writer)
{
int i, n, z;
z = stream_write(strm, start);
n = strings_size(strs);
for (i = 0; i < n; ++i)
{
const char* value = strings_item(strs, i);
if (i > 0) z |= stream_write(strm, infix);
z |= stream_write(strm, prefix);
z |= stream_write(strm, value);
z |= stream_write(strm, postfix);
}
int z = OKAY;
z |= stream_write_strings(strm, strs, start, prefix, postfix, infix, end, writer);
z |= stream_writeline(strm, "");
return z;
}

View File

@ -34,7 +34,7 @@ int stream_write_n(Stream strm, const char* value, int n);
int stream_write_strings(Stream strm, Strings strs, const char* start, const char* prefix, const char* postfix, const char* infix, const char* end, StreamWriterFunc writer);
int stream_write_unicode_marker(Stream strm);
int stream_writeline(Stream strm, const char* value, ...);
int stream_writeline_strings(Stream strm, Strings strs, const char* start, const char* prefix, const char* postfix, const char* infix);
int stream_writeline_strings(Stream strm, Strings strs, const char* start, const char* prefix, const char* postfix, const char* infix, const char* end, StreamWriterFunc writer);
#endif
/** @} */

View File

@ -53,6 +53,7 @@ package.kind = "exe"
{
lua .. "/src/lua.c",
lua .. "/src/luac.c",
lua .. "/src/print.c",
matchfiles(lua .. "/etc/*.c")
}