Get 'compileas' working when using a 'filter "files: ..."' scope.

This commit is contained in:
Ben Ratzlaff 2018-04-08 15:29:24 -07:00
parent e45b8cfc6b
commit be3742dd2a
9 changed files with 356 additions and 36 deletions

View File

@ -73,6 +73,18 @@
end
end)
--
-- Don't create $(OBJDIR) in the d-file rules
--
p.override(make, "objDirInFileRules", function(oldfn, prj, node)
-- node is nil when making pch rules
if not node or not path.isdfile(node.abspath) then
oldfn(prj, node)
end
end)
---
-- Add namespace for element definition lists for p.callarray()
@ -154,14 +166,24 @@
p.override(cpp, "standardFileRules", function(oldfn, prj, node)
-- D file
if path.isdfile(node.abspath) then
_x('$(OBJDIR)/%s.o: %s', node.objname, node.relpath)
_p('\t@echo $(notdir $<)')
_p('\t$(SILENT) $(DC) $(ALL_DFLAGS) $(OUTPUTFLAG) -c $<')
else
oldfn(prj, node)
end
end)
--
-- Let make know it can compile D source files
--
p.override(make, "fileType", function(oldfn, node)
if path.isdfile(node.abspath) then
return "objects"
else
return oldfn(node)
end
end)
--
-- Write out the settings for a particular configuration.

View File

