Merge remote-tracking branch 'refs/remotes/premake/master'

This commit is contained in:
Lynix 2017-05-14 14:11:16 +02:00
commit 57d6e06a2f
68 changed files with 2311 additions and 871 deletions

View File

@ -53,7 +53,7 @@ mingw: $(SRC)
osx: $(SRC)
mkdir -p build/bootstrap
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_USE_MACOSX -I"$(LUA_DIR)" -framework CoreServices $?
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_USE_MACOSX -I"$(LUA_DIR)" -framework CoreServices -framework Foundation -framework Security $?
./build/bootstrap/premake_bootstrap embed
./build/bootstrap/premake_bootstrap --to=build/bootstrap gmake
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN`
@ -65,10 +65,15 @@ linux: $(SRC)
./build/bootstrap/premake_bootstrap --to=build/bootstrap gmake
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN`
windows: $(SRC)
windows-base: $(SRC)
if not exist build\bootstrap (mkdir build\bootstrap)
cl /Fo.\build\bootstrap\ /Fe.\build\bootstrap\premake_bootstrap.exe /DPREMAKE_NO_BUILTIN_SCRIPTS /I"$(LUA_DIR)" user32.lib ole32.lib $**
cl /Fo.\build\bootstrap\ /Fe.\build\bootstrap\premake_bootstrap.exe /DPREMAKE_NO_BUILTIN_SCRIPTS /I"$(LUA_DIR)" user32.lib ole32.lib advapi32.lib $**
.\build\bootstrap\premake_bootstrap.exe embed
.\build\bootstrap\premake_bootstrap --to=build/bootstrap $(MSDEV)
windows: windows-base
devenv .\build\bootstrap\Premake5.sln /Upgrade
devenv .\build\bootstrap\Premake5.sln /Build Release
windows-msbuild: windows-base
msbuild /p:Configuration=Release .\build\bootstrap\Premake5.sln

View File

@ -5,6 +5,43 @@
See https://github.com/premake/premake-core/wiki/What's-New-in-5.0
for the complete list of changes from the Premake 4.x series.
Since 5.0-alpha10:
* PR 523 New API symbols() replaces and extends "Symbols" flag
* PR 524 New API symbolspath() specifies location of symbol database
* PR 556 Add initialization hook for actions
* PR 553 Enable "list of paths" for rule properties
* PR 555 Allow multiple extensions for custom rules
* PR 561 Add IA32 to vectorextensions()
* PR 568 New API runpathdirs() adds rpath support
* PR 525 Add support for Visual Studio Debug Fast Link setting
* PR 401 Enable GCC link mode with ":static", ":shared"
* PR 543 Remove architecture specific include paths on macOS
* PR 554 Improve token expansion in rules
* PR 570 Normalize paths to os.execute()
* PR 546 Switch from openssl to mbedtls
* PR 545 compilebuildoutputs() adds generated files to build
* PR 575 New "raw" exporter
* PR 581 Fix path.normalize() handling of ".." sequences
* PR 587 Fix os.copyfile() handling of paths with spaces
* PR 597 Enable edit-and-continue for VS 2015 64-bit builds
* PR 583 Allow duplicate build commands
* PR 605 Fix for objdir() forced path operator "!"
* PR 603 Allow toolset-specific arguments to static linker
* PR 608 Allow Visual Studio StaticLib projects to link dependencies
* PR 610 Add defines and include paths to makefile projects
* PR 611 Prevent force includes from breaking precompiled headers
* PR 613 Fix os.match() detection of dot files
* PR 607 Remove support for deprecated MonoDevelop project formats
* PR 600 Fix VS support for symbolpath()
* PR 512 Make Clang default toolset for macOS
* PR 624 GCC support for C90 and C99
* PR 628 New API linkbuildoutputs() disables automatic linking of *.obj files
* PR 635 Improved parallelization of Makefile builds
* PR 619 Per-file configuration support for C# projects
* PR 649 Fix Visual Studio 2015 solution version identifier
* PR 645 Add initial Visual Studio 2017 support
Since 5.0-alpha9:
* New: `symbols()`, replaces and extends flags {"Symbols"}

View File

@ -2,7 +2,7 @@ project "curl-lib"
language "C"
kind "StaticLib"
includedirs { "include", "lib", "../mbedtls/include/" }
defines { "BUILDING_LIBCURL", "CURL_STATICLIB", "HTTP_ONLY", "USE_MBEDTLS" }
defines { "BUILDING_LIBCURL", "CURL_STATICLIB", "HTTP_ONLY" }
warnings "off"
if not _OPTIONS["no-zlib"] then
@ -15,6 +15,15 @@ project "curl-lib"
"**.h",
"**.c"
}
filter { "system:windows" }
defines { "USE_SCHANNEL", "USE_WINDOWS_SSPI" }
filter { "system:macosx" }
defines { "USE_DARWINSSL" }
filter { "system:not windows", "system:not macosx" }
defines { "USE_MBEDTLS" }
filter { "system:linux" }
defines { "CURL_HIDDEN_SYMBOLS" }

View File

@ -4,8 +4,9 @@
-- Author: Ryan Pusztai
-- Modified by: Andrea Zanellato
-- Manu Evans
-- Tom van Dijck
-- Created: 2013/05/06
-- Copyright: (c) 2008-2015 Jason Perkins and the Premake project
-- Copyright: (c) 2008-2016 Jason Perkins and the Premake project
--
local p = premake
@ -196,7 +197,7 @@
end
local toolset = m.getcompiler(cfg)
local cxxflags = table.concat(table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions), ";")
local cxxflags = table.concat(table.join(toolset.getcxxflags(cfg), cfg.buildoptions), ";")
local cflags = table.concat(table.join(toolset.getcflags(cfg), cfg.buildoptions), ";")
local asmflags = ""
local pch = ""
@ -219,23 +220,10 @@
end
local toolset = m.getcompiler(cfg)
local flags = table.join(toolset.getldflags(cfg), cfg.linkoptions)
local withdeps = table.join(flags, codelite.getSiblingLinks(cfg))
local ldflags = table.concat(withdeps, ";")
local flags = table.join(toolset.getldflags(cfg), cfg.linkoptions, toolset.getlinks(cfg))
_x(3, '<Linker Required="yes" Options="%s">', ldflags)
_x(3, '<Linker Required="yes" Options="%s">', table.concat(flags, ";"))
if #cfg.libdirs > 0 then
local libdirs = project.getrelative(cfg.project, cfg.libdirs)
for _, libpath in ipairs(libdirs) do
_x(4, '<LibraryPath Value="%s" />', libpath)
end
end
local links = codelite.getLinks(cfg)
for _, libname in ipairs(links) do
_x(4, '<Library Value="%s" />', libname)
end
_p(3, '</Linker>')
end
@ -268,7 +256,8 @@
local targetpath = project.getrelative(prj, cfg.buildtarget.directory)
local objdir = project.getrelative(prj, cfg.objdir)
local targetname = project.getrelative(prj, cfg.buildtarget.abspath)
local command = iif(isExe, targetname, "")
local workingdir = cfg.debugdir or prj.location
local command = iif(isExe, path.getrelative(workingdir, cfg.buildtarget.abspath), "")
local cmdargs = iif(isExe, table.concat(cfg.debugargs, " "), "") -- TODO: should this be debugargs instead?
local useseparatedebugargs = "no"
local debugargs = ""

View File

@ -89,20 +89,16 @@
codelite.project.linker(cfg)
test.capture [[
<Linker Required="yes" Options="">
<LibraryPath Value="test" />
<LibraryPath Value="test2" />
</Linker>
]]
end
function suite.OnProjectCfg_Libs()
links { "lib", "lib2" }
links { "a", "b" }
prepare()
codelite.project.linker(cfg)
test.capture [[
<Linker Required="yes" Options="">
<Library Value="lib" />
<Library Value="lib2" />
<Linker Required="yes" Options="-la;-lb">
</Linker>
]]
end

View File

@ -1021,6 +1021,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CONFIGURATION_BUILD_DIR = bin/Debug;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_DYNAMIC_NO_PIC = NO;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = MyProject;
@ -1265,6 +1266,36 @@
prepare()
xcode.XCBuildConfiguration_Project(tr, tr.configs[1])
test.capture [[
[MyProject:Debug(2)] /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
CONFIGURATION_BUILD_DIR = "$(SYMROOT)";
CONFIGURATION_TEMP_DIR = "$(OBJROOT)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
OBJROOT = obj/Debug;
ONLY_ACTIVE_ARCH = NO;
SYMROOT = bin/Debug;
USER_HEADER_SEARCH_PATHS = (
../include,
../libs,
"\"../name with spaces\"",
);
};
name = Debug;
};
]]
end
function suite.XCBuildConfigurationProject_OnSysIncludeDirs()
sysincludedirs { "../include", "../libs", "../name with spaces" }
prepare()
xcode.XCBuildConfiguration_Project(tr, tr.configs[1])
test.capture [[
[MyProject:Debug(2)] /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1280,6 +1311,7 @@
../include,
../libs,
"\"../name with spaces\"",
"$(inherited)",
);
OBJROOT = obj/Debug;
ONLY_ACTIVE_ARCH = NO;
@ -1290,7 +1322,6 @@
]]
end
function suite.XCBuildConfigurationProject_OnBuildOptions()
buildoptions { "build option 1", "build option 2" }
prepare()

View File

@ -884,7 +884,7 @@
settings['ALWAYS_SEARCH_USER_PATHS'] = 'NO'
if not (cfg.symbols == p.ON) then
if cfg.symbols ~= p.OFF then
settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf-with-dsym'
end
@ -983,12 +983,18 @@
settings['CONFIGURATION_TEMP_DIR'] = '$(OBJROOT)'
if cfg.symbols == p.ON then
if config.isDebugBuild(cfg) then
settings['COPY_PHASE_STRIP'] = 'NO'
end
settings['GCC_C_LANGUAGE_STANDARD'] = 'gnu99'
if cfg.flags['C++14'] then
settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++14'
elseif cfg.flags['C++11'] then
settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++0x'
end
if cfg.exceptionhandling == p.OFF then
settings['GCC_ENABLE_CPP_EXCEPTIONS'] = 'NO'
end
@ -1013,7 +1019,11 @@
settings['GCC_PREFIX_HEADER'] = cfg.pchheader
end
settings['GCC_PREPROCESSOR_DEFINITIONS'] = cfg.defines
local escapedDefines = { }
for i,v in ipairs(cfg.defines) do
escapedDefines[i] = escapeArg(v)
end
settings['GCC_PREPROCESSOR_DEFINITIONS'] = escapedDefines
settings["GCC_SYMBOLS_PRIVATE_EXTERN"] = 'NO'
@ -1028,7 +1038,16 @@
for i,v in ipairs(includedirs) do
cfg.includedirs[i] = premake.quoted(v)
end
settings['HEADER_SEARCH_PATHS'] = table.join(cfg.includedirs, cfg.sysincludedirs)
settings['USER_HEADER_SEARCH_PATHS'] = cfg.includedirs
local sysincludedirs = project.getrelative(cfg.project, cfg.sysincludedirs)
for i,v in ipairs(sysincludedirs) do
cfg.sysincludedirs[i] = premake.quoted(v)
end
if not table.isempty(cfg.sysincludedirs) then
table.insert(cfg.sysincludedirs, "$(inherited)")
end
settings['HEADER_SEARCH_PATHS'] = cfg.sysincludedirs
for i,v in ipairs(cfg.libdirs) do
cfg.libdirs[i] = premake.project.getrelative(cfg.project, cfg.libdirs[i])

View File

@ -87,24 +87,12 @@
tr.products = tree.insert(tr, tree.new("Products"))
-- the special folder "Projects" lists sibling project dependencies
tr.projects = tree.new("Projects")
for _, dep in ipairs(project.getdependencies(prj, "sibling", "object")) do
-- create a child node for the dependency's xcodeproj
local xcpath = xcode.getxcodeprojname(dep)
local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
xcnode.path = xcpath
xcnode.project = dep
xcnode.productgroupid = xcode.newid(xcnode.name, "prodgrp")
xcnode.productproxyid = xcode.newid(xcnode.name, "prodprox")
xcnode.targetproxyid = xcode.newid(xcnode.name, "targprox")
xcnode.targetdependid = xcode.newid(xcnode.name, "targdep")
-- create a grandchild node for the dependency's link target
local lprj = premake.workspace.findproject(prj.workspace, dep.name)
local cfg = project.findClosestMatch(lprj, prj.configurations[1])
node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
node.path = cfg.linktarget.fullpath
node.cfg = cfg
tr.projects = tree.new("Projects")
for _, dep in ipairs(project.getdependencies(prj, "linkOnly")) do
xcode.addDependency(prj, tr, dep, true)
end
for _, dep in ipairs(project.getdependencies(prj, "dependOnly")) do
xcode.addDependency(prj, tr, dep, false)
end
if #tr.projects.children > 0 then
@ -120,7 +108,7 @@
node.isResource = xcode.isItemResource(prj, node)
-- assign build IDs to buildable files
if xcode.getbuildcategory(node) then
if xcode.getbuildcategory(node) and not node.excludefrombuild then
node.buildid = xcode.newid(node.name, "build", node.path)
end
@ -145,6 +133,30 @@
return tr
end
function xcode.addDependency(prj, tr, dep, build)
-- create a child node for the dependency's xcodeproj
local xcpath = xcode.getxcodeprojname(dep)
local xcnode = tree.insert(tr.projects, tree.new(path.getname(xcpath)))
xcnode.path = xcpath
xcnode.project = dep
xcnode.productgroupid = xcode.newid(xcnode.name, "prodgrp")
xcnode.productproxyid = xcode.newid(xcnode.name, "prodprox")
xcnode.targetproxyid = xcode.newid(xcnode.name, "targprox")
xcnode.targetdependid = xcode.newid(xcnode.name, "targdep")
-- create a grandchild node for the dependency's link target
local lprj = premake.workspace.findproject(prj.workspace, dep.name)
local cfg = project.findClosestMatch(lprj, prj.configurations[1])
node = tree.insert(xcnode, tree.new(cfg.linktarget.name))
node.path = cfg.linktarget.fullpath
node.cfg = cfg
-- don't link the dependency if it's a dependency only
if build == false then
node.excludefrombuild = true
end
end
---
-- Generate an Xcode .xcodeproj for a Premake project.

