summaryrefslogtreecommitdiffstats
path: root/autoconf
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--autoconf/LICENSE.txt27
-rw-r--r--autoconf/api.lua305
-rw-r--r--autoconf/autoconf.lua18
-rw-r--r--autoconf/clang.lua27
-rw-r--r--autoconf/gcc.lua27
-rw-r--r--autoconf/msc.lua62
6 files changed, 466 insertions, 0 deletions
diff --git a/autoconf/LICENSE.txt b/autoconf/LICENSE.txt
new file mode 100644
index 00000000..eb1b1720
--- /dev/null
+++ b/autoconf/LICENSE.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2016 Blizzard Entertainment and individual contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ 3. Neither the name of Premake nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/autoconf/api.lua b/autoconf/api.lua
new file mode 100644
index 00000000..064ea795
--- /dev/null
+++ b/autoconf/api.lua
@@ -0,0 +1,305 @@
+---
+-- Autoconfiguration.
+-- Copyright (c) 2016 Blizzard Entertainment
+-- Enhanced by re3
+---
+local p = premake
+local autoconf = p.modules.autoconf
+autoconf.cache = {}
+autoconf.parameters = ""
+
+
+---
+-- register autoconfigure api.
+---
+p.api.register {
+ name = "autoconfigure",
+ scope = "config",
+ kind = "table"
+}
+
+---
+-- Check for a particular include file.
+--
+-- @cfg : Current config.
+-- @variable : The variable to store the result, such as 'HAVE_STDINT_H'.
+-- @filename : The header file to check for.
+---
+function check_include(cfg, variable, filename)
+ local res = autoconf.cache_compile(cfg, variable, function ()
+ p.outln('#include <' .. filename .. '>')
+ p.outln('int main(void) { return 0; }')
+ end)
+
+ if res.value then
+ autoconf.set_value(cfg, variable, 1)
+ end
+end
+
+
+---
+-- Check for size of a particular type.
+--
+-- @cfg : Current config.
+-- @variable : The variable to use, such as 'SIZEOF_SIZE_T', this method will also add "'HAVE_' .. variable".
+-- @type : The type to check.
+-- @headers : An optional array of header files to include.
+-- @defines : An optional array of defines to define.
+---
+function check_type_size(cfg, variable, type, headers, defines)
+ check_include(cfg, 'HAVE_SYS_TYPES_H', 'sys/types.h')
+ check_include(cfg, 'HAVE_STDINT_H', 'stdint.h')
+ check_include(cfg, 'HAVE_STDDEF_H', 'stddef.h')
+
+ local res = autoconf.cache_compile(cfg, variable .. cfg.platform,
+ function ()
+ if cfg.autoconf['HAVE_SYS_TYPES_H'] then
+ p.outln('#include <sys/types.h>')
+ end
+
+ if cfg.autoconf['HAVE_STDINT_H'] then
+ p.outln('#include <stdint.h>')
+ end
+
+ if cfg.autoconf['HAVE_STDDEF_H'] then
+ p.outln('#include <stddef.h>')
+ end
+
+ autoconf.include_defines(defines)
+ autoconf.include_headers(headers)
+ p.outln("")
+ p.outln("#define SIZE (sizeof(" .. type .. "))")
+ p.outln("char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',")
+ p.outln(" ('0' + ((SIZE / 10000)%10)),")
+ p.outln(" ('0' + ((SIZE / 1000)%10)),")
+ p.outln(" ('0' + ((SIZE / 100)%10)),")
+ p.outln(" ('0' + ((SIZE / 10)%10)),")
+ p.outln(" ('0' + (SIZE %10)),")
+ p.outln(" ']', '\\0'};")
+ p.outln("")
+ p.outln("int main(int argc, char *argv[]) {")
+ p.outln(" int require = 0;")
+ p.outln(" require += info_size[argc];")
+ p.outln(" (void)argv;")
+ p.outln(" return require;")
+ p.outln("}")
+ end,
+ function (e)
+ -- if the compile step succeeded, we should have a binary with 'INFO:size[*****]'
+ -- somewhere in there.
+ local content = io.readfile(e.binary)
+ if content then
+ local size = string.find(content, 'INFO:size')
+ if size then
+ e.size = tonumber(string.sub(content, size+10, size+14))
+ end
+ end
+ end
+ )
+
+ if res.size then
+ autoconf.set_value(cfg, 'HAVE_' .. variable, 1)
+ autoconf.set_value(cfg, variable, res.size)
+ end
+end
+
+
+---
+-- Check if the given struct or class has the specified member variable
+--
+-- @cfg : current config.
+-- @variable : variable to store the result.
+-- @type : the name of the struct or class you are interested in
+-- @member : the member which existence you want to check
+-- @headers : an optional array of header files to include.
+-- @defines : An optional array of defines to define.
+---
+function check_struct_has_member(cfg, variable, type, member, headers, defines)
+ local res = autoconf.cache_compile(cfg, variable, function ()
+ autoconf.include_defines(defines)
+ autoconf.include_headers(headers)
+ p.outln('int main(void) {')
+ p.outln(' (void)sizeof(((' .. type .. '*)0)->' .. member ..');')
+ p.outln(' return 0;')
+ p.outln('}')
+ end)
+
+ if res.value then
+ autoconf.set_value(cfg, variable, 1)
+ end
+end
+
+
+---
+-- Check if a symbol exists as a function, variable, or macro
+--
+-- @cfg : current config.
+-- @variable : variable to store the result.
+-- @symbol : The symbol to check for.
+-- @headers : an optional array of header files to include.
+-- @defines : An optional array of defines to define.
+---
+function check_symbol_exists(cfg, variable, symbol, headers, defines)
+ local h = headers
+ local res = autoconf.cache_compile(cfg, variable, function ()
+ autoconf.include_defines(defines)
+ autoconf.include_headers(headers)
+ p.outln('int main(int argc, char** argv) {')
+ p.outln(' (void)argv;')
+ p.outln('#ifndef ' .. symbol)
+ p.outln(' return ((int*)(&' .. symbol .. '))[argc];')
+ p.outln('#else')
+ p.outln(' (void)argc;')
+ p.outln(' return 0;')
+ p.outln('#endif')
+ p.outln('}')
+ end)
+
+ if res.value then
+ autoconf.set_value(cfg, variable, 1)
+ end
+end
+
+
+---
+-- try compiling a piece of c/c++
+---
+function autoconf.try_compile(cfg, cpp)
+ local ts = autoconf.toolset(cfg)
+ if ts then
+ return ts.try_compile(cfg, cpp, autoconf.parameters)
+ else
+ p.warnOnce('autoconf', 'no toolset found, autoconf always failing.')
+ end
+end
+
+
+function autoconf.cache_compile(cfg, entry, func, post)
+ if not autoconf.cache[entry] then
+ local cpp = p.capture(func)
+ local res = autoconf.try_compile(cfg, cpp)
+ if res then
+ local e = { binary = res, value = true }
+ if post then
+ post(e)
+ end
+ autoconf.cache[entry] = e
+ else
+ autoconf.cache[entry] = { }
+ end
+ end
+ return autoconf.cache[entry]
+end
+
+
+---
+-- get the current configured toolset, or the default.
+---
+function autoconf.toolset(cfg)
+ local ts = p.config.toolset(cfg)
+ if not ts then
+ local tools = {
+ -- Actually we always return nil on msc. see msc.lua
+ ['vs2010'] = p.tools.msc,
+ ['vs2012'] = p.tools.msc,
+ ['vs2013'] = p.tools.msc,
+ ['vs2015'] = p.tools.msc,
+ ['vs2017'] = p.tools.msc,
+ ['vs2019'] = p.tools.msc,
+ ['gmake'] = premake.tools.gcc,
+ ['gmake2'] = premake.tools.gcc,
+ ['codelite'] = premake.tools.gcc,
+ ['xcode4'] = premake.tools.clang,
+ }
+ ts = tools[_ACTION]
+ end
+ return ts
+end
+
+
+---
+-- store the value of the variable in the configuration
+---
+function autoconf.set_value(cfg, variable, value)
+ cfg.autoconf[variable] = value
+end
+
+
+---
+-- write the cfg.autoconf table to the file
+---
+function autoconf.writefile(cfg, filename)
+ if cfg.autoconf then
+ local file = io.open(filename, "w+")
+ for variable, value in pairs(cfg.autoconf) do
+ file:write('#define ' .. variable .. ' ' .. tostring(value) .. (_eol or '\n'))
+ end
+ file:close()
+ end
+end
+
+
+---
+-- Utility method to add a table of headers.
+---
+function autoconf.include_headers(headers)
+ if headers ~= nil then
+ if type(headers) == "table" then
+ for _, v in ipairs(headers) do
+ p.outln('#include <' .. v .. '>')
+ end
+ else
+ p.outln('#include <' .. headers .. '>')
+ end
+ end
+end
+
+function autoconf.include_defines(defines)
+ if defines ~= nil then
+ if type(defines) == "table" then
+ for _, v in ipairs(defines) do
+ p.outln('#define ' .. v)
+ end
+ else
+ p.outln('#define ' .. defines)
+ end
+ end
+end
+
+---
+-- attach ourselfs to the running action.
+---
+p.override(p.action, 'call', function (base, name)
+ local a = p.action.get(name)
+
+ -- store the old callback.
+ local onBaseProject = a.onProject or a.onproject
+
+ -- override it with our own.
+ a.onProject = function(prj)
+ -- go through each configuration, and call the setup configuration methods.
+ for cfg in p.project.eachconfig(prj) do
+ cfg.autoconf = {}
+ if cfg.autoconfigure then
+ verbosef('Running auto config steps for "%s/%s".', prj.name, cfg.name)
+ for file, func in pairs(cfg.autoconfigure) do
+ func(cfg)
+
+ if not (file ~= "dontWrite") then
+ os.mkdir(cfg.objdir)
+ local filename = path.join(cfg.objdir, file)
+ autoconf.writefile(cfg, filename)
+ end
+ end
+ end
+ end
+
+ -- then call the old onProject.
+ if onBaseProject then
+ onBaseProject(prj)
+ end
+ end
+
+ -- now call the original action.call methods
+ base(name)
+end)
diff --git a/autoconf/autoconf.lua b/autoconf/autoconf.lua
new file mode 100644
index 00000000..6c99f9da
--- /dev/null
+++ b/autoconf/autoconf.lua
@@ -0,0 +1,18 @@
+---
+-- Autoconfiguration.
+-- Copyright (c) 2016 Blizzard Entertainment
+---
+ local p = premake
+
+ if not premake.modules.autoconf then
+ p.modules.autoconf = {}
+ p.modules.autoconf._VERSION = p._VERSION
+
+ verbosef('Loading autoconf module...')
+ include('api.lua')
+ include('msc.lua')
+ include('clang.lua')
+ include('gcc.lua')
+ end
+
+ return p.modules.autoconf
diff --git a/autoconf/clang.lua b/autoconf/clang.lua
new file mode 100644
index 00000000..fdb5f405
--- /dev/null
+++ b/autoconf/clang.lua
@@ -0,0 +1,27 @@
+---
+-- Autoconfiguration.
+-- Copyright (c) 2016 Blizzard Entertainment
+---
+local p = premake
+local clang = p.tools.clang
+
+function clang.try_compile(cfg, text, parameters)
+ -- write the text to a temporary file.
+ local cppFile = path.join(cfg.objdir, "temp.cpp")
+ if not io.writefile(cppFile, text) then
+ return nil
+ end
+
+ if parameters == nil then
+ parameters = ""
+ end
+
+ local outFile = path.join(cfg.objdir, "temp.out")
+
+ -- compile that text file.
+ if os.execute('clang "' .. cppFile .. '" ' .. parameters .. ' -o "' .. outFile ..'" &> /dev/null') then
+ return outFile
+ else
+ return nil
+ end
+end
diff --git a/autoconf/gcc.lua b/autoconf/gcc.lua
new file mode 100644
index 00000000..34520139
--- /dev/null
+++ b/autoconf/gcc.lua
@@ -0,0 +1,27 @@
+---
+-- Autoconfiguration.
+-- Copyright (c) 2016 Blizzard Entertainment
+---
+local p = premake
+local gcc = p.tools.gcc
+
+function gcc.try_compile(cfg, text, parameters)
+ -- write the text to a temporary file.
+ local cppFile = path.join(cfg.objdir, "temp.cpp")
+ if not io.writefile(cppFile, text) then
+ return nil
+ end
+
+ if parameters == nil then
+ parameters = ""
+ end
+
+ local outFile = path.join(cfg.objdir, "temp.out")
+
+ -- compile that text file.
+ if os.execute('gcc "' .. cppFile .. '" ' .. parameters .. ' -o "' .. outFile ..'" &> /dev/null') then
+ return outFile
+ else
+ return nil
+ end
+end
diff --git a/autoconf/msc.lua b/autoconf/msc.lua
new file mode 100644
index 00000000..b96a82ec
--- /dev/null
+++ b/autoconf/msc.lua
@@ -0,0 +1,62 @@
+---
+-- Autoconfiguration.
+-- Copyright (c) 2016 Blizzard Entertainment
+---
+local p = premake
+local msc = p.tools.msc
+
+-- "parameters" is unused, matter of fact this file is unused - re3
+function msc.try_compile(cfg, text, parameters)
+
+ return nil
+--[[
+ -- write the text to a temporary file.
+ local cppFile = path.join(cfg.objdir, "temp.cpp")
+ if not io.writefile(cppFile, text) then
+ return nil
+ end
+
+ -- write out a batch file.
+ local batch = p.capture(function ()
+ p.outln('@echo off')
+ p.outln('SET mypath=%~dp0')
+ p.outln('pushd %mypath%')
+
+ local map = {
+ vs2010 = 'VS100COMNTOOLS',
+ vs2012 = 'VS110COMNTOOLS',
+ vs2013 = 'VS120COMNTOOLS',
+ vs2015 = 'VS140COMNTOOLS',
+ vs2017 = 'VS141COMNTOOLS',
+ vs2019 = 'VS142COMNTOOLS',
+ }
+
+ local a = map[_ACTION]
+ if a then
+ a = path.translate(os.getenv(a), '/')
+ a = path.join(a, '../../VC/vcvarsall.bat')
+
+ if cfg.platform == 'x86' then
+ p.outln('call "' .. a .. '" > NUL')
+ else
+ p.outln('call "' .. a .. '" amd64 > NUL')
+ end
+
+ p.outln('cl.exe /nologo temp.cpp > NUL')
+ else
+ error('Unsupported Visual Studio version: ' .. _ACTION)
+ end
+ end)
+
+ local batchFile = path.join(cfg.objdir, "compile.bat")
+ if not io.writefile(batchFile, batch) then
+ return nil
+ end
+
+ if os.execute(batchFile) then
+ return path.join(cfg.objdir, "temp.exe")
+ else
+ return nil
+ end
+--]]
+end