@ -43,18 +43,74 @@
}
end
-- should be part of the toolset?
function make.fileTypeExtensions()
return {
["objects"] = "o",
["resources"] = "res",
}
end
-- should be part of the toolset?
function make.fileType(node)
local kind
if path.iscppfile(node.abspath) then
kind = "objects"
elseif path.isresourcefile(node.abspath) then
kind = "resources"
end
return kind
end
function make.fileDependency(prj, node)
local filetype = make.fileType(node)
_x('$(OBJDIR)/%s.%s: %s', node.objname, make.fileTypeExtensions()[filetype], node.relpath)
_p('\t@echo $(notdir $<)')
end
function make.objDirInFileRules(prj, node)
make.mkdir('$(OBJDIR)')
end
function make.cpp.generate(prj)
p.eol("\n")
p.callArray(cpp.elements.makefile, prj)
end
--
-- Write out the commands for compiling a file
--
cpp.elements.standardFileRules = function(prj, node)
return {
make.fileDependency,
make.objDirInFileRules,
cpp.standardFileRules,
}
end
cpp.elements.customFileRules = function(prj, node)
return {
make.fileDependency,
make.objDirInFileRules,
cpp.customFileRules,
}
end
cpp.elements.customBuildRules = function(prj, node)
return {
cpp.customFileRules
}
end
--
-- Write out the settings for a particular configuration.
--
cpp.elements.configuration = function(cfg)
cpp.elements.configuration = function(cfg, toolset)
return {
make.configBegin,
make.cppTools,
make.target,
make.objdir,
@ -76,6 +132,7 @@
make.postBuildCmds,
make.cppAllRules,
make.settings,
make.configEnd,
}
end
@ -89,9 +146,7 @@
error("Invalid toolset '" .. cfg.toolset .. "'")
end
_x('ifeq ($(config),%s)', cfg.shortname)
p.callArray(cpp.elements.configuration, cfg, toolset)
_p('endif')
_p('')
end
end
@ -105,13 +160,33 @@
end
end
--
-- Return the start of the compilation string that corresponds to the 'compileas' enum if set
--
function cpp.compileas(prj, node)
local result
if node["compileas"] then
if p.languages.isc(node.compileas) then
result = '$(CC) $(ALL_CFLAGS)'
elseif p.languages.iscpp(node.compileas) then
result = '$(CXX) $(ALL_CXXFLAGS)'
end
end
return result
end
--
-- Build command for a single file.
--
function cpp.buildcommand(prj, objext, node)
local iscfile = node and path.iscfile(node.abspath) or false
local flags = iif(prj.language == "C" or iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)')
local flags = cpp.compileas(prj, node)
if not flags then
local iscfile = node and path.iscfile(node.abspath) or false
flags = iif(prj.language == "C" or iscfile, '$(CC) $(ALL_CFLAGS)', '$(CXX) $(ALL_CXXFLAGS)')
end
_p('\t$(SILENT) %s $(FORCE_INCLUDE) -o "$@" -MF "$(@:%%.%s=%%.d)" -c "$<"', flags, objext)
end
@ -129,17 +204,22 @@
for cfg in project.eachconfig(prj) do
local filecfg = fileconfig.getconfig(node, cfg)
if fileconfig.hasCustomBuildRule(filecfg) then
rules = true
rules = cpp.elements.customBuildRules(prj, node)
break
end
if fileconfig.hasFileSettings(filecfg) then
rules = cpp.elements.customFileRules(prj, node)
break
end
end
-- if it has custom rules, need to break them out
-- into individual configurations
if not rules and make.fileType(node) then
rules = cpp.elements.standardFileRules(prj, node)
end
if rules then
cpp.customFileRules(prj, node)
else
cpp.standardFileRules(prj, node)
p.callArray(rules, prj, node)
end
end
})
@ -147,18 +227,13 @@
end
function cpp.standardFileRules(prj, node)
-- C/C++ file
if path.iscppfile(node.abspath) then
_x('$(OBJDIR)/%s.o: %s', node.objname, node.relpath)
_p('\t@echo $(notdir $<)')
make.mkdir('$(OBJDIR)')
cpp.buildcommand(prj, "o", node)
local kind = make.fileType(node)
-- C/C++ file
if kind == "objects" then
cpp.buildcommand(prj, make.fileTypeExtensions()[kind], node)
-- resource file
elseif path.isresourcefile(node.abspath) then
_x('$(OBJDIR)/%s.res: %s', node.objname, node.relpath)
_p('\t@echo $(notdir $<)')
make.mkdir('$(OBJDIR)')
elseif kind == "resources" then
_p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)')
end
end
@ -167,8 +242,9 @@
for cfg in project.eachconfig(prj) do
local filecfg = fileconfig.getconfig(node, cfg)
if filecfg then
_x('ifeq ($(config),%s)', cfg.shortname)
make.configBegin(cfg)
if fileconfig.hasCustomBuildRule(filecfg) then
local output = project.getrelative(prj, filecfg.buildoutputs[1])
local dependencies = filecfg.relpath
if filecfg.buildinputs and #filecfg.buildinputs > 0 then
@ -186,7 +262,10 @@
_p('\t$(SILENT) %s', cmd)
end
end
_p('endif')
else
cpp.standardFileRules(prj, filecfg)
end
make.configEnd(cfg)
end
end
end
@ -287,7 +366,7 @@
for cfg in project.eachconfig(prj) do
local files = configs[cfg]
if #files.objects > 0 or #files.resources > 0 or #files.customfiles > 0 then
_x('ifeq ($(config),%s)', cfg.shortname)
make.configBegin(cfg, toolset)
if #files.objects > 0 then
listobjects(' OBJECTS +=', files.objects)
end
@ -297,7 +376,7 @@
if #files.customfiles > 0 then
listobjects(' CUSTOMFILES +=', files.customfiles)
end
_p('endif')
make.configEnd(cfg, toolset)
_p('')
end
end
@ -310,6 +389,18 @@
--
---------------------------------------------------------------------------
function make.configBegin(cfg, toolset)
if cfg then
_x('ifeq ($(config),%s)', cfg.shortname)
end
end
function make.configEnd(cfg, toolset)
if cfg then
_p('endif')
end
end
function make.cFlags(cfg, toolset)
_p(' ALL_CFLAGS += $(CFLAGS) $(ALL_CPPFLAGS)%s', make.list(table.join(toolset.getcflags(cfg), cfg.buildoptions)))
end
@ -512,7 +603,7 @@
_p('$(OBJECTS): $(GCH) $(PCH)')
_p('$(GCH): $(PCH)')
_p('\t@echo $(notdir $<)')
make.mkdir('$(OBJDIR)')
make.objDirInFileRules(prj, nil)
local cmd = iif(prj.language == "C", "$(CC) -x c-header $(ALL_CFLAGS)", "$(CXX) -x c++-header $(ALL_CXXFLAGS)")
_p('\t$(SILENT) %s -o "$@" -MF "$(@:%%.gch=%%.d)" -c "$<"', cmd)

