Bug 1674173: Allow source files to have the same name

This commit is contained in:
Jason Perkins 2012-06-19 15:58:16 -04:00
parent 759c169b94
commit 808aa41177
10 changed files with 231 additions and 23 deletions

View File

@ -17,6 +17,7 @@
* path.translate() now defaults to Windows-style backslashes
* Added NoWarnings flag for Visual Studio (xpol)
* Added debugcommand for Visual Studio (xpol)
* Bug 1674173: Allow source files to have the same name
-------

View File

@ -113,22 +113,9 @@
-- precompiler header rule
cpp.pchrules(prj)
--[[
-- per-file rules
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
cpp.buildcommand_old(path.iscfile(file))
elseif (path.getextension(file) == ".rc") then
_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(RESFLAGS)')
end
end
_p('')
--]]
-- file building rules
cpp.filerules(prj)
-- include the dependencies, built by GCC (with the -MMD flag)
_p('-include $(OBJECTS:%%.o=%%.d)')
@ -222,6 +209,42 @@
end
--
-- Output the list of file building rules.
--
function cpp.filerules(prj)
local tr = project.getsourcetree(prj)
premake.tree.traverse(tr, {
onleaf = function(node, depth)
if path.iscppfile(node.abspath) then
local objectname = project.getfileobject(prj, node.abspath)
_p('$(OBJDIR)/%s.o: %s', make.esc(objectname), make.esc(node.relpath))
_p('')
end
end
})
--[[
-- per-file rules
for _, file in ipairs(prj.files) do
if path.iscppfile(file) then
_p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
cpp.buildcommand_old(path.iscfile(file))
elseif (path.getextension(file) == ".rc") then
_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(RESFLAGS)')
end
end
_p('')
--]]
end
--
-- Compile flags
--
@ -290,6 +313,10 @@
return
end
-- assign a unique object file name to avoid collisions from
-- files at different folder levels with the same name
local objectname = project.getfileobject(prj, node.abspath)
-- see what set of configurations contains this file
local inallcfgs = true
for cfg in project.eachconfig(prj) do
@ -303,13 +330,13 @@
-- if this file exists in all configurations, write it to
-- the project's list of files
if inallcfgs then
_p('\t$(OBJDIR)/%s.o \\', make.esc(node.basename))
_p('\t$(OBJDIR)/%s.o \\', make.esc(objectname))
-- otherwise add it to the individual configuration lists
else
for cfg in project.eachconfig(prj) do
if incfg[cfg] then
table.insert(cfgfiles[cfg], node.basename)
table.insert(cfgfiles[cfg], objectname)
end
end
end
@ -322,8 +349,8 @@
if #cfgfiles[cfg] > 0 then
_p('ifeq ($(config),%s)', make.esc(cfg.shortname))
_p(' OBJECTS += \\')
for _, basename in ipairs(cfgfiles[cfg]) do
_p('\t$(OBJDIR)/%s.o \\', make.esc(basename))
for _, objectname in ipairs(cfgfiles[cfg]) do
_p('\t$(OBJDIR)/%s.o \\', make.esc(objectname))
end
_p('')
_p('endif')

View File

@ -775,6 +775,15 @@
end
end
-- see if this file needs a modified object file name
local objectname
if path.iscppfile(node.name) then
objectname = project.getfileobject(prj, node.abspath)
if objectname == path.getbasename(node.abspath) then
objectname = nil
end
end
for cfg in project.eachconfig(prj) do
-- get any settings specific to this file for this configuration;
@ -789,7 +798,7 @@
local isPchSource = (cfg.pchsource == node.abspath and not cfg.flags.NoPCH)
-- only write the element if we have something to say
if compileAs or isPchSource or not filecfg or hasSettings then
if compileAs or isPchSource or not filecfg or hasSettings or objectname then
_p(depth,'<FileConfiguration')
depth = depth + 1
@ -819,6 +828,10 @@
_p(depth, 'CompileAs="%s"', iif(compileAs == "C++", 1, 2))
end
if objectname then
_p(depth, 'ObjectFile="$(IntDir)\\%s.obj"', objectname)
end
-- include the precompiled header, if this is marked as the PCH source
if isPchSource then
if cfg.system == premake.PS3 then

View File