View File

@ -17,24 +17,25 @@
targetname "premake5"
language "C"
kind "ConsoleApp"
defines { "PREMAKE_NO_BUILTIN_SCRIPTS" }
flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" }
includedirs { "src/host/lua/src" }
includedirs { "contrib/lua/src" }
files
{
"*.txt", "**.lua",
"src/**.h", "src/**.c",
"src/host/scripts.c"
"contrib/lua/src/*.c", "contrib/lua/src/*.h",
"src/host/*.c"
}
excludes
{
"src/host/lua/src/lauxlib.c",
"src/host/lua/src/lua.c",
"src/host/lua/src/luac.c",
"src/host/lua/src/print.c",
"src/host/lua/**.lua",
"src/host/lua/etc/*.c"
"contrib/lua/src/lauxlib.c",
"contrib/lua/src/lua.c",
"contrib/lua/src/luac.c",
"contrib/lua/src/print.c",
"contrib/lua/**.lua",
"contrib/lua/etc/*.c"
}
configuration "Debug"
@ -54,7 +55,7 @@
defines {"_CRT_SECURE_NO_DEPRECATE" }
configuration "windows"
links { "ole32" }
links { "ole32", "advapi32" }
configuration "linux or bsd or hurd"
defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" }

View File

@ -136,7 +136,7 @@
end
if not _OPTIONS["no-curl"] then
includedirs { "contrib/curl/include" }
links { "curl-lib", "mbedtls-lib" }
links { "curl-lib" }
end
files
@ -159,7 +159,7 @@
targetdir "bin/release"
filter "system:windows"
links { "ole32", "ws2_32" }
links { "ole32", "ws2_32", "advapi32" }
filter "system:linux or bsd or hurd"
defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" }
@ -169,9 +169,14 @@
filter "system:linux or hurd"
links { "dl", "rt" }
filter { "system:not windows", "system:not macosx" }
if not _OPTIONS["no-curl"] then
links { "mbedtls-lib" }
end
filter "system:macosx"
defines { "LUA_USE_MACOSX" }
links { "CoreServices.framework" }
links { "CoreServices.framework", "Foundation.framework", "Security.framework" }
filter { "system:macosx", "action:gmake" }
toolset "clang"

View File

@ -3,9 +3,9 @@ PREMAKE RELEASE CHECKLIST
PREP
* Make sure submodules are up to date
* Create a new release branch and push to origin
* Create working branch for release prep
* Notify developer list of release branch availability; request testing
* Update CHANGES.txt and CONTRIBUTORS.txt
@ -34,7 +34,7 @@ RELEASE
CYCLE
* Update to new dev version in src/host/premake.c and commit
* Update to new dev version in src/host/premake.h and commit
* Merge working branch to master

View File

@ -19,7 +19,9 @@
"base/tools.lua",
"base/tree.lua",
"base/globals.lua",
"base/moduledownloader.lua",
"base/semver.lua",
"base/http.lua",
-- configuration data
"base/field.lua",
@ -86,6 +88,7 @@
"actions/vstudio/vs2012.lua",
"actions/vstudio/vs2013.lua",
"actions/vstudio/vs2015.lua",
"actions/vstudio/vs2017.lua",
-- Clean action
"actions/clean/_clean.lua",

View File

@ -214,6 +214,7 @@
kind = "list:string",
tokens = true,
pathVars = true,
allowDuplicates = true,
}
api.register {
@ -448,6 +449,12 @@
tokens = true,
}
api.register {
name = "functionlevellinking",
scope = "config",
kind = "boolean"
}
api.register {
name = "flags",
scope = "config",
@ -503,6 +510,9 @@
"WPF",
"C++11",
"C++14",
"C90",
"C99",
"C11",
},
aliases = {
FatalWarnings = { "FatalWarnings", "FatalCompileWarnings", "FatalLinkWarnings" },
@ -523,6 +533,12 @@
}
}
api.register {
name = "floatingpointexceptions",
scope = "config",
kind = "boolean"
}
api.register {
name = "inlining",
scope = "config",
@ -654,6 +670,12 @@
tokens = true,
}
api.register {
name = "intrinsics",
scope = "config",
kind = "boolean"
}
api.register {
name = "bindirs",
scope = "config",
@ -701,6 +723,12 @@
tokens = true,
}
api.register {
name = "linkbuildoutputs",
scope = "config",
kind = "boolean"
}
api.register {
name = "linkoptions",
scope = "config",
@ -960,6 +988,12 @@
}
}
api.register {
name = "stringpooling",
scope = "config",
kind = "boolean"
}
api.register {
name = "symbols",
scope = "config",
@ -969,6 +1003,7 @@
"On",
"Off",
"FastLink", -- Visual Studio 2015+ only, considered 'On' for all other cases.
"Full", -- Visual Studio 2017+ only, considered 'On' for all other cases.
},
}

View File

@ -58,6 +58,7 @@
-- list of paths where to look for the module
local paths = {
".modules/" .. full,
"modules/" .. full,
full,
name .. ".lua"

View File

@ -144,8 +144,19 @@
_p('')
if kind == "workspace" then
_p('.NOTPARALLEL:')
_p('')
local haspch = false
for _, prj in ipairs(target.projects) do
for cfg in project.eachconfig(prj) do
if cfg.pchheader then
haspch = true
end
end
end
if haspch then
_p('.NOTPARALLEL:')
_p('')
end
end
make.defaultconfig(target)
@ -162,17 +173,20 @@
-- it screws up the escaping of spaces and parethesis (anyone know a fix?)
--
function make.mkdirRules(dirname)
_p('%s:', dirname)
_p('\t@echo Creating %s', dirname)
function make.mkdir(dirname)
_p('ifeq (posix,$(SHELLTYPE))')
_p('\t$(SILENT) mkdir -p %s', dirname)
_p('else')
_p('\t$(SILENT) mkdir $(subst /,\\\\,%s)', dirname)
_p('endif')
_p('')
end
function make.mkdirRules(dirname)
_p('%s:', dirname)
_p('\t@echo Creating %s', dirname)
make.mkdir(dirname)
_p('')
end
--
-- Format a list of values to be safely written as part of a variable assignment.

View File

@ -34,8 +34,6 @@
make.cppObjects,
make.shellType,
make.cppTargetRules,
make.targetDirRules,
make.objDirRules,
make.cppCleanRules,
make.preBuildRules,
make.preLinkRules,
@ -153,12 +151,14 @@
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)
-- resource file
elseif path.isresourcefile(node.abspath) then
_x('$(OBJDIR)/%s.res: %s', node.objname, node.relpath)
_p('\t@echo $(notdir $<)')
make.mkdir('$(OBJDIR)')
_p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(ALL_RESFLAGS)')
end
end
@ -257,10 +257,8 @@
for cfg in project.eachconfig(prj) do
local filecfg = incfg[cfg]
if filecfg then
-- if the custom build outputs an object file, add it to
-- the link step automatically to match Visual Studio
local output = project.getrelative(prj, filecfg.buildoutputs[1])
if path.isobjectfile(output) then
if path.isobjectfile(output) and (filecfg.linkbuildoutputs == true or filecfg.linkbuildoutputs == nil) then
table.insert(configs[cfg].objects, output)
else
table.insert(configs[cfg].customfiles, output)
@ -319,13 +317,13 @@
function make.cppAllRules(cfg, toolset)
if cfg.system == premake.MACOSX and cfg.kind == premake.WINDOWEDAPP then
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist')
_p('all: prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist')
_p('\t@:')
_p('')
_p('$(dir $(TARGETDIR))PkgInfo:')
_p('$(dir $(TARGETDIR))Info.plist:')
else
_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)')
_p('all: prebuild prelink $(TARGET)')
_p('\t@:')
end
end
@ -337,7 +335,7 @@
function make.cxxFlags(cfg, toolset)
_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CFLAGS)%s', make.list(toolset.getcxxflags(cfg)))
_p(' ALL_CXXFLAGS += $(CXXFLAGS) $(ALL_CPPFLAGS)%s', make.list(table.join(toolset.getcxxflags(cfg), cfg.buildoptions)))
end
@ -367,6 +365,7 @@
function make.cppTargetRules(prj)
_p('$(TARGET): $(GCH) ${CUSTOMFILES} $(OBJECTS) $(LDDEPS) $(RESOURCES)')
_p('\t@echo Linking %s', prj.name)
make.mkdir('$(TARGETDIR)')
_p('\t$(SILENT) $(LINKCMD)')
_p('\t$(POSTBUILDCMDS)')
_p('')

View File

@ -347,26 +347,7 @@
---
function vstudio.getLinks(cfg, explicit)
local links = {}
-- If we need sibling projects to be listed explicitly, grab them first
if explicit then
links = config.getlinks(cfg, "siblings", "fullpath")
end
-- Then the system libraries, which come undecorated
local system = config.getlinks(cfg, "system", "fullpath")
for i = 1, #system do
-- Add extension if required
local link = system[i]
if not p.tools.msc.getLibraryExtensions()[link:match("[^.]+$")] then
link = path.appendextension(link, ".lib")
end
table.insert(links, link)
end
return links
return p.tools.msc.getlinks(cfg, not explicit)
end

View File

@ -114,82 +114,106 @@
end
function cs2005.dofile(node, cfg, condition)
local filecfg = fileconfig.getconfig(node, cfg)
if filecfg then
local fname = path.translate(node.relpath)
-- Files that live outside of the project tree need to be "linked"
-- and provided with a project relative pseudo-path. Check for any
-- leading "../" sequences and, if found, remove them and mark this
-- path as external.
local link, count = node.relpath:gsub("%.%.%/", "")
local external = (count > 0)
-- Try to provide a little bit of flexibility by allowing virtual
-- paths for external files. Would be great to support them for all
-- files but Visual Studio chokes if file is already in project area.
if external and node.vpath ~= node.relpath then
link = node.vpath
end
-- Deduce what, if any, special attributes are required for this file.
-- For example, forms may have related source, designer, and resource
-- files which need to be associated.
local info = dotnet.fileinfo(filecfg)
-- Process any sub-elements required by this file; choose the write
-- element form to use based on the results.
local contents = premake.capture(function ()
-- Try to write file-level elements in the same order as Visual Studio
local elements = {
"AutoGen",
"CopyToOutputDirectory",
"DesignTime",
"DependentUpon",
"DesignTimeSharedInput",
"Generator",
"LastGenOutput",
"SubType",
}
for _, el in ipairs(elements) do
local value = info[el]
if value then
_p(3,"<%s>%s</%s>", el, value, el)
end
end
if info.action == "EmbeddedResource" and cfg.customtoolnamespace then
_p(3,"<CustomToolNamespace>%s</CustomToolNamespace>", cfg.customtoolnamespace)
end
end)
if #contents > 0 or external then
_p(2,'<%s%s Include="%s">', info.action, condition, fname)
if external then
_p(3,'<Link>%s</Link>', path.translate(link))
end
if #contents > 0 then
_p("%s", contents)
end
_p(2,'</%s>', info.action)
else
_p(2,'<%s%s Include="%s" />', info.action, condition, fname)
end
end
end
--
-- Write out the source files item group.
--
function cs2005.files(prj)
-- Some settings applied at project level; can't be changed in cfg
local cfg = project.getfirstconfig(prj)
-- Try to write file-level elements in the same order as Visual Studio
local elements = {
"AutoGen",
"CopyToOutputDirectory",
"DesignTime",
"DependentUpon",
"DesignTimeSharedInput",
"Generator",
"LastGenOutput",
"SubType",
}
local firstcfg = project.getfirstconfig(prj)
local tr = project.getsourcetree(prj)
premake.tree.traverse(tr, {
onleaf = function(node, depth)
local filecfg = fileconfig.getconfig(node, cfg)
local fname = path.translate(node.relpath)
-- test if all fileinfo's are going to be the same for each config.
local allsame = true
local first = nil
for cfg in project.eachconfig(prj) do
local filecfg = fileconfig.getconfig(node, cfg)
local info = dotnet.fileinfo(filecfg)
-- Files that live outside of the project tree need to be "linked"
-- and provided with a project relative pseudo-path. Check for any
-- leading "../" sequences and, if found, remove them and mark this
-- path as external.
local link, count = node.relpath:gsub("%.%.%/", "")
local external = (count > 0)
-- Try to provide a little bit of flexibility by allowing virtual
-- paths for external files. Would be great to support them for all
-- files but Visual Studio chokes if file is already in project area.
if external and node.vpath ~= node.relpath then
link = node.vpath
if first == nil then
first = info
elseif not table.equals(first, info) then
allsame = false
end
end
-- Deduce what, if any, special attributes are required for this file.
-- For example, forms may have related source, designer, and resource
-- files which need to be associated.
local info = dotnet.fileinfo(filecfg)
-- Process any sub-elements required by this file; choose the write
-- element form to use based on the results.
local contents = premake.capture(function ()
for _, el in ipairs(elements) do
local value = info[el]
if value then
_p(3,"<%s>%s</%s>", el, value, el)
end
end
end)
if #contents > 0 or external then
_p(2,'<%s Include="%s">', info.action, fname)
if external then
_p(3,'<Link>%s</Link>', path.translate(link))
end
if #contents > 0 then
_p("%s", contents)
end
if info.action == "EmbeddedResource" and cfg.customtoolnamespace then
_p(3,"<CustomToolNamespace>%s</CustomToolNamespace>", cfg.customtoolnamespace)
end
_p(2,'</%s>', info.action)
-- output to csproj.
if allsame then
cs2005.dofile(node, firstcfg, '')
else
_p(2,'<%s Include="%s" />', info.action, fname)
for cfg in project.eachconfig(prj) do
cs2005.dofile(node, cfg, ' ' .. cs2005.condition(cfg))
end
end
end
}, false)
end
@ -319,7 +343,12 @@
if decorated:find("/", nil, true) then
_x(2,'<Reference Include="%s">', name)
_x(3,'<HintPath>%s</HintPath>', path.appendextension(path.translate(decorated), ".dll"))
local decPath, decVars = decorated:match("(.-),")
if not decPath then
decPath = decorated
end
_x(3,'<HintPath>%s</HintPath>', path.appendextension(path.translate(decPath), ".dll"))
if not config.isCopyLocal(prj, original, true) then
_p(3,"<Private>False</Private>")
@ -417,9 +446,9 @@
--
function cs2005.propertyGroup(cfg)
local platform = vstudio.projectPlatform(cfg)
p.push('<PropertyGroup %s>', cs2005.condition(cfg))
local arch = cs2005.arch(cfg)
p.push('<PropertyGroup Condition=" \'$(Configuration)|$(Platform)\' == \'%s|%s\' ">', platform, arch)
if arch ~= "AnyCPU" or _ACTION > "vs2008" then
p.x('<PlatformTarget>%s</PlatformTarget>', arch)
end
@ -450,7 +479,9 @@
--
function cs2005.condition(cfg)
return string.format('Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"', premake.esc(vstudio.projectConfig(cfg)))
local platform = vstudio.projectPlatform(cfg)
local arch = cs2005.arch(cfg)
return string.format('Condition=" \'$(Configuration)|$(Platform)\' == \'%s|%s\' "', platform, arch)
end