View File

@ -84,6 +84,73 @@ endif
]]
end
--
-- C files in C++ projects can be compiled as C++ with 'compileas'
--
function suite.cFilesGetsCompiledWithCXXWithCompileas()
files { "src/hello.c", "src/test.c" }
filter { "files:src/hello.c" }
compileas "C++"
prepare()
test.capture [[
$(OBJDIR)/hello.o: src/hello.c
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
ifeq ($(config),debug)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
endif
ifeq ($(config),release)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
endif
$(OBJDIR)/test.o: src/test.c
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
]]
end
--
-- C files in C++ projects can be compiled as C++ with 'compileas' on a configuration basis
--
function suite.cFilesGetsCompiledWithCXXWithCompileasDebugOnly()
files { "src/test.c", "src/hello.c" }
filter { "configurations:Debug", "files:src/hello.c" }
compileas "C++"
prepare()
test.capture [[
$(OBJDIR)/hello.o: src/hello.c
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
ifeq ($(config),debug)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
endif
ifeq ($(config),release)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
endif
$(OBJDIR)/test.o: src/test.c
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
]]
end
--
-- If a custom build rule is supplied, it should be used.

View File

@ -198,6 +198,21 @@
end
end
function cpp.determineFiletype(cfg, node)
-- determine which filetype to use
local filecfg = fileconfig.getconfig(node, cfg)
local fileext = path.getextension(node.abspath):lower()
if filecfg and filecfg.compileas then
if p.languages.isc(filecfg.compileas) then
fileext = ".c"
elseif p.languages.iscpp(filecfg.compileas) then
fileext = ".cpp"
end
end
return fileext;
end
function cpp.addGeneratedFile(cfg, source, filename)
-- mark that we have generated files.
cfg.project.hasGeneratedFiles = true
@ -220,9 +235,11 @@
fileconfig.addconfig(node, cfg)
end
-- determine which filetype to use
local fileext = cpp.determineFiletype(cfg, node)
-- add file to the fileset.
local filesets = cfg.project._gmake.filesets
local kind = filesets[path.getextension(filename):lower()] or "CUSTOM"
local kind = filesets[fileext] or "CUSTOM"
-- don't link generated object files automatically if it's explicitly
-- disabled.
@ -260,7 +277,8 @@
function cpp.addRuleFile(cfg, node)
local rules = cfg.project._gmake.rules
local rule = rules[path.getextension(node.abspath):lower()]
local fileext = cpp.determineFiletype(cfg, node)
local rule = rules[fileext]
if rule then
local filecfg = fileconfig.getconfig(node, cfg)
@ -589,6 +607,14 @@
return fcfg.flagsVariable
end
if fcfg and fcfg.compileas then
if p.languages.isc(fcfg.compileas) then
return 'ALL_CFLAGS'
elseif p.languages.iscpp(fcfg.compileas) then
return 'ALL_CXXFLAGS'
end
end
if path.iscfile(file.name) then
return 'ALL_CFLAGS'
else

View File

