Added mkdir and clean rules to gmake (r380:382)

This commit is contained in:
starkos 2008-05-18 15:20:32 +00:00
parent 98d19823c1
commit 8377b2e217
9 changed files with 210 additions and 20 deletions

View File

@ -33,8 +33,11 @@ static SessionProjectCallback ProjectCallbacks[] =
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

View File

@ -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/sh.exe,$(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;
}

View File

@ -12,6 +12,27 @@
#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.
*/
@ -30,7 +51,7 @@ int make_project_config_cflags(Session sess, Project prj, Stream strm)
{
UNUSED(sess);
UNUSED(prj);
return stream_writeline(strm, " CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)");
return stream_writeline(strm, " CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)");
}
@ -77,7 +98,7 @@ int make_project_config_lddeps(Session sess, Project prj, Stream strm)
{
UNUSED(sess);
UNUSED(prj);
return stream_writeline(strm, " LDDEPS :=");
return stream_writeline(strm, " LDDEPS :=");
}
@ -88,7 +109,7 @@ int make_project_config_ldflags(Session sess, Project prj, Stream strm)
{
UNUSED(sess);
UNUSED(prj);
return stream_writeline(strm, " LDFLAGS +=");
return stream_writeline(strm, " LDFLAGS +=");
}
@ -99,7 +120,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 := .", cfg_name);
return stream_writeline(strm, " OBJDIR := obj/%s", cfg_name);
}
@ -110,7 +131,7 @@ int make_project_config_outdir(Session sess, Project prj, Stream strm)
{
UNUSED(sess);
UNUSED(prj);
return stream_writeline(strm, " OUTDIR := .");
return stream_writeline(strm, " OUTDIR := .");
}
@ -121,7 +142,7 @@ int make_project_config_outfile(Session sess, Project prj, Stream strm)
{
UNUSED(sess);
UNUSED(prj);
return stream_writeline(strm, " OUTFILE := MyApp");
return stream_writeline(strm, " OUTFILE := $(OUTDIR)/MyApp");
}
@ -166,6 +187,26 @@ int make_project_include_dependencies(Session sess, Project prj, Stream strm)
}
/**
* 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.
*/
@ -249,7 +290,6 @@ int make_project_source_rules(Session sess, Project prj, Stream strm)
const char* filename = strings_item(files, i);
const char* obj_name = make_get_obj_filename(filename);
z |= stream_writeline(strm, "%s: %s", obj_name, filename);
z |= stream_writeline(strm, "\t-@$(CMD_MKOBJDIR)");
z |= stream_writeline(strm, "\t@echo $(notdir $<)");
z |= stream_writeline(strm, "\t@$(CXX) $(CXXFLAGS) -o $@ -c $<");
z |= stream_writeline(strm, "");
@ -264,9 +304,9 @@ int make_project_source_rules(Session sess, Project prj, Stream strm)
*/
int make_project_target(Session sess, Project prj, Stream strm)
{
int z;
int z = OKAY;
UNUSED(sess);
z = stream_writeline(strm, "$(OUTDIR)/$(OUTFILE): $(OBJECTS) $(LDDEPS) $(RESOURCES)");
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, "");

View File

@ -8,6 +8,9 @@
#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);
@ -21,6 +24,7 @@ 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);

View File

