Bug 1674173: Allow source files to have the same name
This commit is contained in:
parent
759c169b94
commit
808aa41177
@ -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
|
||||
|
||||
|
||||
-------
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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>')
|
||||
|
@ -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.
|
||||
--
|
||||
|
42
tests/actions/make/cpp/test_file_rules.lua
Normal file
42
tests/actions/make/cpp/test_file_rules.lua
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
Reference in New Issue
Block a user