View File

@ -822,7 +822,7 @@
function m.additionalExternalCompilerOptions(cfg, toolset)
local buildoptions = table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions)
local buildoptions = table.join(toolset.getcxxflags(cfg), cfg.buildoptions)
if not cfg.flags.NoPCH and cfg.pchheader then
table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"')
end

View File

@ -31,7 +31,10 @@
["file.basename"] = { absolute = false, token = "%(Filename)" },
["file.abspath"] = { absolute = true, token = "%(FullPath)" },
["file.relpath"] = { absolute = false, token = "%(Identity)" },
["file.path"] = { absolute = true, token = "%(RelativeDir)" },
["file.path"] = { absolute = false, token = "%(Identity)" },
["file.directory"] = { absolute = true, token = "%(RootDir)%(Directory)" },
["file.reldirectory"] = { absolute = false, token = "%(RelativeDir)" },
["file.extension"] = { absolute = false, token = "%(Extension)" },
}

View File

@ -119,7 +119,7 @@
m.stringListProperty(def)
elseif type(def.values) == "table" then
m.enumProperty(def)
elseif def.kind:startswith("list:") then
elseif def.kind and def.kind:startswith("list:") then
m.stringListProperty(def)
else
m.stringProperty(def)

View File

@ -216,6 +216,37 @@
end
end
--
-- Write the NMake property group for Makefile projects, which includes the custom
-- build commands, output file location, etc.
--
m.elements.nmakeProperties = function(cfg)
return {
m.nmakeOutput,
m.nmakeBuildCommands,
m.nmakeRebuildCommands,
m.nmakeCleanCommands,
m.nmakePreprocessorDefinitions,
m.nmakeIncludeDirs
}
end
function m.nmakeProperties(cfg)
if vstudio.isMakefile(cfg) then
m.propertyGroup(cfg)
p.callArray(m.elements.nmakeProperties, cfg)
p.pop('</PropertyGroup>')
end
end
--
-- Output properties and NMake properties should appear side-by-side
-- for each configuration.
--
function m.outputPropertiesGroup(prj)
for cfg in project.eachconfig(prj) do
m.outputProperties(cfg)
@ -225,25 +256,6 @@
--
-- Write the NMake property group for Makefile projects, which includes the custom
-- build commands, output file location, etc.
--
function m.nmakeProperties(cfg)
if vstudio.isMakefile(cfg) then
m.propertyGroup(cfg)
m.nmakeOutput(cfg)
m.nmakeCommandLine(cfg, cfg.buildcommands, "Build")
m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild")
m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean")
m.nmakePreprocessorDefinitions(cfg, cfg.defines, false, nil)
m.nmakeIncludeDirs(cfg, cfg.includedirs)
p.pop('</PropertyGroup>')
end
end
--
-- Write a configuration's item definition group, which contains all
-- of the per-configuration compile and link settings.
@ -323,6 +335,7 @@
m.bufferSecurityCheck,
m.treatWChar_tAsBuiltInType,
m.floatingPointModel,
m.floatingPointExceptions,
m.inlineFunctionExpansion,
m.enableEnhancedInstructionSet,
m.multiProcessorCompilation,
@ -391,12 +404,14 @@
if cfg.kind == p.STATICLIB then
return {
m.subSystem,
m.fullProgramDatabaseFile,
m.generateDebugInformation,
m.optimizeReferences,
}
else
return {
m.subSystem,
m.fullProgramDatabaseFile,
m.generateDebugInformation,
m.optimizeReferences,
m.additionalDependencies,
@ -609,7 +624,7 @@
---
m.categories.ClInclude = {
name = "ClInclude",
extensions = { ".h", ".hh", ".hpp", ".hxx" },
extensions = { ".h", ".hh", ".hpp", ".hxx", ".inl" },
priority = 1,
emitFiles = function(prj, group)
@ -644,7 +659,10 @@
m.enableEnhancedInstructionSet,
m.additionalCompileOptions,
m.disableSpecificWarnings,
m.treatSpecificWarningsAsErrors
m.treatSpecificWarningsAsErrors,
m.basicRuntimeChecks,
m.exceptionHandling,
m.compileAsManaged,
}
else
return {
@ -719,6 +737,7 @@
m.excludedFromBuild,
m.buildCommands,
m.buildOutputs,
m.linkObjects,
m.buildMessage,
m.buildAdditionalInputs
}
@ -945,13 +964,34 @@
end
function m.isClrMixed(prj)
-- check to see if any files are marked with clr
local isMixed = false
if not prj.clr or prj.clr == p.OFF then
if prj._isClrMixed ~= nil then
isMixed = prj._isClrMixed
else
table.foreachi(prj._.files, function(file)
for cfg in p.project.eachconfig(prj) do
local fcfg = p.fileconfig.getconfig(file, cfg)
if fcfg and fcfg.clr and fcfg.clr ~= p.OFF then
isMixed = true
end
end
end)
prj._isClrMixed = isMixed -- cache the results
end
end
return isMixed
end
--
-- Generate the list of project dependencies.
--
m.elements.projectReferences = function(prj, ref)
if prj.clr ~= p.OFF then
if prj.clr ~= p.OFF or (m.isClrMixed(prj) and ref and ref.kind ~=p.STATICLIB) then
return {
m.referenceProject,
m.referencePrivate,
@ -1059,10 +1099,24 @@
end
function m.basicRuntimeChecks(cfg)
local runtime = config.getruntime(cfg)
if cfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(cfg) and runtime:endswith("Debug")) then
m.element("BasicRuntimeChecks", nil, "Default")
function m.compileAsManaged(fcfg, condition)
if fcfg.clr and fcfg ~= p.OFF then
m.element("CompileAsManaged", condition, "true")
end
end
function m.basicRuntimeChecks(cfg, condition)
local prjcfg, filecfg = p.config.normalize(cfg)
local runtime = config.getruntime(prjcfg)
if filecfg then
if filecfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(filecfg) and runtime:endswith("Debug")) then
m.element("BasicRuntimeChecks", condition, "Default")
end
else
if prjcfg.flags.NoRuntimeChecks or (config.isOptimizedBuild(prjcfg) and runtime:endswith("Debug")) then
m.element("BasicRuntimeChecks", nil, "Default")
end
end
end
@ -1104,6 +1158,13 @@
end
function m.linkObjects(fcfg, condition)
if fcfg.linkbuildoutputs ~= nil then
m.element("LinkObjects", condition, tostring(fcfg.linkbuildoutputs))
end
end
function m.characterSet(cfg)
if not vstudio.isMakefile(cfg) then
m.element("CharacterSet", nil, iif(cfg.characterset == p.MBCS, "MultiByte", "Unicode"))
@ -1127,7 +1188,11 @@
function m.clCompilePreprocessorDefinitions(cfg, condition)
m.preprocessorDefinitions(cfg, cfg.defines, false, condition)
local defines = cfg.defines
if cfg.exceptionhandling == p.OFF and _ACTION >= "vs2013" then
defines = table.join(defines, "_HAS_EXCEPTIONS=0")
end
m.preprocessorDefinitions(cfg, defines, false, condition)
end
@ -1250,12 +1315,11 @@
end
function m.exceptionHandling(cfg)
local value
function m.exceptionHandling(cfg, condition)
if cfg.exceptionhandling == p.OFF then
m.element("ExceptionHandling", nil, "false")
m.element("ExceptionHandling", condition, "false")
elseif cfg.exceptionhandling == "SEH" then
m.element("ExceptionHandling", nil, "Async")
m.element("ExceptionHandling", condition, "Async")
end
end
@ -1286,6 +1350,18 @@
end
end
function m.floatingPointExceptions(cfg)
if cfg.floatingpointexceptions ~= nil then
if cfg.floatingpointexceptions then
m.element("FloatingPointExceptions", nil, "true")
else
m.element("FloatingPointExceptions", nil, "false")
end
end
end
function m.inlineFunctionExpansion(cfg)
if cfg.inlining then
local types = {
@ -1298,6 +1374,7 @@
end
end
function m.forceIncludes(cfg, condition)
if #cfg.forceincludes > 0 then
local includes = vstudio.path(cfg, cfg.forceincludes)
@ -1314,8 +1391,21 @@
end
function m.fullProgramDatabaseFile(cfg)
if _ACTION >= "vs2015" and cfg.symbols == "FastLink" then
m.element("FullProgramDatabaseFile", nil, "true")
end
end
function m.functionLevelLinking(cfg)
if config.isOptimizedBuild(cfg) then
if cfg.functionlevellinking ~= nil then
if cfg.functionlevellinking then
m.element("FunctionLevelLinking", nil, "true")
else
m.element("FunctionLevelLinking", nil, "false")
end
elseif config.isOptimizedBuild(cfg) then
m.element("FunctionLevelLinking", nil, "true")
end
end
@ -1323,18 +1413,21 @@
function m.generateDebugInformation(cfg)
local lookup = {}
if _ACTION >= "vs2015" then
lookup[p.ON] = "Debug"
lookup[p.OFF] = "No"
if _ACTION >= "vs2017" then
lookup[p.ON] = "true"
lookup[p.OFF] = "false"
lookup["FastLink"] = "DebugFastLink"
if cfg.symbols == "FastLink" then
m.element("FullProgramDatabaseFile", nil, "true")
end
lookup["Full"] = "DebugFull"
elseif _ACTION == "vs2015" then
lookup[p.ON] = "true"
lookup[p.OFF] = "false"
lookup["FastLink"] = "DebugFastLink"
lookup["Full"] = "true"
else
lookup[p.ON] = "true"
lookup[p.OFF] = "false"
lookup["FastLink"] = "true"
lookup["Full"] = "true"
end
local value = lookup[cfg.symbols]
@ -1561,13 +1654,18 @@
function m.intrinsicFunctions(cfg)
if config.isOptimizedBuild(cfg) then
if cfg.intrinsics ~= nil then
if cfg.intrinsics then
m.element("IntrinsicFunctions", nil, "true")
else
m.element("IntrinsicFunctions", nil, "false")
end
elseif config.isOptimizedBuild(cfg) then
m.element("IntrinsicFunctions", nil, "true")
end
end
function m.keyword(prj)
-- try to determine what kind of targets we're building here
local isWin, isManaged, isMakefile
@ -1587,8 +1685,10 @@
if isMakefile then
m.element("Keyword", nil, "MakeFileProj")
else
if isManaged then
if isManaged or m.isClrMixed(prj) then
m.targetFramework(prj)
end
if isManaged then
m.element("Keyword", nil, "ManagedCProj")
else
m.element("Keyword", nil, "Win32Proj")
@ -1653,6 +1753,16 @@
end
function m.nmakeBuildCommands(cfg)
m.nmakeCommandLine(cfg, cfg.buildcommands, "Build")
end
function m.nmakeCleanCommands(cfg)
m.nmakeCommandLine(cfg, cfg.cleancommands, "Clean")
end
function m.nmakeCommandLine(cfg, commands, phase)
if #commands > 0 then
commands = os.translateCommands(commands, p.WINDOWS)
@ -1662,6 +1772,16 @@
end
function m.nmakeIncludeDirs(cfg)
if cfg.kind ~= p.NONE and #cfg.includedirs > 0 then
local dirs = vstudio.path(cfg, cfg.includedirs)
if #dirs > 0 then
m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";"))
end
end
end
function m.nmakeOutDirs(cfg)
if vstudio.isMakefile(cfg) then
m.outDir(cfg)
@ -1669,30 +1789,26 @@
end
end
function m.nmakeOutput(cfg)
m.element("NMakeOutput", nil, "$(OutDir)%s", cfg.buildtarget.name)
end
function m.nmakePreprocessorDefinitions(cfg, defines, escapeQuotes, condition)
if #defines > 0 then
defines = table.concat(defines, ";")
if escapeQuotes then
defines = defines:gsub('"', '\\"')
end
function m.nmakePreprocessorDefinitions(cfg)
if cfg.kind ~= p.NONE and #cfg.defines > 0 then
local defines = table.concat(cfg.defines, ";")
defines = p.esc(defines) .. ";$(NMakePreprocessorDefinitions)"
m.element('NMakePreprocessorDefinitions', condition, defines)
m.element('NMakePreprocessorDefinitions', nil, defines)
end
end
function m.nmakeIncludeDirs(cfg, includedirs)
if #includedirs > 0 then
local dirs = vstudio.path(cfg, includedirs)
if #dirs > 0 then
m.element("NMakeIncludeSearchPath", nil, "%s", table.concat(dirs, ";"))
end
end
function m.nmakeRebuildCommands(cfg)
m.nmakeCommandLine(cfg, cfg.rebuildcommands, "ReBuild")
end
function m.objectFileName(fcfg)
if fcfg.objname ~= fcfg.basename then
m.element("ObjectFileName", m.condition(fcfg.config), "$(IntDir)\\%s.obj", fcfg.objname)
@ -1899,7 +2015,11 @@
function m.resourcePreprocessorDefinitions(cfg)
m.preprocessorDefinitions(cfg, table.join(cfg.defines, cfg.resdefines), true)
local defines = table.join(cfg.defines, cfg.resdefines)
if cfg.exceptionhandling == p.OFF and _ACTION >= "vs2013" then
table.insert(defines, "_HAS_EXCEPTIONS=0")
end
m.preprocessorDefinitions(cfg, defines, true)
end
@ -1936,7 +2056,13 @@
end
function m.stringPooling(cfg)
if config.isOptimizedBuild(cfg) then
if cfg.stringpooling ~= nil then
if cfg.stringpooling then
m.element("StringPooling", nil, "true")
else
m.element("StringPooling", nil, "false")
end
elseif config.isOptimizedBuild(cfg) then
m.element("StringPooling", nil, "true")
end
end