@ -97,6 +97,61 @@ $(OBJDIR)/test.o: src/test.cpp
]]
end
--
-- C files in C++ projects can be compiled as C++ with compileas
--
function suite.cFilesGetsCompiledWithCXXWithCompileas()
files { "src/hello.c", "src/test.c" }
filter { "files:src/hello.c" }
compileas "C++"
prepare()
test.capture [[
# File Rules
# #############################################
$(OBJDIR)/hello.o: src/hello.c
@echo $(notdir $<)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/test.o: src/test.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
]]
end
--
-- C files in C++ projects can be compiled as C++ with 'compileas' on a configuration basis
--
function suite.cFilesGetsCompiledWithCXXWithCompileasDebugOnly()
files { "src/hello.c", "src/test.c" }
filter { "configurations:Debug", "files:src/hello.c" }
compileas "C++"
prepare()
test.capture [[
# File Rules
# #############################################
$(OBJDIR)/test.o: src/test.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
ifeq ($(config),debug)
$(OBJDIR)/hello.o: src/hello.c
@echo $(notdir $<)
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
else ifeq ($(config),release)
$(OBJDIR)/hello.o: src/hello.c
@echo $(notdir $<)
$(SILENT) $(CC) $(ALL_CFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
else
$(error "invalid configuration $(config)")
endif
]]
end
--
-- If a custom build rule is supplied, it should be used.

View File

@ -437,6 +437,33 @@
]]
end
--
-- Check handling of per-file compileas options.
--
function suite.onCompileAs()
files { "hello.c" }
filter "files:hello.c"
compileas "C++"
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="hello.c">
<CompileAs>CompileAsCpp</CompileAs>
]]
end
function suite.onCompileAsDebug()
files { "hello.c" }
filter { "configurations:Debug", "files:hello.c" }
compileas "C++"
prepare()
test.capture [[
<ItemGroup>
<ClCompile Include="hello.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CompileAsCpp</CompileAs>
]]
end
--
-- Check handling of per-file optimization levels.

View File

@ -744,6 +744,7 @@
m.basicRuntimeChecks,
m.exceptionHandling,
m.compileAsManaged,
m.compileAs,
m.runtimeTypeInfo,
m.warningLevelFile,
}
@ -1545,11 +1546,11 @@
end
function m.compileAs(cfg)
function m.compileAs(cfg, condition)
if p.languages.isc(cfg.compileas) then
m.element("CompileAs", nil, "CompileAsC")
m.element("CompileAs", condition, "CompileAsC")
elseif p.languages.iscpp(cfg.compileas) then
m.element("CompileAs", nil, "CompileAsCpp")
m.element("CompileAs", condition, "CompileAsCpp")
end
end

View File

@ -161,6 +161,19 @@
]]
end
function suite.PBXFileReference_ListsSourceFilesCompileAs()
files { "source.c" }
filter { "files:source.c" }
compileas "C++"
prepare()
xcode.PBXFileReference(tr)
test.capture [[
/* Begin PBXFileReference section */
[MyProject:product] /* MyProject */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; name = MyProject; path = MyProject; sourceTree = BUILT_PRODUCTS_DIR; };
[source.c] /* source.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; name = source.c; path = source.c; sourceTree = "<group>"; };
]]
end
function suite.PBXFileReference_ListsXibCorrectly()
files { "English.lproj/MainMenu.xib", "French.lproj/MainMenu.xib" }

View File

@ -79,6 +79,20 @@
return false
end
--
-- Return 'explicitFileType' if the given file is being set with 'compileas'
--
function xcode.getfiletypekey(node, cfg)
if node.configs then
local filecfg = fileconfig.getconfig(node, cfg)
if filecfg and filecfg["compileas"] then
return "explicitFileType"
end
end
return "lastKnownFileType"
end
--
-- Return the Xcode type for a given file, based on the file extension.
--
@ -93,7 +107,11 @@
if node.configs then
local filecfg = fileconfig.getconfig(node, cfg)
if filecfg then
if filecfg.language == "ObjC" then
if p.languages.isc(filecfg.compileas) then
return "sourcecode.c.c"
elseif p.languages.iscpp(filecfg.compileas) then
return "sourcecode.cpp.cpp"
elseif filecfg.language == "ObjC" then
return "sourcecode.c.objc"
elseif filecfg.language == "ObjCpp" then
return "sourcecode.cpp.objcpp"
@ -495,8 +513,8 @@
end
--end
end
_p(level,'%s /* %s */ = {isa = PBXFileReference; lastKnownFileType = %s; name = %s; path = %s; sourceTree = %s; };',
node.id, node.name, xcode.getfiletype(node, cfg), stringifySetting(node.name), stringifySetting(pth), stringifySetting(src))
_p(level,'%s /* %s */ = {isa = PBXFileReference; %s = %s; name = %s; path = %s; sourceTree = %s; };',
node.id, node.name, xcode.getfiletypekey(node, cfg), xcode.getfiletype(node, cfg), stringifySetting(node.name), stringifySetting(pth), stringifySetting(src))
end
end
end