summaryrefslogtreecommitdiff
path: root/xmake/core/project
diff options
context:
space:
mode:
authorruki <[email protected]>2016-03-21 20:57:23 +0800
committerruki <[email protected]>2016-03-21 20:57:37 +0800
commitb898400a3a5f18d332ce7ef159769d8f17fd28e5 (patch)
tree275f124aa7c17c6090d25fefb226b0678f6d231d /xmake/core/project
parentf0623bf26279430deb6799b7816fb61996120166 (diff)
add project option
Diffstat (limited to 'xmake/core/project')
-rw-r--r--xmake/core/project/option.lua302
-rw-r--r--xmake/core/project/project.lua378
-rw-r--r--xmake/core/project/target.lua35
3 files changed, 428 insertions, 287 deletions
diff --git a/xmake/core/project/option.lua b/xmake/core/project/option.lua
new file mode 100644
index 000000000..2c4fd1876
--- /dev/null
+++ b/xmake/core/project/option.lua
@@ -0,0 +1,302 @@
+--!The Automatic Cross-platform Build Tool
+--
+-- XMake is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU Lesser General Public License as published by
+-- the Free Software Foundation; either version 2.1 of the License, or
+-- (at your option) any later version.
+--
+-- XMake is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU Lesser General Public License for more details.
+--
+-- You should have received a copy of the GNU Lesser General Public License
+-- along with XMake;
+-- If not, see <a href="http://www.gnu.org/licenses/"> http://www.gnu.org/licenses/</a>
+--
+-- Copyright (C) 2015 - 2016, ruki All rights reserved.
+--
+-- @author ruki
+-- @file option.lua
+--
+
+-- define module
+local option = option or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local table = require("base/table")
+local utils = require("base/utils")
+local config = require("project/config")
+local linker = require("platform/linker")
+local compiler = require("platform/compiler")
+
+-- check option for checking links
+function option._check_links(self, cfile, objectfile, targetfile)
+
+ -- get links
+ local links = self:get("links")
+ if not links then
+ return true
+ end
+
+ -- the links string
+ local links_str = table.concat(table.wrap(links), ", ")
+
+ -- this links has been checked?
+ option._CHECKED_LINKS = option._CHECKED_LINKS or {}
+ if option._CHECKED_LINKS[links_str] then
+ return true
+ end
+
+ -- only for compile a object file
+ local ok = compiler.check_include(self, nil, cfile, objectfile)
+
+ -- check link
+ if ok then ok = linker.check_links(self, cfile, objectfile, targetfile) end
+
+ -- trace
+ utils.printf("checking for the links %s ... %s", links_str, utils.ifelse(ok, "ok", "no"))
+
+ -- cache the result
+ option._CHECKED_LINKS[links_str] = ok
+
+ -- ok?
+ return ok
+end
+
+-- check option for checking cincludes
+function option._check_cincludes(self, cfile, objectfile)
+
+ -- done
+ for _, cinclude in ipairs(table.wrap(self:get("cincludes"))) do
+
+ -- this cinclude has been checked?
+ option._CHECKED_CINCLUDES = option._CHECKED_CINCLUDES or {}
+ if option._CHECKED_CINCLUDES[cinclude] then return true end
+
+ -- check cinclude
+ local ok = compiler.check_include(self, cinclude, cfile, objectfile)
+
+ -- trace
+ utils.printf("checking for the c include %s ... %s", cinclude, utils.ifelse(ok, "ok", "no"))
+
+ -- cache the result
+ option._CHECKED_CINCLUDES[cinclude] = ok
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option for checking cxxincludes
+function option._check_cxxincludes(self, cxxfile, objectfile)
+
+ -- done
+ for _, cxxinclude in ipairs(table.wrap(self:get("cxxincludes"))) do
+
+ -- this cxxinclude has been checked?
+ option._CHECKED_CXXINCLUDES = option._CHECKED_CXXINCLUDES or {}
+ if option._CHECKED_CXXINCLUDES[cinclude] then return true end
+
+ -- check cinclude
+ local ok = compiler.check_include(self, cxxinclude, cxxfile, objectfile)
+
+ -- trace
+ utils.printf("checking for the c++ include %s ... %s", cxxinclude, utils.ifelse(ok, "ok", "no"))
+
+ -- cache the result
+ option._CHECKED_CXXINCLUDES[cxxinclude] = ok
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option for checking cfunctions
+function option._check_cfuncs(self, cfile, objectfile, targetfile)
+
+ -- done
+ for _, cfunc in ipairs(table.wrap(self:get("cfuncs"))) do
+
+ -- check function
+ local ok = compiler.check_function(self, cfunc, cfile, objectfile)
+
+ -- check link
+ if ok and self:get("links") then ok = linker.check_links(self, cfile, objectfile, targetfile) end
+
+ -- trace
+ utils.printf("checking for the c function %s ... %s", cfunc, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option for checking cxxfunctions
+function option._check_cxxfuncs(self, cxxfile, objectfile, targetfile)
+
+ -- done
+ for _, cxxfunc in ipairs(table.wrap(self:get("cxxfuncs"))) do
+
+ -- check function
+ local ok = compiler.check_function(self, cxxfunc, cxxfile, objectfile)
+
+ -- check link
+ if ok and self:get("links") then ok = linker.check_links(self, cxxfile, objectfile, targetfile) end
+
+ -- trace
+ utils.printf("checking for the c++ function %s ... %s", cxxfunc, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option for checking ctypes
+function option._check_ctypes(self, cfile, objectfile, targetfile)
+
+ -- done
+ for _, ctype in ipairs(table.wrap(self:get("ctypes"))) do
+
+ -- check type
+ local ok = compiler.check_typedef(self, ctype, cfile, objectfile)
+
+ -- trace
+ utils.printf("checking for the c type %s ... %s", ctype, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option for checking cxxtypes
+function option._check_cxxtypes(self, cxxfile, objectfile, targetfile)
+
+ -- done
+ for _, cxxtype in ipairs(table.wrap(self:get("cxxtypes"))) do
+
+ -- check type
+ local ok = compiler.check_typedef(self, cxxtype, cxxfile, objectfile)
+
+ -- trace
+ utils.printf("checking for the c++ type %s ... %s", cxxtype, utils.ifelse(ok, "ok", "no"))
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- check option
+function option.check(self, cfile, cxxfile, objectfile, targetfile)
+
+ -- check links
+ if not self:_check_links(cfile, objectfile, targetfile) then return false end
+
+ -- check ctypes
+ if not self:_check_ctypes(cfile, objectfile, targetfile) then return false end
+
+ -- check cxxtypes
+ if not self:_check_cxxtypes(cxxfile, objectfile, targetfile) then return false end
+
+ -- check includes and functions
+ if self:get("cincludes") or self:get("cxxincludes") then
+
+ -- check cincludes
+ if not self:_check_cincludes(cfile, objectfile) then return false end
+
+ -- check cxxincludes
+ if not self:_check_cxxincludes(cxxfile, objectfile) then return false end
+
+ -- check cfuncs
+ if not self:_check_cfuncs(cfile, objectfile, targetfile) then return false end
+
+ -- check cxxfuncs
+ if not self:_check_cxxfuncs(cxxfile, objectfile, targetfile) then return false end
+
+ end
+
+ -- ok
+ return true
+end
+
+-- get the option info
+function option.get(self, infoname)
+
+ -- check
+ assert(self and self._INFO and infoname)
+
+ -- get it
+ return self._INFO[infoname]
+end
+
+-- save the option info to the project configure
+function option.save(self, is_clear)
+
+ -- check
+ assert(self)
+
+ -- save it
+ config.set("__option_" .. self:name(), self._INFO)
+end
+
+-- clear the option info for the project configure
+function option.clear(self)
+
+ -- check
+ assert(self)
+
+ -- clear it
+ config.set("__option_" .. self:name(), nil)
+end
+
+-- load the option info from the project configure
+function option.load(name)
+
+ -- check
+ assert(name)
+
+ -- get info
+ local info = config.get("__option_" .. name)
+ if info == nil then
+ return
+ end
+
+ -- init option instance
+ local instance = {}
+ instance._INFO = info
+ instance._NAME = name
+
+ -- ok
+ return instance
+end
+
+-- get the option name
+function option.name(self)
+
+ -- get it
+ return self._NAME
+end
+
+
+-- return module
+return option
diff --git a/xmake/core/project/project.lua b/xmake/core/project/project.lua
index 8e941fb2e..491eb4a44 100644
--- a/xmake/core/project/project.lua
+++ b/xmake/core/project/project.lua
@@ -29,11 +29,11 @@ local io = require("base/io")
local path = require("base/path")
local utils = require("base/utils")
local table = require("base/table")
-local option = require("base/option")
local filter = require("base/filter")
local interpreter = require("base/interpreter")
local target = require("project/target")
local config = require("project/config")
+local option = require("project/option")
local deprecated_project = require("project/deprecated/project")
local linker = require("platform/linker")
local compiler = require("platform/compiler")
@@ -150,7 +150,7 @@ function project._api_add_cfunc(interp, module, alias, links, includes, cfunc)
-- save the current scope
local scope = interp:scope_save()
- -- make option
+ -- check option
interp:api_call("option", name)
interp:api_call("set_option_category", "cfuncs")
interp:api_call("add_option_cfuncs", cfunc)
@@ -196,7 +196,7 @@ function project._api_add_cfuncs(interp, module, links, includes, ...)
-- save the current scope
local scope = interp:scope_save()
- -- make option
+ -- check option
interp:api_call("option", name)
interp:api_call("set_option_category", "cfuncs")
interp:api_call("add_option_cfuncs", cfunc)
@@ -237,7 +237,7 @@ function project._api_add_cxxfunc(interp, module, alias, links, includes, cxxfun
-- save the current scope
local scope = interp:scope_save()
- -- make option
+ -- check option
interp:api_call("option", name)
interp:api_call("set_option_category", "cxxfuncs")
interp:api_call("add_option_cxxfuncs", cxxfunc)
@@ -283,7 +283,7 @@ function project._api_add_cxxfuncs(interp, module, links, includes, ...)
-- save the current scope
local scope = interp:scope_save()
- -- make option
+ -- check option
interp:api_call("option", name)
interp:api_call("set_option_category", "cxxfuncs")
interp:api_call("add_option_cxxfuncs", cxxfunc)
@@ -476,251 +476,60 @@ function project._interpreter()
return interp
end
--- make option for checking links
-function project._make_option_for_checking_links(opt, links, cfile, objectfile, targetfile)
-
- -- the links string
- local links_str = table.concat(table.wrap(links), ", ")
-
- -- this links has been checked?
- project._CHECKED_LINKS = project._CHECKED_LINKS or {}
- if project._CHECKED_LINKS[links_str] then return true end
-
- -- only for compile a object file
- local ok = compiler.check_include(opt, nil, cfile, objectfile)
-
- -- check link
- if ok then ok = linker.check_links(opt, links, cfile, objectfile, targetfile) end
-
- -- trace
- utils.printf("checking for the links %s ... %s", links_str, utils.ifelse(ok, "ok", "no"))
-
- -- cache the result
- project._CHECKED_LINKS[links_str] = ok
-
- -- ok?
- return ok
-end
-
--- make option for checking cincludes
-function project._make_option_for_checking_cincludes(opt, cincludes, cfile, objectfile)
-
- -- done
- for _, cinclude in ipairs(table.wrap(cincludes)) do
-
- -- this cinclude has been checked?
- project._CHECKED_CINCLUDES = project._CHECKED_CINCLUDES or {}
- if project._CHECKED_CINCLUDES[cinclude] then return true end
-
- -- check cinclude
- local ok = compiler.check_include(opt, cinclude, cfile, objectfile)
-
- -- trace
- utils.printf("checking for the c include %s ... %s", cinclude, utils.ifelse(ok, "ok", "no"))
-
- -- cache the result
- project._CHECKED_CINCLUDES[cinclude] = ok
-
- -- failed
- if not ok then return false end
- end
-
- -- ok
- return true
-end
-
--- make option for checking cxxincludes
-function project._make_option_for_checking_cxxincludes(opt, cxxincludes, cxxfile, objectfile)
-
- -- done
- for _, cxxinclude in ipairs(table.wrap(cxxincludes)) do
-
- -- this cxxinclude has been checked?
- project._CHECKED_CXXINCLUDES = project._CHECKED_CXXINCLUDES or {}
- if project._CHECKED_CXXINCLUDES[cinclude] then return true end
-
- -- check cinclude
- local ok = compiler.check_include(opt, cxxinclude, cxxfile, objectfile)
-
- -- trace
- utils.printf("checking for the c++ include %s ... %s", cxxinclude, utils.ifelse(ok, "ok", "no"))
-
- -- cache the result
- project._CHECKED_CXXINCLUDES[cxxinclude] = ok
-
- -- failed
- if not ok then return false end
- end
-
- -- ok
- return true
-end
-
--- make option for checking cfunctions
-function project._make_option_for_checking_cfuncs(opt, cfuncs, cfile, objectfile, targetfile)
-
- -- done
- for _, cfunc in ipairs(table.wrap(cfuncs)) do
-
- -- check function
- local ok = compiler.check_function(opt, cfunc, cfile, objectfile)
-
- -- check link
- if ok and opt.links then ok = linker.check_links(opt, opt.links, cfile, objectfile, targetfile) end
-
- -- trace
- utils.printf("checking for the c function %s ... %s", cfunc, utils.ifelse(ok, "ok", "no"))
-
- -- failed
- if not ok then return false end
- end
-
- -- ok
- return true
-end
-
--- make option for checking cxxfunctions
-function project._make_option_for_checking_cxxfuncs(opt, cxxfuncs, cxxfile, objectfile, targetfile)
-
- -- done
- for _, cxxfunc in ipairs(table.wrap(cxxfuncs)) do
-
- -- check function
- local ok = compiler.check_function(opt, cxxfunc, cxxfile, objectfile)
-
- -- check link
- if ok and opt.links then ok = linker.check_links(opt, opt.links, cxxfile, objectfile, targetfile) end
-
- -- trace
- utils.printf("checking for the c++ function %s ... %s", cxxfunc, utils.ifelse(ok, "ok", "no"))
-
- -- failed
- if not ok then return false end
- end
-
- -- ok
- return true
-end
-
--- make option for checking ctypes
-function project._make_option_for_checking_ctypes(opt, ctypes, cfile, objectfile, targetfile)
-
- -- done
- for _, ctype in ipairs(table.wrap(ctypes)) do
-
- -- check type
- local ok = compiler.check_typedef(opt, ctype, cfile, objectfile)
-
- -- trace
- utils.printf("checking for the c type %s ... %s", ctype, utils.ifelse(ok, "ok", "no"))
-
- -- failed
- if not ok then return false end
- end
-
- -- ok
- return true
-end
-
--- make option for checking cxxtypes
-function project._make_option_for_checking_cxxtypes(opt, cxxtypes, cxxfile, objectfile, targetfile)
-
- -- done
- for _, cxxtype in ipairs(table.wrap(cxxtypes)) do
-
- -- check type
- local ok = compiler.check_typedef(opt, cxxtype, cxxfile, objectfile)
-
- -- trace
- utils.printf("checking for the c++ type %s ... %s", cxxtype, utils.ifelse(ok, "ok", "no"))
+-- probe the project
+function project.probe()
- -- failed
- if not ok then return false end
+ -- enter the project directory
+ local ok, errors = os.cd(xmake._PROJECT_DIR)
+ if not ok then
+ return false, errors
end
- -- ok
- return true
-end
-
--- make option
-function project._make_option(name, opt, cfile, cxxfile, objectfile, targetfile)
-
- -- check links
- if opt.links and not project._make_option_for_checking_links(opt, opt.links, cfile, objectfile, targetfile) then return end
-
- -- check ctypes
- if opt.ctypes and not project._make_option_for_checking_ctypes(opt, opt.ctypes, cfile, objectfile, targetfile) then return end
-
- -- check cxxtypes
- if opt.cxxtypes and not project._make_option_for_checking_cxxtypes(opt, opt.cxxtypes, cxxfile, objectfile, targetfile) then return end
-
- -- check includes and functions
- if opt.cincludes or opt.cxxincludes then
-
- -- check cincludes
- if opt.cincludes and not project._make_option_for_checking_cincludes(opt, opt.cincludes, cfile, objectfile) then return end
-
- -- check cxxincludes
- if opt.cxxincludes and not project._make_option_for_checking_cxxincludes(opt, opt.cxxincludes, cxxfile, objectfile) then return end
-
- -- check cfuncs
- if opt.cfuncs and not project._make_option_for_checking_cfuncs(opt, opt.cfuncs, cfile, objectfile, targetfile) then return end
-
- -- check cxxfuncs
- if opt.cxxfuncs and not project._make_option_for_checking_cxxfuncs(opt, opt.cxxfuncs, cxxfile, objectfile, targetfile) then return end
-
+ -- load the options from the the project file
+ local options, errors = project.options(true)
+ if not options then
+ return false, errors
end
-
- -- ok
- return opt
-end
-
--- make options from the project file
-function project._make_options(options)
-
- -- check
- assert(options)
-
+
-- the source file path
- local cfile = os.tmpdir() .. "/__checking.c"
- local cxxfile = os.tmpdir() .. "/__checking.cpp"
+ local cfile = path.join(os.tmpdir(), "__checking.c")
+ local cxxfile = path.join(os.tmpdir(), "__checking.cpp")
-- the object file path
- local objectfile = os.tmpdir() .. "/" .. target.filename("__checking", "object")
+ local objectfile = path.join(os.tmpdir(), target.filename("__checking", "object"))
-- the target file path
- local targetfile = os.tmpdir() .. "/" .. target.filename("__checking", "binary")
+ local targetfile = path.join(os.tmpdir(), target.filename("__checking", "binary"))
-- make all options
- for k, v in pairs(options) do
+ for name, opt in pairs(options) do
-- this option need be probed automatically?
if config.get(name) == nil then
- -- make option
- local o = project._make_option(k, v, cfile, cxxfile, objectfile, targetfile)
- if o then
+ -- check option
+ if opt:check(cfile, cxxfile, objectfile, targetfile) then
-- enable this option
- config.set(k, true)
+ config.set(name, true)
-- save this option to configure
- config.set("__" .. k, o)
+ opt:save()
else
-- disable this option
- config.set(k, false)
+ config.set(name, false)
-- clear this option to configure
- config.set("__" .. k, nil)
+ opt:clear()
end
- elseif nil == config.get("__" .. k) then
+ elseif nil == option.load(name) then
-- save this option to configure
- config.set("__" .. k, v)
+ opt:save()
end
end
@@ -730,54 +539,6 @@ function project._make_options(options)
os.rm(objectfile)
os.rm(targetfile)
-end
-
--- get the given target
-function project.target(targetname)
-
- -- check
- assert(targetname and targetname ~= "all")
-
- -- the targets
- local targets = project.targets()
- assert(targets)
-
- -- get it
- return targets[targetname]
-end
-
--- get the current configure for targets
-function project.targets()
-
- -- check
- assert(project._TARGETS)
-
- -- return it
- return project._TARGETS
-end
-
--- probe the project
-function project.probe()
-
- -- get interpreter
- local interp = project._interpreter()
- assert(interp)
-
- -- enter the project directory
- local ok, errors = os.cd(xmake._PROJECT_DIR)
- if not ok then
- return false, errors
- end
-
- -- load the options from the the project file
- local options, errors = interp:load(xmake._PROJECT_FILE, "option", true, true)
- if not options then
- return false, errors
- end
-
- -- make the options from the the project file
- project._make_options(options)
-
-- leave the project directory
ok, errors = os.cd("-")
if not ok then
@@ -836,29 +597,72 @@ function project.load()
return true
end
--- dump the current configure
-function project.dump()
-
- -- dump
- if option.get("verbose") then
- table.dump(project.targets())
- end
-
+-- get the given target
+function project.target(targetname)
+
+ -- check
+ assert(targetname and targetname ~= "all")
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- get it
+ return targets[targetname]
end
--- get the project menu
-function project.menu()
+-- get the current configure for targets
+function project.targets()
+
+ -- check
+ assert(project._TARGETS)
+
+ -- return it
+ return project._TARGETS
+end
+
+-- get options
+function project.options(enable_filter)
-- get interpreter
local interp = project._interpreter()
assert(interp)
+ -- load the options from the the project file
+ local results, errors = interp:load(xmake._PROJECT_FILE, "option", true, enable_filter)
+ if not results then
+ return nil, errors
+ end
+
+ -- check options
+ local options = {}
+ for optionname, optioninfo in pairs(results) do
+
+ -- init a option instance
+ local instance = table.inherit(option)
+ assert(instance)
+
+ -- save name and info
+ instance._NAME = optionname
+ instance._INFO = optioninfo
+
+ -- save it
+ options[optionname] = instance
+ end
+
+ -- ok?
+ return options
+
+end
+
+-- get the project menu
+function project.menu()
+
-- attempt to load options from the project file
local options = nil
local errors = nil
- local projectfile = xmake._PROJECT_FILE
- if projectfile and os.isfile(projectfile) then
- options, errors = interp:load(projectfile, "option", true, false)
+ if os.isfile(xmake._PROJECT_FILE) then
+ options, errors = project.options(false)
end
-- failed?
@@ -873,7 +677,7 @@ function project.menu()
-- make the category
local category = "default"
- if opt.category then category = table.unwrap(opt.category) end
+ if opt:get("category") then category = table.unwrap(opt:get("category")) end
options_by_category[category] = options_by_category[category] or {}
-- append option to the current category
@@ -889,12 +693,12 @@ function project.menu()
for name, opt in pairs(opts) do
-- show menu?
- if opt.showmenu then
+ if opt:get("showmenu") then
-- the default value
local default = "auto"
- if opt.enable ~= nil then
- default = opt.enable
+ if opt:get("enable") ~= nil then
+ default = opt:get("enable")
end
-- is first?
@@ -908,8 +712,8 @@ function project.menu()
end
-- append it
- if opt.description then
- table.insert(menu, {nil, name, "kv", default, opt.description})
+ if opt:get("description") then
+ table.insert(menu, {nil, name, "kv", default, opt:get("description")})
else
table.insert(menu, {nil, name, "kv", default, nil})
end
diff --git a/xmake/core/project/target.lua b/xmake/core/project/target.lua
index 6b1da3215..a7fd954d3 100644
--- a/xmake/core/project/target.lua
+++ b/xmake/core/project/target.lua
@@ -27,7 +27,9 @@ local target = target or {}
local os = require("base/os")
local path = require("base/path")
local table = require("base/table")
+local option = require("project/option")
local config = require("project/config")
+local linker = require("platform/linker")
local platform = require("platform/platform")
-- get the filename from the given name and kind
@@ -60,6 +62,39 @@ function target.name(self)
return self._NAME
end
+-- get the linker with the target kind
+function target.linker(self)
+
+ -- init the linker from the given kind
+ local result = linker.init(self:get("kind"))
+ if not result then
+ os.raise("cannot get linker with kind: %s", self:get("kind"))
+ end
+
+ -- ok?
+ return result
+
+end
+
+-- get the options
+function target.options(self)
+
+ -- the options
+ local options = {}
+ for _, name in ipairs(table.wrap(self:get("options"))) do
+
+ -- get option if be enabled
+ local opt = nil
+ if config.get(name) then opt = poption.load(name) end
+ if nil ~= opt then
+ options[name] = opt
+ end
+ end
+
+ -- ok?
+ return options
+end
+
-- get the object file directory
function target.objectdir(self)