View File

@ -65,7 +65,7 @@
vstudio = {
solutionVersion = "12",
versionName = "2015",
versionName = "14",
targetFramework = "4.5",
toolsVersion = "14.0",
filterToolsVersion = "4.0",

View File

@ -0,0 +1,74 @@
--
-- actions/vstudio/vs2017.lua
-- Extend the existing exporters with support for Visual Studio 2017.
-- Copyright (c) 2017-2017 Jason Perkins and the Premake project
--
premake.vstudio.vc2017 = {}
local p = premake
local vstudio = p.vstudio
local vc2010 = vstudio.vc2010
local m = vstudio.vc2017
---
-- Define the Visual Studio 2017 export action.
---
newaction {
-- Metadata for the command line and help system
trigger = "vs2017",
shortname = "Visual Studio 2017",
description = "Generate Visual Studio 2017 project files",
-- Visual Studio always uses Windows path and naming conventions
os = "windows",
-- The capabilities of this action
valid_kinds = { "ConsoleApp", "WindowedApp", "StaticLib", "SharedLib", "Makefile", "None", "Utility", "Installer" },
valid_languages = { "C", "C++", "C#" },
valid_tools = {
cc = { "msc" },
dotnet = { "msnet" },
},
-- Workspace and project generation logic
onWorkspace = function(wks)
vstudio.vs2005.generateSolution(wks)
end,
onProject = function(prj)
vstudio.vs2010.generateProject(prj)
end,
onRule = function(rule)
vstudio.vs2010.generateRule(rule)
end,
onCleanWorkspace = function(wks)
vstudio.cleanSolution(wks)
end,
onCleanProject = function(prj)
vstudio.cleanProject(prj)
end,
onCleanTarget = function(prj)
vstudio.cleanTarget(prj)
end,
pathVars = vstudio.pathVars,
-- This stuff is specific to the Visual Studio exporters
vstudio = {
solutionVersion = "12",
versionName = "15",
targetFramework = "4.5.2",
toolsVersion = "15.0",
filterToolsVersion = "4.0",
platformToolset = "v141"
}
}

View File

@ -413,7 +413,10 @@
--
function config.isDebugBuild(cfg)
return cfg.symbols == p.ON and not config.isOptimizedBuild(cfg)
return cfg.symbols ~= nil and
cfg.symbols ~= p.OFF and
cfg.symbols ~= "Default" and
not config.isOptimizedBuild(cfg)
end
@ -490,6 +493,9 @@
-- replacement, if any, to the result
local values = cfg[field.name]
if type(values) == "boolean" then
values = iif(values, "On", "Off")
end
if type(values) ~= "table" then
values = { values }
end

View File

@ -243,7 +243,6 @@
return context.__mt.__index(fsub, key)
end
--
-- And here are the path building functions.
--
@ -257,6 +256,9 @@
return path.getdirectory(fcfg.abspath)
end
function fcfg_mt.reldirectory(fcfg)
return path.getdirectory(fcfg.relpath)
end
function fcfg_mt.name(fcfg)
return path.getname(fcfg.abspath)
@ -286,3 +288,8 @@
-- This only gets called if no explicit virtual path was set
return fcfg.relpath
end
function fcfg_mt.extension(fcfg)
return path.getextension(fcfg.abspath)
end

View File

@ -57,7 +57,6 @@
end
---
-- Extend require() with a second argument to specify the expected
-- version of the loaded module. Raises an error if the version criteria
@ -76,7 +75,12 @@
premake.override(_G, "require", function(base, modname, versions)
local result, mod = pcall(base,modname)
if not result then
error( mod, 3 )
if (premake.downloadModule(modname, versions)) then
result, mod = pcall(base, modname);
end
if not result then
error(mod, 3)
end
end
if mod and versions and not premake.checkVersion(mod._VERSION, versions) then
error(string.format("module %s %s does not meet version criteria %s",

View File

@ -31,22 +31,30 @@
end
-- display all options
for k, options in pairs(categories) do
for k, options in spairs(categories) do
printf(k)
printf("")
local length = 0
for _, option in ipairs(options) do
local trigger = option.trigger
if (option.value) then trigger = trigger .. "=" .. option.value end
if (#trigger > length) then length = #trigger end
end
for _, option in ipairs(options) do
local trigger = option.trigger
local description = option.description
if (option.value) then trigger = trigger .. "=" .. option.value end
if (option.allowed) then description = description .. "; one of:" end
printf(" --%-15s %s", trigger, description)
printf(" --%-" .. length .. "s %s", trigger, description)
if (option.allowed) then
for _, value in ipairs(option.allowed) do
printf(" %-14s %s", value[1], value[2])
printf(" %-" .. length-1 .. "s %s", value[1], value[2])
end
printf("")
end
printf("")
end
printf("")
end

68
src/base/http.lua Normal file
View File

@ -0,0 +1,68 @@
--
-- http.lua
-- Additions to the http namespace.
-- Copyright (c) 2008-2014 Jason Perkins and the Premake project
--
if http == nil then
return
end
---
-- Simple progress bar on stdout for curl downloads.
---
function http.reportProgress(total, current)
local width = 70
local progress = math.floor(current * width / total)
if progress == width then
io.write(string.rep(' ', width + 2) .. '\r')
else
io.write('[' .. string.rep('=', progress) .. string.rep(' ', width - progress) .. ']\r')
end
end
---
-- Correctly escape parameters for use in a url.
---
function http.escapeUrlParam(param)
local url_encodings = {
[' '] = '%%20',
['!'] = '%%21',
['"'] = '%%22',
['#'] = '%%23',
['$'] = '%%24',
['&'] = '%%26',
['\''] = '%%27',
['('] = '%%28',
[')'] = '%%29',
['*'] = '%%2A',
['+'] = '%%2B',
['-'] = '%%2D',
['.'] = '%%2E',
['/'] = '%%2F',
[':'] = '%%3A',
[';'] = '%%3B',
['<'] = '%%3C',
['='] = '%%3D',
['>'] = '%%3E',
['?'] = '%%3F',
['@'] = '%%40',
['['] = '%%5B',
['\\'] = '%%5C',
[']'] = '%%5D',
['^'] = '%%5E',
['_'] = '%%5F',
['`'] = '%%60'
}
param = param:gsub('%%', '%%25')
for k,v in pairs(url_encodings) do
param = param:gsub('%' .. k, v)
end
return param
end

View File

@ -0,0 +1,67 @@
--
-- moduledownloader.lua
-- Downloads a module from a package server
-- Copyright (c) 2002-2017 Jason Perkins and the Premake project
--
---
-- Downloads a module from a package server
--
-- @param modname
-- The name of the module to download.
-- @param versions
-- An optional version criteria string; see premake.checkVersion()
-- for more information on the format.
-- @return
-- If successful, the module was downloaded into the .modules folder.
---
function premake.downloadModule(modname, versions)
if http == nil then
return false
end
-- get current user.
local user = 'UNKNOWN'
if os.get() == 'windows' then
user = os.getenv('USERNAME') or user
else
user = os.getenv('LOGNAME') or user
end
-- what server to ask?
local server = package.server or 'http://packagesrv.com';
-- get the link to the module?
local url = 'api/v1/module/' .. http.escapeUrlParam(modname)
if versions then
url = url .. '/' .. http.escapeUrlParam(versions)
end
local content, result_str, response_code = http.get(server .. '/' .. url)
if content then
url = content
else
-- no content, module doesn't exist.
return false
end
-- Download the module.
local location = '.modules/' .. modname
local destination = location .. '/temp.zip'
os.mkdir(location)
local result_str, response_code = http.download(url, destination, {
headers = {'X-Premake-User: ' .. user},
progress = iif(_OPTIONS.verbose, http.reportProgress, nil)
})
if result_str ~= 'OK' then
premake.error('Download of %s failed (%d)\n%s', url, response_code, result_str)
end
-- Unzip the module, and delete the temporary zip file.
verbosef(' UNZIP : %s', destination)
zip.extract(destination, location)
os.remove(destination)
return true;
end

View File

@ -587,7 +587,7 @@
context.addFilter(ctx, "architecture", ctx.architecture)
-- allow the project script to override the default toolset
ctx.toolset = ctx.toolset or toolset
ctx.toolset = _OPTIONS.cc or ctx.toolset or toolset
context.addFilter(ctx, "toolset", ctx.toolset)
-- if a kind is set, allow that to influence the configuration

View File

@ -1,5 +1,5 @@
local semver = {
_VERSION = '1.2.0',
_VERSION = '1.2.1',
_DESCRIPTION = 'semver for Lua',
_URL = 'https://github.com/kikito/semver.lua',
_LICENSE = [[
@ -173,6 +173,9 @@ end
-- if a and b are versions, a ^ b means "b is backwards-compatible with a"
-- in other words, "it's safe to upgrade from a to b"
function mt:__pow(other)
if self.major == 0 then
return self == other
end
return self.major == other.major and
self.minor <= other.minor
end

View File

@ -514,3 +514,43 @@
end
end)
end
--
-- Compares two tables.
--
function table.equals(a, b)
for k, v in pairs(a) do
if b[k] ~= v then
return false
end
end
for k, v in pairs(b) do
if a[k] ~= v then
return false
end
end
return true
end
--
-- Enumerate a table sorted by its keys.
--
function spairs(t)
-- collect the keys
local keys = {}
for k in pairs(t) do
table.insert(keys, k)
end
table.sort(keys)
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end

View File

@ -7,27 +7,24 @@
#include <stdlib.h>
#include <string.h>
#include "premake.h"
#include "buffered_io.h"
typedef struct struct_Buffer
void buffer_init(Buffer* b)
{
size_t capacity;
size_t length;
char* data;
} Buffer;
int buffered_new(lua_State* L)
{
Buffer* b = (Buffer*)malloc(sizeof(Buffer));
b->capacity = 0;
b->length = 0;
b->data = NULL;
lua_pushlightuserdata(L, b);
return 1;
}
void buffer_destroy(Buffer* b)
{
free(b->data);
b->capacity = 0;
b->length = 0;
b->data = NULL;
}
static void do_write(Buffer* b, const char *s, size_t len)
void buffer_puts(Buffer* b, const void* ptr, size_t len)
{
char* data;
@ -52,10 +49,29 @@ static void do_write(Buffer* b, const char *s, size_t len)
b->capacity = cap;
}
memcpy(b->data + b->length, s, len);
memcpy(b->data + b->length, ptr, len);
b->length += len;
}
void buffer_printf(Buffer* b, const char *fmt, ...)
{
char text[2048];
va_list args;
va_start(args, fmt);
int len = vsnprintf(text, sizeof(text) - 1, fmt, args);
va_end(args);
buffer_puts(b, text, len);
}
// -- Lua wrappers ----------------------------------------
int buffered_new(lua_State* L)
{
Buffer* b = (Buffer*)malloc(sizeof(Buffer));
buffer_init(b);
lua_pushlightuserdata(L, b);
return 1;
}
int buffered_write(lua_State* L)
{
@ -63,11 +79,10 @@ int buffered_write(lua_State* L)
const char *s = luaL_checklstring(L, 2, &len);
Buffer* b = (Buffer*)lua_touserdata(L, 1);
do_write(b, s, len);
buffer_puts(b, s, len);
return 0;
}
int buffered_writeln(lua_State* L)
{
size_t len;
@ -75,21 +90,19 @@ int buffered_writeln(lua_State* L)
Buffer* b = (Buffer*)lua_touserdata(L, 1);
if (s != NULL)
do_write(b, s, len);
do_write(b, "\r\n", 2);
buffer_puts(b, s, len);
buffer_puts(b, "\r\n", 2);
return 0;
}
int buffered_close(lua_State* L)
{
Buffer* b = (Buffer*)lua_touserdata(L, 1);
free(b->data);
buffer_destroy(b);
free(b);
return 0;
}
int buffered_tostring(lua_State* L)
{
Buffer* b = (Buffer*)lua_touserdata(L, 1);

24
src/host/buffered_io.h Normal file
View File

@ -0,0 +1,24 @@
/**
* \file buffered_io.h
* \brief provide buffered io.
* \author Copyright (c) 2014
*/
#ifndef buffered_io_h
#define buffered_io_h
#include <stdio.h>
typedef struct struct_Buffer
{
size_t capacity;
size_t length;
char* data;
} Buffer;
void buffer_init(Buffer* b);
void buffer_destroy(Buffer* b);
void buffer_puts(Buffer* b, const void* ptr, size_t len);
void buffer_printf(Buffer* b, const char* s, ...);
#endif

187
src/host/curl_utils.c Normal file
View File

@ -0,0 +1,187 @@
/**
* \file curl_utils.c
* \brief curl utilities for the http library.
* \author Copyright (c) 2017 Tom van Dijck, João Matos and the Premake project
*/
#ifdef PREMAKE_CURL
#include "curl_utils.h"
#include "premake.h"
#include <string.h>
int curlProgressCallback(curl_state* state, double dltotal, double dlnow, double ultotal, double ulnow)
{
lua_State* L = state->L;
(void)ultotal;
(void)ulnow;
if (dltotal == 0) return 0;
/* retrieve the lua progress callback we saved before */
lua_rawgeti(L, LUA_REGISTRYINDEX, state->RefIndex);
lua_pushnumber(L, (lua_Number)dltotal);
lua_pushnumber(L, (lua_Number)dlnow);
lua_pcall(L, 2, LUA_MULTRET, 0);
return 0;
}
size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb, curl_state* state)
{
size_t length = size * nmemb;
buffer_puts(&state->S, ptr, length);
return length;
}
static void curl_init()
{
static int initializedHTTP = 0;
if (initializedHTTP)
return;
curl_global_init(CURL_GLOBAL_ALL);
atexit(curl_global_cleanup);
initializedHTTP = 1;
}
static void get_headers(lua_State* L, int headersIndex, struct curl_slist** headers)
{
lua_pushnil(L);
while (lua_next(L, headersIndex) != 0)
{
const char *item = luaL_checkstring(L, -1);
lua_pop(L, 1);
*headers = curl_slist_append(*headers, item);
}
}
CURL* curlRequest(lua_State* L, curl_state* state, int optionsIndex, int progressFnIndex, int headersIndex)
{
char agent[1024];
CURL* curl;
state->L = 0;
state->RefIndex = 0;
state->errorBuffer[0] = '\0';
state->headers = NULL;
buffer_init(&state->S);
curl_init();
curl = curl_easy_init();
if (!curl)
return NULL;
strcpy(agent, "Premake/");
strcat(agent, PREMAKE_VERSION);
curl_easy_setopt(curl, CURLOPT_URL, luaL_checkstring(L, 1));
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, state->errorBuffer);
curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
if (optionsIndex && lua_istable(L, optionsIndex))
{
lua_pushnil(L);
while (lua_next(L, optionsIndex) != 0)
{
const char* key = luaL_checkstring(L, -2);
if (!strcmp(key, "headers") && lua_istable(L, -1))
{
get_headers(L, lua_gettop(L), &state->headers);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->headers);
}
else if (!strcmp(key, "progress") && lua_isfunction(L, -1))
{
state->L = L;
lua_pushvalue(L, -1);
state->RefIndex = luaL_ref(L, LUA_REGISTRYINDEX);
}
else if (!strcmp(key, "userpwd") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_USERPWD, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "username") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_USERNAME, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "password") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_PASSWORD, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "timeout") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "timeoutms") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "sslverifyhost") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "sslverifypeer") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long)luaL_checknumber(L, -1));
}
// pop the value, leave the key for lua_next
lua_pop(L, 1);
}
}
else
{
if (progressFnIndex && lua_type(L, progressFnIndex) == LUA_TFUNCTION)
{
state->L = L;
lua_pushvalue(L, progressFnIndex);
state->RefIndex = luaL_ref(L, LUA_REGISTRYINDEX);
}
if (headersIndex && lua_istable(L, headersIndex))
{
get_headers(L, headersIndex, &state->headers);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->headers);
}
}
curl_easy_setopt(curl, CURLOPT_WRITEDATA, state);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
if (state->L != 0)
{
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, state);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curlProgressCallback);
}
// clear error buffer.
state->errorBuffer[0] = 0;
return curl;
}
void curlCleanup(CURL* curl, curl_state* state)
{
if (state->headers)
{
curl_slist_free_all(state->headers);
state->headers = 0;
}
curl_easy_cleanup(curl);
}
#endif

