diff --git a/CHANGES.txt b/CHANGES.txt index 01d95057..9e31e213 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -28,6 +28,7 @@ * Added NoRuntimeChecks flag to disable Visual Studio default checks * Generated Visual Studio GUIDs are now deterministic * Added support for Visual Studio solution groups +* Added dependson() to specify non-linking dependencies (Alexey Orlov) ------- diff --git a/src/actions/make/_make.lua b/src/actions/make/_make.lua index 4c52bbcd..7e25f394 100644 --- a/src/actions/make/_make.lua +++ b/src/actions/make/_make.lua @@ -20,7 +20,7 @@ -- temporary, until I can phase out the legacy implementations isnextgen = true, - + valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" }, valid_languages = { "C", "C++", "C#" }, @@ -42,11 +42,11 @@ premake.generate(prj, makefile, make.cpp.generate) end end, - + oncleansolution = function(sln) premake.clean.file(sln, make.getmakefilename(sln, false)) end, - + oncleanproject = function(prj) premake.clean.file(prj, make.getmakefilename(prj, true)) end @@ -63,7 +63,7 @@ -- find the right configuration iterator function for this object local eachconfig = iif(target.project, project.eachconfig, solution.eachconfig) local iter = eachconfig(target) - + -- grab the first configuration and write the block local cfg = iter() if cfg then @@ -109,7 +109,7 @@ result = result:gsub(" ", "\\ ") result = result:gsub("%(", "\\%(") result = result:gsub("%)", "\\%)") - + -- leave $(...) shell replacement sequences alone result = result:gsub("$\\%((.-)\\%)", "$%(%1%)") return result @@ -126,10 +126,10 @@ function make.getmakefilename(this, searchprjs) local count = 0 for sln in premake.solution.each() do - if sln.location == this.location then - count = count + 1 + if sln.location == this.location then + count = count + 1 end - + if searchprjs then for _, prj in ipairs(sln.projects) do if prj.location == this.location then @@ -138,11 +138,11 @@ end end end - + if count == 1 then return "Makefile" else - return this.name .. ".make" + return ".make" end end @@ -157,7 +157,7 @@ function make.header(target) -- find the right configuration iterator function for this object local kind = iif(target.project, "project", "solution") - + _p('# %s %s makefile autogenerated by Premake', premake.action.current().shortname, kind) _p('') @@ -194,7 +194,7 @@ _p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname) _p('endif') _p('') - end + end -- @@ -222,7 +222,7 @@ -- function make.targetconfig(cfg) - local targetdir = + local targetdir = _p(' TARGETDIR = %s', make.esc(project.getrelative(cfg.project, cfg.buildtarget.directory))) _p(' TARGET = $(TARGETDIR)/%s', make.esc(cfg.buildtarget.name)) _p(' OBJDIR = %s', make.esc(project.getrelative(cfg.project, cfg.objdir))) @@ -238,138 +238,3 @@ value = value:gsub("[()]", "") return value end - - - ------------------------------------------------------------------------------ --- Everything below this point is a candidate for deprecation ------------------------------------------------------------------------------ - - _MAKE = { } - - --- --- Escape a string so it can be written to a makefile. --- - - function _MAKE.esc(value) - local result - if (type(value) == "table") then - result = { } - for _,v in ipairs(value) do - table.insert(result, _MAKE.esc(v)) - end - return result - else - -- handle simple replacements - result = value:gsub("\\", "\\\\") - result = result:gsub(" ", "\\ ") - result = result:gsub("%(", "\\%(") - result = result:gsub("%)", "\\%)") - - -- leave $(...) shell replacement sequences alone - result = result:gsub("$\\%((.-)\\%)", "$%(%1%)") - return result - end - end - - - --- --- Rules for file ops based on the shell type. Can't use defines and $@ because --- it screws up the escaping of spaces and parethesis (anyone know a solution?) --- - - function premake.make_copyrule(source, target) - _p('%s: %s', target, source) - _p('\t@echo Copying $(notdir %s)', target) - _p('ifeq (posix,$(SHELLTYPE))') - _p('\t$(SILENT) cp -fR %s %s', source, target) - _p('else') - _p('\t$(SILENT) copy /Y $(subst /,\\\\,%s) $(subst /,\\\\,%s)', source, target) - _p('endif') - end - - function premake.make_mkdirrule(var) - _p('\t@echo Creating %s', var) - _p('ifeq (posix,$(SHELLTYPE))') - _p('\t$(SILENT) mkdir -p %s', var) - _p('else') - _p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', var) - _p('endif') - _p('') - end - - - --- --- Returns a list of object names, properly escaped to be included in the makefile. --- - - function _MAKE.getnames(tbl) - local result = table.extract(tbl, "name") - for k,v in pairs(result) do - result[k] = _MAKE.esc(v) - end - return result - end - - - --- --- Write out the raw settings blocks. --- - - function make.settings_old(cfg, cc) - if #cfg.makesettings > 0 then - for _, value in ipairs(cfg.makesettings) do - _p(value) - end - end - - local toolsettings = cc.platforms[cfg.platform].cfgsettings - if toolsettings then - _p(toolsettings) - end - end - - --- --- Register the "gmake" action --- - - newaction { - trigger = "gmake", - shortname = "GNU Make", - description = "Generate GNU makefiles for POSIX, MinGW, and Cygwin", - - valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib" }, - - valid_languages = { "C", "C++", "C#" }, - - valid_tools = { - cc = { "gcc" }, - dotnet = { "mono", "msnet", "pnet" }, - }, - - onsolution = function(sln) - premake.generate(sln, make.getmakefilename(sln, false), premake.make_solution) - end, - - onproject = function(prj) - local makefile = make.getmakefilename(prj, true) - if premake.isdotnetproject(prj) then - premake.generate(prj, makefile, premake.make_csharp) - else - premake.generate(prj, makefile, premake.make_cpp) - end - end, - - oncleansolution = function(sln) - premake.clean.file(sln, make.getmakefilename(sln, false)) - end, - - oncleanproject = function(prj) - premake.clean.file(prj, make.getmakefilename(prj, true)) - end - } diff --git a/src/actions/make/make_solution.lua b/src/actions/make/make_solution.lua index 9ccff439..31e08691 100644 --- a/src/actions/make/make_solution.lua +++ b/src/actions/make/make_solution.lua @@ -58,8 +58,10 @@ _p('clean:') for prj in solution.eachproject_ng(sln) do local slnpath = solution.getlocation(sln) - local prjpath = path.getrelative(slnpath, project.getlocation(prj)) - _p(1,'@${MAKE} --no-print-directory -C %s -f %s clean', make.esc(prjpath), make.esc(make.getmakefilename(prj, true))) + local prjpath = project.getfilename(prj, make.getmakefilename(prj, true)) + local prjdir = path.getdirectory(path.getrelative(slnpath, prjpath)) + local prjname = path.getname(prjpath) + _p(1,'@${MAKE} --no-print-directory -C %s -f %s clean', make.esc(prjdir), make.esc(prjname)) end _p('') end @@ -111,19 +113,21 @@ function make.projectrules(sln) for prj in solution.eachproject_ng(sln) do local deps = project.getdependencies(prj) - deps = table.extract(deps, "name") + deps = table.extract(deps, "name") _p('%s: %s', make.esc(prj.name), table.concat(deps, " ")) - + local cfgvar = make.tovar(prj.name) _p('ifneq (,$(%s_config))', cfgvar) - + _p(1,'@echo "==== Building %s ($(%s_config)) ===="', prj.name, cfgvar) local slnpath = solution.getlocation(sln) - local prjpath = path.getrelative(slnpath, project.getlocation(prj)) - local filename = make.getmakefilename(prj, true) - _p(1,'@${MAKE} --no-print-directory -C %s -f %s config=$(%s_config)', make.esc(prjpath), make.esc(filename), cfgvar) - + local prjpath = project.getfilename(prj, make.getmakefilename(prj, true)) + local prjdir = path.getdirectory(path.getrelative(slnpath, prjpath)) + local prjname = path.getname(prjpath) + + _p(1,'@${MAKE} --no-print-directory -C %s -f %s config=$(%s_config)', make.esc(prjdir), make.esc(prjname), cfgvar) + _p('endif') _p('') end diff --git a/src/project/project.lua b/src/project/project.lua index 46202e5a..89afb263 100755 --- a/src/project/project.lua +++ b/src/project/project.lua @@ -85,10 +85,10 @@ -- create a list of build cfg/platform pairs for the project local cfgs = table.fold(ctx.configurations or {}, ctx.platforms or {}) - + -- roll up any config maps from the contained configurations project.bakeconfigmap(ctx, prj.configset, cfgs) - + -- apply any mappings to the project's list of configurations and platforms ctx._cfglist = project.bakeconfiglist(ctx, cfgs) @@ -138,7 +138,7 @@ -- -- It can be useful to state "use this map if this configuration is present". -- To allow this to happen, config maps that are specified within a project --- configuration are allowed to "bubble up" to the top level. Currently, +-- configuration are allowed to "bubble up" to the top level. Currently, -- maps are the only values that get this special behavior. -- -- @param ctx @@ -153,7 +153,7 @@ function project.bakeconfigmap(ctx, cset, cfgs) -- It can be useful to state "use this map if this configuration is present". -- To allow this to happen, config maps that are specified within a project - -- configuration are allowed to "bubble up" to the top level. Currently, + -- configuration are allowed to "bubble up" to the top level. Currently, -- maps are the only values that get this special behavior. for _, cfg in ipairs(cfgs) do local terms = table.join(ctx.terms, (cfg[1] or ""):lower(), (cfg[2] or ""):lower()) @@ -186,26 +186,26 @@ for i, cfg in ipairs(cfgs) do cfgs[i] = project.mapconfig(ctx, cfg[1], cfg[2]) end - + -- walk through the result and remove any duplicates local buildcfgs = {} local platforms = {} - + for _, pairing in ipairs(cfgs) do local buildcfg = pairing[1] local platform = pairing[2] - + if not table.contains(buildcfgs, buildcfg) then table.insert(buildcfgs, buildcfg) end - + if platform and not table.contains(platforms, platform) then table.insert(platforms, platform) end end -- merge these de-duped lists back into pairs for the final result - return table.fold(buildcfgs, platforms) + return table.fold(buildcfgs, platforms) end @@ -254,7 +254,7 @@ -- if a kind is set, allow that to influence the configuration context.addterms(ctx, ctx.kind) - + -- process that context.compile(ctx) @@ -264,7 +264,7 @@ ctx.buildcfg = buildcfg ctx.platform = platform ctx.action = _ACTION - ctx.language = prj.language + ctx.language = prj.language -- TODO: OLD, REMOVE: build an old-style configuration to wrap context, for now @@ -321,10 +321,10 @@ -- - - - - + + + + -- Returns an iterator function for the configuration objects contained by -- the project. Each configuration corresponds to a build configuration/ -- platform pair (i.e. "Debug|x32") as specified in the solution. @@ -427,7 +427,7 @@ -- function project.getdependencies(prj) - if not prj.dependencies then + if not prj.dependencies then local result = {} local function add_to_project_list(cfg, depproj, result) local dep = premake.solution.findproject(cfg.solution, depproj) @@ -488,14 +488,22 @@ -- @param prj -- The project object to query. -- @param ext --- An optional file extension to add, with the leading dot. +-- An optional file extension to add, with the leading dot. If provided +-- without a leading dot, it will treated as a file name. -- @return -- The absolute path to the project's file. -- function project.getfilename(prj, ext) - local fn = path.join(project.getlocation(prj), prj.filename) - if ext then fn = fn .. ext end + local fn = project.getlocation(prj) + if ext and not ext:startswith(".") then + fn = path.join(fn, ext) + else + fn = path.join(fn, prj.filename) + if ext then + fn = fn .. ext + end + end return fn end diff --git a/tests/project/test_filename.lua b/tests/project/test_filename.lua index 4c8e028d..de209763 100644 --- a/tests/project/test_filename.lua +++ b/tests/project/test_filename.lua @@ -15,11 +15,11 @@ -- local sln - + function suite.setup() sln, prj = test.createsolution() end - + local function prepare() prj = premake.solution.getproject_ng(sln, 1) end @@ -87,3 +87,14 @@ test.isequal("MyProject", path.getname(project.getfilename(prj))) end + +-- +-- If extension is provided without a leading dot, it should override any +-- project filename. +-- + + function suite.canOverrideFilename() + prepare() + test.isequal("Makefile", path.getname(project.getfilename(prj, "Makefile"))) + end + diff --git a/tests/test_premake.lua b/tests/test_premake.lua index c2eb0f65..4750634b 100644 --- a/tests/test_premake.lua +++ b/tests/test_premake.lua @@ -17,10 +17,10 @@ function suite.setup() sln = test.createsolution() location "MyLocation" - prj = premake.solution.getproject_ng(sln, 1) + prj = premake.solution.getproject_ng(sln, 1) end - + -- -- generate() tests --