@ -42,7 +42,7 @@ SUITE(action)
{
make_project_config_cflags(sess, prj, strm);
CHECK_EQUAL(
" CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)\n",
" CFLAGS += $(CPPFLAGS) $(ARCHFLAGS)\n",
buffer);
}
@ -66,7 +66,7 @@ SUITE(action)
{
make_project_config_lddeps(sess, prj, strm);
CHECK_EQUAL(
" LDDEPS :=\n",
" LDDEPS :=\n",
buffer);
}
@ -74,7 +74,7 @@ SUITE(action)
{
make_project_config_ldflags(sess, prj, strm);
CHECK_EQUAL(
" LDFLAGS +=\n",
" LDFLAGS +=\n",
buffer);
}
@ -82,7 +82,7 @@ SUITE(action)
{
make_project_config_objdir(sess, prj, strm);
CHECK_EQUAL(
" OBJDIR := .\n",
" OBJDIR := obj/Debug\n",
buffer);
}
@ -90,7 +90,7 @@ SUITE(action)
{
make_project_config_outfile(sess, prj, strm);
CHECK_EQUAL(
" OUTFILE := MyApp\n",
" OUTFILE := $(OUTDIR)/MyApp\n",
buffer);
}
@ -98,7 +98,7 @@ SUITE(action)
{
make_project_config_outdir(sess, prj, strm);
CHECK_EQUAL(
" OUTDIR := .\n",
" OUTDIR := .\n",
buffer);
}
@ -165,7 +165,7 @@ SUITE(action)
{
make_project_target(sess, prj, strm);
CHECK_EQUAL(
"$(OUTDIR)/$(OUTFILE): $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
"$(OUTFILE): $(OUTDIR) $(OBJDIR) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n"
"\t@echo Linking MyProject\n"
"\t$(CXX) -o $@ $(LDFLAGS) $(ARCHFLAGS) $(OBJECTS) $(RESOURCES)\n"
"\n",
@ -173,6 +173,48 @@ SUITE(action)
}
/**********************************************************************
* 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
**********************************************************************/
@ -184,7 +226,6 @@ SUITE(action)
make_project_source_rules(sess, prj, strm);
CHECK_EQUAL(
"$(OBJDIR)/Hello.o: Hello.cpp\n"
"\t-@$(CMD_MKOBJDIR)\n"
"\t@echo $(notdir $<)\n"
"\t@$(CXX) $(CXXFLAGS) -o $@ -c $<\n"
"\n",

View File

@ -4,6 +4,7 @@
* \author Copyright (c) 2002-2008 Jason Perkins and the Premake project
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@ -38,7 +39,7 @@ int cstr_ends_with(const char* str, const char* expected)
* Compares two C strings for equality.
* \param str The string to compare.
* \param expected The value to compare against.
* \returns Nonzero if the strings match, zero otherwise.
* \returns True if the strings match, zero otherwise.
*/
int cstr_eq(const char* str, const char* expected)
{
@ -50,6 +51,33 @@ int cstr_eq(const char* str, const char* expected)
}
/**
* Performs a case-insensitive comparasion on two C strings for equality.
* \param str The string to compare.
* \param expected The value to compare against.
* \returns True if the strings match, zero otherwise.
*/
int cstr_eqi(const char* str, const char* expected)
{
if (str != NULL && expected != NULL)
{
while (*str && *expected)
{
if (tolower(*str) != tolower(*expected))
{
return 0;
}
str++;
expected++;
}
return (*str == *expected);
}
return 0;
}
/**
* Builds a string using printf-style formatting codes.
* \param format The format string, which may contain printf-style formatting codes.

View File

@ -8,6 +8,7 @@
int cstr_ends_with(const char* str, const char* expected);
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);

View File

@ -212,10 +212,9 @@ int path_is_cpp_source(const char* path)
return 0;
}
_strlwr(ext);
for (i = 0; CppFileExtensions[i] != NULL; ++i)
{
if (cstr_eq(CppFileExtensions[i], ext))
if (cstr_eqi(CppFileExtensions[i], ext))
return 1;
}

View File

@ -67,6 +67,31 @@ SUITE(cstr)
}
/**************************************************************************
* cstr_eqi() tests
**************************************************************************/
TEST(CStrEqi_ReturnsTrue_OnMatch)
{
CHECK(cstr_eqi("A string", "a String"));
}
TEST(CStrEqi_ReturnsFalse_OnMismatch)
{
CHECK(!cstr_eqi("A string", "a different string"));
}
TEST(CStrEqi_ReturnsFalse_OnNullTarget)
{
CHECK(!cstr_eqi(NULL, "something"));
}
TEST(CStrEqi_ReturnsFalse_OnNullPattern)
{
CHECK(!cstr_eqi("something", NULL));
}
/**************************************************************************
* cstr_format() tests
**************************************************************************/