summaryrefslogtreecommitdiff
path: root/xmake/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/scripts')
-rw-r--r--xmake/scripts/base/compiler.lua215
-rw-r--r--xmake/scripts/base/linker.lua73
-rw-r--r--xmake/scripts/base/main.lua54
-rw-r--r--xmake/scripts/base/makefile.lua2
-rw-r--r--xmake/scripts/base/project.lua143
-rw-r--r--xmake/scripts/base/rule.lua1
6 files changed, 407 insertions, 81 deletions
diff --git a/xmake/scripts/base/compiler.lua b/xmake/scripts/base/compiler.lua
index 685d8dc66..8120bd037 100644
--- a/xmake/scripts/base/compiler.lua
+++ b/xmake/scripts/base/compiler.lua
@@ -25,6 +25,7 @@ local compiler = compiler or {}
-- load modules
local path = require("base/path")
+local rule = require("base/rule")
local utils = require("base/utils")
local table = require("base/table")
local string = require("base/string")
@@ -102,6 +103,28 @@ function compiler._getflags(module, names, flags)
return flags_mapped
end
+-- get the flag names from the given compiler name
+function compiler._flagnames(name)
+
+ -- check
+ assert(name)
+
+ -- the flag names
+ local flagnames = nil
+ if name == "cc" then flagnames = { "cxflags", "cflags" }
+ elseif name == "cxx" then flagnames = { "cxflags", "cxxflags" }
+ elseif name == "mm" then flagnames = { "mxflags", "mflags" }
+ elseif name == "mxx" then flagnames = { "mxflags", "mxxflags" }
+ elseif name == "as" then flagnames = { "asflags" }
+ -- error
+ utils.error("unknown compiler: %s", name)
+ return
+ end
+
+ -- ok
+ return flagnames
+end
+
-- get the compiler name from the source file type
function compiler._name(srcfile)
@@ -159,31 +182,19 @@ function compiler.make(module, target, srcfile, objfile)
-- check
assert(module and target)
- -- the compiler name
- local name = module._NAME
- assert(name)
-
-- the flag names
- local flag_names = nil
- if name == "cc" then flag_names = { "cxflags", "cflags" }
- elseif name == "cxx" then flag_names = { "cxflags", "cxxflags" }
- elseif name == "mm" then flag_names = { "mxflags", "mflags" }
- elseif name == "mxx" then flag_names = { "mxflags", "mxxflags" }
- elseif name == "as" then flag_names = { "asflags" }
- -- error
- utils.error("unknown compiler: %s", name)
- return
- end
+ local flagnames = compiler._flagnames(module._NAME)
+ assert(flagnames)
-- append the common flags from the current compiler
local flags = {}
- for _, flag_name in ipairs(flag_names) do
- table.join2(flags, module[flag_name])
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, module[flagname])
end
-- append the target flags from the current project
- for _, flag_name in ipairs(flag_names) do
- table.join2(flags, compiler._mapflags(module, target[flag_name]))
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(module, target[flagname]))
end
-- append the symbols flags from the current project
@@ -257,13 +268,177 @@ function compiler.make(module, target, srcfile, objfile)
end
-- append the flags from the configure
- for _, flag_name in ipairs(flag_names) do
- table.join2(flags, compiler._mapflags(module, config.get(flag_name)))
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(module, config.get(flagname)))
end
-- make the compile command
return module.command_compile(srcfile, objfile, table.concat(flags, " "):trim())
end
+-- check include for the project option
+function compiler.check_include(opt, include, srcpath, objpath)
+
+ -- check
+ assert(opt and include and srcpath and objpath)
+
+ -- open the checking source file
+ local srcfile = io.open(srcpath, "w")
+ if not srcfile then return end
+
+ -- make include
+ srcfile:write(string.format("#include <%s>\n\n", include))
+
+ -- make the main function header
+ srcfile:write("int main(int argc, char** argv)\n")
+ srcfile:write("{\n")
+ srcfile:write(" return 0;\n")
+ srcfile:write("}\n")
+
+ -- exit this file
+ srcfile:close()
+
+ -- get the compiler
+ local c = compiler.get(srcpath)
+ if not c then return end
+
+ -- the flag names
+ local flagnames = compiler._flagnames(c._NAME)
+ assert(flagnames)
+
+ -- append the common flags
+ local flags = {}
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, c[flagname])
+ end
+
+ -- append the option flags
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(c, opt[flagname]))
+ end
+
+ -- append the defines flags
+ if opt.defines and c.flag_define then
+ local defines = utils.wrap(opt.defines)
+ for _, define in ipairs(defines) do
+ table.join2(flags, c.flag_define(define))
+ end
+ end
+
+ -- append the undefines flags
+ if opt.undefines and c.flag_undefine then
+ local undefines = utils.wrap(opt.undefines)
+ for _, undefine in ipairs(undefines) do
+ table.join2(flags, c.flag_undefine(undefine))
+ end
+ end
+
+ -- append the includedirs flags
+ if opt.includedirs and c.flag_includedir then
+ for _, includedir in ipairs(utils.wrap(opt.includedirs)) do
+ table.join2(flags, c.flag_includedir(includedir))
+ end
+ end
+
+ -- make the compile command
+ local cmd = string.format("%s > %s 2>&1", c.command_compile(srcpath, objpath, table.concat(flags, " "):trim()), xmake._NULDEV)
+ if not cmd then return end
+
+ -- check it
+ if 0 ~= os.execute(cmd) then return end
+
+ -- ok
+ return true
+end
+
+-- check function for the project option
+function compiler.check_function(opt, interface, srcpath, objpath)
+
+ -- check
+ assert(opt and interface)
+
+ -- open the checking source file
+ local srcfile = io.open(srcpath, "w")
+ if not srcfile then return end
+
+ -- get the compiler
+ local c = compiler.get(srcpath)
+ if not c then return end
+
+ -- make includes
+ local includes = nil
+ if c._NAME == "cc" then includes = opt.cincludes
+ elseif c._NAME == "cxx" then includes = opt.cxxincludes
+ end
+ if includes then
+ for _, include in ipairs(utils.wrap(includes)) do
+ srcfile:write(string.format("#include <%s>\n", include))
+ end
+ srcfile:write("\n")
+ end
+
+ -- make the main function header
+ srcfile:write("int main(int argc, char** argv)\n")
+ srcfile:write("{\n")
+
+ -- make interfaces
+ srcfile:write(string.format(" volatile void* p%s = (void*)&%s;\n\n", interface, interface))
+
+ -- make the main function tailer
+ srcfile:write(" return 0;\n")
+ srcfile:write("}\n")
+
+ -- exit this file
+ srcfile:close()
+
+ -- the flag names
+ local flagnames = compiler._flagnames(c._NAME)
+ assert(flagnames)
+
+ -- append the common flags
+ local flags = {}
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, c[flagname])
+ end
+
+ -- append the option flags
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(c, opt[flagname]))
+ end
+
+ -- append the defines flags
+ if opt.defines and c.flag_define then
+ local defines = utils.wrap(opt.defines)
+ for _, define in ipairs(defines) do
+ table.join2(flags, c.flag_define(define))
+ end
+ end
+
+ -- append the undefines flags
+ if opt.undefines and c.flag_undefine then
+ local undefines = utils.wrap(opt.undefines)
+ for _, undefine in ipairs(undefines) do
+ table.join2(flags, c.flag_undefine(undefine))
+ end
+ end
+
+ -- append the includedirs flags
+ if opt.includedirs and c.flag_includedir then
+ for _, includedir in ipairs(utils.wrap(opt.includedirs)) do
+ table.join2(flags, c.flag_includedir(includedir))
+ end
+ end
+
+ -- make the compile command
+ local cmd = string.format("%s > %s 2>&1", c.command_compile(srcpath, objpath, table.concat(flags, " "):trim()), xmake._NULDEV)
+ if not cmd then return end
+
+ -- check it
+ if 0 ~= os.execute(cmd) then return end
+
+ -- ok
+ return true
+end
+
-- return module: compiler
return compiler
diff --git a/xmake/scripts/base/linker.lua b/xmake/scripts/base/linker.lua
index cefb24050..517f376fc 100644
--- a/xmake/scripts/base/linker.lua
+++ b/xmake/scripts/base/linker.lua
@@ -101,6 +101,31 @@ function linker._getflags(module, names, flags)
return flags_mapped
end
+-- get the linker from the given kind
+function linker.get(kind)
+
+ -- check
+ assert(kind)
+
+ -- get the linker name from the kind
+ local name = nil
+ if kind == "binary" then name = "ld"
+ elseif kind == "static" then name = "ar"
+ elseif kind == "shared" then name = "sh"
+ else return end
+
+ -- get it
+ local module = tools.get(name)
+
+ -- invalid linker?
+ if module and not module.command_link then
+ return
+ end
+
+ -- ok?
+ return module
+end
+
-- make the link command
function linker.make(module, target, objfiles, targetfile)
@@ -156,30 +181,42 @@ function linker.make(module, target, objfiles, targetfile)
return module.command_link(table.concat(objfiles, " "), targetfile, table.concat(flags, " "):trim())
end
--- get the linker from the given kind
-function linker.get(kind)
+-- check link for the project option
+function linker.check_link(opt, link, objectfile, targetfile)
-- check
- assert(kind)
+ assert(opt and link and objectfile and targetfile)
- -- get the linker name from the kind
- local name = nil
- if kind == "binary" then name = "ld"
- elseif kind == "static" then name = "ar"
- elseif kind == "shared" then name = "sh"
- else return end
-
- -- get it
- local module = tools.get(name)
+ -- get the linker
+ local l = linker.get("binary")
+ assert(l and l.flag_link)
- -- invalid linker?
- if module and not module.command_link then
- return
+ -- append the common flags
+ local flags = {}
+ table.join2(flags, l.ldflags)
+
+ -- append the option flags
+ table.join2(flags, linker._mapflags(l, opt.ldflags))
+
+ -- append the linkdirs flags
+ if opt.linkdirs and l.flag_linkdir then
+ for _, linkdir in ipairs(utils.wrap(opt.linkdirs)) do
+ table.join2(flags, l.flag_linkdir(linkdir))
+ end
end
- -- ok?
- return module
-end
+ -- append the links flags
+ table.join2(flags, l.flag_link(link))
+ -- make the compile command
+ local cmd = string.format("%s > %s 2>&1", l.command_link(objectfile, targetfile, table.concat(flags, " "):trim()), xmake._NULDEV)
+ if not cmd then return end
+
+ -- check it
+ if 0 ~= os.execute(cmd) then return end
+
+ -- ok
+ return true
+end
-- return module: linker
return linker
diff --git a/xmake/scripts/base/main.lua b/xmake/scripts/base/main.lua
index 2f038c8cd..888c4d41a 100644
--- a/xmake/scripts/base/main.lua
+++ b/xmake/scripts/base/main.lua
@@ -87,7 +87,7 @@ local menu =
}
-- prepare global
-function main._prepare_global()
+function main._init_global()
-- the options
local options = xmake._OPTIONS
@@ -110,8 +110,8 @@ function main._prepare_global()
return true
end
--- prepare project
-function main._prepare_project()
+-- init project
+function main._init_project()
-- the options
local options = xmake._OPTIONS
@@ -132,6 +132,21 @@ function main._prepare_project()
-- probe the current platform
platform.probe(false)
+ end
+
+ -- merge the default options
+ for k, v in pairs(options._DEFAULTS) do
+ if nil == options[k] then options[k] = v end
+ end
+
+ -- make the current platform configure
+ if not platform.make() then
+ return string.format("make platform configure: %s failed!", config.get("plat"))
+ end
+
+ -- xmake config or marked as "reconfig"?
+ if options._ACTION == "config" or config._RECONFIG then
+
-- probe the current project
project.probe()
@@ -140,11 +155,6 @@ function main._prepare_project()
end
- -- merge the default options
- for k, v in pairs(options._DEFAULTS) do
- if nil == options[k] then options[k] = v end
- end
-
-- load the project
return project.load()
end
@@ -200,35 +210,21 @@ function main._done_option()
return action.done("lua")
end
- -- prepare global
- main._prepare_global()
+ -- init global
+ main._init_global()
-- done global?
if options._ACTION == "global" then
return action.done("global")
end
- -- prepare project
- local errors = main._prepare_project()
+ -- init project
+ local errors = main._init_project()
if errors then
-- error
utils.error(errors)
return false
end
-
- -- make the current platform configure
- if not platform.make() then
- -- error
- utils.error("make platform configure: %s failed!", config.get("plat"))
- return false
- end
-
- -- enter the project directory
- if not os.cd(xmake._PROJECT_DIR) then
- -- error
- utils.error("not found project: %s!", xmake._PROJECT_DIR)
- return false
- end
-- reconfig it first if marked as "reconfig"
if config._RECONFIG and not action.done("config") then
@@ -262,6 +258,12 @@ function main._init()
xmake._PROJECT_FILE = projectfile
assert(projectfile)
+ -- enter the project directory
+ if not os.cd(xmake._PROJECT_DIR) then
+ -- error
+ utils.error("not found project: %s!", xmake._PROJECT_DIR)
+ return false
+ end
end
-- the main function
diff --git a/xmake/scripts/base/makefile.lua b/xmake/scripts/base/makefile.lua
index 9287c1bae..0453df95d 100644
--- a/xmake/scripts/base/makefile.lua
+++ b/xmake/scripts/base/makefile.lua
@@ -43,7 +43,7 @@ function makefile._make_object(file, target, srcfile, objfile)
assert(file and target and srcfile and objfile)
-- get the compiler
- local c = compiler.get(srcfile);
+ local c = compiler.get(srcfile)
if not c then
-- error
utils.error("unknown source file: %s", srcfile)
diff --git a/xmake/scripts/base/project.lua b/xmake/scripts/base/project.lua
index bad0e215f..d78bb7d5f 100644
--- a/xmake/scripts/base/project.lua
+++ b/xmake/scripts/base/project.lua
@@ -24,10 +24,15 @@
local project = project or {}
-- load modules
+local os = require("base/os")
+local io = require("base/io")
+local rule = require("base/rule")
local path = require("base/path")
local utils = require("base/utils")
local table = require("base/table")
local config = require("base/config")
+local linker = require("base/linker")
+local compiler = require("base/compiler")
-- the current mode is belong to the given modes?
function project._api_modes(env, ...)
@@ -213,12 +218,14 @@ function project._filter(values)
-- filter all
local newvals = {}
for _, v in ipairs(utils.wrap(values)) do
- v = v:gsub("%$%((.*)%)", function (w)
- local r = config.get(w)
- if r and type(r) == "string" then return r
- elseif w == "projectdir" then return xmake._PROJECT_DIR
- end
- end)
+ if type(v) == "string" then
+ v = v:gsub("%$%((.*)%)", function (w)
+ local r = config.get(w)
+ if r and type(r) == "string" then return r
+ elseif w == "projectdir" then return xmake._PROJECT_DIR
+ end
+ end)
+ end
table.insert(newvals, v)
end
@@ -381,9 +388,97 @@ function project._make_targets(configs)
end
-- make option
-function project._make_option(name, opt)
+function project._make_option(name, opt, cfile, cxxfile, objectfile, targetfile)
+
+ -- remove repeat values and unwrap it
+ for k, v in pairs(opt) do
+
+ -- remove repeat first
+ v = utils.unique(v)
+
+ -- filter values
+ v = project._filter(v)
+
+ -- unwrap it if be only one
+ v = utils.unwrap(v)
+
+ -- update it
+ opt[k] = v
+ end
+
+ -- check includes and functions
+ if opt.cincludes or opt.cxxincludes then
+
+ -- check cincludes
+ for _, cinclude in ipairs(utils.wrap(opt.cincludes)) do
+
+ -- check cinclude
+ local ok = compiler.check_include(opt, cinclude, cfile, objectfile)
+
+ -- trace
+ utils.verbose("checking for the c include %s ... %s", cinclude, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return end
+ end
+
+ -- check cxxincludes
+ for _, cinclude in ipairs(utils.wrap(opt.cxxincludes)) do
+
+ -- check cxxinclude
+ local ok = compiler.check_include(opt, cxxinclude, cxxfile, objectfile)
+
+ -- trace
+ utils.verbose("checking for the c++ include %s ... %s", cxxinclude, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return end
+ end
+
+ -- check cfuncs
+ for _, cfunc in ipairs(utils.wrap(opt.cfuncs)) do
+
+ -- check function
+ local ok = compiler.check_function(opt, cfunc, cfile, objectfile)
+
+ -- trace
+ utils.verbose("checking for the c function %s ... %s", cfunc, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return end
+ end
+
+ -- check cxxfuncs
+ for _, cxxfunc in ipairs(utils.wrap(opt.cxxfuncs)) do
+
+ -- check function
+ local ok = compiler.check_function(opt, cxxfunc, cxxfile, objectfile)
+
+ -- trace
+ utils.verbose("checking for the c++ function %s ... %s", cxxfunc, utils.ifelse(ok, "ok", "no"))
+ -- failed
+ if not ok then return end
+ end
+ end
+
+ -- check links
+ if opt.links then
+ for _, link in ipairs(utils.wrap(opt.links)) do
+
+ -- check link
+ local ok = linker.check_link(opt, link, objectfile, targetfile)
+
+ -- trace
+ utils.verbose("checking for the link %s ... %s", link, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return end
+ end
+ end
+ -- ok
+ return opt
end
-- make options from the project file
@@ -392,6 +487,16 @@ function project._make_options(configs)
-- check
assert(configs and configs._OPTIONS)
+ -- the source file path
+ local cfile = os.tmpdir() .. "/__checking.c"
+ local cxxfile = os.tmpdir() .. "/__checking.cpp"
+
+ -- the object file path
+ local objectfile = os.tmpdir() .. "/" .. rule.filename("__checking", "object")
+
+ -- the target file path
+ local targetfile = os.tmpdir() .. "/" .. rule.filename("__checking", "binary")
+
-- make all options
for k, v in pairs(configs._OPTIONS) do
@@ -399,7 +504,7 @@ function project._make_options(configs)
if nil == config.get(k) then
-- make option
- local o = project._make_option(k, v)
+ local o = project._make_option(k, v, cfile, cxxfile, objectfile, targetfile)
if o then
-- enable this option
@@ -419,9 +524,16 @@ function project._make_options(configs)
end
-- trace
- utils.verbose("checking for %s ... %s", k, utils.ifelse(o, "ok", "no"))
+ utils.verbose("checking for the option %s ... %s", k, utils.ifelse(o, "ok", "no"))
end
end
+
+ -- remove files
+ os.rm(cfile)
+ os.rm(cxxfile)
+ os.rm(objectfile)
+ os.rm(targetfile)
+
end
-- only load options from the the project file
@@ -462,18 +574,19 @@ function project._load_options(file)
interfaces = { "links"
, "linkdirs"
, "includedirs"
- , "includes"
- , "interfaces"
+ , "cincludes"
+ , "cxxincludes"
+ , "cfuncs"
+ , "cxxfuncs"
, "cflags"
, "cxflags"
, "cxxflags"
- , "mflags"
- , "mxflags"
- , "mxxflags"
, "ldflags"
, "shflags"
, "defines"
- , "undefines"}
+ , "undefines"
+ , "defines_if_ok"
+ , "undefines_if_ok"}
for _, interface in ipairs(interfaces) do
newenv["add_option_" .. interface] = function (...) return project._api_add_values(newenv._OPTION, interface, ...) end
diff --git a/xmake/scripts/base/rule.lua b/xmake/scripts/base/rule.lua
index 6ce441be8..321ceb8c6 100644
--- a/xmake/scripts/base/rule.lua
+++ b/xmake/scripts/base/rule.lua
@@ -28,7 +28,6 @@ local os = require("base/os")
local path = require("base/path")
local utils = require("base/utils")
local config = require("base/config")
-local project = require("base/project")
local platform = require("platform/platform")
-- get the building log file path