@ -405,13 +405,20 @@
for _, file in ipairs(files) do
_x(2,'<ClCompile Include=\"%s\">', path.translate(file.relpath))
for cfg in project.eachconfig(prj) do
local condition = vc2010.condition(cfg)
local filecfg = config.getfileconfig(cfg, file.abspath)
if not filecfg then
_p(3,'<ExcludedFromBuild %s>true</ExcludedFromBuild>', vc2010.condition(cfg))
_p(3,'<ExcludedFromBuild %s>true</ExcludedFromBuild>', condition)
end
local objectname = project.getfileobject(prj, file.abspath)
if objectname ~= path.getbasename(file.abspath) then
_p(3,'<ObjectFileName %s>$(IntDir)\\%s.obj</ObjectFileName>', condition, objectname)
end
if cfg.pchsource == file.abspath and not cfg.flags.NoPCH then
_p(3,'<PrecompiledHeader %s>Create</PrecompiledHeader>', vc2010.condition(cfg))
_p(3,'<PrecompiledHeader %s>Create</PrecompiledHeader>', condition)
end
end
_p(2,'</ClCompile>')

View File

@ -281,6 +281,44 @@
end
--
-- Returns a unique object file name for a project source code file.
--
-- @param prj
-- The project object to query.
-- @param filename
-- The name of the file being compiled to the object file.
--
function project.getfileobject(prj, filename)
-- make sure I have the project, and not it's root configuration
prj = prj.project or prj
-- create a list of objects if necessary
prj.fileobjects = prj.fileobjects or {}
-- look for the corresponding object file
local basename = path.getbasename(filename)
local uniqued = basename
local i = 0
while prj.fileobjects[uniqued] do
-- found a match?
if prj.fileobjects[uniqued] == filename then
return uniqued
end
-- check a different name
i = i + 1
uniqued = basename .. i
end
-- no match, create a new one
prj.fileobjects[uniqued] = filename
return uniqued
end
--
-- Retrieve the project's file name.
--

View File

@ -0,0 +1,42 @@
--
-- tests/actions/make/cpp/test_file_rules.lua
-- Validate the makefile source building rules.
-- Copyright (c) 2009-2012 Jason Perkins and the Premake project
--
T.make_cpp_file_rules = { }
local suite = T.make_cpp_file_rules
local cpp = premake.make.cpp
local project = premake5.project
--
-- Setup
--
local sln, prj
function suite.setup()
sln = test.createsolution()
end
local function prepare()
prj = premake.solution.getproject_ng(sln, 1)
cpp.filerules(prj)
end
--
-- Two files with the same base name should have different object files.
--
function suite.uniqueObjNames_onBaseNameCollision()
files { "src/hello.cpp", "src/greetings/hello.cpp" }
prepare()
test.capture [[
$(OBJDIR)/hello.o: src/greetings/hello.cpp
$(OBJDIR)/hello1.o: src/hello.cpp
]]
end

View File

@ -77,3 +77,19 @@ endif
]]
end
--
-- Two files with the same base name should have different object files.
--
function suite.uniqueObjNames_onBaseNameCollision()
files { "src/hello.cpp", "src/greetings/hello.cpp" }
prepare()
test.capture [[
OBJECTS := \
$(OBJDIR)/hello.o \
$(OBJDIR)/hello1.o \
]]
end

View File

@ -256,3 +256,45 @@
</FileConfiguration>
]]
end
--
-- If two files at different folder levels have the same name, a different
-- object file name should be used for each.
--
function suite.uniqueObjectNames_onSourceNameCollision()
files { "hello.cpp", "greetings/hello.cpp" }
prepare()
test.capture [[
<Filter
Name="greetings"
Filter=""
>
<File
RelativePath="greetings\hello.cpp"
>
</File>
</Filter>
<File
RelativePath="hello.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\hello1.obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\hello1.obj"
/>
</FileConfiguration>
</File>
]]
end

View File

@ -129,3 +129,24 @@
</ItemGroup>
]]
end
--
-- If two files at different folder levels have the same name, a different
-- object file name should be used for each.
--
function suite.uniqueObjectNames_onSourceNameCollision()
files { "hello.cpp", "greetings/hello.cpp" }
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="greetings\hello.cpp">
</ClCompile>
<ClCompile Include="hello.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)\hello1.obj</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)\hello1.obj</ObjectFileName>
</ClCompile>
</ItemGroup>
]]
end

View File

@ -158,6 +158,7 @@
dofile("actions/make/solution/test_help_rule.lua")
-- Makefile C/C++ projects
dofile("actions/make/cpp/test_file_rules.lua")
dofile("actions/make/cpp/test_make_pch.lua")
dofile("actions/make/cpp/test_make_linking.lua")
dofile("actions/make/cpp/test_objects.lua")