36
src/host/curl_utils.h Normal file
View File

@ -0,0 +1,36 @@
/**
* \file curl_utils.h
* \brief curl utilities for the http library.
* \author Copyright (c) 2017 Tom van Dijck, João Matos and the Premake project
*/
#ifndef curl_utils_h
#define curl_utils_h
#ifdef PREMAKE_CURL
#include "buffered_io.h"
#include "lua.h"
#define _MPRINTF_REPLACE /* use curl functions only */
#include <curl/curl.h>
#include <curl/mprintf.h>
typedef struct
{
lua_State* L;
int RefIndex;
Buffer S;
char errorBuffer[256];
struct curl_slist* headers;
} curl_state;
int curlProgressCallback(curl_state* state, double dltotal, double dlnow, double ultotal, double ulnow);
size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb, curl_state* state);
CURL* curlRequest(lua_State* L, curl_state* state, int optionsIndex, int progressFnIndex, int headersIndex);
void curlCleanup(CURL* curl, curl_state* state);
#endif // PREMAKE_CURL
#endif // curl_utils_h

View File

@ -1,394 +0,0 @@
/**
* \file http.c
* \brief HTTP requests support using libcurl.
* \author Copyright (c) 2014 João Matos and the Premake project
*/
#include "premake.h"
#include <stdlib.h>
#include <string.h>
#ifdef PREMAKE_CURL
#include <curl/curl.h>
#define _MPRINTF_REPLACE /* use curl functions only */
#include <curl/mprintf.h>
typedef struct {
char* ptr;
size_t len;
} string;
void string_init(string* s)
{
s->len = 0;
s->ptr = (char*) malloc(s->len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
void string_free(string* s)
{
free(s->ptr);
s->ptr = NULL;
s->len = 0;
}
typedef struct
{
lua_State* L;
int RefIndex;
string S;
char errorBuffer[CURL_ERROR_SIZE];
struct curl_slist* headers;
} curl_state;
static int curl_progress_cb(void* userdata, double dltotal, double dlnow, double ultotal, double ulnow)
{
curl_state* state = (curl_state*) userdata;
lua_State* L = state->L;
(void)ultotal;
(void)ulnow;
if (dltotal == 0) return 0;
/* retrieve the lua progress callback we saved before */
lua_rawgeti(L, LUA_REGISTRYINDEX, state->RefIndex);
lua_pushnumber(L, (lua_Number) dltotal);
lua_pushnumber(L, (lua_Number) dlnow);
lua_pcall(L, 2, LUA_MULTRET, 0);
return 0;
}
static size_t curl_write_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
{
curl_state* state = (curl_state*) userdata;
string* s = &state->S;
size_t new_len = s->len + size * nmemb;
s->ptr = (char*) realloc(s->ptr, new_len+1);
if (s->ptr == NULL)
{
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size * nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size * nmemb;
}
static size_t curl_file_cb(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
}
static void curl_init()
{
static int initializedHTTP = 0;
if (initializedHTTP)
return;
curl_global_init(CURL_GLOBAL_ALL);
atexit(curl_global_cleanup);
initializedHTTP = 1;
}
static void get_headers(lua_State* L, int headersIndex, struct curl_slist** headers)
{
lua_pushnil(L);
while (lua_next(L, headersIndex) != 0)
{
const char *item = luaL_checkstring(L, -1);
lua_pop(L, 1);
*headers = curl_slist_append(*headers, item);
}
}
static CURL* curl_request(lua_State* L, curl_state* state, int optionsIndex, int progressFnIndex, int headersIndex)
{
CURL* curl;
state->L = 0;
state->RefIndex = 0;
state->S.ptr = NULL;
state->S.len = 0;
state->errorBuffer[0] = '\0';
state->headers = NULL;
curl_init();
curl = curl_easy_init();
if (!curl)
return NULL;
curl_easy_setopt(curl, CURLOPT_URL, luaL_checkstring(L, 1));
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, state->errorBuffer);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Premake/" PREMAKE_VERSION);
if (optionsIndex && lua_istable(L, optionsIndex))
{
lua_pushnil(L);
while (lua_next(L, optionsIndex) != 0)
{
const char* key = luaL_checkstring(L, -2);
if (!strcmp(key, "headers") && lua_istable(L, -1))
{
get_headers(L, lua_gettop(L), &state->headers);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->headers);
}
else if (!strcmp(key, "progress") && lua_isfunction(L, -1))
{
state->L = L;
lua_pushvalue(L, -1);
state->RefIndex = luaL_ref(L, LUA_REGISTRYINDEX);
}
else if (!strcmp(key, "userpwd") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_USERPWD, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "username") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_USERNAME, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "password") && lua_isstring(L, -1))
{
curl_easy_setopt(curl, CURLOPT_PASSWORD, luaL_checkstring(L, -1));
}
else if (!strcmp(key, "timeout") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "timeoutms") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "sslverifyhost") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, (long)luaL_checknumber(L, -1));
}
else if (!strcmp(key, "sslverifypeer") && lua_isnumber(L, -1))
{
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long)luaL_checknumber(L, -1));
}
// pop the value, leave the key for lua_next
lua_pop(L, 1);
}
}
else
{
if (progressFnIndex && lua_type(L, progressFnIndex) == LUA_TFUNCTION)
{
state->L = L;
lua_pushvalue(L, progressFnIndex);
state->RefIndex = luaL_ref(L, LUA_REGISTRYINDEX);
}
if (headersIndex && lua_istable(L, headersIndex))
{
get_headers(L, headersIndex, &state->headers);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->headers);
}
}
curl_easy_setopt(curl, CURLOPT_WRITEDATA, state);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
if (state->L != 0)
{
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, state);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, curl_progress_cb);
}
// clear error buffer.
state->errorBuffer[0] = 0;
return curl;
}
static void curl_cleanup(CURL* curl, curl_state* state)
{
if (state->headers)
{
curl_slist_free_all(state->headers);
state->headers = 0;
}
curl_easy_cleanup(curl);
}
int http_get(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
if (lua_istable(L, 2))
{
// http.get(source, { options })
curl = curl_request(L, &state, /*optionsIndex=*/2, /*progressFnIndex=*/0, /*headersIndex=*/0);
}
else
{
// backward compatible function signature
// http.get(source, progressFunction, { headers })
curl = curl_request(L, &state, /*optionsIndex=*/0, /*progressFnIndex=*/2, /*headersIndex=*/3);
}
string_init(&state.S);
if (curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curl_cleanup(curl, &state);
}
if (code != CURLE_OK)
{
char errorBuf[1024];
lua_pushnil(L);
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushlstring(L, state.S.ptr, state.S.len);
lua_pushstring(L, "OK");
}
string_free(&state.S);
lua_pushnumber(L, responseCode);
return 3;
}
int http_post(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
// http.post(source, postdata, { options })
curl = curl_request(L, &state, /*optionsIndex=*/3, /*progressFnIndex=*/0, /*headersIndex=*/0);
string_init(&state.S);
if (curl)
{
size_t dataSize;
const char* data = luaL_checklstring(L, 2, &dataSize);
curl_easy_setopt(curl, CURLOPT_POST, 1);
if (data && dataSize > 0)
{
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)dataSize);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
}
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curl_cleanup(curl, &state);
}
if (code != CURLE_OK)
{
char errorBuf[1024];
lua_pushnil(L);
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushlstring(L, state.S.ptr, state.S.len);
lua_pushstring(L, "OK");
}
string_free(&state.S);
lua_pushnumber(L, responseCode);
return 3;
}
int http_download(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
FILE* fp;
const char* file = luaL_checkstring(L, 2);
fp = fopen(file, "wb");
if (!fp)
{
lua_pushstring(L, "Unable to open file.");
lua_pushnumber(L, -1);
return 2;
}
if (lua_istable(L, 3))
{
// http.download(source, destination, { options })
curl = curl_request(L, &state, /*optionsIndex=*/3, /*progressFnIndex=*/0, /*headersIndex=*/0);
}
else
{
// backward compatible function signature
// http.download(source, destination, progressFunction, { headers })
curl = curl_request(L, &state, /*optionsIndex=*/0, /*progressFnIndex=*/3, /*headersIndex=*/4);
}
if (curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_file_cb);
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curl_cleanup(curl, &state);
}
fclose(fp);
if (code != CURLE_OK)
{
char errorBuf[1024];
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushstring(L, "OK");
}
lua_pushnumber(L, responseCode);
return 2;
}
#endif

76
src/host/http_download.c Normal file
View File

@ -0,0 +1,76 @@
/**
* \file http_download.c
* \brief HTTP download support using libcurl.
* \author Copyright (c) 2017 Blizzard Entertainment, João Matos and the Premake project
*/
#include "premake.h"
#include "curl_utils.h"
#ifdef PREMAKE_CURL
static size_t curl_file_cb(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
}
int http_download(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
FILE* fp;
const char* file = luaL_checkstring(L, 2);
fp = fopen(file, "wb");
if (!fp)
{
lua_pushstring(L, "Unable to open file.");
lua_pushnumber(L, -1);
return 2;
}
if (lua_istable(L, 3))
{
// http.download(source, destination, { options })
curl = curlRequest(L, &state, /*optionsIndex=*/3, /*progressFnIndex=*/0, /*headersIndex=*/0);
}
else
{
// backward compatible function signature
// http.download(source, destination, progressFunction, { headers })
curl = curlRequest(L, &state, /*optionsIndex=*/0, /*progressFnIndex=*/3, /*headersIndex=*/4);
}
if (curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_file_cb);
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curlCleanup(curl, &state);
}
fclose(fp);
if (code != CURLE_OK)
{
char errorBuf[1024];
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushstring(L, "OK");
}
buffer_destroy(&state.S);
lua_pushnumber(L, (lua_Number)responseCode);
return 2;
}
#endif

59
src/host/http_get.c Normal file
View File

@ -0,0 +1,59 @@
/**
* \file http_get.c
* \brief HTTP get request support using libcurl.
* \author Copyright (c) 2017 Blizzard Entertainment, João Matos and the Premake project
*/
#include "premake.h"
#include "curl_utils.h"
#ifdef PREMAKE_CURL
int http_get(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
if (lua_istable(L, 2))
{
// http.get(source, { options })
curl = curlRequest(L, &state, /*optionsIndex=*/2, /*progressFnIndex=*/0, /*headersIndex=*/0);
}
else
{
// backward compatible function signature
// http.get(source, progressFunction, { headers })
curl = curlRequest(L, &state, /*optionsIndex=*/0, /*progressFnIndex=*/2, /*headersIndex=*/3);
}
if (curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curlCleanup(curl, &state);
}
if (code != CURLE_OK)
{
char errorBuf[1024];
lua_pushnil(L);
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushlstring(L, state.S.data, state.S.length);
lua_pushstring(L, "OK");
}
buffer_destroy(&state.S);
lua_pushnumber(L, (lua_Number)responseCode);
return 3;
}
#endif

57
src/host/http_post.c Normal file
View File

@ -0,0 +1,57 @@
/**
* \file http_post.c
* \brief HTTP post request support using libcurl.
* \author Copyright (c) 2017 Blizzard Entertainment, João Matos and the Premake project
*/
#include "premake.h"
#include "curl_utils.h"
#ifdef PREMAKE_CURL
int http_post(lua_State* L)
{
curl_state state;
CURL* curl;
CURLcode code = CURLE_FAILED_INIT;
long responseCode = 0;
// http.post(source, postdata, { options })
curl = curlRequest(L, &state, /*optionsIndex=*/3, /*progressFnIndex=*/0, /*headersIndex=*/0);
if (curl)
{
size_t dataSize;
const char* data = luaL_checklstring(L, 2, &dataSize);
curl_easy_setopt(curl, CURLOPT_POST, 1);
if (data && dataSize > 0)
{
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)dataSize);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
}
code = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
curlCleanup(curl, &state);
}
if (code != CURLE_OK)
{
char errorBuf[1024];
lua_pushnil(L);
snprintf(errorBuf, sizeof(errorBuf) - 1, "%s\n%s\n", curl_easy_strerror(code), state.errorBuffer);
lua_pushstring(L, errorBuf);
}
else
{
lua_pushlstring(L, state.S.data, state.S.length);
lua_pushstring(L, "OK");
}
buffer_destroy(&state.S);
lua_pushnumber(L, (lua_Number)responseCode);
return 3;
}
#endif

View File

@ -10,6 +10,9 @@
#include <string.h>
#include <errno.h>
#if PLATFORM_WINDOWS
#include <io.h>
#endif
int os_chmod(lua_State* L)
{

View File

@ -0,0 +1,144 @@
/**
* \file os_reg.c
* \brief Returns true if the given file exists on the file system.
* \author Copyright (c) 2002-2016 Jason Perkins and the Premake project
*/
#include "premake.h"
#if PLATFORM_WINDOWS
typedef struct RegKeyInfo
{
HKEY key;
HKEY subkey;
char * value;
} RegKeyInfo;
static HKEY get_key(const char **path)
{
if (_strnicmp(*path, "HKCU:", 5) == 0) {
*path += 5;
return HKEY_CURRENT_USER;
}
if (_strnicmp(*path, "HKLM:", 5) == 0) {
*path += 5;
return HKEY_LOCAL_MACHINE;
}
if (_strnicmp(*path, "HKCR:", 5) == 0) {
*path += 5;
return HKEY_CLASSES_ROOT;
}
if (_strnicmp(*path, "HKU:", 4) == 0) {
*path += 4;
return HKEY_USERS;
}
if (_strnicmp(*path, "HKCC:", 5) == 0) {
*path += 5;
return HKEY_CURRENT_CONFIG;
}
// unsupported or invalid key prefix
return NULL;
}
static HKEY get_subkey(HKEY key, const char **path)
{
HKEY subkey;
size_t length;
char *subpath;
const char *value;
char hasValue;
if (key == NULL)
return NULL;
// skip the initial path separator
if ((*path)[0] == '\\')
(*path)++;
// make a copy of the subkey path that excludes the value name (if present)
value = strrchr(*path, '\\');
hasValue = value ? value[1] : 0;
if (hasValue) {
length = (size_t)(value - *path);
subpath = (char *)malloc(length + 1);
strncpy(subpath, *path, length);
subpath[length] = 0;
}
// no value separator means we should check the default value
else {
subpath = (char *)*path;
length = strlen(subpath);
}
// open the key for reading
if (RegOpenKeyExA(key, subpath, 0, KEY_READ, &subkey) != ERROR_SUCCESS)
subkey = NULL;
// free the subpath if one was allocated
if (hasValue)
free(subpath);
*path += length;
return subkey;
}
static char * get_value(HKEY key, const char * name)
{
DWORD length;
char * value;
if (key == NULL || name == NULL)
return NULL;
// skip the initial path separator
if (name[0] == '\\')
name++;
// query length of value
if (RegQueryValueExA(key, name, NULL, NULL, NULL, &length) != ERROR_SUCCESS)
return NULL;
// allocate room for the value and fetch it
value = (char *)malloc((size_t)length + 1);
if (RegQueryValueExA(key, name, NULL, NULL, (LPBYTE)value, &length) != ERROR_SUCCESS) {
free(value);
return NULL;
}
value[length] = 0;
return value;
}
static void fetch_keyinfo(struct RegKeyInfo *info, const char *path)
{
info->key = get_key(&path);
info->subkey = get_subkey(info->key, &path);
info->value = get_value(info->subkey, path);
}
static void release_keyinfo(struct RegKeyInfo *info)
{
free(info->value);
RegCloseKey(info->subkey);
}
int os_getWindowsRegistry(lua_State *L)
{
RegKeyInfo info;
fetch_keyinfo(&info, luaL_checkstring(L, 1));
lua_pushstring(L, info.value);
release_keyinfo(&info);
return 1;
}
#else
int os_getWindowsRegistry(lua_State *L)
{
lua_pushnil(L);
return 1;
}
#endif

View File

@ -24,7 +24,7 @@ int do_getcwd(char* buffer, size_t size)
int result;
#if PLATFORM_WINDOWS
result = (GetCurrentDirectoryA(size, buffer) != 0);
result = (GetCurrentDirectoryA((DWORD)size, buffer) != 0);
if (result) {
do_translate(buffer, '/');
}

View File

@ -18,14 +18,14 @@ int os_getpass(lua_State* L)
char buffer[1024];
const char* newline = "\n";
WriteConsoleA(hstdout, prompt, strlen(prompt), &written_chars, NULL);
WriteConsoleA(hstdout, prompt, (DWORD)strlen(prompt), &written_chars, NULL);
GetConsoleMode(hstdin, &mode);
SetConsoleMode(hstdin, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
ReadConsoleA(hstdin, buffer, sizeof (buffer), &read_chars, NULL);
SetConsoleMode(hstdin, mode);
WriteConsoleA(hstdout, newline, strlen(newline), &written_chars, NULL);
WriteConsoleA(hstdout, newline, (DWORD)strlen(newline), &written_chars, NULL);
buffer[strcspn(buffer, "\r\n")] = '\0';

View File

@ -16,13 +16,15 @@ struct OsVersionInfo
int isalloc;
};
static void getversion(struct OsVersionInfo* info);
static int getversion(struct OsVersionInfo* info);
int os_getversion(lua_State* L)
{
struct OsVersionInfo info = {0, 0, 0, NULL, 0};
getversion(&info);
if (!getversion(&info))
{
return 0;
}
lua_newtable(L);
@ -53,114 +55,53 @@ int os_getversion(lua_State* L)
#if defined(PLATFORM_WINDOWS)
#if !defined(VER_SUITE_WH_SERVER)
#define VER_SUITE_WH_SERVER (0x00008000)
#endif
#pragma comment(lib, "version.lib")
#ifndef SM_SERVERR2
# define SM_SERVERR2 89
#endif
SYSTEM_INFO getsysteminfo()
int getKernelVersion(struct OsVersionInfo* info)
{
typedef void (WINAPI *GetNativeSystemInfoSig)(LPSYSTEM_INFO);
GetNativeSystemInfoSig nativeSystemInfo = (GetNativeSystemInfoSig)
GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetNativeSystemInfo");
SYSTEM_INFO systemInfo = {{0}};
if ( nativeSystemInfo ) nativeSystemInfo(&systemInfo);
else GetSystemInfo(&systemInfo);
return systemInfo;
DWORD size = GetFileVersionInfoSizeA("kernel32.dll", NULL);
if (size > 0)
{
void* data = malloc(size);
if (GetFileVersionInfoA("kernel32.dll", 0, size, data))
{
void* fixedInfoPtr;
UINT fixedInfoSize;
if (VerQueryValueA(data, "\\", &fixedInfoPtr, &fixedInfoSize))
{
VS_FIXEDFILEINFO* fileInfo = (VS_FIXEDFILEINFO*)fixedInfoPtr;
info->majorversion = HIWORD(fileInfo->dwProductVersionMS);
info->minorversion = LOWORD(fileInfo->dwProductVersionMS);
info->revision = HIWORD(fileInfo->dwProductVersionLS);
return TRUE;
}
}
}
return FALSE;
}
void getversion(struct OsVersionInfo* info)
int getversion(struct OsVersionInfo* info)
{
OSVERSIONINFOEX versionInfo = {0};
info->description = "Windows";
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO*)&versionInfo);
// First get a friendly product name from the registry.
HKEY key;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &key) == ERROR_SUCCESS)
{
char value[512];
DWORD value_length = sizeof(value);
DWORD type;
RegQueryValueExA(key, "productName", NULL, &type, (LPBYTE)value, &value_length);
RegCloseKey(key);
if (type == REG_SZ)
{
info->description = strdup(value);
info->isalloc = 1;
}
}
info->majorversion = versionInfo.dwMajorVersion;
info->minorversion = versionInfo.dwMinorVersion;
info->revision = versionInfo.wServicePackMajor;
if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 0)
{
info->description = "Windows 2000";
}
else if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 1)
{
info->description = "Windows XP";
}
else if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 2)
{
SYSTEM_INFO systemInfo = getsysteminfo();
if (versionInfo.wProductType == VER_NT_WORKSTATION &&
systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
info->description = "Windows XP Professional x64";
}
else if (versionInfo.wSuiteMask & VER_SUITE_WH_SERVER)
{
info->description = "Windows Home Server";
}
else if (GetSystemMetrics(SM_SERVERR2) == 0)
{
info->description = "Windows Server 2003";
}
else
{
info->description = "Windows Server 2003 R2";
}
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 0)
{
if (versionInfo.wProductType == VER_NT_WORKSTATION)
{
info->description = "Windows Vista";
}
else
{
info->description = "Windows Server 2008";
}
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 1 )
{
if (versionInfo.wProductType != VER_NT_WORKSTATION)
{
info->description = "Windows Server 2008 R2";
}
else
{
info->description = "Windows 7";
}
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 2 )
{
if (versionInfo.wProductType != VER_NT_WORKSTATION)
{
info->description = "Windows Server 2012";
}
else
{
info->description = "Windows 8";
}
}
else if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 3 )
{
if (versionInfo.wProductType != VER_NT_WORKSTATION)
{
info->description = "Windows Server 2012 R2";
}
else
{
info->description = "Windows 8.1";
}
}
else
{
info->description = "Windows";
}
// See if we can get a product version number from kernel32.dll
return getKernelVersion(info);
}
/*************************************************************/
@ -172,23 +113,20 @@ void getversion(struct OsVersionInfo* info)
#include <string.h>
#include <stdio.h>
void getversion(struct OsVersionInfo* info)
int getversion(struct OsVersionInfo* info)
{
info->description = "Mac OS";
info->majorversion=0;
info->minorversion=0;
info->revision=0;
int mib[] = {CTL_KERN, KERN_OSRELEASE};
size_t len;
sysctl(mib, sizeof(mib)/sizeof(mib[0]), NULL, &len, NULL, 0);
int mib[] = { CTL_KERN, KERN_OSRELEASE };
size_t len;
sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0);
char kernel_version[len];
sysctl(mib, sizeof(mib)/sizeof(mib[0]), kernel_version, &len, NULL, 0);
sysctl(mib, sizeof(mib) / sizeof(mib[0]), kernel_version, &len, NULL, 0);
int kern_major;
int kern_minor;
sscanf(kernel_version, "%d.%d.%*d",&kern_major,&kern_minor);
sscanf(kernel_version, "%d.%d.%*d", &kern_major, &kern_minor);
switch (kern_major)
{
case 8:
@ -210,32 +148,46 @@ void getversion(struct OsVersionInfo* info)
info->revision = kern_minor;
break;
case 11:
info->description = "Mac OS X Lion";
info->description = "OS X Lion";
info->majorversion = 10;
info->minorversion = 7;
info->revision = kern_minor;
break;
case 12:
info->description = "Mac OS X Mountain Lion";
info->description = "OS X Mountain Lion";
info->majorversion = 10;
info->minorversion = 8;
info->revision = kern_minor;
break;
case 13:
info->description = "Mac OS X Mavericks";
info->description = "OS X Mavericks";
info->majorversion = 10;
info->minorversion = 9;
info->revision = kern_minor;
break;
case 14:
info->description = "Mac OS X Yosemite";
info->description = "OS X Yosemite";
info->majorversion = 10;
info->minorversion = 10;
info->revision = kern_minor;
break;
case 15:
info->description = "OS X El Capitan";
info->majorversion = 10;
info->minorversion = 11;
info->revision = kern_minor;
break;
case 16:
info->description = "macOS Sierra";
info->majorversion = 10;
info->minorversion = 12;
info->revision = kern_minor;
break;
default:
break;
}
return 1;
}
@ -246,7 +198,7 @@ void getversion(struct OsVersionInfo* info)
#include <string.h>
#include <sys/utsname.h>
void getversion(struct OsVersionInfo* info)
int getversion(struct OsVersionInfo* info)
{
struct utsname u;
char* ver;
@ -259,7 +211,7 @@ void getversion(struct OsVersionInfo* info)
{
// error
info->description = PLATFORM_STRING;
return;
return 0;
}
#if __GLIBC__
@ -284,18 +236,17 @@ void getversion(struct OsVersionInfo* info)
info->revision = atoi(ver);
}
}
return 1;
}
/*************************************************************/
#else
void getversion(struct OsVersionInfo* info)
int getversion(struct OsVersionInfo* info)
{
info->majorversion = 0;
info->minorversion = 0;
info->revision = 0;
info->description = PLATFORM_STRING;
return 0;
}
#endif

View File

@ -26,7 +26,7 @@ int do_mkdir(const char* path)
return 1;
// find the parent folder name.
length = strlen(path);
length = (int)strlen(path);
for (i = length - 1; i >= 0; --i)
{
if (path[i] == '/' || path[i] == '\\')

View File

@ -58,6 +58,7 @@ static const luaL_Reg os_functions[] = {
{ "isdir", os_isdir },
{ "getcwd", os_getcwd },
{ "getpass", os_getpass },
{ "getWindowsRegistry", os_getWindowsRegistry },
{ "getversion", os_getversion },
{ "isfile", os_isfile },
{ "islink", os_islink },

View File

@ -10,7 +10,7 @@
#include "lualib.h"
#define PREMAKE_VERSION "5.0.0-dev"
#define PREMAKE_COPYRIGHT "Copyright (C) 2002-2016 Jason Perkins and the Premake Project"
#define PREMAKE_COPYRIGHT "Copyright (C) 2002-2017 Jason Perkins and the Premake Project"
#define PREMAKE_PROJECT_URL "https://github.com/premake/premake-core/wiki"
/* Identify the current platform I'm not sure how to reliably detect
@ -48,6 +48,7 @@
#if PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#else
#include <unistd.h>
#endif
@ -104,6 +105,7 @@ int os_chmod(lua_State* L);
int os_copyfile(lua_State* L);
int os_getcwd(lua_State* L);
int os_getpass(lua_State* L);
int os_getWindowsRegistry(lua_State* L);
int os_getversion(lua_State* L);
int os_is64bit(lua_State* L);
int os_isdir(lua_State* L);

View File

@ -41,11 +41,11 @@
-- An array of C compiler flags.
--
clang.cflags = {
architecture = gcc.cflags.architecture,
flags = gcc.cflags.flags,
floatingpoint = gcc.cflags.floatingpoint,
strictaliasing = gcc.cflags.strictaliasing,
clang.shared = {
architecture = gcc.shared.architecture,
flags = gcc.shared.flags,
floatingpoint = gcc.shared.floatingpoint,
strictaliasing = gcc.shared.strictaliasing,
optimize = {
Off = "-O0",
On = "-O2",
@ -54,25 +54,27 @@
Size = "-Os",
Speed = "-O3",
},
pic = gcc.cflags.pic,
vectorextensions = gcc.cflags.vectorextensions,
warnings = gcc.cflags.warnings,
symbols = gcc.cflags.symbols
pic = gcc.shared.pic,
vectorextensions = gcc.shared.vectorextensions,
warnings = gcc.shared.warnings,
symbols = gcc.shared.symbols
}
clang.cflags = table.merge(gcc.cflags, {
})
function clang.getcflags(cfg)
local shared = config.mapFlags(cfg, clang.shared)
local cflags = config.mapFlags(cfg, clang.cflags)
local flags = config.mapFlags(cfg, clang.cflags)
local flags = table.join(shared, cflags)
flags = table.join(flags, clang.getwarnings(cfg))
return flags
return flags
end
function clang.getwarnings(cfg)
-- Just pass through to GCC for now
return gcc.getwarnings(cfg)
end
@ -87,12 +89,15 @@
-- An array of C++ compiler flags.
--
clang.cxxflags = table.merge(gcc.cxxflags, {
})
function clang.getcxxflags(cfg)
-- Just pass through to GCC for now
local flags = gcc.getcxxflags(cfg)
local shared = config.mapFlags(cfg, clang.shared)
local cxxflags = config.mapFlags(cfg, clang.cxxflags)
local flags = table.join(shared, cxxflags)
flags = table.join(flags, clang.getwarnings(cfg))
return flags
end

View File

@ -30,6 +30,9 @@
function dotnet.fileinfo(fcfg)
local info = {}
if (fcfg == nil) then
return info
end
local fname = fcfg.abspath
local ext = path.getextension(fname):lower()
@ -41,13 +44,17 @@
info.action = "Compile"
elseif fcfg.buildaction == "Embed" or ext == ".resx" then
info.action = "EmbeddedResource"
elseif fcfg.buildaction == "Copy" or ext == ".asax" or ext == ".aspx" then
elseif fcfg.buildaction == "Copy" or ext == ".asax" or ext == ".aspx" or ext == ".dll" then
info.action = "Content"
elseif fcfg.buildaction == "Resource" then
info.action = "Resource"
elseif ext == ".xaml" then
if fcfg.buildaction == "Application" or path.getbasename(fname) == "App" then
info.action = "ApplicationDefinition"
if fcfg.project.kind == premake.SHAREDLIB then
info.action = "None"
else
info.action = "ApplicationDefinition"
end
else
info.action = "Page"
end
@ -278,6 +285,8 @@
return "WinExe"
elseif (cfg.kind == "SharedLib") then
return "Library"
else
error("invalid dotnet kind " .. cfg.kind .. ". Valid kinds are ConsoleApp, WindowsApp, SharedLib")
end
end

View File

@ -34,8 +34,7 @@
--
-- Returns list of C compiler flags for a configuration.
--
gcc.cflags = {
gcc.shared = {
architecture = {
x86 = "-m32",
x86_64 = "-m64",
@ -86,8 +85,18 @@
}
}
gcc.cflags = {
flags = {
["C90"] = "-std=gnu90",
["C99"] = "-std=gnu99",
["C11"] = "-std=gnu11",
},
}
function gcc.getcflags(cfg)
local flags = config.mapFlags(cfg, gcc.cflags)
local shared_flags = config.mapFlags(cfg, gcc.shared)
local cflags = config.mapFlags(cfg, gcc.cflags)
local flags = table.join(shared_flags, cflags)
flags = table.join(flags, gcc.getwarnings(cfg))
return flags
end
@ -126,7 +135,10 @@
}
function gcc.getcxxflags(cfg)
local flags = config.mapFlags(cfg, gcc.cxxflags)
local shared_flags = config.mapFlags(cfg, gcc.shared)
local cxxflags = config.mapFlags(cfg, gcc.cxxflags)
local flags = table.join(shared_flags, cxxflags)
flags = table.join(flags, gcc.getwarnings(cfg))
return flags
end
@ -192,7 +204,7 @@
end
--
-- Return a list of decorated rpaths
-- Return a list of decorated rpaths
--
function gcc.getrunpathdirs(cfg, dirs)
@ -386,7 +398,7 @@
return ptrn == string.sub(s, -string.len(ptrn))
end
local name = path.getname(link)
-- Check whether link mode decorator is present
-- Check whether link mode decorator is present
if endswith(name, ":static") then
name = string.sub(name, 0, -8)
table.insert(static_syslibs, "-l" .. name)

View File

@ -28,7 +28,7 @@
-- Returns list of C compiler flags for a configuration.
--
msc.cflags = {
msc.shared = {
clr = {
On = "/clr",
Unsafe = "/clr",
@ -41,17 +41,30 @@
NoFramePointer = "/Oy",
NoMinimalRebuild = "/Gm-",
OmitDefaultLibrary = "/Zl",
StaticRuntime = function(cfg) return iif(config.isDebugBuild(cfg), "/MTd", "/MT") end,
_StaticRuntime = function(cfg) return iif(config.isDebugBuild(cfg), "/MDd", "/MD") end
},
floatingpoint = {
Fast = "/fp:fast",
Strict = "/fp:strict",
},
floatingpointexceptions = {
On = "/fp:except",
Off = "/fp:except-",
},
functionlevellinking = {
On = "/Gy",
Off = "/Gy-",
},
callingconvention = {
Cdecl = "/Gd",
FastCall = "/Gr",
StdCall = "/Gz",
VectorCall = "/Gv",
},
intrinsics = {
On = "/Oi",
},
optimize = {
Off = "/Od",
On = "/Ot",
@ -73,37 +86,25 @@
Extra = "/W4",
Off = "/W0",
},
stringpooling = {
On = "/GF",
Off = "/GF-",
},
symbols = {
On = "/Z7"
}
}
msc.cflags = {
}
function msc.getcflags(cfg)
local flags = config.mapFlags(cfg, msc.cflags)
flags = table.join(flags, msc.getwarnings(cfg))
local runtime = iif(cfg.flags.StaticRuntime, "/MT", "/MD")
if config.isDebugBuild(cfg) then
runtime = runtime .. "d"
end
table.insert(flags, runtime)
local shared = config.mapFlags(cfg, msc.shared)
local cflags = config.mapFlags(cfg, msc.cflags)
local flags = table.join(shared, cflags, msc.getwarnings(cfg))
return flags
end
function msc.getwarnings(cfg)
local result = {}
-- NOTE: VStudio can't enable specific warnings (workaround?)
for _, disable in ipairs(cfg.disablewarnings) do
table.insert(result, '/wd"' .. disable .. '"')
end
for _, fatal in ipairs(cfg.fatalwarnings) do
table.insert(result, '/we"' .. fatal .. '"')
end
return result
end
--
-- Returns list of C++ compiler flags for a configuration.
@ -121,7 +122,9 @@
}
function msc.getcxxflags(cfg)
local flags = config.mapFlags(cfg, msc.cxxflags)
local shared = config.mapFlags(cfg, msc.shared)
local cxxflags = config.mapFlags(cfg, msc.cxxflags)
local flags = table.join(shared, cxxflags, msc.getwarnings(cfg))
return flags
end
@ -154,6 +157,11 @@
for _, define in ipairs(defines) do
table.insert(result, '/D"' .. define .. '"')
end
if cfg and cfg.exceptionhandling == p.OFF then
table.insert(result, "/D_HAS_EXCEPTIONS=0")
end
return result
end
@ -286,14 +294,26 @@
-- Return the list of libraries to link, decorated with flags as needed.
--
function msc.getlinks(cfg)
local links = config.getlinks(cfg, "system", "fullpath")
for i = 1, #links do
-- Add extension if required
if not msc.getLibraryExtensions()[links[i]:match("[^.]+$")] then
links[i] = path.appendextension(links[i], ".lib")
end
function msc.getlinks(cfg, systemonly, nogroups)
local links = {}
-- If we need sibling projects to be listed explicitly, grab them first
if not systemonly then
links = config.getlinks(cfg, "siblings", "fullpath")
end
-- Then the system libraries, which come undecorated
local system = config.getlinks(cfg, "system", "fullpath")
for i = 1, #system do
-- Add extension if required
local link = system[i]
if not p.tools.msc.getLibraryExtensions()[link:match("[^.]+$")] then
link = path.appendextension(link, ".lib")
end
table.insert(links, link)
end
return links
end
@ -323,3 +343,19 @@
function msc.gettoolname(cfg, tool)
return nil
end
function msc.getwarnings(cfg)
local result = {}
-- NOTE: VStudio can't enable specific warnings (workaround?)
for _, disable in ipairs(cfg.disablewarnings) do
table.insert(result, '/wd"' .. disable .. '"')
end
for _, fatal in ipairs(cfg.fatalwarnings) do
table.insert(result, '/we"' .. fatal .. '"')
end
return result
end

View File

@ -1,20 +1,21 @@
--
-- snc.lua
-- Provides Sony SNC-specific configuration strings.
-- Copyright (c) 2010-2012 Jason Perkins and the Premake project
-- Copyright (c) 2010-2016 Jason Perkins and the Premake project
--
premake.tools.snc = {}
local snc = premake.tools.snc
local gcc = premake.tools.gcc
local config = premake.config
local p = premake
p.tools.snc = {}
local snc = p.tools.snc
local gcc = p.tools.gcc
--
-- Retrieve the CFLAGS for a specific configuration.
--
snc.cflags = {
snc.shared = {
flags = {
FatalCompileWarnings = "-Xquit=2",
},
@ -31,8 +32,13 @@
}
}
snc.cflags = {
}
function snc.getcflags(cfg)
local flags = config.mapFlags(cfg, snc.cflags)
local shared = p.config.mapFlags(cfg, snc.shared)
local cflags = p.config.mapFlags(cfg, snc.cflags)
local flags = table.join(shared, cflags, snc.getwarnings(cfg))
return flags
end
@ -41,22 +47,23 @@
-- Retrieve the CXXFLAGS for a specific configuration.
--
snc.cxxflags = {
exceptionhandling = {
Default = "-Xc+=exceptions",
On = "-Xc+=exceptions",
SEH = "-Xc-=exceptions",
},
rtti = {
Default = "-Xc+=rtti",
On = "-Xc+=rtti",
SEH = "-Xc-=rtti",
}
}
function snc.getcxxflags(cfg)
local flags = {}
-- turn on exceptions and RTTI by default, to match other toolsets
if cfg.exceptionhandling == p.ON then
table.insert(flags, "-Xc+=exceptions")
elseif cfg.exceptionhandling == p.OFF then
table.insert(flags, "-Xc-=exceptions")
end
if cfg.rtti == p.ON then
table.insert(flags, "-Xc+=rtti")
elseif cfg.rtti == p.OFF then
table.insert(flags, "-Xc-=rtti")
end
local shared = config.mapFlags(cfg, snc.shared)
local cxxflags = config.mapFlags(cfg, snc.cxxflags)
local flags = table.join(shared, cxxflags, snc.getwarnings(cfg))
return flags
end
@ -72,11 +79,9 @@
--
function snc.getforceincludes(cfg)
-- Just pass through to GCC for now
local flags = gcc.getforceincludes(cfg)
return flags
end

View File

@ -136,6 +136,7 @@ return {
"actions/vstudio/vc2010/test_rule_props.lua",
"actions/vstudio/vc2010/test_rule_targets.lua",
"actions/vstudio/vc2010/test_rule_vars.lua",
"actions/vstudio/vc2010/test_rule_xml.lua",
"actions/vstudio/vc2010/test_target_machine.lua",
"actions/vstudio/vc2010/test_user_file.lua",
"actions/vstudio/vc2010/test_vectorextensions.lua",

View File

@ -36,9 +36,19 @@
test.capture [[
$(OBJDIR)/hello.o: src/greetings/hello.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
$(OBJDIR)/hello1.o: src/hello.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
]]
@ -55,9 +65,19 @@ $(OBJDIR)/hello1.o: src/hello.cpp
test.capture [[
$(OBJDIR)/hello.o: src/hello.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 "$<"
$(OBJDIR)/test.o: src/test.cpp
@echo $(notdir $<)
ifeq (posix,$(SHELLTYPE))
$(SILENT) mkdir -p $(OBJDIR)
else
$(SILENT) mkdir $(subst /,\\,$(OBJDIR))
endif
$(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -MF "$(@:%.o=%.d)" -c "$<"
]]

View File

@ -110,7 +110,7 @@ OBJECTS := \
-- link automatically to match the behavior of Visual Studio
--
function suite.customBuildRule()
function suite.linkBuildOutputs_onNotSpecified()
files { "hello.x" }
filter "files:**.x"
buildmessage "Compiling %{file.name}"
@ -137,6 +137,72 @@ endif
end
--
-- Also include it in the link step if we explicitly specified so with
-- linkbuildoutputs.
--
function suite.linkBuildOutputs_onOn()
files { "hello.x" }
filter "files:**.x"
buildmessage "Compiling %{file.name}"
buildcommands {
'cxc -c "%{file.path}" -o "%{cfg.objdir}/%{file.basename}.xo"',
'c2o -c "%{cfg.objdir}/%{file.basename}.xo" -o "%{cfg.objdir}/%{file.basename}.obj"'
}
buildoutputs { "%{cfg.objdir}/%{file.basename}.obj" }
linkbuildoutputs "On"
prepare()
test.capture [[
OBJECTS := \
RESOURCES := \
CUSTOMFILES := \
ifeq ($(config),debug)
OBJECTS += \
obj/Debug/hello.obj \
endif
]]
end
--
-- If linkbuildoutputs says that we shouldn't include it in the link however,
-- don't do it.
--
function suite.linkBuildOutputs_onOff()
files { "hello.x" }
filter "files:**.x"
buildmessage "Compiling %{file.name}"
buildcommands {
'cxc -c "%{file.path}" -o "%{cfg.objdir}/%{file.basename}.xo"',
'c2o -c "%{cfg.objdir}/%{file.basename}.xo" -o "%{cfg.objdir}/%{file.basename}.obj"'
}
buildoutputs { "%{cfg.objdir}/%{file.basename}.obj" }
linkbuildoutputs "Off"
prepare()
test.capture [[
OBJECTS := \
RESOURCES := \
CUSTOMFILES := \
ifeq ($(config),debug)
CUSTOMFILES += \
obj/Debug/hello.obj \
endif
]]
end
--
-- If a file is excluded from a configuration, it should not be listed.
--

View File

@ -32,7 +32,7 @@
function suite.defaultRules()
prepare()
test.capture [[
all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)
all: prebuild prelink $(TARGET)
@:
]]
end
@ -47,7 +47,7 @@ all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)
kind "WindowedApp"
prepare()
test.capture [[
all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist
all: prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist
@:
$(dir $(TARGETDIR))PkgInfo:

View File

@ -46,6 +46,18 @@
end
function suite.PerConfigFile()
files { "Hello.cs" }
configuration { 'debug' }
files { "HelloTwo.cs" }
prepare()
test.capture [[
<Compile Include="Hello.cs" />
<Compile Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' " Include="HelloTwo.cs" />
]]
end
--
-- Test file dependencies
--

View File

@ -534,6 +534,22 @@
]]
end
function suite.exceptions_onNoExceptionsVS2013()
exceptionhandling "Off"
premake.action.set("vs2013")
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>Disabled</Optimization>
<ExceptionHandling>false</ExceptionHandling>
]]
end
function suite.exceptions_onSEH()
exceptionhandling "SEH"
prepare()
@ -786,3 +802,172 @@
<Optimization>Disabled</Optimization>
]]
end
--
-- Check handling of the stringpooling api
--
function suite.onStringPoolingOff()
stringpooling 'Off'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<StringPooling>false</StringPooling>
]]
end
function suite.onStringPoolingOn()
stringpooling 'On'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<StringPooling>true</StringPooling>
]]
end
function suite.onStringPoolingNotSpecified()
optimize "On"
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
]]
end
--
-- Check handling of the floatingpointexceptions api
--
function suite.onFloatingPointExceptionsOff()
floatingpointexceptions 'Off'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<FloatingPointExceptions>false</FloatingPointExceptions>
]]
end
function suite.onFloatingPointExceptionsOn()
floatingpointexceptions 'On'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<FloatingPointExceptions>true</FloatingPointExceptions>
]]
end
function suite.onFloatingPointExceptionsNotSpecified()
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
]]
end
--
-- Check handling of the functionlevellinking api
--
function suite.onFunctionLevelLinkingOff()
functionlevellinking 'Off'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>false</FunctionLevelLinking>
]]
end
function suite.onFunctionLevelLinkingOn()
functionlevellinking 'On'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
]]
end
function suite.onFunctionLevelLinkingNotSpecified()
optimize "On"
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
]]
end
--
-- Check handling of the intrinsics api
--
function suite.onIntrinsicsOff()
intrinsics 'Off'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<IntrinsicFunctions>false</IntrinsicFunctions>
]]
end
function suite.onIntrinsicsOn()
intrinsics 'On'
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
]]
end
function suite.onIntrinsicsNotSpecified()
optimize "On"
prepare()
test.capture [[
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<MinimalRebuild>false</MinimalRebuild>
<StringPooling>true</StringPooling>
]]
end

View File

@ -68,10 +68,10 @@
--
function suite.debuggerCommandArgs_onDebugArgs()
debugargs { "arg1", "arg2" }
debugargs { "arg1", "arg2", "arg1" }
prepare()
test.capture [[
<LocalDebuggerCommandArguments>arg1 arg2</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>arg1 arg2 arg1</LocalDebuggerCommandArguments>
]]
end

View File

@ -333,6 +333,75 @@
end
--
-- If a custom rule outputs an object file, it's automatically linked, unless
-- we explicitly specify that it isn't with linkbuildoutputs.
--
function suite.linkBuildOutputs_onNotSpecified()
files { "hello.x" }
filter "files:**.x"
buildcommands { "echo $(InputFile)" }
buildoutputs { "$(InputName).obj" }
prepare()
test.capture [[
<ItemGroup>
<CustomBuild Include="hello.x">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(InputName).obj</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(InputName).obj</Outputs>
</CustomBuild>
</ItemGroup>
]]
end
function suite.linkBuildOutputs_onOff()
files { "hello.x" }
filter "files:**.x"
buildcommands { "echo $(InputFile)" }
buildoutputs { "$(InputName).obj" }
linkbuildoutputs "Off"
prepare()
test.capture [[
<ItemGroup>
<CustomBuild Include="hello.x">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(InputName).obj</Outputs>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(InputName).obj</Outputs>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
</CustomBuild>
</ItemGroup>
]]
end
function suite.linkBuildOutputs_onOn()
files { "hello.x" }
filter "files:**.x"
buildcommands { "echo $(InputFile)" }
buildoutputs { "$(InputName).obj" }
linkbuildoutputs "On"
prepare()
test.capture [[
<ItemGroup>
<CustomBuild Include="hello.x">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(InputName).obj</Outputs>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkObjects>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo $(InputFile)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(InputName).obj</Outputs>
<LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkObjects>
</CustomBuild>
</ItemGroup>
]]
end
--
-- If two files at different folder levels have the same name, a different
-- object file name should be used for each.

View File

@ -129,7 +129,8 @@
-- Test the handling of the Symbols flag.
--
function suite.generateDebugInfo_onSymbols()
function suite.generateDebugInfo_onSymbolsOn_on2010()
premake.action.set("vs2010")
symbols "On"
prepare()
test.capture [[
@ -139,6 +140,72 @@
]]
end
function suite.generateDebugInfo_onSymbolsFastLink_on2010()
premake.action.set("vs2010")
symbols "FastLink"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
]]
end
function suite.generateDebugInfo_onSymbolsFull_on2010()
premake.action.set("vs2010")
symbols "Full"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
]]
end
function suite.generateDebugInfo_onSymbolsOn_on2015()
premake.action.set("vs2015")
symbols "On"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
]]
end
function suite.generateDebugInfo_onSymbolsFastLink_on2015()
premake.action.set("vs2015")
symbols "FastLink"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
<GenerateDebugInformation>DebugFastLink</GenerateDebugInformation>
]]
end
function suite.generateDebugInfo_onSymbolsFull_on2015()
premake.action.set("vs2015")
symbols "Full"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
]]
end
function suite.generateDebugInfo_onSymbolsFull_on2017()
premake.action.set("vs2017")
symbols "Full"
prepare()
test.capture [[
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
]]
end
--
-- Any system libraries specified in links() should be listed as

View File

@ -136,3 +136,21 @@ command 2</NMakeBuildCommandLine>
</PropertyGroup>
]]
end
--
-- Should not emit include dirs or preprocessor definitions if the project
-- kind is "None", since that project is by definition not buildable.
---
function suite.noIncludeDirsOrPreprocessorDefs_onKindNone()
kind "None"
defines { "DEBUG", "_DEBUG" }
includedirs { "include/lua", "include/zlib" }
prepare()
test.capture [[
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<NMakeOutput>$(OutDir)MyProject</NMakeOutput>
</PropertyGroup>
]]
end

View File

@ -0,0 +1,61 @@
--
-- tests/actions/vstudio/vc2010/test_rule_xml.lua
-- Validate generation of custom rules
-- Author Jason Perkins
-- Copyright (c) 2016 Jason Perkins and the Premake project
--
local suite = test.declare("vstudio_vs2010_rule_xml")
local vc2010 = premake.vstudio.vc2010
local m = premake.vstudio.vs2010.rules.xml
--
-- Setup
--
function suite.setup()
premake.action.set("vs2010")
rule "MyRule"
wks, prj = test.createWorkspace()
rules { "MyRule" }
end
local function createVar(def)
rule "MyRule"
propertydefinition(def)
project "MyProject"
end
---
-- Property definitions
---
function suite.properties_onString()
createVar { name="MyVar", kind="string" }
local r = test.getRule("MyRule")
m.properties(r)
test.capture [[
<StringProperty
Name="MyVar"
HelpContext="0"
DisplayName="MyVar"
Switch="[value]" />
]]
end
function suite.properties_onStringWithNoKind()
createVar { name="MyVar" }
local r = test.getRule("MyRule")
m.properties(r)
test.capture [[
<StringProperty
Name="MyVar"
HelpContext="0"
DisplayName="MyVar"
Switch="[value]" />
]]
end

View File

@ -38,6 +38,18 @@
end
end
function suite.https_get_verify_peer()
local result, err = http.get("https://httpbin.org/user-agent")
if result then
p.out(result)
test.capture(
'{\n "user-agent": "Premake/' .. _PREMAKE_VERSION .. '"\n}'
)
else
test.fail(err);
end
end
function suite.http_responsecode()
local result, err, responseCode = http.get("http://httpbin.org/status/418")
test.isequal(responseCode, 418)

View File

@ -220,3 +220,57 @@
function suite.translateCommand_windowsCopyNoQuotesSrc_ExtraSpace()
test.isequal('IF EXIST a\\ (xcopy /Q /E /Y /I a "b" > nul) ELSE (xcopy /Q /Y /I a "b" > nul)', os.translateCommands('{COPY} a "b" ', "windows"))
end
--
-- os.getWindowsRegistry windows tests
--
function suite.getreg_nonExistentValue()
if os.is("windows") then
local x = os.getWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All")
test.isequal(nil, x)
end
end
function suite.getreg_nonExistentDefaultValue()
if os.is("windows") then
local x = os.getWindowsRegistry("HKCU:Should\\Not\\Exist\\At\\All\\")
test.isequal(nil, x)
end
end
function suite.getreg_noSeparators()
if os.is("windows") then
os.getWindowsRegistry("HKCU:ShouldNotExistAtAll")
end
end
function suite.getreg_namedValue()
if os.is("windows") then
local x = os.getWindowsRegistry("HKCU:Environment\\TEMP")
test.istrue(x ~= nil)
end
end
function suite.getreg_namedValueOptSeparator()
if os.is("windows") then
local x = os.getWindowsRegistry("HKCU:\\Environment\\TEMP")
test.istrue(x ~= nil)
end
end
function suite.getreg_defaultValue()
if os.is("windows") then
local x = os.getWindowsRegistry("HKLM:SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Minimal\\AppInfo\\")
test.isequal("Service", x)
end
end
--
-- os.getversion tests.
--
function suite.getversion()
local version = os.getversion();
test.istrue(version ~= nil)
end

View File

@ -77,6 +77,65 @@
test.contains("/GL", msc.getldflags(cfg))
end
function suite.cflags_onStringPoolingOn()
stringpooling "On"
prepare()
test.contains("/GF", msc.getcflags(cfg))
end
function suite.cflags_onStringPoolingOff()
stringpooling "Off"
prepare()
test.contains("/GF-", msc.getcflags(cfg))
end
function suite.cflags_onStringPoolingNotSpecified()
prepare()
test.excludes("/GF", msc.getcflags(cfg))
test.excludes("/GF-", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsOn()
floatingpointexceptions "On"
prepare()
test.contains("/fp:except", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsOff()
floatingpointexceptions "Off"
prepare()
test.contains("/fp:except-", msc.getcflags(cfg))
end
function suite.cflags_onFloatingPointExceptionsNotSpecified()
prepare()
test.excludes("/fp:except", msc.getcflags(cfg))
test.excludes("/fp:except-", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingOn()
functionlevellinking "On"
prepare()
test.contains("/Gy", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingOff()
functionlevellinking "Off"
prepare()
test.contains("/Gy-", msc.getcflags(cfg))
end
function suite.cflags_onFunctionLevelLinkingNotSpecified()
prepare()
test.excludes("/Gy", msc.getcflags(cfg))
test.excludes("/Gy-", msc.getcflags(cfg))
end
function suite.cflags_onIntrinsicsOn()
intrinsics "On"
prepare()
test.contains("/Oi", msc.getcflags(cfg))
end
--
-- Check the translation of symbols.
@ -387,3 +446,19 @@
test.contains('/NODEFAULTLIB:lib1.lib', msc.getldflags(cfg))
end
--
-- Check handling of shared C/C++ flags.
--
function suite.mixedToolFlags_onCFlags()
flags { "FatalCompileWarnings" }
prepare()
test.isequal({ "/WX", "/MD" }, msc.getcflags(cfg))
end
function suite.mixedToolFlags_onCxxFlags()
flags { "FatalCompileWarnings" }
prepare()
test.isequal({ "/WX", "/MD", "/EHsc" }, msc.getcxxflags(cfg))
end