summaryrefslogtreecommitdiff
path: root/xmake/core
diff options
context:
space:
mode:
authorruki <[email protected]>2016-01-14 09:19:14 +0800
committerruki <[email protected]>2016-01-14 09:19:14 +0800
commitcdcf953259aee5e7e1a06855ddbedbaabf585bc9 (patch)
tree47b8e5de10522cca3b67354fa527b3525193e880 /xmake/core
parent8c50566e7ab2139b9f6c2976b9ce875b7ad11b7a (diff)
rename script directory to core
Diffstat (limited to 'xmake/core')
-rw-r--r--xmake/core/_xmake_main.lua50
-rw-r--r--xmake/core/action/_build.lua120
-rw-r--r--xmake/core/action/_clean.lua106
-rw-r--r--xmake/core/action/_config.lua215
-rw-r--r--xmake/core/action/_create.lua173
-rw-r--r--xmake/core/action/_debug.lua89
-rw-r--r--xmake/core/action/_global.lua104
-rw-r--r--xmake/core/action/_install.lua224
-rw-r--r--xmake/core/action/_lua.lua168
-rw-r--r--xmake/core/action/_man.lua89
-rw-r--r--xmake/core/action/_package.lua365
-rw-r--r--xmake/core/action/_run.lua179
-rw-r--r--xmake/core/action/_uninstall.lua160
-rw-r--r--xmake/core/action/action.lua190
-rw-r--r--xmake/core/base/clean.lua192
-rw-r--r--xmake/core/base/compiler.lua574
-rw-r--r--xmake/core/base/config.lua395
-rw-r--r--xmake/core/base/global.lua246
-rw-r--r--xmake/core/base/install.lua143
-rw-r--r--xmake/core/base/io.lua324
-rw-r--r--xmake/core/base/linker.lua386
-rw-r--r--xmake/core/base/main.lua179
-rw-r--r--xmake/core/base/makefile.lua417
-rw-r--r--xmake/core/base/option.lua650
-rw-r--r--xmake/core/base/os.lua237
-rw-r--r--xmake/core/base/package.lua314
-rw-r--r--xmake/core/base/path.lua72
-rw-r--r--xmake/core/base/project.lua1469
-rw-r--r--xmake/core/base/rule.lua300
-rw-r--r--xmake/core/base/string.lua115
-rw-r--r--xmake/core/base/table.lua99
-rw-r--r--xmake/core/base/template.lua77
-rw-r--r--xmake/core/base/uninstall.lua104
-rw-r--r--xmake/core/base/utils.lua258
-rw-r--r--xmake/core/module/os.lua46
-rw-r--r--xmake/core/module/path.lua25
-rw-r--r--xmake/core/module/project.lua73
-rw-r--r--xmake/core/module/string.lua24
-rw-r--r--xmake/core/module/utils.lua24
-rw-r--r--xmake/core/platform/android/android.lua120
-rw-r--r--xmake/core/platform/android/prober.lua269
-rw-r--r--xmake/core/platform/iphoneos/iphoneos.lua141
-rw-r--r--xmake/core/platform/iphoneos/package.lua76
-rw-r--r--xmake/core/platform/iphoneos/prober.lua310
-rw-r--r--xmake/core/platform/iphonesimulator/iphonesimulator.lua138
-rw-r--r--xmake/core/platform/iphonesimulator/prober.lua308
-rw-r--r--xmake/core/platform/linux/install.lua182
-rw-r--r--xmake/core/platform/linux/linux.lua103
-rw-r--r--xmake/core/platform/linux/prober.lua198
-rw-r--r--xmake/core/platform/linux/uninstall.lua134
-rw-r--r--xmake/core/platform/macosx/install.lua182
-rw-r--r--xmake/core/platform/macosx/macosx.lua140
-rw-r--r--xmake/core/platform/macosx/prober.lua307
-rw-r--r--xmake/core/platform/macosx/uninstall.lua134
-rw-r--r--xmake/core/platform/mingw/mingw.lua93
-rw-r--r--xmake/core/platform/mingw/prober.lua207
-rw-r--r--xmake/core/platform/platform.lua385
-rw-r--r--xmake/core/platform/watchos/package.lua76
-rw-r--r--xmake/core/platform/watchos/prober.lua310
-rw-r--r--xmake/core/platform/watchos/watchos.lua141
-rw-r--r--xmake/core/platform/watchsimulator/prober.lua308
-rw-r--r--xmake/core/platform/watchsimulator/watchsimulator.lua138
-rw-r--r--xmake/core/platform/windows/prober.lua300
-rw-r--r--xmake/core/platform/windows/tools/cl.lua139
-rw-r--r--xmake/core/platform/windows/tools/lib.lua138
-rw-r--r--xmake/core/platform/windows/tools/link.lua128
-rw-r--r--xmake/core/platform/windows/tools/ml.lua132
-rw-r--r--xmake/core/platform/windows/tools/nmake.lua74
-rw-r--r--xmake/core/platform/windows/windows.lua144
-rw-r--r--xmake/core/tools/ar.lua114
-rw-r--r--xmake/core/tools/cat.lua43
-rw-r--r--xmake/core/tools/clang++.lua38
-rw-r--r--xmake/core/tools/clang.lua38
-rw-r--r--xmake/core/tools/cp.lua44
-rw-r--r--xmake/core/tools/dispatcher.lua80
-rw-r--r--xmake/core/tools/echo.lua44
-rw-r--r--xmake/core/tools/g++.lua38
-rwxr-xr-xxmake/core/tools/gas-preprocessor.pl1025
-rw-r--r--xmake/core/tools/gcc.lua192
-rw-r--r--xmake/core/tools/make.lua82
-rw-r--r--xmake/core/tools/mkdir.lua46
-rw-r--r--xmake/core/tools/mv.lua43
-rw-r--r--xmake/core/tools/rm.lua46
-rw-r--r--xmake/core/tools/rmdir.lua46
-rw-r--r--xmake/core/tools/swiftc.lua117
-rw-r--r--xmake/core/tools/tools.lua222
-rw-r--r--xmake/core/tools/verbose.lua47
87 files changed, 16735 insertions, 0 deletions
diff --git a/xmake/core/_xmake_main.lua b/xmake/core/_xmake_main.lua
new file mode 100644
index 000000000..49fbb0105
--- /dev/null
+++ b/xmake/core/_xmake_main.lua
@@ -0,0 +1,50 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _xmake_main.lua
+--
+
+-- init namespace: xmake
+xmake = xmake or {}
+xmake._ARGV = _ARGV
+xmake._HOST = _HOST
+xmake._ARCH = _ARCH
+xmake._NULDEV = _NULDEV
+xmake._VERSION = _VERSION
+xmake._PROGRAM_DIR = _PROGRAM_DIR
+xmake._PROJECT_DIR = _PROJECT_DIR
+xmake._CORE_DIR = _PROGRAM_DIR .. "/core"
+xmake._PACKAGES_DIR = _PROGRAM_DIR .. "/packages"
+xmake._TEMPLATES_DIR = _PROGRAM_DIR .. "/templates"
+xmake._PROJECT_FILE = "xmake.lua"
+xmake._OPTIONS = {}
+xmake._CONFIGS = {}
+
+-- init package path
+package.path = xmake._CORE_DIR .. "/?.lua;" .. package.path
+
+-- load modules
+local main = require("base/main")
+
+-- the main function
+function _xmake_main()
+
+ -- done main
+ return main.done()
+end
diff --git a/xmake/core/action/_build.lua b/xmake/core/action/_build.lua
new file mode 100644
index 000000000..bf660eab5
--- /dev/null
+++ b/xmake/core/action/_build.lua
@@ -0,0 +1,120 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _build.lua
+--
+
+-- define module: _build
+local _build = _build or {}
+
+-- load modules
+local rule = require("base/rule")
+local utils = require("base/utils")
+local clean = require("base/clean")
+local config = require("base/config")
+local project = require("base/project")
+local makefile = require("base/makefile")
+
+-- need access to the given file?
+function _build.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { config = true, global = true, project = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _build.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- the target name
+ local target_name = options.target
+
+ -- check target
+ if not project.checktarget(target_name) then
+ return false
+ end
+
+ -- rebuild it?
+ if options.rebuild or config.get("__rebuild") then
+ clean.remove(target_name, "build")
+ -- update it?
+ elseif options.update then
+ clean.remove(target_name, "targets")
+ end
+
+ -- clear rebuild mark and save configure to file
+ if config.get("__rebuild") then
+
+ -- clear it
+ config.set("__rebuild", nil)
+
+ -- save the configure
+ if not config.save() then
+ -- error
+ utils.error("update configure failed!")
+ end
+ end
+
+ -- check makefile
+ if not os.isfile(rule.makefile()) then
+
+ -- make the configure file for the given target
+ if not project.makeconf(options.target) then
+ -- error
+ utils.error("make configure failed!")
+ return false
+ end
+
+ -- make makefile
+ if not makefile.make() then
+ -- error
+ utils.error("make makefile failed!")
+ return false
+ end
+ end
+
+ -- build target for makefile
+ if not makefile.build(target_name) then
+ -- error
+ print("")
+ if options.verbose then
+ io.cat(rule.logfile())
+ else
+ io.tail(rule.logfile(), 32)
+ end
+ utils.error("build target: %s failed!\n", target_name)
+ return false
+ end
+
+ -- ok
+ print("build ok!")
+ return true
+end
+
+-- return module: _build
+return _build
diff --git a/xmake/core/action/_clean.lua b/xmake/core/action/_clean.lua
new file mode 100644
index 000000000..677ff2470
--- /dev/null
+++ b/xmake/core/action/_clean.lua
@@ -0,0 +1,106 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _clean.lua
+--
+
+-- define module: _clean
+local _clean = _clean or {}
+
+-- load modules
+local clean = require("base/clean")
+local config = require("base/config")
+local project = require("base/project")
+local utils = require("base/utils")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _clean.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { global = true, config = true, project = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _clean.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- check target
+ if not project.checktarget(options.target) then
+ return false
+ end
+
+ -- clean the current target
+ if not clean.remove(options.target, utils.ifelse(options.all, "all", "build")) then
+ return false
+ end
+
+ -- trace
+ print("clean ok!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _clean.menu()
+
+ return {
+ -- xmake c
+ shortname = 'c'
+
+ -- usage
+ , usage = "xmake clean|c [options] [target]"
+
+ -- description
+ , description = "Remove all binary and temporary files."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {}
+ , {'a', "all", "k", nil, "Clean all auto-generated files by xmake." }
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Clean for the given target." }
+ }
+ }
+end
+
+-- return module: _clean
+return _clean
diff --git a/xmake/core/action/_config.lua b/xmake/core/action/_config.lua
new file mode 100644
index 000000000..a883b0499
--- /dev/null
+++ b/xmake/core/action/_config.lua
@@ -0,0 +1,215 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _config.lua
+--
+
+-- define module: _config
+local _config = _config or {}
+
+-- load modules
+local utils = require("base/utils")
+local config = require("base/config")
+local project = require("base/project")
+local makefile = require("base/makefile")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _config.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { config = true, global = true, project = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _config.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- check target
+ if not project.checktarget(options.target) then
+ return false
+ end
+
+ -- trace
+ print("configure ...")
+
+ -- save the configure
+ if not config.save() then
+ -- error
+ utils.error("save configure failed!")
+ return false
+ end
+
+ -- make the configure file for the given target
+ if not project.makeconf(options.target) then
+ -- error
+ utils.error("make configure failed!")
+ return false
+ end
+
+ -- make makefile
+ if not makefile.make() then
+ -- error
+ utils.error("make makefile failed!")
+ return false
+ end
+
+ -- dump configure
+ config.dump()
+
+ -- trace
+ print("configure ok!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _config.menu()
+
+ return {
+ -- xmake f
+ shortname = 'f'
+
+ -- usage
+ , usage = "xmake config|f [options] [target]"
+
+ -- description
+ , description = "Configure the project."
+
+ -- options
+ , options =
+ {
+ {'c', "clean", "k", nil, "Clean the cached configure and configure all again." }
+
+ , {}
+ , {'p', "plat", "kv", xmake._HOST, "Compile for the given platform."
+ , function ()
+ local descriptions = {}
+ local plats = platform.plats()
+ if plats then
+ for i, plat in ipairs(plats) do
+ descriptions[i] = " - " .. plat
+ end
+ end
+ return descriptions
+ end }
+ , {'a', "arch", "kv", "auto", "Compile for the given architecture."
+ , function ()
+ local descriptions = {}
+ local plats = platform.plats()
+ if plats then
+ for i, plat in ipairs(plats) do
+ descriptions[i] = " - " .. plat .. ":"
+ local archs = platform.archs(plat)
+ if archs then
+ for _, arch in ipairs(archs) do
+ descriptions[i] = descriptions[i] .. " " .. arch
+ end
+ end
+ end
+ end
+ return descriptions
+ end }
+ , {'m', "mode", "kv", "release", "Compile for the given mode."
+ , " - debug"
+ , " - release"
+ , " - profile" }
+ , {'k', "kind", "kv", "static", "Compile for the given target kind."
+ , " - static"
+ , " - shared"
+ , " - binary" }
+ , {nil, "host", "kv", xmake._HOST, "The current host environment." }
+
+ -- the options for project
+ , function () return project.menu() end
+
+ , {}
+ , {nil, "make", "kv", "auto", "Set the make path." }
+ , {nil, "ccache", "kv", "auto", "Enable or disable the c/c++ compiler cache." }
+
+ , {}
+ , {nil, "cross", "kv", nil, "The cross toolchains prefix"
+ , ".e.g"
+ , " - i386-mingw32-"
+ , " - arm-linux-androideabi-" }
+ , {nil, "toolchains", "kv", nil, "The cross toolchains directory" }
+
+ , {}
+ , {nil, "cc", "kv", nil, "The C Compiler" }
+ , {nil, "cxx", "kv", nil, "The C++ Compiler" }
+ , {nil, "cflags", "kv", nil, "The C Compiler Flags" }
+ , {nil, "cxflags", "kv", nil, "The C/C++ compiler Flags" }
+ , {nil, "cxxflags", "kv", nil, "The C++ Compiler Flags" }
+
+ , {}
+ , {nil, "as", "kv", nil, "The Assembler" }
+ , {nil, "asflags", "kv", nil, "The Assembler Flags" }
+
+ , {}
+ , {nil, "sc", "kv", nil, "The Swift Compiler" }
+ , {nil, "scflags", "kv", nil, "The Swift Compiler Flags" }
+
+ , {}
+ , {nil, "ld", "kv", nil, "The Linker" }
+ , {nil, "ldflags", "kv", nil, "The Binary Linker Flags" }
+
+ , {}
+ , {nil, "ar", "kv", nil, "The Static Library Linker" }
+ , {nil, "arflags", "kv", nil, "The Static Library Linker Flags" }
+
+ , {}
+ , {nil, "sh", "kv", nil, "The Shared Library Linker" }
+ , {nil, "shflags", "kv", nil, "The Shared Library Linker Flags" }
+
+ -- the options for all platforms
+ , function () return platform.menu("config") end
+
+ , {}
+ , {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {'o', "buildir", "kv", "build", "Set the build directory." }
+
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Configure for the given target." }
+ }
+ }
+end
+
+-- return module: _config
+return _config
diff --git a/xmake/core/action/_create.lua b/xmake/core/action/_create.lua
new file mode 100644
index 000000000..840631f65
--- /dev/null
+++ b/xmake/core/action/_create.lua
@@ -0,0 +1,173 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _create.lua
+--
+
+-- define module: _create
+local _create = _create or {}
+
+-- load modules
+local utils = require("base/utils")
+local template = require("base/template")
+
+-- need access to the given file?
+function _create.need(name)
+
+ -- no accessors
+ return false
+end
+
+-- done
+function _create.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- the target name
+ local targetname = options.target or options.name or path.basename(xmake._PROJECT_DIR) or "demo"
+
+ -- trace
+ utils.printf("create %s ...", targetname)
+
+ -- the language
+ local language = options.language
+ if not language then
+ utils.error("no language!")
+ return false
+ end
+
+ -- the template id
+ local templateid = tonumber(options.template)
+ if type(templateid) ~= "number" then
+ utils.error("invalid template id: %s!", options.template)
+ return false
+ end
+
+ -- load all templates for the given language
+ local templates = template.loadall(language)
+
+ -- load the template module
+ local module = nil
+ if templates then module = templates[templateid] end
+ if not module then
+ utils.error("invalid template id: %s!", options.template)
+ return false
+ end
+
+ -- enter the template directory
+ if not module._DIRECTORY or not os.cd(module._DIRECTORY) then
+ -- error
+ utils.error("not found template id: %s!", options.template)
+ return false
+ end
+
+ -- check the template project
+ if not os.isdir("project") then
+ -- errors
+ utils.error("the template project not exists!")
+ return false
+ end
+
+ -- ensure the project directory
+ if not os.isdir(xmake._PROJECT_DIR) then
+ os.mkdir(xmake._PROJECT_DIR)
+ end
+
+ -- copy the project files
+ local ok, errors = os.cp("project/*", xmake._PROJECT_DIR)
+ if not ok then
+ -- errors
+ utils.error(errors)
+ return false
+ end
+
+ -- done the template files
+ if not module.done(targetname, xmake._PROJECT_DIR, xmake._PACKAGES_DIR) then
+ utils.error("update the template failed!")
+ return false
+ end
+
+ -- trace
+ utils.printf("create %s ok!", targetname)
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _create.menu()
+
+ return {
+ -- usage
+ usage = "xmake create [options] [target]"
+
+ -- description
+ , description = "Create a new project."
+
+ -- options
+ , options =
+ {
+ {'n', "name", "kv", nil, "The project name." }
+ , {'f', "file", "kv", "xmake.lua", "Create a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Create from the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {'l', "language", "kv", "c", "The project language"
+ , function ()
+ local descriptions = {}
+ local languages = template.languages()
+ for _, language in ipairs(languages) do
+ table.insert(descriptions, " - " .. language)
+ end
+ return descriptions
+ end }
+ , {'t', "template", "kv", "1", "Select the project template id of the given language."
+ , function ()
+ local descriptions = {}
+ local languages = template.languages()
+ for _, language in ipairs(languages) do
+ table.insert(descriptions, string.format(" - language: %s", language))
+ local templates = template.loadall(language)
+ if templates then
+ for i, template in ipairs(templates) do
+ table.insert(descriptions, string.format(" %d. %s", i, utils.ifelse(template.description, template.description, "The Unknown Project")))
+ end
+ end
+ end
+ return descriptions
+ end }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", nil, "Create the given target."
+ , "Uses the project name as target if not exists." }
+ }
+ }
+end
+
+-- return module: _create
+return _create
diff --git a/xmake/core/action/_debug.lua b/xmake/core/action/_debug.lua
new file mode 100644
index 000000000..c84d78073
--- /dev/null
+++ b/xmake/core/action/_debug.lua
@@ -0,0 +1,89 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _debug.lua
+--
+
+-- define module: _debug
+local _debug = _debug or {}
+
+-- load modules
+local utils = require("base/utils")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _debug.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { config = true, global = true, project = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _debug.done()
+
+ -- TODO
+ print("not implement!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _debug.menu()
+
+ return {
+ -- xmake d
+ shortname = 'd'
+
+ -- usage
+ , usage = "xmake debug|d [options] [target]"
+
+ -- description
+ , description = "Debug target."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", "xmake.lua", "Create a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Create from the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", nil, "Debug a given target" }
+ }
+ }
+end
+
+-- return module: _debug
+return _debug
diff --git a/xmake/core/action/_global.lua b/xmake/core/action/_global.lua
new file mode 100644
index 000000000..a8fffa0bc
--- /dev/null
+++ b/xmake/core/action/_global.lua
@@ -0,0 +1,104 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _global.lua
+--
+
+-- define module: _global
+local _global = _global or {}
+
+-- load modules
+local utils = require("base/utils")
+local global = require("base/global")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _global.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { global = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _global.done()
+
+ -- probe the global platform configure
+ if not platform.probe(true) then
+ return false
+ end
+
+ -- clear up the global configure
+ global.clearup()
+
+ -- save the global configure
+ if not global.save() then
+ -- error
+ utils.error("save configure failed!")
+ return false
+ end
+
+ -- dump global
+ global.dump()
+
+ -- ok
+ print("configure ok!")
+ return true
+end
+
+-- the menu
+function _global.menu()
+
+ return {
+ -- xmake g
+ shortname = 'g'
+
+ -- usage
+ , usage = "xmake global|g [options] [target]"
+
+ -- description
+ , description = "Configure the global options for xmake."
+
+ -- options
+ , options =
+ {
+ {'c', "clean", "k", nil, "Clean the cached configure and configure all again." }
+ , {nil, "make", "kv", "auto", "Set the make path." }
+ , {nil, "ccache", "kv", "auto", "Enable or disable the c/c++ compiler cache."
+ , " --ccache=[y|n]" }
+
+ , {}
+ -- the options for all platforms
+ , function () return platform.menu("global") end
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+ }
+ }
+end
+
+-- return module: _global
+return _global
diff --git a/xmake/core/action/_install.lua b/xmake/core/action/_install.lua
new file mode 100644
index 000000000..28ef3650d
--- /dev/null
+++ b/xmake/core/action/_install.lua
@@ -0,0 +1,224 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _install.lua
+--
+
+-- define module: _install
+local _install = _install or {}
+
+-- load modules
+local utils = require("base/utils")
+local config = require("base/config")
+local global = require("base/global")
+local install = require("base/install")
+local package = require("base/package")
+local project = require("base/project")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _install.need(name)
+
+ -- no accessors
+ return false
+end
+
+-- make configure for the given target
+function _install._makeconf(configs, target_name, target)
+
+ -- check
+ assert(configs and target_name and target)
+
+ -- init configs for targets
+ configs[target_name] = configs[target_name] or {}
+ local configs_target = configs[target_name]
+
+ -- save the install script
+ local installscript = target.installscript
+ if type(installscript) == "string" and os.isfile(installscript) then
+ local script, errors = loadfile(installscript)
+ if script then
+ installscript = script()
+ if type(installscript) == "table" and installscript.main then
+ installscript = installscript.main
+ end
+ else
+ utils.error(errors)
+ return false
+ end
+ end
+ if target.installscript and type(installscript) ~= "function" then
+ utils.error("invalid install script!")
+ return false
+ end
+ configs_target.installscript = installscript
+
+ -- ok
+ return true
+end
+
+-- package target
+function _install._package(target_name)
+
+ -- get the target name
+ if not target_name or target_name == "all" then
+ target_name = ""
+ end
+
+ -- package it
+ if os.execute(string.format("xmake p -P %s -f %s %s", xmake._PROJECT_DIR, xmake._PROJECT_FILE, target_name)) ~= 0 then
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- done
+function _install.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- trace
+ print("install: ...")
+
+ -- load the global configure first
+ global.load()
+
+ -- enter the project directory
+ if not os.cd(xmake._PROJECT_DIR) then
+ -- errors
+ utils.error("not found project: %s!", xmake._PROJECT_DIR)
+ return false
+ end
+
+ -- package the given target first
+ if not _install._package(options.target) then
+ -- errors
+ utils.error("package: failed!")
+ return false
+ end
+
+ -- load the package configure
+ local configs, errors = package.load()
+ if not configs then
+ -- errors
+ utils.error(errors)
+ return false
+ end
+
+ -- reload configure
+ local errors = config.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- make the platform configure
+ if not platform.make() then
+ utils.error("make platform configure: %s failed!", config.get("plat"))
+ return false
+ end
+
+ -- reload project
+ local errors = project.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- update the outputdir
+ for _, target in pairs(configs) do
+ target.outputdir = options.installdir
+ end
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- make configure for the given target
+ if target_name and target_name ~= "all" then
+ if not _install._makeconf(configs, target_name, targets[target_name]) then
+ utils.error("make target configure: %s failed!", target_name)
+ return false
+ end
+ else
+ for target_name, target in pairs(targets) do
+ if not _install._makeconf(configs, target_name, target) then
+ utils.error("make target configure: %s failed!", target_name)
+ return false
+ end
+ end
+ end
+
+ -- done install
+ if not install.done(configs) then
+ -- errors
+ utils.error("install: failed!")
+ return false
+ end
+
+ -- trace
+ print("install: ok!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _install.menu()
+
+ return {
+ -- xmake i
+ shortname = 'i'
+
+ -- usage
+ , usage = "xmake install|i [options] [target]"
+
+ -- description
+ , description = "Package and install the project binary files."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {'o', "installdir", "kv", nil, "Set the install directory." }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Install the given target." }
+ }
+ }
+end
+
+-- return module: _install
+return _install
diff --git a/xmake/core/action/_lua.lua b/xmake/core/action/_lua.lua
new file mode 100644
index 000000000..e342d82e7
--- /dev/null
+++ b/xmake/core/action/_lua.lua
@@ -0,0 +1,168 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _lua.lua
+--
+
+-- define module: _lua
+local _lua = _lua or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local config = require("base/config")
+local string = require("base/string")
+local tools = require("tools/tools")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _lua.need(name)
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- do not load config if be not given -f or -P options
+ if options.file == nil and options.project == nil then
+ return false
+ end
+
+ -- patch target for loading config ok
+ options.target = "all"
+
+ -- the accessors
+ local accessors = { config = true, global = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _lua.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- no script?
+ if not options.script then
+ return false
+ end
+
+ -- the arguments
+ local arguments = options.arguments or {}
+ if type(arguments) ~= "table" then
+ arguments = {}
+ end
+
+ -- is string script?
+ if options.string then
+
+ -- trace
+ utils.verbose("script: %s", options.script)
+
+ -- load and run string
+ local script = loadstring(options.script)
+ if script then
+ return script(arguments)
+ end
+ else
+ -- attempt to load script from the given file if exists
+ local file = options.script
+ if not path.is_absolute(file) then
+ file = path.absolute(file)
+ end
+
+ -- attempt to load script from the tools directory
+ if not os.isfile(file) then
+ file = tools.find(options.script, xmake._CORE_DIR .. "/tools")
+ end
+
+ -- load and run the script file
+ if os.isfile(file) then
+
+ -- load script
+ local script = loadfile(file)
+ if script then
+
+ -- load module
+ local module = script()
+ if module then
+
+ -- init module
+ if module.init then
+ module:init(options.script)
+ end
+
+ -- done module
+ return module:main(arguments)
+ end
+ end
+ end
+ end
+
+ -- failed
+ utils.error("cannot run this script: %s", options.script)
+ return false
+end
+
+-- the menu
+function _lua.menu()
+
+ return {
+ -- xmake l
+ shortname = 'l'
+
+ -- usage
+ , usage = "xmake lua|l [options] [script] [arguments]"
+
+ -- description
+ , description = "Run the lua script."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", nil, "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+
+ , {}
+ , {'s', "string", "k", nil, "Run the lua string script." }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "script", "v", nil, "Run the given lua script."
+ , " - The script name from the xmake tool directory"
+ , " - The script file"
+ , " - The script string" }
+ , {nil, "arguments", "vs", nil, "The script arguments" }
+ }
+ }
+end
+
+-- return module: _lua
+return _lua
diff --git a/xmake/core/action/_man.lua b/xmake/core/action/_man.lua
new file mode 100644
index 000000000..feb70dd92
--- /dev/null
+++ b/xmake/core/action/_man.lua
@@ -0,0 +1,89 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _man.lua
+--
+
+-- define module: _man
+local _man = _man or {}
+
+-- load modules
+local utils = require("base/utils")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _man.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { config = true, global = true, project = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _man.done()
+
+ -- TODO
+ print("not implement!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _man.menu()
+
+ return {
+ -- xmake m
+ shortname = 'm'
+
+ -- usage
+ , usage = "xmake man|m [options] [target]"
+
+ -- description
+ , description = "Create a project man."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", "xmake.lua", "Create a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Create from the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Create man for the given target" }
+ }
+ }
+end
+
+-- return module: _man
+return _man
diff --git a/xmake/core/action/_package.lua b/xmake/core/action/_package.lua
new file mode 100644
index 000000000..e39604a33
--- /dev/null
+++ b/xmake/core/action/_package.lua
@@ -0,0 +1,365 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _package.lua
+--
+
+-- define module: _package
+local _package = _package or {}
+
+-- load modules
+local rule = require("base/rule")
+local path = require("base/path")
+local utils = require("base/utils")
+local config = require("base/config")
+local global = require("base/global")
+local string = require("base/string")
+local project = require("base/project")
+local package = require("base/package")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _package.need(name)
+
+ -- no accessors
+ return false
+end
+
+-- configure target for the given architecture
+function _package._config(arch, target_name)
+
+ -- need not configure it
+ if not arch then return true end
+
+ -- done the command
+ return os.execute(string.format("xmake f -P %s -f %s -a %s %s", xmake._PROJECT_DIR, xmake._PROJECT_FILE, arch, target_name)) == 0;
+end
+
+-- build target for the given architecture
+function _package._build(arch, target_name)
+
+ -- get the target name
+ if not target_name or target_name == "all" then
+ target_name = ""
+ end
+
+ -- configure it first
+ if not _package._config(arch, target_name) then return false end
+
+ -- build it
+ if os.execute(string.format("xmake -P %s %s", xmake._PROJECT_DIR, target_name)) ~= 0 then
+ -- errors
+ utils.error("build failed!")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- backup the target files
+function _package._backup(rootdir, filepath)
+
+ -- the relative file path
+ if filepath and path.is_absolute(filepath) then
+ filepath = path.relative(filepath, xmake._PROJECT_DIR)
+ end
+
+ -- not exists? return it directly
+ if not filepath or not os.isfile(filepath) then return end
+
+ -- the backup file
+ local backupfile = string.format("%s/%s", rootdir, filepath)
+
+ -- backup it
+ local ok, errors = os.cp(filepath, backupfile)
+ if not ok then
+ -- errors
+ utils.error(errors)
+ return
+ end
+
+ -- ok
+ return filepath
+end
+
+-- make configure for the given target
+function _package._makeconf(target_name, target)
+
+ -- check
+ assert(target_name and target)
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- the configs
+ local configs = _package._CONFIGS
+ assert(configs)
+
+ -- the architecture
+ local arch = config.get("arch")
+ if not arch then return false end
+
+ -- init configs for targets
+ configs[target_name] = configs[target_name] or {}
+ local configs_target = configs[target_name]
+
+ -- init configs for architectures
+ configs_target.archs = configs_target.archs or {}
+
+ -- init configs for architecture
+ configs_target.archs[arch] = configs_target.archs[arch] or {}
+ local configs_arch = configs_target.archs[arch]
+
+ -- save name
+ configs_target.name = target_name
+
+ -- save kind
+ configs_target.kind = target.kind
+
+ -- save the output directory
+ configs_target.outputdir = options.outputdir or config.get("buildir")
+
+ -- save the header files
+ configs_target.headers = target.headers
+
+ -- save the target directory
+ configs_arch.targetdir = rule.backupdir(target_name, arch)
+
+ -- save the config file
+ configs_arch.config_h = _package._backup(configs_arch.targetdir, rule.config_h(target))
+
+ -- save the target file
+ configs_arch.targetfile = _package._backup(configs_arch.targetdir, rule.targetfile(target_name, target))
+
+ -- save the package script
+ local packagescript = target.packagescript
+ if type(packagescript) == "string" and os.isfile(packagescript) then
+ local script, errors = loadfile(packagescript)
+ if script then
+ packagescript = script()
+ if type(packagescript) == "table" and packagescript.main then
+ packagescript = packagescript.main
+ end
+ else
+ utils.error(errors)
+ return false
+ end
+ end
+ if target.packagescript and type(packagescript) ~= "function" then
+ utils.error("invalid package script!")
+ return false
+ end
+ configs_target.packagescript = packagescript
+
+ -- ok
+ return true
+end
+
+-- load configure for the given target
+function _package._loadconf(target_name)
+
+ -- reload configure
+ local errors = config.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- make the platform configure
+ if not platform.make() then
+ utils.error("make platform configure: %s failed!", config.get("plat"))
+ return false
+ end
+
+ -- reload project
+ local errors = project.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- make configure for the given target
+ if target_name and target_name ~= "all" then
+ if not _package._makeconf(target_name, targets[target_name]) then
+ utils.error("make target configure: %s failed!", target_name)
+ return false
+ end
+ else
+ for target_name, target in pairs(targets) do
+ if not _package._makeconf(target_name, target) then
+ utils.error("make target configure: %s failed!", target_name)
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- build target for all architectures
+function _package._build_all(archs, target_name)
+
+ -- exists the given architectures?
+ if archs then
+
+ -- split all architectures
+ archs = archs:split(",")
+ if not archs then return false end
+
+ -- build for all architectures
+ for _, arch in ipairs(archs) do
+
+ -- trim it
+ arch = arch:trim()
+
+ -- build it
+ if not _package._build(arch, target_name) then return false end
+
+ -- load configure
+ if not _package._loadconf(target_name) then return false end
+
+ end
+
+ -- build for single architecture
+ else
+
+ -- build it
+ if not _package._build(nil, target_name) then return false end
+
+ -- load configure
+ if not _package._loadconf(target_name) then return false end
+
+ end
+
+ -- ok
+ return true
+end
+
+-- done
+function _package.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- trace
+ print("package: ...")
+
+ -- init configs
+ _package._CONFIGS = _package._CONFIGS or {}
+ local configs = _package._CONFIGS
+
+ -- load the global configure first
+ global.load()
+
+ -- enter the project directory
+ if not os.cd(xmake._PROJECT_DIR) then
+ -- errors
+ utils.error("not found project: %s!", xmake._PROJECT_DIR)
+ return false
+ end
+
+ -- build the given target first for all architectures
+ if not _package._build_all(options.archs, options.target) then
+ -- errors
+ utils.error("build package failed!")
+ return false
+ end
+
+ -- done package
+ if not package.done(configs) then
+ -- errors
+ utils.error("package: failed!")
+ return false
+ end
+
+ -- trace
+ print("package: ok!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _package.menu()
+
+ return {
+ -- xmake p
+ shortname = 'p'
+
+ -- usage
+ , usage = "xmake package|p [options] [target]"
+
+ -- description
+ , description = "Package target."
+
+ -- options
+ , options =
+ {
+ {'a', "archs", "kv", nil, "Package multiple given architectures."
+ , " .e.g --archs=\"armv7, arm64\" or -a i386"
+ , ""
+ , function ()
+ local descriptions = {}
+ local plats = platform.plats()
+ if plats then
+ for i, plat in ipairs(plats) do
+ descriptions[i] = " - " .. plat .. ":"
+ local archs = platform.archs(plat)
+ if archs then
+ for _, arch in ipairs(archs) do
+ descriptions[i] = descriptions[i] .. " " .. arch
+ end
+ end
+ end
+ end
+ return descriptions
+ end }
+
+ , {}
+ , {'f', "file", "kv", "xmake.lua", "Create a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Create from the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {'o', "outputdir", "kv", nil, "Set the output directory." }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Package a given target" }
+ }
+ }
+end
+
+-- return module: _package
+return _package
diff --git a/xmake/core/action/_run.lua b/xmake/core/action/_run.lua
new file mode 100644
index 000000000..64649fcb8
--- /dev/null
+++ b/xmake/core/action/_run.lua
@@ -0,0 +1,179 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _run.lua
+--
+
+-- define module: _run
+local _run = _run or {}
+
+-- load modules
+local rule = require("base/rule")
+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")
+
+-- need access to the given file?
+function _run.need(name)
+
+ -- check
+ assert(name)
+
+ -- the accessors
+ local accessors = { config = true, global = true, project = true, platform = true }
+
+ -- need it?
+ return accessors[name]
+end
+
+-- done
+function _run.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options and xmake._PROJECT_DIR)
+
+ -- the target name
+ local name = options.target
+ if not name then
+ -- error
+ utils.error("no runable target!")
+ return false
+ end
+
+ -- the arguments
+ local arguments = options.arguments or {}
+ if type(arguments) ~= "table" then
+ arguments = {}
+ end
+
+ -- the targets
+ local targets = project.targets()
+ if not targets or not targets[name] then
+ -- error
+ utils.error("not found target: %s!", name)
+ return false
+ end
+
+ -- the target
+ local target = targets[name]
+
+ -- the target file
+ local targetfile = rule.targetfile(name, target)
+ if targetfile and not path.is_absolute(targetfile) then
+ targetfile = path.absolute(targetfile, xmake._PROJECT_DIR)
+ end
+
+ -- load the run script
+ local runscript = target.runscript
+ if type(runscript) == "string" and os.isfile(runscript) then
+ local script, errors = loadfile(runscript)
+ if script then
+ runscript = script()
+ if type(runscript) == "table" and runscript.main then
+ runscript = runscript.main
+ end
+ else
+ utils.error(errors)
+ return false
+ end
+ end
+
+ -- run script
+ if runscript ~= nil then
+ if type(runscript) == "function" then
+
+ -- make passed target
+ local target_passed = {}
+ target_passed.name = name
+ target_passed.arguments = arguments
+ target_passed.targetfile = targetfile
+
+ -- run it
+ local ok = runscript(target_passed)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+ else
+ utils.error("invalid run script!")
+ return false
+ end
+ end
+
+ -- not executale?
+ if not target.kind or type(target.kind) ~= "string" or target.kind ~= "binary" then
+ -- error
+ utils.error("the target %s is not executale!", name)
+ return false
+ end
+
+ -- check the target file
+ if not targetfile and not os.isfile(targetfile) then
+ -- error
+ utils.error("not found target file: %s!", targetfile)
+ return false
+ end
+
+ -- done
+ local ok = os.execute(string.format("%s %s", targetfile, table.concat(arguments, " ")))
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- the menu
+function _run.menu()
+
+ return {
+ -- xmake r
+ shortname = 'r'
+
+ -- usage
+ , usage = "xmake run|r [options] [target] [arguments]"
+
+ -- description
+ , description = "Run the project target."
+
+ -- options
+ , options =
+ {
+ {'d', "debug", "k", nil, "Run and debug the given target." }
+ , {nil, "debugger", "kv", "auto", "Set the debugger path." }
+
+ , {}
+ , {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", nil, "Run the given target." }
+ , {nil, "arguments", "vs", nil, "The target arguments" }
+ }
+ }
+end
+
+-- return module: _run
+return _run
diff --git a/xmake/core/action/_uninstall.lua b/xmake/core/action/_uninstall.lua
new file mode 100644
index 000000000..8f82907d6
--- /dev/null
+++ b/xmake/core/action/_uninstall.lua
@@ -0,0 +1,160 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file _uninstall.lua
+--
+
+-- define module: _uninstall
+local _uninstall = _uninstall or {}
+
+-- load modules
+local utils = require("base/utils")
+local config = require("base/config")
+local global = require("base/global")
+local install = require("base/install")
+local uninstall = require("base/uninstall")
+local package = require("base/package")
+local project = require("base/project")
+local platform = require("platform/platform")
+
+-- need access to the given file?
+function _uninstall.need(name)
+
+ -- no accessors
+ return false
+end
+
+-- package target
+function _uninstall._package(target_name)
+
+ -- get the target name
+ if not target_name or target_name == "all" then
+ target_name = ""
+ end
+
+ -- package it
+ if os.execute(string.format("xmake p -P %s -f %s %s", xmake._PROJECT_DIR, xmake._PROJECT_FILE, target_name)) ~= 0 then
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+
+-- done
+function _uninstall.done()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- trace
+ print("uninstall: ...")
+
+ -- load the global configure first
+ global.load()
+
+ -- enter the project directory
+ if not os.cd(xmake._PROJECT_DIR) then
+ -- errors
+ utils.error("not found project: %s!", xmake._PROJECT_DIR)
+ return false
+ end
+
+ -- load the install configure
+ local configs, errors = install.load()
+ if not configs then
+ -- errors
+ utils.error(errors)
+ return false
+ end
+
+ -- reload configure
+ local errors = config.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- make the platform configure
+ if not platform.make() then
+ utils.error("make platform configure: %s failed!", config.get("plat"))
+ return false
+ end
+
+ -- reload project
+ local errors = project.reload()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- done uninstall
+ if not uninstall.done(configs) then
+ -- errors
+ utils.error("uninstall: failed!")
+ return false
+ end
+
+ -- trace
+ print("uninstall: ok!")
+
+ -- ok
+ return true
+end
+
+-- the menu
+function _uninstall.menu()
+
+ return {
+ -- xmake u
+ shortname = 'u'
+
+ -- usage
+ , usage = "xmake uninstall|u [options] [target]"
+
+ -- description
+ , description = "Uninstall the project binary files."
+
+ -- options
+ , options =
+ {
+ {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+
+ , {}
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Install the given target." }
+ }
+ }
+end
+
+-- return module: _uninstall
+return _uninstall
diff --git a/xmake/core/action/action.lua b/xmake/core/action/action.lua
new file mode 100644
index 000000000..96e51b5d8
--- /dev/null
+++ b/xmake/core/action/action.lua
@@ -0,0 +1,190 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file action.lua
+--
+
+-- define module: action
+local action = action or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local global = require("base/global")
+local config = require("base/config")
+local project = require("base/project")
+local platform = require("platform/platform")
+
+-- load the given action
+function action._load(name)
+
+ -- load the given action
+ return require("action/_" .. name)
+end
+
+-- load the project file
+function action._load_project()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- enter the project directory
+ if not os.cd(xmake._PROJECT_DIR) then
+ -- error
+ return string.format("not found project: %s!", xmake._PROJECT_DIR)
+ end
+
+ -- check the project file
+ if not os.isfile(xmake._PROJECT_FILE) then
+ return string.format("not found the project file: %s", xmake._PROJECT_FILE)
+ end
+
+ -- init the build directory
+ if options.buildir and path.is_absolute(options.buildir) then
+ options.buildir = path.relative(options.buildir, xmake._PROJECT_DIR)
+ end
+
+ -- xmake config or marked as "reconfig"?
+ if options._ACTION == "config" or config._RECONFIG then
+
+ -- probe the current project
+ project.probe()
+
+ -- clear up the configure
+ config.clearup()
+
+ end
+
+ -- load the project
+ return project.load()
+end
+
+-- done the given action
+function action.done(name)
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- load the given action
+ local _action = action._load(name)
+ if not _action then return false end
+
+ -- load the global configure first
+ if _action.need("global") then global.load() end
+
+ -- load the project configure
+ if _action.need("config") then
+ local errors = config.load()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+ end
+
+ -- probe the platform
+ if _action.need("platform") and (options._ACTION == "config" or config._RECONFIG) then
+ if not platform.probe(false) then
+ return false
+ end
+ 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 platform configure
+ if _action.need("platform") and not platform.make() then
+ utils.error("make platform configure: %s failed!", config.get("plat"))
+ return false
+ end
+
+ -- load the project file
+ if _action.need("project") then
+ local errors = action._load_project()
+ if errors then
+ -- error
+ utils.error(errors)
+ return false
+ end
+ end
+
+ -- reconfig it first if marked as "reconfig"
+ if _action.need("config") and config._RECONFIG then
+
+ -- config it
+ local _action_config = action._load("config")
+ if not _action_config or not _action_config.done() then
+ -- error
+ utils.error("reconfig failed for the changed host!")
+ return false
+ end
+ end
+
+ -- done the given action
+ return _action.done()
+end
+
+-- list the all actions
+function action.list()
+
+ -- find all action scripts
+ local list = {}
+ local files = os.match(xmake._CORE_DIR .. "/action/_*.lua")
+ if files then
+ for _, file in ipairs(files) do
+ local name = path.basename(file)
+ if name and name ~= "_build" then
+ table.insert(list, name:sub(2))
+ end
+ end
+ end
+
+ -- ok?
+ return list
+end
+
+-- get the all action menus
+function action.menu()
+
+ -- get all actions
+ local menus = {}
+ local actions = action.list()
+ for _, name in ipairs(actions) do
+
+ -- load action
+ local a = action._load(name)
+ if a and a.menu then
+ local m = a.menu()
+ if m then
+ menus[name] = m
+ end
+ end
+ end
+
+ -- ok?
+ return menus
+end
+
+-- return module: action
+return action
diff --git a/xmake/core/base/clean.lua b/xmake/core/base/clean.lua
new file mode 100644
index 000000000..9fbb3258a
--- /dev/null
+++ b/xmake/core/base/clean.lua
@@ -0,0 +1,192 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file clean.lua
+--
+
+-- define module: clean
+local clean = clean or {}
+
+-- load modules
+local os = require("base/os")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local config = require("base/config")
+local project = require("base/project")
+
+-- remove the given files or directories
+function clean._remove(filedirs)
+
+ -- empty?
+ if not filedirs then return true end
+
+ -- wrap it first
+ filedirs = utils.wrap(filedirs)
+ for _, filedir in ipairs(filedirs) do
+
+ -- exists? remove it
+ if os.exists(filedir) then
+ -- remove it
+ local ok, errors = os.rm(filedir)
+ if not ok then
+ -- error
+ utils.error(errors)
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- remove the given target name
+function clean._remove_target(target_name, target, mode, buildir)
+
+ -- check
+ assert(target_name and target)
+
+ -- remove the target file
+ if not clean._remove(rule.targetfile(target_name, target, buildir)) then
+ return false
+ end
+
+ -- not only remove target file?
+ if mode ~= "targets" then
+
+ -- remove the object files
+ if not clean._remove(rule.objectfiles(target_name, target, rule.sourcefiles(target), buildir)) then
+ return false
+ end
+
+ -- remove the header files
+ local _, dstheaders = rule.headerfiles(target)
+ if not clean._remove(dstheaders) then
+ return false
+ end
+
+ -- remove the config.h file
+ if mode == "all" and target.config_h then
+
+ -- translate file path
+ local config_h = nil
+ if not path.is_absolute(target.config_h) then
+ config_h = path.absolute(target.config_h, xmake._PROJECT_DIR)
+ else
+ config_h = path.translate(target.config_h)
+ end
+ if not clean._remove(config_h) then
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- remove the given target and all dependent targets
+function clean._remove_target_and_deps(target_name, mode, buildir)
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- the target
+ local target = targets[target_name]
+ assert(target)
+
+ -- remove the target
+ if not clean._remove_target(target_name, target, mode, buildir) then
+ return false
+ end
+
+ -- exists the dependent targets?
+ if target.deps then
+ local deps = utils.wrap(target.deps)
+ for _, dep in ipairs(deps) do
+ if not clean._remove_target_and_deps(dep, mode, buildir) then return false end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- remove the target and object files for the given target
+--
+-- mode:
+-- all
+-- build
+-- targets
+--
+function clean.remove(target_name, mode)
+
+ -- the build directory
+ local buildir = config.get("buildir")
+ assert(buildir and mode)
+
+ -- the target name
+ if target_name and target_name ~= "all" then
+ -- remove target
+ if not clean._remove_target_and_deps(target_name, mode, buildir) then return false end
+ else
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- remove targets
+ for target_name, target in pairs(targets) do
+ if not clean._remove_target(target_name, target, mode, buildir) then return false end
+ end
+ end
+
+ -- remove all
+ if mode == "all" then
+
+ -- remove makefile
+ if not clean._remove(rule.makefile()) then
+ return false
+ end
+
+ -- remove the configure directory
+ if not clean._remove(config.directory()) then
+ return false
+ end
+
+ -- remove the log file
+ if not clean._remove(rule.logfile()) then
+ return false
+ end
+
+ -- remove build directory if be empty
+ local buildir = config.get("buildir")
+ if os.isdir(buildir) then
+ os.rm(buildir, true)
+ end
+
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: clean
+return clean
diff --git a/xmake/core/base/compiler.lua b/xmake/core/base/compiler.lua
new file mode 100644
index 000000000..a64f8bae0
--- /dev/null
+++ b/xmake/core/base/compiler.lua
@@ -0,0 +1,574 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file compiler.lua
+--
+
+-- define module: compiler
+local compiler = compiler or {}
+
+-- load modules
+local io = require("base/io")
+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")
+local config = require("base/config")
+local tools = require("tools/tools")
+local platform = require("platform/platform")
+
+-- map gcc flag to the given compiler flag
+function compiler._mapflag(module, flag)
+
+ -- check
+ assert(module.mapflags and flag)
+
+ -- attempt to map it directly
+ local flag_mapped = module.mapflags[flag]
+ if flag_mapped and type(flag_mapped) == "string" then
+ return flag_mapped
+ end
+
+ -- find and replace it using pattern
+ for k, v in pairs(module.mapflags) do
+ local flag_mapped, count = flag:gsub("^" .. k .. "$", function (w)
+ if type(v) == "function" then
+ return v(module, w)
+ else
+ return v
+ end
+ end)
+ if flag_mapped and count ~= 0 then
+ return utils.ifelse(#flag_mapped ~= 0, flag_mapped, nil)
+ end
+ end
+
+ -- return it directly
+ return flag
+end
+
+-- map gcc flags to the given compiler flags
+function compiler._mapflags(module, flags)
+
+ -- check
+ assert(module)
+
+ -- wrap flags first
+ flags = utils.wrap(flags)
+
+ -- need not map flags? return it directly
+ if not module.mapflags then
+ return flags
+ end
+
+ -- map flags
+ local flags_mapped = {}
+ for _, flag in pairs(flags) do
+ -- map it
+ local flag_mapped = compiler._mapflag(module, flag)
+ if flag_mapped then
+ table.insert(flags_mapped, flag_mapped)
+ end
+ end
+
+ -- ok?
+ return flags_mapped
+end
+
+-- get the compiler flags from names
+function compiler._getflags(module, names, flags)
+
+ -- check
+ assert(flags)
+
+ -- the mapped flags
+ local flags_mapped = {}
+
+ -- wrap it first
+ names = utils.wrap(names)
+ for _, name in ipairs(names) do
+ table.join2(flags_mapped, compiler._mapflags(module, flags[name]))
+ end
+
+ -- get it
+ return flags_mapped
+end
+
+-- add flags from the compiler
+function compiler._addflags_from_compiler(module, flags, flagnames, kind)
+
+ -- check
+ assert(module and flags and flagnames)
+
+ -- done
+ for _, flagname in ipairs(flagnames) do
+
+ -- add compiler.xxflags
+ table.join2(flags, module, module[flagname])
+
+ -- add compiler.kind.xxflags
+ if kind ~= nil and module[kind] ~= nil then
+ table.join2(flags, module, module[kind][flagname])
+ end
+ end
+end
+
+-- add flags from the configure
+function compiler._addflags_from_config(module, flags, flagnames)
+
+ -- check
+ assert(module and flags and flagnames)
+
+ -- done
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, config.get(flagname))
+ end
+end
+
+-- add flags from the platform
+function compiler._addflags_from_platform(module, flags, flagnames)
+
+ -- check
+ assert(module and flags and flagnames)
+
+ -- add flags
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(module, platform.get(flagname)))
+ end
+
+ -- add the includedirs flags
+ if module.flag_includedir then
+ for _, includedir in ipairs(utils.wrap(platform.get("includedirs"))) do
+ table.join2(flags, module:flag_includedir(includedir))
+ end
+ end
+
+ -- add the defines flags
+ if module.flag_define then
+ for _, define in ipairs(utils.wrap(platform.get("defines"))) do
+ table.join2(flags, module:flag_define(define))
+ end
+ end
+
+ -- append the undefines flags
+ if module.flag_undefine then
+ for _, undefine in ipairs(utils.wrap(platform.get("undefines"))) do
+ table.join2(flags, module:flag_undefine(undefine))
+ end
+ end
+end
+
+
+-- add flags from the target
+function compiler._addflags_from_target(module, flags, flagnames, target)
+
+ -- check
+ assert(module and flags and flagnames and target)
+
+ -- add the target flags from the current project
+ for _, flagname in ipairs(flagnames) do
+ table.join2(flags, compiler._mapflags(module, target[flagname]))
+ end
+
+ -- add the symbols flags from the current project
+ table.join2(flags, compiler._getflags(module, target.symbols, { debug = "-g"
+ , hidden = "-fvisibility=hidden"
+ }))
+
+ -- add the warning flags from the current project
+ table.join2(flags, compiler._getflags(module, target.warnings, { none = "-w"
+ , less = "-W1"
+ , more = "-W3"
+ , all = "-Wall"
+ , error = "-Werror"
+ }))
+
+ -- add the optimize flags from the current project
+ table.join2(flags, compiler._getflags(module, target.optimize, { none = "-O0"
+ , fast = "-O1"
+ , faster = "-O2"
+ , fastest = "-O3"
+ , smallest = "-Os"
+ , aggressive = "-Ofast"
+ }))
+
+ -- add the vector extensions flags from the current project
+ table.join2(flags, compiler._getflags(module, target.vectorexts, { mmx = "-mmmx"
+ , sse = "-msse"
+ , sse2 = "-msse2"
+ , sse3 = "-msse3"
+ , ssse3 = "-mssse3"
+ , avx = "-mavx"
+ , avx2 = "-mavx2"
+ , neon = "-mfpu=neon"
+ }))
+
+ -- add the language flags from the current project
+ local languages = {}
+ for _, flagname in ipairs(flagnames) do
+ if flagname == "cflags" or flagname == "mflags" then
+ table.join2(languages, { ansi = "-ansi"
+ , c89 = "-std=c89"
+ , gnu89 = "-std=gnu89"
+ , c99 = "-std=c99"
+ , gnu99 = "-std=gnu99"
+ , c11 = "-std=c11"
+ , gnu11 = "-std=gnu11"
+ })
+ elseif flagname == "cxxflags" or flagname == "mxxflags" then
+ table.join2(languages, { cxx98 = "-std=c++98"
+ , gnuxx98 = "-std=gnu++98"
+ , cxx11 = "-std=c++11"
+ , gnuxx11 = "-std=gnu++11"
+ , cxx14 = "-std=c++14"
+ , gnuxx14 = "-std=gnu++14"
+ })
+ end
+ end
+ table.join2(flags, compiler._getflags(module, target.languages, languages))
+
+ -- add the includedirs flags from the current project
+ if module.flag_includedir then
+ for _, includedir in ipairs(utils.wrap(target.includedirs)) do
+ table.join2(flags, module:flag_includedir(includedir))
+ end
+ end
+
+ -- add the defines flags from the current project
+ if module.flag_define then
+ for _, define in ipairs(utils.wrap(target.defines)) do
+ table.join2(flags, module:flag_define(define))
+ end
+ end
+
+ -- append the undefines flags from the current project
+ if module.flag_undefine then
+ for _, undefine in ipairs(utils.wrap(target.undefines)) do
+ table.join2(flags, module:flag_undefine(undefine))
+ end
+ end
+
+ -- the options
+ if target.options then
+ for _, name in ipairs(utils.wrap(target.options)) do
+
+ -- get option if be enabled
+ local opt = nil
+ if config.get(name) then opt = config.get("__" .. name) end
+ if nil ~= opt then
+
+ -- add the flags from the option
+ compiler._addflags_from_target(module, flags, flagnames, opt)
+
+ -- append the defines flags
+ if opt.defines_if_ok and module.flag_define then
+ local defines = utils.wrap(opt.defines_if_ok)
+ for _, define in ipairs(defines) do
+ table.join2(flags, module:flag_define(define))
+ end
+ end
+
+ -- append the undefines flags
+ if opt.undefines_if_ok and module.flag_undefine then
+ local undefines = utils.wrap(opt.undefines_if_ok)
+ for _, undefine in ipairs(undefines) do
+ table.join2(flags, module:flag_undefine(undefine))
+ end
+ end
+ end
+ end
+ end
+end
+
+-- add flags from the option
+function compiler._addflags_from_option(module, flags, flagnames, opt)
+
+ -- check
+ assert(module and flags and flagnames and opt)
+
+ -- add the flags from the option
+ compiler._addflags_from_target(module, flags, flagnames, opt)
+
+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" }
+ elseif name == "sc" then flagnames = { "scflags" }
+ else
+ -- error
+ utils.error("unknown compiler: %s", name)
+ return
+ end
+
+ -- ok
+ return flagnames
+end
+
+-- get the compiler kind from the source file type
+function compiler._kind(srcfile)
+
+ -- get the source file type
+ local filetype = path.extension(srcfile)
+ if not filetype then
+ return nil
+ end
+
+ -- get the lower file type
+ filetype = filetype:lower()
+
+ -- get the compiler kind
+ local kind = nil
+ if filetype == ".c" then kind = "cc"
+ elseif filetype == ".cpp" or filetype == ".cc" then kind = "cxx"
+ elseif filetype == ".m" then kind = "mm"
+ elseif filetype == ".mm" then kind = "mxx"
+ elseif filetype == ".s" or filetype == ".asm" then kind = "as"
+ elseif filetype == ".swift" then kind = "sc"
+ end
+
+ -- ok
+ return kind
+end
+
+-- make the compile command for option
+function compiler._make_for_option(module, opt, srcfile, objfile, logfile)
+
+ -- check
+ assert(module and opt)
+
+ -- the flag names
+ local flagnames = compiler._flagnames(module._KIND)
+ assert(flagnames)
+
+ -- init flags
+ local flags = {}
+
+ -- add flags from the configure
+ compiler._addflags_from_config(module, flags, flagnames)
+
+ -- add flags from the option
+ compiler._addflags_from_option(module, flags, flagnames, opt)
+
+ -- add flags from the platform
+ compiler._addflags_from_platform(module, flags, flagnames)
+
+ -- add flags from the compiler
+ compiler._addflags_from_compiler(module, flags, flagnames)
+
+ -- remove repeat
+ flags = utils.unique(flags)
+
+ -- execute the compile command
+ return module:command_compile(srcfile, objfile, table.concat(flags, " "):trim(), logfile)
+end
+
+-- get the compiler from the given source file
+function compiler.get(srcfile)
+
+ -- get the compiler kind
+ local kind = compiler._kind(srcfile)
+ if not kind then
+ return nil, string.format("unknown source file: %s", srcfile)
+ end
+
+ -- get compiler from the source file type
+ local module = tools.get(kind)
+ if module then
+
+ -- invalid compiler
+ if not module.command_compile then
+ return nil, string.format("invalid compiler for %s", kind)
+ end
+
+ -- save kind
+ module._KIND = kind
+ else
+ return nil, string.format("unknown compiler for %s", kind)
+ end
+
+ -- ok?
+ return module
+end
+
+-- make the compile command
+function compiler.make(module, target, srcfile, objfile, logfile)
+
+ -- check
+ assert(module and target)
+
+ -- the flag names
+ local flagnames = compiler._flagnames(module._KIND)
+ assert(flagnames)
+
+ -- init flags
+ local flags = {}
+
+ -- add flags from the configure
+ compiler._addflags_from_config(module, flags, flagnames)
+
+ -- add flags from the target
+ compiler._addflags_from_target(module, flags, flagnames, target)
+
+ -- add flags from the platform
+ compiler._addflags_from_platform(module, flags, flagnames)
+
+ -- add flags from the compiler
+ compiler._addflags_from_compiler(module, flags, flagnames, target.kind)
+
+ -- remove repeat
+ flags = utils.unique(flags)
+
+ -- make the compile command
+ return module:command_compile(srcfile, objfile, table.concat(flags, " "):trim(), logfile)
+end
+
+-- check include for the project option
+function compiler.check_include(opt, include, srcpath, objpath)
+
+ -- check
+ assert(opt and srcpath and objpath)
+
+ -- open the checking source file
+ local srcfile = io.openmk(srcpath)
+ if not srcfile then return end
+
+ -- make include
+ if include then
+ srcfile:write(string.format("#include <%s>\n\n", include))
+ end
+
+ -- 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 module = compiler.get(srcpath)
+ if not module then return end
+
+ -- execute the compile command
+ return module:main(compiler._make_for_option(module, opt, srcpath, objpath, utils.ifelse(xmake._OPTIONS.verbose, nil, xmake._NULDEV)))
+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.openmk(srcpath)
+ if not srcfile then return end
+
+ -- get the compiler
+ local module = compiler.get(srcpath)
+ if not module then return end
+
+ -- make includes
+ local includes = nil
+ if module._KIND == "cc" then includes = opt.cincludes
+ elseif module._KIND == "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()
+
+ -- execute the compile command
+ return module:main(compiler._make_for_option(module, opt, srcpath, objpath, utils.ifelse(xmake._OPTIONS.verbose, nil, xmake._NULDEV)))
+end
+
+-- check typedef for the project option
+function compiler.check_typedef(opt, typedef, srcpath, objpath)
+
+ -- check
+ assert(opt and typedef)
+
+ -- open the checking source file
+ local srcfile = io.openmk(srcpath)
+ if not srcfile then return end
+
+ -- get the compiler
+ local module = compiler.get(srcpath)
+ if not module then return end
+
+ -- make includes
+ local includes = nil
+ if module._KIND == "cc" then includes = opt.cincludes
+ elseif module._KIND == "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(" typedef %s __type_xxx;\n\n", typedef))
+
+ -- make the main function tailer
+ srcfile:write(" return 0;\n")
+ srcfile:write("}\n")
+
+ -- exit this file
+ srcfile:close()
+
+ -- execute the compile command
+ return module:main(compiler._make_for_option(module, opt, srcpath, objpath, utils.ifelse(xmake._OPTIONS.verbose, nil, xmake._NULDEV)))
+end
+
+-- return module: compiler
+return compiler
diff --git a/xmake/core/base/config.lua b/xmake/core/base/config.lua
new file mode 100644
index 000000000..3cea6a652
--- /dev/null
+++ b/xmake/core/base/config.lua
@@ -0,0 +1,395 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file config.lua
+--
+
+-- define module: config
+local config = config or {}
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local utils = require("base/utils")
+local option = require("base/option")
+local global = require("base/global")
+
+-- make configure for the current target
+function config._make(configs)
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- init current target configure
+ local current = {}
+
+ -- get configs from the default configure
+ if configs._DEFAULTS then
+ for k, v in pairs(configs._DEFAULTS) do
+ if type(v) ~= "string" or v ~= "auto" then current[k] = v end
+ end
+ end
+
+ -- get configs from the global configure
+ if global._CURRENT then
+ for k, v in pairs(global._CURRENT) do
+ current[k] = v
+ end
+ end
+
+ -- get configs from all targets
+ for k, v in pairs(configs) do
+ if type(k) == "string" and not k:find("^_%u+") then
+ current[k] = v
+ end
+ end
+
+ -- get configs from the current target
+ if configs._TARGETS and current.target ~= "all" then
+
+ -- get the target config
+ local target_config = configs._TARGETS[current.target]
+ if target_config then
+
+ -- merge it
+ for k, v in pairs(target_config) do
+ current[k] = v
+ end
+ end
+ end
+
+ -- ok?
+ return current
+end
+
+-- get the configure file
+function config._file()
+
+ -- get it
+ return config.directory() .. "/xmake.conf"
+end
+
+-- need configure?
+function config._need(name)
+ return name and name ~= "target" and name ~= "file" and name ~= "project" and name ~= "verbose" and name ~= "clean"
+end
+
+-- get the current target scope
+function config._target()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- check
+ local configs = config._CONFIGS
+ assert(configs)
+
+ -- the target name
+ local name = options.target or options._DEFAULTS.target
+ assert(name and type(name) == "string")
+
+ -- for all targets?
+ if name == "all" then
+ return configs
+ elseif configs._TARGETS then
+ -- get it
+ return configs._TARGETS[name]
+ end
+end
+
+-- get the given configure from the current
+function config.get(name)
+
+ -- the configure has been not loaded
+ if not config._CURRENT then return end
+
+ -- get it
+ return config._CURRENT[name]
+end
+
+-- set the given configure to the current
+function config.set(name, value)
+
+ -- check
+ assert(config._CURRENT and name)
+
+ -- get the current target
+ local target = config._target()
+ assert(target)
+
+ -- set it to the current target configure for saving to file
+ target[name] = value
+
+ -- set it to the current configure
+ config._CURRENT[name] = value
+end
+
+-- the given configure need probe automatically
+function config.auto(name)
+
+ -- the configs
+ local configs = config._CONFIGS
+ assert(configs)
+
+ -- need probe it automatically?
+ if configs._DEFAULTS then
+ local value = configs._DEFAULTS[name]
+ if value then
+ if type(value) == "string" and value == "auto" then
+ return true
+ end
+ end
+ end
+
+ -- need not probe it if have been setted manually
+ if config._CURRENT and nil ~= config._CURRENT[name] then
+ return false
+ end
+
+ -- attempt to probe it if not exists
+ return true
+end
+
+-- get the configure directory
+function config.directory()
+
+ -- the directory
+ local dir = xmake._PROJECT_DIR .. "/.xmake"
+
+ -- create it directly first if not exists
+ if not os.isdir(dir) then
+ assert(os.mkdir(dir))
+ end
+
+ -- get it
+ return dir
+end
+
+-- save xmake.conf
+function config.save()
+
+ -- the configs
+ local configs = config._CONFIGS
+ assert(configs)
+
+ -- save to the configure file
+ return io.save(config._file(), configs)
+end
+
+function config.load()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- check
+ assert(option._MENU)
+ assert(option._MENU.config)
+
+ -- the target name
+ local name = options.target or options._DEFAULTS.target
+ if not name then
+ return "no given target name!"
+ end
+
+ -- does not clean the cached configure?
+ if not options.clean then
+
+ -- load and execute the xmake.xconf
+ local filepath = config._file()
+ if os.isfile(filepath) then
+
+ -- load the configure file
+ local configs, errors = io.load(filepath)
+
+ -- exists local configures?
+ if configs then
+
+ -- save configs
+ config._CONFIGS = configs
+
+ -- make the current target configs
+ local current = config._make(configs)
+
+ -- clear configs and mark as "rebuild" and "reconfig" if the host has been changed
+ if (current and current.host ~= xmake._HOST) then
+
+ -- clear configs and mark as "rebuild"
+ config._CONFIGS = { __rebuild = true }
+
+ -- mark as "reconfig" if the current action is not "config"
+ if options._ACTION ~= "config" then
+ config._RECONFIG = true
+ end
+ end
+
+ -- clear configs and mark as "rebuild" if the plat has been changed
+ if current and current.plat and options.plat and current.plat ~= options.plat then
+
+ -- clear configs and mark as "rebuild"
+ config._CONFIGS = { __rebuild = true }
+ end
+
+ -- mark as "rebuild" if the arch has been changed
+ if current and current.arch and options.arch and current.arch ~= options.arch then
+
+ -- mark as "rebuild"
+ config._CONFIGS.__rebuild = true
+ end
+
+ -- mark as "rebuild" if the mode has been changed
+ if current and current.mode and options.mode and current.mode ~= options.mode then
+
+ -- mark as "rebuild"
+ config._CONFIGS.__rebuild = true
+ end
+ elseif errors then
+ -- error
+ utils.error(errors)
+ end
+ end
+ end
+
+ -- init configs if not exists
+ if not config._CONFIGS then
+ -- clear configs and mark as "rebuild"
+ config._CONFIGS = { __rebuild = true }
+
+ -- mark as "reconfig" if the current action is not "config"
+ if options._ACTION ~= "config" then
+ config._RECONFIG = true
+ end
+ end
+
+ -- the configs
+ local configs = config._CONFIGS
+
+ -- mark as "rebuild" if clean the cached configure
+ if options.clean then
+ configs.__rebuild = true
+ end
+
+ -- init the defaults
+ local defaults = nil
+ if not configs._DEFAULTS then
+ if config._RECONFIG then defaults = option.defaults("config")
+ elseif options._ACTION == "config" then defaults = options._DEFAULTS
+ end
+ if defaults then
+ for k, v in pairs(defaults) do
+
+ -- check
+ assert(type(k) == "string")
+
+ -- skip some options
+ if config._need(k) then
+
+ -- save the default option
+ configs._DEFAULTS = configs._DEFAULTS or {}
+ configs._DEFAULTS[k] = v
+ end
+ end
+ end
+ end
+ defaults = configs._DEFAULTS
+
+ -- init targets
+ configs._TARGETS = configs._TARGETS or {}
+ if name ~= "all" then
+ configs._TARGETS[name] = configs._TARGETS[name] or {}
+ end
+
+ -- get the current target scope
+ local target = config._target()
+ assert(target and type(target) == "table")
+
+ -- merge xmake._OPTIONS to target
+ if options._ACTION == "config" then
+ for k, v in pairs(options) do
+
+ -- check
+ assert(type(k) == "string")
+
+ -- skip some options
+ if not k:startswith("_") and config._need(k) then
+
+ -- save the option to the target
+ target[k] = v
+
+ -- remove it from the defaults, because we have setted it manually
+ if defaults then defaults[k] = nil end
+ end
+ end
+ end
+
+ -- make the current config
+ config._CURRENT = config._make(config._CONFIGS)
+end
+
+-- clear up and remove all auto values
+function config.clearup()
+
+ -- clear up the current configure
+ local current = config._CURRENT
+ if current then
+ for k, v in pairs(current) do
+ if type(v) == "string" and v == "auto" then
+ current[k] = nil
+ end
+ end
+ end
+
+ -- clear up the current target configure
+ local target = config._target()
+ if target then
+ for k, v in pairs(target) do
+ if type(v) == "string" and v == "auto" then
+ target[k] = nil
+ end
+ end
+ end
+
+end
+
+-- reload configure
+function config.reload()
+
+ -- clear the old configure
+ config._CURRENT = nil
+ config._CONFIGS = nil
+
+ -- load it
+ return config.load()
+end
+
+-- dump the current configure
+function config.dump()
+
+ -- check
+ assert(config._CURRENT)
+
+ -- dump
+ utils.dump(config._CURRENT, "__%w*", "configure")
+
+end
+
+-- return module: config
+return config
diff --git a/xmake/core/base/global.lua b/xmake/core/base/global.lua
new file mode 100644
index 000000000..0017590c6
--- /dev/null
+++ b/xmake/core/base/global.lua
@@ -0,0 +1,246 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file global.lua
+--
+
+-- define module: global
+local global = global or {}
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local utils = require("base/utils")
+local option = require("base/option")
+
+-- make configure
+function global._make()
+
+ -- the configs
+ local configs = global._CONFIGS
+ assert(configs)
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- init current global configure
+ global._CURRENT = global._CURRENT or {}
+ local current = global._CURRENT
+
+ -- make current global configure
+ for k, v in pairs(configs) do
+ if type(k) == "string" and not k:find("^_%u+") then
+ current[k] = v
+ end
+ end
+end
+
+-- get the configure file
+function global._file()
+
+ -- get it
+ return global.directory() .. "/xmake.conf"
+end
+
+-- need configure?
+function global._need(name)
+ return name and name ~= "verbose" and name ~= "clean"
+end
+
+-- get the given configure from the current
+function global.get(name)
+
+ -- check
+ assert(global._CURRENT)
+
+ -- the value
+ local value = global._CURRENT[name]
+ if value and value == "auto" then
+ value = nil
+ end
+
+ -- get it
+ return value
+end
+
+-- set the given configure to the current
+function global.set(name, value)
+
+ -- check
+ assert(global._CURRENT and global._CONFIGS)
+ assert(name and value and type(value) ~= "table")
+
+ -- set it to the current configure
+ global._CURRENT[name] = value
+
+ -- set it to the configure for saving to file
+ global._CONFIGS[name] = value
+
+end
+
+-- get the global configure directory
+function global.directory()
+
+ -- the directory
+ local dir = path.translate("~/.xmake")
+
+ -- create it directly first if not exists
+ if not os.isdir(dir) then
+ assert(os.mkdir(dir))
+ end
+
+ -- get it
+ return dir
+end
+
+-- save xmake.conf
+function global.save()
+
+ -- the configs
+ local configs = global._CONFIGS
+ assert(configs)
+
+ -- save to the configure file
+ return io.save(global._file(), configs)
+end
+
+-- load xmake.conf
+function global.load()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- check
+ assert(option._MENU)
+ assert(option._MENU.global)
+
+ -- get all configure names
+ local i = 1
+ local configures = {}
+ for _, o in ipairs(option._MENU.global.options) do
+ local name = o[2]
+ if global._need(name) then
+ configures[i] = name
+ i = i + 1
+ end
+ end
+
+ -- does not clean the cached configure?
+ if not options.clean then
+
+ -- load and execute the xmake.conf
+ local filepath = global._file()
+ if os.isfile(filepath) then
+
+ -- load the configure file
+ local configs, errors = io.load(filepath)
+
+ -- exists local configures?
+ if configs then
+ -- save configs
+ global._CONFIGS = configs
+ elseif errors then
+ -- error
+ utils.error(errors)
+ end
+ end
+ end
+
+ -- init configs
+ global._CONFIGS = global._CONFIGS or {}
+ local configs = global._CONFIGS
+
+ -- xmake global?
+ if options._ACTION == "global" then
+
+ -- merge xmake._OPTIONS to the global configure
+ for k, v in pairs(options) do
+
+ -- check
+ assert(type(k) == "string")
+
+ -- need configure it?
+ if not k:startswith("_") and global._need(k) then
+ configs[k] = v
+ end
+ end
+
+ -- merge the default global configure options to the global configure
+ local defaults = options._DEFAULTS
+ if defaults then
+ for k, v in pairs(defaults) do
+
+ -- check
+ assert(type(k) == "string")
+
+ -- need configure it?
+ if global._need(k) then
+
+ -- save the default option
+ if nil == configs[k] then
+ configs[k] = v
+ end
+ end
+ end
+ end
+ end
+
+ -- make the current global
+ global._make()
+end
+
+-- clear up and remove all auto values
+function global.clearup()
+
+ -- clear up the current configure
+ local current = global._CURRENT
+ if current then
+ for k, v in pairs(current) do
+ if v and type(v) and v == "auto" then
+ current[k] = nil
+ end
+ end
+ end
+
+ -- clear up the configure
+ local configs = global._CONFIGS
+ if configs then
+ for k, v in pairs(configs) do
+ if v and type(v) and v == "auto" then
+ configs[k] = nil
+ end
+ end
+ end
+end
+
+-- dump the current configure
+function global.dump()
+
+ -- check
+ assert(global._CURRENT)
+
+ -- dump
+ utils.dump(global._CURRENT, "__%w*", "configure")
+
+end
+
+-- return module: global
+return global
diff --git a/xmake/core/base/install.lua b/xmake/core/base/install.lua
new file mode 100644
index 000000000..9fc41a14a
--- /dev/null
+++ b/xmake/core/base/install.lua
@@ -0,0 +1,143 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file install.lua
+--
+
+-- define module: install
+local install = install 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 config = require("base/config")
+local platform = require("platform/platform")
+
+-- install target from the project script
+function install._done_from_project(target)
+
+ -- check
+ assert(target)
+
+ -- install it using the project script first
+ local installscript = target.installscript
+ if type(installscript) == "function" then
+
+ -- remove it
+ target.installscript = nil
+
+ -- install it
+ return installscript(target)
+ end
+
+ -- continue
+ return 0
+end
+
+-- install target from the platform script
+function install._done_from_platform(target)
+
+ -- check
+ assert(target)
+
+ -- the platform install script file
+ local installscript = nil
+ local scriptfile = platform.directory() .. "/install.lua"
+ if os.isfile(scriptfile) then
+
+ -- load the install script
+ local script, errors = loadfile(scriptfile)
+ if script then
+ installscript = script()
+ if type(installscript) == "table" and installscript.main then
+ installscript = installscript.main
+ end
+ else
+ utils.error(errors)
+ end
+ end
+
+ -- install it
+ if type(installscript) == "function" then
+ return installscript(target)
+ end
+
+ -- continue
+ return 0
+end
+
+-- install target from the given target configure
+function install._done(target)
+
+ -- check
+ assert(target)
+
+ -- install it from the project script
+ local ok = install._done_from_project(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- install it from the platform script
+ local ok = install._done_from_platform(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- ok
+ return true
+end
+
+-- get the configure file
+function install._file()
+
+ -- get it
+ return config.directory() .. "/install.conf"
+end
+
+-- done install from the configure
+function install.done(configs)
+
+ -- check
+ assert(configs)
+
+ -- install targets
+ for _, target in pairs(configs) do
+
+ -- install it
+ if not install._done(target) then
+ -- errors
+ utils.error("install %s failed!", target.name)
+ return false
+ end
+
+ end
+
+ -- save to the configure file
+ return io.save(install._file(), configs)
+end
+
+-- load the install configure
+function install.load()
+
+ -- load it
+ return io.load(install._file())
+end
+
+-- return module: install
+return install
diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua
new file mode 100644
index 000000000..66b23911a
--- /dev/null
+++ b/xmake/core/base/io.lua
@@ -0,0 +1,324 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file io.lua
+--
+
+-- define module: io
+local io = io or {}
+
+-- load modules
+local path = require("base/path")
+local utils = require("base/utils")
+
+-- save object with the level
+function io._save_with_level(file, object, level)
+
+ -- save string
+ if type(object) == "string" then
+ file:write(string.format("%q", object))
+ -- save boolean
+ elseif type(object) == "boolean" then
+ file:write(tostring(object))
+ -- save number
+ elseif type(object) == "number" then
+ file:write(object)
+ -- save table
+ elseif type(object) == "table" then
+
+ -- save head
+ file:write("\n")
+ for l = 1, level do
+ file:write(" ")
+ end
+ file:write("{\n")
+
+ -- save body
+ local i = 0
+ for k, v in pairs(object) do
+
+ -- save spaces and separator
+ for l = 1, level do
+ file:write(" ")
+ end
+
+ file:write(utils.ifelse(i == 0, " ", ", "))
+
+ -- save key
+ if type(k) == "string" then
+ file:write(string.format("[%q]", k), " = ")
+ end
+
+ -- save value
+ if not io._save_with_level(file, v, level + 1) then
+ return false
+ end
+
+ -- save newline
+ file:write("\n")
+ i = i + 1
+ end
+
+ -- save tail
+ for l = 1, level do
+ file:write(" ")
+ end
+ file:write("}\n")
+ else
+ -- error
+ utils.error("invalid object type: %s", type(object))
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- save object to given file
+function io._save(file, object)
+
+ -- save it
+ return io._save_with_level(file, object, 0)
+end
+
+-- create directory and open a writable file
+function io.openmk(filepath)
+
+ -- check
+ assert(filepath)
+
+ -- get the file directory
+ local dir = path.directory(filepath)
+
+ -- ensure the file directory
+ if not os.isdir(dir) then os.mkdir(dir) end
+
+ -- open it
+ return io.open(filepath, "w")
+end
+
+-- read all data from file
+function io.readall(filepath)
+
+ -- open file
+ local file = io.open(filepath, "r")
+ if not file then
+ -- error
+ return nil, string.format("open %s failed!", filepath)
+ end
+
+ -- read all
+ local data = file:read("*all")
+
+ -- exit file
+ file:close()
+
+ -- ok?
+ return data
+end
+
+-- write all data to file
+function io.writall(filepath, data)
+
+ -- open file
+ local file = io.open(filepath, "w")
+ if not file then
+ -- error
+ return false, string.format("open %s failed!", filepath)
+ end
+
+ -- write all
+ file:write(data)
+
+ -- exit file
+ file:close()
+
+ -- ok?
+ return true
+end
+
+-- save object the the given filepath
+function io.save(filepath, object)
+
+ -- open the file
+ local file = io.openmk(filepath)
+ if not file then
+ -- error
+ return false, string.format("open %s failed!", filepath)
+ end
+
+ -- save object to file
+ if not io._save(file, object) then
+ -- error
+ file:close()
+ return false, string.format("save %s failed!", filepath)
+ end
+
+ -- close file
+ file:close()
+
+ -- ok
+ return true
+end
+
+-- load object from the given file
+function io.load(filepath)
+
+ -- open the file
+ local file = io.open(filepath, "r")
+ if not file then
+ -- error
+ return nil, string.format("open %s failed!", filepath)
+ end
+
+ -- load data
+ local result = nil
+ local errors = nil
+ local data = file:read("*all")
+ if data and type(data) == "string" then
+
+ -- load script
+ local script, errs = loadstring("return " .. data)
+ if script then
+
+ -- load object
+ local ok, object = pcall(script)
+ if ok and object then
+ result = object
+ elseif object then
+ -- error
+ errors = object
+ else
+ -- error
+ errors = string.format("load %s failed!", filepath)
+ end
+ -- errors
+ else errors = errs end
+ end
+
+ -- close file
+ file:close()
+
+ -- ok?
+ return result, errors
+end
+
+-- gsub the given file and return replaced data
+function io.gsub(filepath, pattern, replace)
+
+ -- read all data from file
+ local data, errors = io.readall(filepath)
+ if not data then return nil, 0, errors end
+
+ -- replace it
+ local count = 0
+ if type(data) == "string" then
+ data, count = data:gsub(pattern, replace)
+ else
+ return nil, 0, string.format("data is not string!")
+ end
+
+ -- replace ok?
+ if count ~= 0 then
+ -- write all data to file
+ local ok, errors = io.writall(filepath, data)
+ if not ok then return nil, 0, errors end
+ end
+
+ -- ok
+ return data, count
+end
+
+-- cat the given file
+function io.cat(filepath, linecount)
+
+ -- open file
+ local file = io.open(filepath, "r")
+ if file then
+
+ -- show file
+ local count = 1
+ for line in file:lines() do
+
+ -- show line
+ print(line)
+
+ -- end?
+ if linecount and count >= linecount then
+ break
+ end
+
+ -- update the line count
+ count = count + 1
+ end
+
+ -- exit file
+ file:close()
+ end
+end
+
+-- tail the given file
+function io.tail(filepath, linecount)
+
+ -- open file
+ local file = io.open(filepath, "r")
+ if file then
+
+ -- read lines
+ local lines = {}
+ for line in file:lines() do
+ table.insert(lines, line)
+ end
+
+ -- tail lines
+ local tails = {}
+ if #lines ~= 0 then
+ local count = 1
+ for index = #lines, 1, -1 do
+
+ -- show line
+ table.insert(tails, lines[index])
+
+ -- end?
+ if linecount and count >= linecount then
+ break
+ end
+
+ -- update the line count
+ count = count + 1
+ end
+ end
+
+ -- show tails
+ if #tails ~= 0 then
+ for index = #tails, 1, -1 do
+
+ -- show tail
+ print(tails[index])
+
+ end
+ end
+
+ -- exit file
+ file:close()
+ end
+end
+
+-- return module: io
+return io
diff --git a/xmake/core/base/linker.lua b/xmake/core/base/linker.lua
new file mode 100644
index 000000000..9a0388757
--- /dev/null
+++ b/xmake/core/base/linker.lua
@@ -0,0 +1,386 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file linker.lua
+--
+
+-- define module: linker
+local linker = linker or {}
+
+-- load modules
+local utils = require("base/utils")
+local table = require("base/table")
+local string = require("base/string")
+local config = require("base/config")
+local compiler = require("base/compiler")
+local tools = require("tools/tools")
+local platform = require("platform/platform")
+
+-- map gcc flag to the given linker flag
+function linker._mapflag(module, flag)
+
+ -- check
+ assert(module.mapflags and flag)
+
+ -- attempt to map it directly
+ local flag_mapped = module.mapflags[flag]
+ if flag_mapped and type(flag_mapped) == "string" then
+ return flag_mapped
+ end
+
+ -- find and replace it using pattern
+ for k, v in pairs(module.mapflags) do
+ local flag_mapped, count = flag:gsub("^" .. k .. "$", function (w)
+ if type(v) == "function" then
+ return v(module, w)
+ else
+ return v
+ end
+ end)
+ if flag_mapped and count ~= 0 then
+ return utils.ifelse(#flag_mapped ~= 0, flag_mapped, nil)
+ end
+ end
+
+ -- return it directly
+ return flag
+end
+
+-- map gcc flags to the given linker flags
+function linker._mapflags(module, flags)
+
+ -- check
+ assert(module)
+
+ -- wrap flags first
+ flags = utils.wrap(flags)
+
+ -- need not map flags? return it directly
+ if not module.mapflags then
+ return flags
+ end
+
+ -- map flags
+ local flags_mapped = {}
+ for _, flag in pairs(flags) do
+ -- map it
+ local flag_mapped = linker._mapflag(module, flag)
+ if flag_mapped then
+ table.insert(flags_mapped, flag_mapped)
+ end
+ end
+
+ -- ok?
+ return flags_mapped
+end
+
+-- get the linker flags from names
+function linker._getflags(module, names, flags)
+
+ -- check
+ assert(flags)
+
+ -- the mapped flags
+ local flags_mapped = {}
+
+ -- wrap it first
+ names = utils.wrap(names)
+ for _, name in ipairs(names) do
+ table.join2(flags_mapped, linker._mapflags(module, flags[name]))
+ end
+
+ -- get it
+ return flags_mapped
+end
+
+
+-- add flags from the links
+function linker._addflags_from_links(module, flags, links)
+
+ -- check
+ assert(module and flags and links)
+
+ -- done
+ if module.flag_link then
+ for _, link in ipairs(utils.wrap(links)) do
+ table.join2(flags, module:flag_link(link))
+ end
+ end
+end
+
+-- add flags from the linker
+function linker._addflags_from_linker(module, flags, flagname)
+
+ -- check
+ assert(module and flags and flagname)
+
+ -- done
+ table.join2(flags, module[flagname])
+end
+
+-- add flags from the compiler
+function linker._addflags_from_compiler(module, flags, flagname, srcfiles)
+
+ -- check
+ assert(module and flags and flagname)
+
+ -- add the flags for compiler
+ local flags_for_compiler = {}
+ if srcfiles then
+ for _, srcfile in ipairs(utils.wrap(srcfiles)) do
+
+ -- get the compiler
+ local c, errors = compiler.get(srcfile)
+ if not c then
+ -- error
+ utils.error(errors)
+ return
+ end
+
+ -- add flags
+ table.join2(flags_for_compiler, c[flagname])
+ end
+ end
+
+ -- done
+ table.join2(flags, utils.unique(flags_for_compiler))
+end
+
+-- add flags from the configure
+function linker._addflags_from_config(module, flags, flagname)
+
+ -- check
+ assert(module and flags and flagname)
+
+ -- done
+ table.join2(flags, config.get(flagname))
+end
+
+-- add flags from the platform
+function linker._addflags_from_platform(module, flags, flagname)
+
+ -- check
+ assert(module and flags and flagname)
+
+ -- add flags
+ table.join2(flags, linker._mapflags(module, platform.get(flagname)))
+
+ -- add the linkdirs flags
+ if module.flag_linkdir then
+ for _, linkdir in ipairs(utils.wrap(platform.get("linkdirs"))) do
+ table.join2(flags, module:flag_linkdir(linkdir))
+ end
+ end
+
+ -- add the links flags
+ if module.flag_link then
+ for _, link in ipairs(utils.wrap(platform.get("links"))) do
+ table.join2(flags, module:flag_link(link))
+ end
+ end
+end
+
+-- add flags from the target
+function linker._addflags_from_target(module, flags, flagname, target)
+
+ -- check
+ assert(module and flags and flagname and target)
+
+ -- add the target flags from the current project
+ table.join2(flags, linker._mapflags(module, target[flagname]))
+
+ -- add the linkdirs flags from the current project
+ if module.flag_linkdir then
+ for _, linkdir in ipairs(utils.wrap(target.linkdirs)) do
+ table.join2(flags, module:flag_linkdir(linkdir))
+ end
+ end
+
+ -- add the links flags from the current project
+ if module.flag_link then
+ for _, link in ipairs(utils.wrap(target.links)) do
+ table.join2(flags, module:flag_link(link))
+ end
+ end
+
+ -- the options
+ if target.options then
+ for _, name in ipairs(utils.wrap(target.options)) do
+
+ -- get option if be enabled
+ local opt = nil
+ if config.get(name) then opt = config.get("__" .. name) end
+ if nil ~= opt then
+
+ -- add the flags from the option
+ table.join2(flags, linker._mapflags(module, opt[flagname]))
+
+ -- add the linkdirs flags from the option
+ if module.flag_linkdir then
+ for _, linkdir in ipairs(utils.wrap(opt.linkdirs)) do
+ table.join2(flags, module:flag_linkdir(linkdir))
+ end
+ end
+
+ -- add the links flags from the option
+ if module.flag_link then
+ for _, link in ipairs(utils.wrap(opt.links)) do
+ table.join2(flags, module:flag_link(link))
+ end
+ end
+ end
+ end
+ end
+
+ -- add the flags from the configure
+ table.join2(flags, linker._mapflags(module, config.get(flagname)))
+
+ -- add the strip flags from the current project
+ table.join2(flags, linker._getflags(module, target.strip, { debug = "-S"
+ , all = "-s"
+ }))
+end
+
+-- add flags from the option
+function linker._addflags_from_option(module, flags, flagname, opt)
+
+ -- check
+ assert(module and flags and flagname and opt)
+
+ -- append the option flags
+ table.join2(flags, linker._mapflags(module, opt[flagname]))
+
+ -- append the linkdirs flags
+ if opt.linkdirs and module.flag_linkdir then
+ for _, linkdir in ipairs(utils.wrap(opt.linkdirs)) do
+ table.join2(flags, module:flag_linkdir(linkdir))
+ end
+ end
+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, srcfiles, objfiles, targetfile, logfile)
+
+ -- check
+ assert(module and target)
+
+ -- the target kind
+ local kind = target.kind or ""
+
+ -- the flag name
+ local flagname = nil
+ if kind == "binary" then flagname = "ldflags"
+ elseif kind == "static" then flagname = "arflags"
+ elseif kind == "shared" then flagname = "shflags"
+ else
+ -- error
+ utils.error("unknown type for linker: %s", kind)
+ return
+ end
+
+ -- init flags
+ local flags = {}
+
+ -- add flags from the configure
+ linker._addflags_from_config(module, flags, flagname)
+
+ -- add flags from the target
+ linker._addflags_from_target(module, flags, flagname, target)
+
+ -- add flags from the platform
+ linker._addflags_from_platform(module, flags, flagname)
+
+ -- add flags from the compiler
+ linker._addflags_from_compiler(module, flags, flagname, srcfiles)
+
+ -- add flags from the linker
+ linker._addflags_from_linker(module, flags, flagname)
+
+ -- remove repeat
+ flags = utils.unique(flags)
+
+ -- make the link command
+ return module:command_link(table.concat(objfiles, " "), targetfile, table.concat(flags, " "):trim(), logfile)
+end
+
+-- check link for the project option
+function linker.check_links(opt, links, sourcefile, objectfile, targetfile)
+
+ -- check
+ assert(opt and links and objectfile and targetfile)
+
+ -- get the linker
+ local module = linker.get("binary")
+ assert(module and module.flag_link)
+
+ -- init flags
+ local flags = {}
+
+ -- add flags from the configure
+ linker._addflags_from_config(module, flags, "ldflags")
+
+ -- add flags from the option
+ linker._addflags_from_option(module, flags, "ldflags", opt)
+
+ -- add flags from the platform
+ linker._addflags_from_platform(module, flags, "ldflags")
+
+ -- add flags from the links
+ linker._addflags_from_links(module, flags, links)
+
+ -- add flags from the compiler
+ linker._addflags_from_compiler(module, flags, "ldflags", sourcefile)
+
+ -- add flags from the linker
+ linker._addflags_from_linker(module, flags, "ldflags")
+
+ -- remove repeat
+ flags = utils.unique(flags)
+
+ -- execute the link command
+ return module:main(module:command_link(objectfile, targetfile, table.concat(flags, " "):trim(), utils.ifelse(xmake._OPTIONS.verbose, nil, xmake._NULDEV)))
+end
+
+-- return module: linker
+return linker
diff --git a/xmake/core/base/main.lua b/xmake/core/base/main.lua
new file mode 100644
index 000000000..470815701
--- /dev/null
+++ b/xmake/core/base/main.lua
@@ -0,0 +1,179 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file main.lua
+--
+
+-- define module: main
+local main = main or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local option = require("base/option")
+local action = require("action/action")
+
+-- init the option menu
+local menu =
+{
+ -- title
+ title = xmake._VERSION .. ", The Automatic Cross-platform Build Tool"
+
+ -- copyright
+, copyright = "Copyright (C) 2015-2016 Ruki Wang, tboox.org\nCopyright (C) 2005-2014 Mike Pall, luajit.org"
+
+ -- build project: xmake
+, main =
+ {
+ -- usage
+ usage = "xmake [action] [options] [target]"
+
+ -- description
+ , description = "Build the project if no given action."
+
+ -- actions
+ , actions = action.list
+
+ -- options
+ , options =
+ {
+ {'b', "build", "k", nil, "Build project. This is default building mode and optional." }
+ , {'u', "update", "k", nil, "Only relink and update the binary files." }
+ , {'r', "rebuild", "k", nil, "Rebuild the project." }
+
+ , {}
+ , {'f', "file", "kv", "xmake.lua", "Read a given xmake.lua file." }
+ , {'P', "project", "kv", nil, "Change to the given project directory."
+ , "Search priority:"
+ , " 1. The Given Command Argument"
+ , " 2. The Envirnoment Variable: XMAKE_PROJECT_DIR"
+ , " 3. The Current Directory" }
+
+
+ , {}
+ , {'j', "jobs", "kv", nil, "Specifies the number of jobs to build simultaneously" }
+ , {'v', "verbose", "k", nil, "Print lots of verbose information." }
+ , {nil, "version", "k", nil, "Print the version number and exit." }
+ , {'h', "help", "k", nil, "Print this help message and exit." }
+
+ , {}
+ , {nil, "target", "v", "all", "Build the given target." }
+ }
+ }
+
+ -- the actions: xmake [action]
+, action.menu
+
+}
+
+-- done help
+function main._done_help()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- done help
+ if options.help then
+
+ -- print menu
+ option.print_menu(options._ACTION)
+
+ -- ok
+ return true
+
+ -- done version
+ elseif options.version then
+
+ -- print title
+ if option._MENU.title then
+ print(option._MENU.title)
+ end
+
+ -- print copyright
+ if option._MENU.copyright then
+ print(option._MENU.copyright)
+ end
+
+ -- ok
+ return true
+ end
+end
+
+-- done option
+function main._done_option()
+
+ -- the options
+ local options = xmake._OPTIONS
+ assert(options)
+
+ -- done help?
+ if main._done_help() then
+ return true
+ end
+
+ -- done action
+ return action.done(options._ACTION or "build")
+end
+
+-- the init function for main
+function main._init()
+
+ -- init the project directory
+ local projectdir = option.find(xmake._ARGV, "project", "P") or xmake._PROJECT_DIR
+ if projectdir and not path.is_absolute(projectdir) then
+ projectdir = path.absolute(projectdir)
+ elseif projectdir then
+ projectdir = path.translate(projectdir)
+ end
+ xmake._PROJECT_DIR = projectdir
+ assert(projectdir)
+
+ -- init the xmake.lua file path
+ local projectfile = option.find(xmake._ARGV, "file", "f") or xmake._PROJECT_FILE
+ if projectfile and not path.is_absolute(projectfile) then
+ projectfile = path.absolute(projectfile, projectdir)
+ end
+ xmake._PROJECT_FILE = projectfile
+ assert(projectfile)
+end
+
+-- the main function
+function main.done()
+
+ -- init
+ main._init()
+
+ -- init option
+ if not option.init(xmake._ARGV, menu) then
+ return -1
+ end
+
+ -- done option
+ if not main._done_option() then
+ return -1
+ end
+
+ -- ok
+ return 0
+end
+
+-- return module: main
+return main
diff --git a/xmake/core/base/makefile.lua b/xmake/core/base/makefile.lua
new file mode 100644
index 000000000..826310d1a
--- /dev/null
+++ b/xmake/core/base/makefile.lua
@@ -0,0 +1,417 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file makefile.lua
+--
+
+-- define module: makefile
+local makefile = makefile or {}
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local rule = require("base/rule")
+local path = require("base/path")
+local utils = require("base/utils")
+local config = require("base/config")
+local project = require("base/project")
+local linker = require("base/linker")
+local compiler = require("base/compiler")
+local tools = require("tools/tools")
+local platform = require("platform/platform")
+
+-- make object for the *.[o|obj] source file
+function makefile._make_object_for_object(file, target, srcfile, objfile)
+
+ -- get the source file type
+ local filetype = path.extension(srcfile)
+ if not filetype then return false end
+
+ -- get the lower file type
+ filetype = filetype:lower()
+
+ -- not object file?
+ if filetype ~= ".o" and filetype ~= ".obj" then return false end
+
+ -- get mode
+ local mode = config.get("mode")
+ if mode then
+ mode = "." .. mode
+ else
+ mode = ""
+ end
+
+ -- make command
+ local cmd = string.format("xmake l cp %s %s", srcfile, objfile)
+
+ -- make head
+ file:write(string.format("%s:", objfile))
+
+ -- make dependence
+ file:write(string.format(" %s\n", srcfile))
+
+ -- make body
+ file:write(string.format("\t@echo inserting%s %s\n", mode, srcfile))
+ file:write(string.format("\t@xmake l $(VERBOSE) verbose \"%s\"\n", cmd:encode()))
+ file:write(string.format("\t@%s\n", cmd))
+
+ -- make tail
+ file:write("\n")
+
+ -- ok
+ return true
+end
+
+-- make object for the *.[a|lib] source file
+function makefile._make_object_for_static(file, target, srcfile, objfile)
+
+ -- get the source file type
+ local filetype = path.extension(srcfile)
+ if not filetype then return false end
+
+ -- get the lower file type
+ filetype = filetype:lower()
+
+ -- not static file?
+ if filetype ~= ".a" and filetype ~= ".lib" then return false end
+
+ -- get mode
+ local mode = config.get("mode")
+ if mode then
+ mode = "." .. mode
+ else
+ mode = ""
+ end
+
+ -- make command
+ local cmd = string.format("xmake l -P %s -f %s dispatcher ex extract %s %s > %s 2>&1", xmake._PROJECT_DIR, xmake._PROJECT_FILE, srcfile:encode(), objfile:encode(), makefile._LOGFILE)
+
+ -- make head
+ file:write(string.format("%s:", objfile))
+
+ -- make dependence
+ file:write(string.format(" %s\n", srcfile))
+
+ -- make body
+ file:write(string.format("\t@echo inserting%s %s\n", mode, srcfile))
+ file:write(string.format("\t@xmake l $(VERBOSE) verbose \"%s\"\n", cmd:encode()))
+ file:write(string.format("\t@xmake l rmdir %s\n", path.directory(objfile)))
+ file:write(string.format("\t@%s\n", cmd))
+
+ -- make tail
+ file:write("\n")
+
+ -- ok
+ return true
+end
+
+-- make the object to the makefile
+function makefile._make_object(file, target, srcfile, objfile)
+
+ -- check
+ assert(file and target and srcfile and objfile)
+
+ -- make object for the *.o/obj source file
+ if makefile._make_object_for_object(file, target, srcfile, objfile) then
+ return true
+ elseif makefile._make_object_for_static(file, target, srcfile, objfile) then
+ return true
+ end
+
+ -- get the compiler
+ local c, errors = compiler.get(srcfile)
+ if not c then
+ -- error
+ utils.error(errors)
+ return false
+ end
+
+ -- get mode
+ local mode = config.get("mode")
+ if mode then
+ mode = "." .. mode
+ else
+ mode = ""
+ end
+
+ -- get ccache
+ local ccache = platform.tool("ccache")
+
+ -- make command
+ local cmd = compiler.make(c, target, srcfile, objfile, makefile._LOGFILE)
+ if ccache then
+ cmd = ccache:append(cmd, " ")
+ end
+
+ -- make head
+ file:write(string.format("%s:", objfile))
+
+ -- make dependence
+ file:write(string.format(" %s\n", srcfile))
+
+ -- make body
+ file:write(string.format("\t@echo %scompiling%s %s\n", utils.ifelse(ccache, "ccache ", ""), mode, srcfile))
+ file:write(string.format("\t@xmake l $(VERBOSE) verbose \"%s\"\n", cmd:encode()))
+ file:write(string.format("\t@xmake l mkdir %s\n", path.directory(objfile)))
+ file:write(string.format("\t@%s\n", cmd))
+
+ -- make tail
+ file:write("\n")
+
+ -- ok
+ return true
+end
+
+-- make all objects of the given target to the makefile
+function makefile._make_objects(file, target, srcfiles, objfiles)
+
+ -- check
+ assert(file and target and srcfiles and objfiles)
+
+ -- make all objects
+ local i = 1
+ for _, objfile in ipairs(objfiles) do
+
+ -- make object
+ if not makefile._make_object(file, target, srcfiles[i], objfile) then
+ return false
+ end
+
+ -- next
+ i = i + 1
+ end
+
+ -- ok
+ return true
+end
+
+-- make the given target to the makefile
+function makefile._make_target(file, name, target)
+
+ -- check
+ assert(file and name and target and target.kind)
+
+ -- get source and object files
+ local srcfiles = rule.sourcefiles(target)
+ local objfiles = rule.objectfiles(name, target, srcfiles)
+ assert(srcfiles and objfiles)
+
+ -- get source and destinate header files
+ local srcheaders, dstheaders = rule.headerfiles(target)
+
+ -- get target file
+ local targetfile = rule.targetfile(name, target)
+ assert(targetfile)
+
+ -- get the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- get the linker from the given kind
+ local l = linker.get(target.kind)
+ if not l then
+ utils.error("cannot get linker with kind: %s", target.kind)
+ return false
+ end
+
+ -- make head
+ file:write(string.format("%s: %s\n", name, targetfile))
+ file:write(string.format("%s:", targetfile))
+
+ -- make dependence for the dependent targets
+ if target.deps then
+
+ -- get all dependent target
+ local deps = utils.wrap(target.deps)
+ for _, dep in ipairs(deps) do
+
+ -- the dependent target
+ local deptarget = targets[dep]
+ if not deptarget then
+ utils.error("the dependent target: %s is invalid!", dep)
+ return false
+ end
+
+ -- get the dependent target file
+ local depfile = rule.targetfile(dep, deptarget)
+ assert(depfile)
+
+ -- add dependence
+ file:write(" " .. depfile)
+ end
+ end
+
+ -- make dependence for objects
+ for _, objfile in ipairs(objfiles) do
+ file:write(" " .. objfile)
+ end
+
+ -- make dependence end
+ file:write("\n")
+
+ -- get mode
+ local mode = config.get("mode")
+ if mode then
+ mode = "." .. mode
+ else
+ mode = ""
+ end
+
+ -- make the command
+ local cmd = linker.make(l, target, srcfiles, objfiles, targetfile, makefile._LOGFILE)
+
+ -- the verbose
+ local verbose = cmd:encode()
+ -- too long?
+ if verbose and #verbose > 256 then
+ verbose = linker.make(l, target, srcfiles, {rule.filename("*", "object")}, targetfile)
+ verbose = verbose:encode()
+ end
+
+ -- make body
+ file:write(string.format("\t@echo linking%s %s\n", mode, path.filename(targetfile)))
+ file:write(string.format("\t@xmake l $(VERBOSE) verbose \"%s\"\n", verbose))
+ file:write(string.format("\t@xmake l mkdir %s\n", path.directory(targetfile)))
+ file:write(string.format("\t@%s\n", cmd))
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ file:write(string.format("\t@xmake l cp %s %s\n", srcheader, dstheader))
+ end
+ i = i + 1
+ end
+ end
+
+ -- make tail
+ file:write("\n")
+
+ -- make objects for this target
+ return makefile._make_objects(file, target, srcfiles, objfiles)
+end
+
+-- make all targets to the makefile
+function makefile._make_targets(file)
+
+ -- check
+ assert(file)
+
+ -- get all project targets
+ local targets = project.targets()
+ if not targets then
+ -- error
+ utils.error("not found target in this project!")
+ return false
+ end
+
+ -- make all first
+ local all = ""
+ for name, _ in pairs(targets) do
+ -- append the target name to all
+ all = all .. " " .. name
+ end
+ file:write(string.format("all: %s\n\n", all))
+ file:write(string.format(".PHONY: all %s\n\n", all))
+
+ -- make it for all targets
+ for name, target in pairs(targets) do
+ -- make target
+ if not makefile._make_target(file, name, target) then
+ -- error
+ utils.error("failed to make target %s to makefile!", name)
+ return false
+ end
+
+ -- append the target name to all
+ all = all .. " " .. name
+ end
+
+ -- ok
+ return true
+end
+
+-- make makefile in the build directory
+function makefile.make()
+
+ -- get the build directory
+ local buildir = config.get("buildir")
+ assert(buildir)
+
+ -- init the log file
+ local logfile = rule.logfile()
+ if logfile and os.isfile(logfile) then
+ os.rmfile(logfile)
+ end
+
+ -- save the log file
+ makefile._LOGFILE = logfile
+ assert(logfile)
+
+ -- open the makefile
+ local path = rule.makefile()
+ local file = io.openmk(path)
+ if not file then
+ -- error
+ utils.error("open %s failed!", path)
+ return false
+ end
+
+ -- make all targets to the makefile
+ if not makefile._make_targets(file) then
+
+ -- error
+ utils.error("save %s failed!", path)
+
+ -- close the makefile
+ file:close()
+
+ -- remove the makefile
+ os.rm(path)
+
+ -- failed
+ return false
+ end
+
+ -- close the makefile
+ file:close()
+
+ -- ok
+ return true
+end
+
+-- build target
+function makefile.build(target)
+
+ -- check
+ assert(target and type(target) == "string")
+
+ -- load make
+ local make = tools.get("make")
+ if not make then
+ utils.error("not found the make command!")
+ return false
+ end
+
+ -- done make
+ return make:main(rule.makefile(), target)
+end
+
+-- return module: makefile
+return makefile
diff --git a/xmake/core/base/option.lua b/xmake/core/base/option.lua
new file mode 100644
index 000000000..1c8c35573
--- /dev/null
+++ b/xmake/core/base/option.lua
@@ -0,0 +1,650 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file option.lua
+--
+
+-- define module: option
+local option = option or {}
+
+-- load modules
+local utils = require("base/utils")
+local table = require("base/table")
+
+-- save the option menu
+function option._save_menu(menu)
+
+ -- translate the action menus if exists function
+ local submenus_all = {}
+ for k, submenu in pairs(menu) do
+ if type(submenu) == "function" then
+ local _submenus = submenu()
+ if _submenus then
+ for k, m in pairs(_submenus) do
+ submenus_all[k] = m
+ end
+ end
+ else
+ submenus_all[k] = submenu
+ end
+ end
+ table.copy2(menu, submenus_all)
+
+ -- translate the actions of the main menu if exists function
+ if menu.main and type(menu.main.actions) == "function" then
+ menu.main.actions = menu.main.actions()
+ end
+
+ -- translate it if exists function in the option menu
+ for _, submenu in pairs(menu) do
+
+ -- exits options?
+ if submenu.options then
+
+ -- translate options
+ local options_all = {}
+ for _, option in ipairs(submenu.options) do
+
+ -- this option is function? translate it
+ if type(option) == "function" then
+ local _options = option()
+ if _options then
+ for _, o in ipairs(_options) do
+ table.insert(options_all, o)
+ end
+ end
+ else
+ table.insert(options_all, option)
+ end
+ end
+
+ -- update the options
+ submenu.options = options_all
+ end
+ end
+
+ -- save menu
+ option._MENU = menu
+
+end
+
+-- init the option
+function option.init(argv, menu)
+
+ -- check
+ assert(argv and menu)
+
+ -- the main menu
+ local main = menu.main
+ assert(main)
+
+ -- init _OPTIONS
+ xmake._OPTIONS = {}
+ xmake._OPTIONS._DEFAULTS = {}
+
+ -- save menu
+ option._save_menu(menu)
+
+ -- parse _ARGV to _OPTIONS
+ local _iter, _s, _k = ipairs(argv)
+ while true do
+
+ -- the idx and arg
+ local idx, arg = _iter(_s, _k)
+
+ -- end?
+ _k = idx
+ if idx == nil then break end
+
+ -- parse key and value
+ local key, value
+ local i = arg:find("=", 1, true)
+
+ -- key=value?
+ if i then
+ key = arg:sub(1, i - 1)
+ value = arg:sub(i + 1)
+ -- only key?
+ else
+ key = arg
+ value = true
+ end
+
+ -- --key?
+ local prefix = 0
+ if key:startswith("--") then
+ key = key:sub(3)
+ prefix = 2
+ -- -k?
+ elseif key:startswith("-") then
+ key = key:sub(2)
+ prefix = 1
+ end
+
+ -- check key
+ if prefix and #key == 0 then
+
+ -- invalid option
+ print("invalid option: " .. arg)
+
+ -- print menu
+ option.print_menu(xmake._OPTIONS._ACTION)
+
+ -- failed
+ return false
+ end
+
+ -- --key=value or -k value or -k?
+ if prefix ~= 0 then
+
+ -- find this option
+ local opt = nil
+ for _, o in ipairs(menu[xmake._OPTIONS._ACTION or "main"].options) do
+
+ -- check
+ assert(o)
+
+ -- --key?
+ if prefix == 2 and key == o[2] then
+ opt = o
+ break
+ -- k?
+ elseif prefix == 1 and key == o[1] then
+ opt = o
+ break
+ end
+ end
+
+ -- not found?
+ if not opt then
+
+ -- invalid option
+ print("invalid option: " .. arg)
+
+ -- print menu
+ option.print_menu(xmake._OPTIONS._ACTION)
+
+ -- failed
+ return false
+ end
+
+ -- -k value? continue to get the value
+ if prefix == 1 and opt[3] == "kv" then
+
+ -- get the next idx and arg
+ idx, arg = _iter(_s, _k)
+
+ -- exists value?
+ _k = idx
+ if idx == nil or arg:startswith("-") then
+
+ -- invalid option
+ print("invalid option: " .. utils.ifelse(idx, arg, key))
+
+ -- print menu
+ option.print_menu(xmake._OPTIONS._ACTION)
+
+ -- failed
+ return false
+ end
+
+ -- get value
+ value = arg
+ end
+
+ -- check mode
+ if (opt[3] == "k" and type(value) ~= "boolean") or (opt[3] == "kv" and type(value) ~= "string") then
+
+ -- invalid option
+ print("invalid option: " .. arg)
+
+ -- print menu
+ option.print_menu(xmake._OPTIONS._ACTION)
+
+ -- failed
+ return false
+ end
+
+ -- value is "true" or "false", translate it
+ if type(value) == "string" then
+ if value == "true" then value = true
+ elseif value == "false" then value = false
+ end
+ end
+
+ -- save option
+ xmake._OPTIONS[utils.ifelse(prefix == 1 and opt[2], opt[2], key)] = value
+
+ -- action?
+ elseif idx == 1 then
+
+ -- find this action
+ for _, action in ipairs(main.actions) do
+
+ -- check
+ assert(menu[action])
+
+ -- ok?
+ if action == key or menu[action].shortname == key then
+ -- save this action
+ xmake._OPTIONS._ACTION = action
+ break
+ end
+ end
+
+ -- not found?
+ if not xmake._OPTIONS._ACTION or not menu[xmake._OPTIONS._ACTION] then
+
+ -- invalid action
+ print("invalid action: " .. key)
+
+ -- print the main menu
+ option.print_main()
+
+ -- failed
+ return false
+
+ end
+
+ -- value?
+ else
+
+ -- find a value option with name
+ local opt = nil
+ for _, o in ipairs(menu[xmake._OPTIONS._ACTION or "main"].options) do
+
+ -- the mode
+ local mode = o[3]
+
+ -- the name
+ local name = o[2]
+
+ -- check
+ assert(o and ((mode ~= "v" and mode ~= "vs") or name))
+
+ -- is value and with name?
+ if mode == "v" and name and not xmake._OPTIONS[name] then
+ opt = o
+ break
+ -- is values and with name?
+ elseif mode == "vs" and name then
+ opt = o
+ break
+ end
+ end
+
+ -- ok? save this value with name opt[2]
+ if opt then
+
+ -- the mode
+ local mode = opt[3]
+
+ -- the name
+ local name = opt[2]
+
+ -- save value
+ if mode == "v" then
+ xmake._OPTIONS[name] = key
+ elseif mode == "vs" then
+ -- the option
+ local o = xmake._OPTIONS[name]
+ if not o then
+ xmake._OPTIONS[name] = {}
+ o = xmake._OPTIONS[name]
+ end
+
+ -- append value
+ table.insert(o, key)
+ end
+ else
+ -- invalid option
+ print("invalid option: " .. arg)
+
+ -- print menu
+ option.print_menu(xmake._OPTIONS._ACTION)
+
+ -- failed
+ return false
+ end
+
+ end
+ end
+
+ -- init the default value
+ for _, o in ipairs(menu[xmake._OPTIONS._ACTION or "main"].options) do
+
+ -- key=value?
+ if o[3] == "kv" then
+
+ -- the key
+ local key = o[2] or o[1]
+ assert(key)
+
+ -- save the default value
+ xmake._OPTIONS._DEFAULTS[key] = o[4]
+ -- value with name?
+ elseif o[3] == "v" and o[2] then
+ -- save the default value
+ xmake._OPTIONS._DEFAULTS[o[2]] = o[4]
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- find the value of a given name from the arguments
+-- only for kv mode and need not check it using menu
+--
+function option.find(argv, name, shortname)
+
+ -- check
+ assert(argv and (name or shortname))
+
+ -- find it
+ local nextvalue = false
+ for _, arg in ipairs(argv) do
+
+ -- get this value
+ if nextvalue then return arg end
+
+ -- --name=value?
+ if name and arg:startswith("--" .. name) then
+
+ -- get value
+ local i = arg:find("=", 1, true)
+ if i then return arg:sub(i + 1) end
+
+ -- -shortname value?
+ elseif shortname and arg:startswith("-" .. shortname) then
+
+ -- get value
+ nextvalue = true
+ end
+
+ end
+end
+
+-- get all default options from the given action
+function option.defaults(action)
+
+ -- make defaults
+ local defaults = {}
+
+ -- init the default value
+ for _, o in ipairs(option._MENU[action or "main"].options) do
+
+ -- key=value?
+ if o[3] == "kv" then
+
+ -- the key
+ local key = o[2] or o[1]
+ assert(key)
+
+ -- save the default value
+ defaults[key] = o[4]
+ -- value with name?
+ elseif o[3] == "v" and o[2] then
+ -- save the default value
+ defaults[o[2]] = o[4]
+ end
+ end
+
+ -- ok?
+ return defaults
+end
+
+-- print the menu
+function option.print_menu(action)
+
+ -- no action? print main menu
+ if not action then
+ option.print_main()
+ return
+ end
+
+ -- the menu
+ local menu = option._MENU
+ assert(menu)
+
+ -- the action
+ action = menu[action]
+ assert(action)
+
+ -- print title
+ if menu.title then
+ print(menu.title)
+ end
+
+ -- print copyright
+ if menu.copyright then
+ print(menu.copyright)
+ end
+
+ -- print usage
+ if action.usage then
+ print("")
+ print("Usage: " .. action.usage)
+ end
+
+ -- print description
+ if action.description then
+ print("")
+ print(action.description)
+ end
+
+ -- print options
+ if action.options then
+ option.print_options(action.options)
+ end
+end
+
+-- print the main menu
+function option.print_main()
+
+ -- the menu
+ local menu = option._MENU
+ assert(menu)
+
+ -- the main menu
+ local main = menu.main
+ assert(main)
+
+ -- print title
+ if menu.title then
+ print(menu.title)
+ end
+
+ -- print copyright
+ if menu.copyright then
+ print(menu.copyright)
+ end
+
+ -- print usage
+ if main.usage then
+ print("")
+ print("Usage: " .. main.usage)
+ end
+
+ -- print description
+ if main.description then
+ print("")
+ print(main.description)
+ end
+
+ -- print actions
+ if main.actions then
+
+ -- print header
+ print("")
+ print("Actions: ")
+
+ -- the padding spaces
+ local padding = 42
+
+ -- print actions
+ for _, action in ipairs(main.actions) do
+
+ -- the action menu
+ local action_menu = menu[action]
+
+ -- init the action info
+ local action_info = " "
+ if action_menu and action_menu.shortname then
+ action_info = action_info .. action_menu.shortname .. ", "
+ else
+ action_info = action_info .. " "
+ end
+
+ -- append the action
+ action_info = action_info .. action
+
+ if action_menu then
+ -- append spaces
+ for i = (#action_info), padding do
+ action_info = action_info .. " "
+ end
+
+ -- append the action description
+ if action_menu.description then
+ action_info = action_info .. action_menu.description
+ end
+ end
+
+ -- print action info
+ print(action_info)
+ end
+ end
+
+ -- print options
+ if main.options then
+ option.print_options(main.options)
+ end
+end
+
+-- print the options menu
+function option.print_options(options)
+
+ -- check
+ assert(options)
+
+ -- print header
+ print("")
+ print("Options: ")
+
+ -- the padding spaces
+ local padding = 42
+
+ -- print options
+ for _, option in ipairs(options) do
+
+ -- init the option info
+ local option_info = ""
+
+ -- append the shortname
+ local shortname = option[1];
+ local name = option[2];
+ local mode = option[3];
+ if shortname then
+ option_info = option_info .. " -" .. shortname
+ if mode == "kv" then
+ option_info = option_info .. " " .. utils.ifelse(name, name:upper(), "XXX")
+ end
+ end
+
+ -- append the name
+ if name then
+ if mode == "v" then
+ option_info = option_info .. " " .. name
+ else
+ option_info = option_info .. utils.ifelse(shortname, ", --", " --") .. name
+ end
+ if mode == "kv" then
+ option_info = option_info .. "=" .. name:upper()
+ end
+ elseif mode == "v" then
+ option_info = option_info .. " ..."
+ end
+
+ -- append spaces
+ for i = (#option_info), padding do
+ option_info = option_info .. " "
+ end
+
+ -- append the option description
+ local description = option[5]
+ if description then
+ option_info = option_info .. description
+ end
+
+ -- append the default value
+ local default = option[4]
+ if default then
+ option_info = option_info .. " (default: " .. tostring(default) .. ")"
+ end
+
+ -- print option info
+ print(option_info)
+
+ -- print more description if exists
+ for i = 6, 64 do
+
+ -- the description, @note some option may be nil
+ local description = option[i]
+ if not description then break end
+
+ -- is function? get results
+ if type(description) == "function" then
+ description = description()
+ end
+
+ -- the description is string?
+ if type(description) == "string" then
+
+ -- make spaces
+ local spaces = ""
+ for i = 0, padding do
+ spaces = spaces .. " "
+ end
+
+ -- print this description
+ print(spaces .. description)
+
+ -- the description is table?
+ elseif type(description) == "table" then
+
+ -- print all descriptions
+ for _, v in pairs(description) do
+
+ -- make spaces
+ local spaces = ""
+ for i = 0, padding do
+ spaces = spaces .. " "
+ end
+
+ -- print this description
+ print(spaces .. v)
+ end
+ end
+ end
+ end
+end
+
+-- return module: option
+return option
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
new file mode 100644
index 000000000..b08ac3820
--- /dev/null
+++ b/xmake/core/base/os.lua
@@ -0,0 +1,237 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file os.lua
+--
+
+-- define module: os
+local os = os or {}
+
+-- load modules
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+
+-- match files or directories
+--
+-- @param pattern the search pattern
+-- uses "*" to match any part of a file or directory name,
+-- uses "**" to recurse into subdirectories.
+--
+-- @param findir true: find directory, false: find file
+-- @return the result array and count
+--
+-- @code
+-- local dirs, count = os.match("./src/*", true)
+-- local files, count = os.match("./src/**.c")
+-- local file = os.match("./src/test.c")
+-- @endcode
+--
+function os.match(pattern, findir)
+
+ -- get the excludes
+ local excludes = pattern:match("|.*$")
+ if excludes then excludes = excludes:split("|") end
+
+ -- translate excludes
+ if excludes then
+ local _excludes = {}
+ for _, exclude in ipairs(excludes) do
+ exclude = path.translate(exclude)
+ exclude = exclude:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
+ exclude = exclude:gsub("%*%*", "\001")
+ exclude = exclude:gsub("%*", "\002")
+ exclude = exclude:gsub("\001", ".*")
+ exclude = exclude:gsub("\002", "[^/]*")
+ table.insert(_excludes, exclude)
+ end
+ excludes = _excludes
+ end
+
+ -- translate path and remove some repeat separators
+ pattern = path.translate(pattern:gsub("|.*$", ""))
+
+ -- get the root directory
+ local rootdir = pattern
+ local starpos = pattern:find("%*")
+ if starpos then
+ rootdir = rootdir:sub(1, starpos - 1)
+ end
+ rootdir = path.directory(rootdir)
+
+ -- is recurse?
+ local recurse = pattern:find("**", nil, true)
+
+ -- convert pattern to a lua pattern
+ pattern = pattern:gsub("([%+%.%-%^%$%(%)%%])", "%%%1")
+ pattern = pattern:gsub("%*%*", "\001")
+ pattern = pattern:gsub("%*", "\002")
+ pattern = pattern:gsub("\001", ".*")
+ pattern = pattern:gsub("\002", "[^/]*")
+
+ -- patch "./" for matching ok if root directory is '.'
+ if rootdir == '.' then
+ pattern = "./" .. pattern
+ end
+
+ -- find it
+ return os.find(rootdir, pattern, recurse, findir, excludes)
+end
+
+-- copy file or directory
+function os.cp(src, dst)
+
+ -- check
+ assert(src and dst)
+
+ -- is file?
+ if os.isfile(src) then
+
+ -- the destination is directory? append the filename
+ if os.isdir(dst) then
+ dst = string.format("%s/%s", dst, path.filename(src))
+ end
+
+ -- copy file
+ if not os.cpfile(src, dst) then
+ return false, string.format("cannot copy file %s to %s %s", src, dst, os.strerror())
+ end
+ -- is directory?
+ elseif os.isdir(src) then
+ -- copy directory
+ if not os.cpdir(src, dst) then
+ return false, string.format("cannot copy directory %s to %s %s", src, dst, os.strerror())
+ end
+ -- cp dir/*?
+ elseif src:find("%*") then
+
+ -- get the root directory
+ local starpos = src:find("%*")
+
+ -- match all files
+ local files = os.match((src:gsub("%*+", "**")))
+ if files then
+ for _, file in ipairs(files) do
+ local dstfile = string.format("%s/%s", dst, file:sub(starpos))
+ if not os.cpfile(file, dstfile) then
+ return false, string.format("cannot copy file %s to %s %s", file, dstfile, os.strerror())
+ end
+ end
+ end
+
+ -- not exists?
+ else
+ return false, string.format("cannot copy file %s, not found this file %s", src, os.strerror())
+ end
+
+ -- ok
+ return true
+end
+
+-- move file or directory
+function os.mv(src, dst)
+
+ -- check
+ assert(src and dst)
+
+ -- exists file or directory?
+ if os.exists(src) then
+ -- move file or directory
+ if not os.rename(src, dst) then
+ return false, string.format("cannot move %s to %s %s", src, dst, os.strerror())
+ end
+ -- not exists?
+ else
+ return false, string.format("cannot move %s to %s, not found this file %s", src, dst, os.strerror())
+ end
+
+ -- ok
+ return true
+end
+
+-- remove file or directory
+function os.rm(file_or_dir, emptydir)
+
+ -- check
+ assert(file_or_dir)
+
+ -- is file?
+ if os.isfile(file_or_dir) then
+ -- remove file
+ if not os.rmfile(file_or_dir) then
+ return false, string.format("cannot remove file %s %s", file_or_dir, os.strerror())
+ end
+ -- is directory?
+ elseif os.isdir(file_or_dir) then
+ -- remove directory
+ if not os.rmdir(file_or_dir, emptydir) then
+ return false, string.format("cannot remove directory %s %s", file_or_dir, os.strerror())
+ end
+ -- not exists?
+ else
+ return false, string.format("cannot remove file %s, not found this file %s", file_or_dir, os.strerror())
+ end
+
+ -- ok
+ return true
+end
+
+-- change to directory
+function os.cd(dir)
+
+ -- check
+ assert(dir)
+
+ -- change to the previous directory?
+ if dir == "-" then
+ -- exists the previous directory?
+ if os._PREDIR then
+ dir = os._PREDIR
+ os._PREDIR = nil
+ else
+ -- error
+ return false, string.format("not found the previous directory %s", os.strerror())
+ end
+ end
+
+ -- is directory?
+ if os.isdir(dir) then
+
+ -- get the current directory
+ local current = os.curdir()
+
+ -- change to directory
+ if not os.chdir(dir) then
+ return false, string.format("cannot change directory %s %s", dir, os.strerror())
+ end
+
+ -- save the previous directory
+ os._PREDIR = current
+
+ -- not exists?
+ else
+ return false, string.format("cannot change directory %s, not found this directory %s", dir, os.strerror())
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: os
+return os
diff --git a/xmake/core/base/package.lua b/xmake/core/base/package.lua
new file mode 100644
index 000000000..ffb1a0d38
--- /dev/null
+++ b/xmake/core/base/package.lua
@@ -0,0 +1,314 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file package.lua
+--
+
+-- define module: package
+local package = package 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 config = require("base/config")
+local platform = require("platform/platform")
+
+-- package target for the library file
+function package._done_library(target)
+
+ -- check
+ assert(target and target.name and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir
+ assert(outputdir)
+
+ -- the plat and mode
+ local plat = config.get("plat")
+ local mode = config.get("mode")
+ assert(plat and mode)
+
+ -- package it
+ for arch, info in pairs(target.archs) do
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- copy the library file to the output directory
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), string.format("%s/%s.pkg/lib/%s/%s/%s/%s", outputdir, target.name, mode, plat, arch, path.filename(info.targetfile)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- copy the config.h to the output directory
+ if info.config_h then
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.config_h), string.format("%s/%s.pkg/inc/%s/%s", outputdir, target.name, plat, path.filename(info.config_h)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ end
+
+ -- copy headers
+ if target.headers then
+ local srcheaders, dstheaders = rule.headerfiles(target, string.format("%s/%s.pkg/inc", outputdir, target.name))
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ local ok, errors = os.cp(srcheader, dstheader)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ i = i + 1
+ end
+ end
+ end
+
+ -- make xmake.lua
+ local file = io.open(string.format("%s/%s.pkg/xmake.lua", outputdir, target.name), "w")
+ if file then
+
+ -- the xmake.lua template content
+ local template = [[
+-- add [targetname] package
+add_option("[targetname]")
+
+ -- show menu
+ set_option_showmenu(true)
+
+ -- set category
+ set_option_category("package")
+
+ -- set description
+ set_option_description("The [targetname] package")
+
+ -- set language: c99, c++11
+ set_option_languages("c99", "cxx11")
+
+ -- add defines to config.h if checking ok
+ add_option_defines_h_if_ok("$(prefix)_PACKAGE_HAVE_[TARGETNAME]")
+
+ -- add links for checking
+ add_option_links("[targetname]")
+
+ -- add link directories
+ add_option_linkdirs("lib/$(mode)/$(plat)/$(arch)")
+
+ -- add c includes for checking
+ add_option_cincludes("[targetname]/[targetname].h")
+
+ -- add include directories
+ add_option_includedirs("inc/$(plat)", "inc")
+]]
+
+ -- save file
+ file:write((template:gsub("%[targetname%]", target.name):gsub("%[TARGETNAME%]", target.name:upper())))
+
+ -- exit file
+ file:close()
+ end
+
+ -- ok
+ return 1
+end
+
+-- package target for the binary file
+function package._done_binary(target)
+
+ -- check
+ assert(target and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir
+ assert(outputdir)
+
+ -- the count of architectures
+ local count = 0
+ for _, _ in pairs(target.archs) do count = count + 1 end
+
+ -- package it
+ local ok = nil
+ local errors = nil
+ for arch, info in pairs(target.archs) do
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- copy the binary file to the output directory
+ if count == 1 then
+ ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), string.format("%s/%s", outputdir, path.filename(info.targetfile)))
+ else
+ ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), string.format("%s/%s", outputdir, rule.filename(path.basename(info.targetfile) .. "_" .. arch, "binary")))
+ end
+
+ -- ok?
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+
+ -- ok
+ return 1
+end
+
+-- package target from the default script
+function package._done_from_default(target)
+
+ -- check
+ assert(target.kind)
+
+ -- the package scripts
+ local packagescripts =
+ {
+ static = package._done_library
+ , shared = package._done_library
+ , binary = package._done_binary
+ }
+
+ -- package it
+ local packagescript = packagescripts[target.kind]
+ if packagescript then return packagescript(target) end
+
+ -- continue
+ return 0
+end
+
+-- package target from the project script
+function package._done_from_project(target)
+
+ -- check
+ assert(target)
+
+ -- package it using the project script first
+ local packagescript = target.packagescript
+ if type(packagescript) == "function" then
+
+ -- remove it
+ target.packagescript = nil
+
+ -- package it
+ return packagescript(target)
+ end
+
+ -- continue
+ return 0
+end
+
+-- package target from the platform script
+function package._done_from_platform(target)
+
+ -- check
+ assert(target)
+
+ -- the platform package script file
+ local packagescript = nil
+ local scriptfile = platform.directory() .. "/package.lua"
+ if os.isfile(scriptfile) then
+
+ -- load the package script
+ local script, errors = loadfile(scriptfile)
+ if script then
+ packagescript = script()
+ if type(packagescript) == "table" and packagescript.main then
+ packagescript = packagescript.main
+ end
+ else
+ utils.error(errors)
+ end
+ end
+
+ -- package it
+ if type(packagescript) == "function" then
+ return packagescript(target)
+ end
+
+ -- continue
+ return 0
+end
+
+-- get the configure file
+function package._file()
+
+ -- get it
+ return config.directory() .. "/package.conf"
+end
+
+-- package target from the given target configure
+function package._done(target)
+
+ -- check
+ assert(target)
+
+ -- package it from the project script
+ local ok = package._done_from_project(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- package it from the platform script
+ local ok = package._done_from_platform(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- package it from the default script
+ local ok = package._done_from_default(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- ok
+ return true
+end
+
+-- done package from the configure
+function package.done(configs)
+
+ -- check
+ assert(configs)
+
+ -- package targets
+ for _, target in pairs(configs) do
+
+ -- package it
+ if not package._done(target) then
+ -- errors
+ utils.error("package %s failed!", target.name)
+ return false
+ end
+
+ end
+
+ -- save to the configure file
+ return io.save(package._file(), configs)
+end
+
+-- load the package configure
+function package.load()
+
+ -- load it
+ return io.load(package._file())
+end
+
+-- return module: package
+return package
diff --git a/xmake/core/base/path.lua b/xmake/core/base/path.lua
new file mode 100644
index 000000000..eb35283b2
--- /dev/null
+++ b/xmake/core/base/path.lua
@@ -0,0 +1,72 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file path.lua
+--
+
+-- define module: path
+local path = path or {}
+
+-- load modules
+local string = require("base/string")
+
+-- get the directory of the path
+function path.directory(p)
+ local i = p:find_last("[/\\]")
+ if i then
+ if i > 1 then i = i - 1 end
+ return p:sub(1, i)
+ else
+ return "."
+ end
+end
+
+-- get the filename of the path
+function path.filename(p)
+ local i = p:find_last("[/\\]")
+ if i then
+ return p:sub(i + 1)
+ else
+ return p
+ end
+end
+
+-- get the basename of the path
+function path.basename(p)
+ local name = path.filename(p)
+ local i = name:find_last(".", true)
+ if i then
+ return name:sub(1, i - 1)
+ else
+ return name
+ end
+end
+
+-- get the file extension of the path: .xxx
+function path.extension(p)
+ local i = p:find_last(".", true)
+ if i then
+ return p:sub(i)
+ else
+ return ""
+ end
+end
+
+-- return module: path
+return path
diff --git a/xmake/core/base/project.lua b/xmake/core/base/project.lua
new file mode 100644
index 000000000..51b46afe3
--- /dev/null
+++ b/xmake/core/base/project.lua
@@ -0,0 +1,1469 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file project.lua
+--
+
+-- define module: project
+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")
+local platform = require("platform/platform")
+
+-- import module
+function project._api_import(env, module)
+
+ -- import
+ return require("module/" .. module)
+end
+
+-- the current os is belong to the given os?
+function project._api_os(env, ...)
+
+ -- get the current os
+ local os = platform.os()
+ if not os then return false end
+
+ -- exists this os?
+ for _, o in ipairs(table.join(...)) do
+ if o and type(o) == "string" and o == os then
+ return true
+ end
+ end
+end
+
+-- the current mode is belong to the given modes?
+function project._api_modes(env, ...)
+
+ -- get the current mode
+ local mode = config.get("mode")
+ if not mode then return false end
+
+ -- exists this mode?
+ for _, m in ipairs(table.join(...)) do
+ if m and type(m) == "string" and m == mode then
+ return true
+ end
+ end
+end
+
+-- the current platform is belong to the given platforms?
+function project._api_plats(env, ...)
+
+ -- get the current platform
+ local plat = config.get("plat")
+ if not plat then return false end
+
+ -- exists this platform? and escape '-'
+ for _, p in ipairs(table.join(...)) do
+ if p and type(p) == "string" and plat:find(p:gsub("%-", "%%-")) then
+ return true
+ end
+ end
+end
+
+-- the current platform is belong to the given architectures?
+function project._api_archs(env, ...)
+
+ -- get the current architecture
+ local arch = config.get("arch")
+ if not arch then return false end
+
+ -- exists this architecture? and escape '-'
+ for _, a in ipairs(table.join(...)) do
+ if a and type(a) == "string" and arch:find(a:gsub("%-", "%%-")) then
+ return true
+ end
+ end
+end
+
+-- the current kind is belong to the given kinds?
+function project._api_kinds(env, ...)
+
+ -- get the current kind
+ local kind = config.get("kind")
+ if not kind then return false end
+
+ -- exists this kind?
+ for _, k in ipairs(table.join(...)) do
+ if k and type(k) == "string" and k == kind then
+ return true
+ end
+ end
+end
+
+-- enable options?
+function project._api_options(env, ...)
+
+ -- some options are enabled?
+ for _, o in ipairs(table.join(...)) do
+ if o and type(o) == "string" and config.get(o) then
+ return true
+ end
+ end
+end
+
+-- get all pathes and translate it
+function project._api_get_pathes(...)
+
+ -- check
+ assert(project._CURDIR)
+
+ -- get all pathes
+ local pathes = table.join(...)
+
+ -- translate the relative path
+ local results = {}
+ for _, p in ipairs(pathes) do
+ if not p:find("^%s-%$%(.-%)") and not path.is_absolute(p) then
+ table.insert(results, path.relative(path.absolute(p, project._CURDIR), project._PROJECT_DIR))
+ else
+ table.insert(results, p)
+ end
+ end
+
+ -- ok?
+ return results
+end
+
+-- add c function
+function project._api_add_cfunc(env, module, alias, links, includes, cfunc)
+
+ -- check
+ assert(env and cfunc)
+
+ -- make the option name
+ local name = nil
+ if module ~= nil then
+ name = string.format("__%s_%s", module, cfunc)
+ else
+ name = string.format("__%s", cfunc)
+ end
+
+ -- make the option define
+ local define = nil
+ if module ~= nil then
+ define = string.format("$(prefix)_%s_HAVE_%s", module:upper(), utils.ifelse(alias, alias, cfunc:upper()))
+ else
+ define = string.format("$(prefix)_HAVE_%s", utils.ifelse(alias, alias, cfunc:upper()))
+ end
+
+ -- make option
+ env.add_option(name)
+ env.set_option_category("cfuncs")
+ env.add_option_cfuncs(cfunc)
+ if links then env.add_option_links(links) end
+ if includes then env.add_option_cincludes(includes) end
+ env.add_option_defines_h_if_ok(define)
+
+ -- add this option
+ env.add_options(name)
+end
+
+-- add c functions
+function project._api_add_cfuncs(env, module, links, includes, ...)
+
+ -- check
+ assert(env)
+
+ -- done
+ for _, cfunc in ipairs({...}) do
+
+ -- check
+ assert(cfunc)
+
+ -- make the option name
+ local name = nil
+ if module ~= nil then
+ name = string.format("__%s_%s", module, cfunc)
+ else
+ name = string.format("__%s", cfunc)
+ end
+
+ -- make the option define
+ local define = nil
+ if module ~= nil then
+ define = string.format("$(prefix)_%s_HAVE_%s", module:upper(), cfunc:upper())
+ else
+ define = string.format("$(prefix)_HAVE_%s", cfunc:upper())
+ end
+
+ -- make option
+ env.add_option(name)
+ env.set_option_category("cfuncs")
+ env.add_option_cfuncs(cfunc)
+ if links then env.add_option_links(links) end
+ if includes then env.add_option_cincludes(includes) end
+ env.add_option_defines_h_if_ok(define)
+
+ -- add this option
+ env.add_options(name)
+ end
+end
+
+-- add c++ function
+function project._api_add_cxxfunc(env, module, alias, links, includes, cxxfunc)
+
+ -- check
+ assert(env and cxxfunc)
+
+ -- make the option name
+ local name = nil
+ if module ~= nil then
+ name = string.format("__%s_%s", module, cxxfunc)
+ else
+ name = string.format("__%s", cxxfunc)
+ end
+
+ -- make the option define
+ local define = nil
+ if module ~= nil then
+ define = string.format("$(prefix)_%s_HAVE_%s", module:upper(), utils.ifelse(alias, alias, cxxfunc:upper()))
+ else
+ define = string.format("$(prefix)_HAVE_%s", utils.ifelse(alias, alias, cxxfunc:upper()))
+ end
+
+ -- make option
+ env.add_option(name)
+ env.set_option_category("cxxfuncs")
+ env.add_option_cxxfuncs(cxxfunc)
+ if links then env.add_option_links(links) end
+ if includes then env.add_option_cxxincludes(includes) end
+ env.add_option_defines_h_if_ok(define)
+
+ -- add this option
+ env.add_options(name)
+end
+
+-- add c++ functions
+function project._api_add_cxxfuncs(env, module, links, includes, ...)
+
+ -- check
+ assert(env and module)
+
+ -- done
+ for _, cxxfunc in ipairs({...}) do
+
+ -- check
+ assert(cxxfunc)
+
+ -- make the option name
+ local name = nil
+ if module ~= nil then
+ name = string.format("__%s_%s", module, cxxfunc)
+ else
+ name = string.format("__%s", cxxfunc)
+ end
+
+ -- make the option define
+ local define = nil
+ if module ~= nil then
+ define = string.format("$(prefix)_%s_HAVE_%s", module:upper(), cxxfunc:upper())
+ else
+ define = string.format("$(prefix)_HAVE_%s", cxxfunc:upper())
+ end
+
+ -- make option
+ env.add_option(name)
+ env.set_option_category("cxxfuncs")
+ env.add_option_cxxfuncs(cxxfunc)
+ if links then env.add_option_links(links) end
+ if includes then env.add_option_cxxincludes(includes) end
+ env.add_option_defines_h_if_ok(define)
+
+ -- add this option
+ env.add_options(name)
+ end
+end
+
+-- add target
+function project._api_add_target(env, name)
+
+ -- check
+ assert(env and name)
+
+ -- the targets
+ local targets = env._CONFIGS._TARGETS
+ assert(targets)
+
+ -- init the target scope
+ targets[name] = targets[name] or {}
+
+ -- switch to this target scope
+ env._TARGET = targets[name]
+end
+
+-- add option
+function project._api_add_option(env, name)
+
+ -- check
+ assert(env and name)
+
+ -- the options
+ local options = env._CONFIGS._OPTIONS
+ assert(options)
+
+ -- init the option scope
+ options[name] = options[name] or {}
+
+ -- switch to this option scope
+ env._OPTION = options[name]
+end
+
+-- load all subprojects from the given directories
+function project._api_add_subdirs(env, ...)
+
+ -- check
+ assert(env)
+
+ -- init mtime for files
+ project._MTIMES = project._MTIMES or {}
+
+ -- save the current project file directory
+ local curdir = project._CURDIR
+
+ -- get all subdirs
+ local subdirs = project._api_get_pathes(...)
+
+ -- match all subdirs
+ local subdirs_matched = {}
+ for _, subdir in ipairs(subdirs) do
+ local dirs = os.match(subdir, true)
+ if dirs then table.join2(subdirs_matched, dirs) end
+ end
+
+ -- done
+ for _, subdir in ipairs(subdirs_matched) do
+ if subdir and type(subdir) == "string" then
+
+ -- the project file
+ local file = subdir .. "/xmake.lua"
+ if not path.is_absolute(file) then
+ file = path.absolute(file, xmake._PROJECT_DIR)
+ end
+
+ -- update the current project file directory
+ project._CURDIR = path.directory(file)
+
+ -- load the project script
+ local script = loadfile(file)
+ if script then
+
+ -- bind environment
+ setfenv(script, env)
+
+ -- done the project script
+ local ok, errors = pcall(script)
+ if not ok then
+ utils.error(errors)
+ assert(false)
+ end
+
+ -- get mtime of the file
+ project._MTIMES[path.relative(file, xmake._PROJECT_DIR)] = os.mtime(file)
+ end
+ end
+ end
+
+ -- restore the current project file directory
+ project._CURDIR = curdir
+
+end
+
+-- load all subprojects from the given files
+function project._api_add_subfiles(env, ...)
+
+ -- check
+ assert(env)
+
+ -- init mtime for files
+ project._MTIMES = project._MTIMES or {}
+
+ -- save the current project file directory
+ local curdir = project._CURDIR
+
+ -- get all subfiles
+ local subfiles = project._api_get_pathes(...)
+
+ -- match all subfiles
+ local subfiles_matched = {}
+ for _, subfile in ipairs(subfiles) do
+ local files = os.match(subfile)
+ if files then table.join2(subfiles_matched, files) end
+ end
+
+ -- done
+ for _, file in ipairs(subfiles_matched) do
+ if file and type(file) == "string" then
+
+ -- the project file
+ if not path.is_absolute(file) then
+ file = path.absolute(file, xmake._PROJECT_DIR)
+ end
+
+ -- update the current project file directory
+ project._CURDIR = path.directory(file)
+
+ -- load the project script
+ local script = loadfile(file)
+ if script then
+
+ -- bind environment
+ setfenv(script, env)
+
+ -- done the project script
+ local ok, errors = pcall(script)
+ if not ok then
+ utils.error(errors)
+ assert(false)
+ end
+
+ -- get mtime of the file
+ project._MTIMES[path.relative(file, xmake._PROJECT_DIR)] = os.mtime(file)
+ end
+ end
+ end
+
+ -- restore the current project file directory
+ project._CURDIR = curdir
+end
+
+-- load all packages from the given directories
+function project._api_add_pkgdirs(env, ...)
+
+ -- get all directories
+ local pkgdirs = {}
+ local dirs = table.join(...)
+ for _, dir in ipairs(dirs) do
+ table.insert(pkgdirs, dir .. "/*.pkg")
+ end
+
+ -- add all packages
+ project._api_add_subdirs(env, pkgdirs)
+end
+
+-- set configure values
+function project._api_set_values(scope, name, ...)
+
+ -- check
+ assert(scope and name)
+
+ -- update values
+ scope[name] = {}
+ table.join2(scope[name], ...)
+end
+
+-- add configure values
+function project._api_add_values(scope, name, ...)
+
+ -- check
+ assert(scope and name)
+
+ -- append values
+ scope[name] = scope[name] or {}
+ table.join2(scope[name], ...)
+end
+
+-- set configure pathes
+function project._api_set_pathes(scope, name, ...)
+
+ -- check
+ assert(scope and name)
+
+ -- update pathes
+ scope[name] = {}
+ table.join2(scope[name], project._api_get_pathes(...))
+end
+
+-- add configure pathes
+function project._api_add_pathes(scope, name, ...)
+
+ -- check
+ assert(scope and name)
+
+ -- append pathes
+ scope[name] = scope[name] or {}
+ table.join2(scope[name], project._api_get_pathes(...))
+end
+
+-- filter the configure value
+function project._filter(values)
+
+ -- check
+ assert(values)
+
+ -- filter all
+ local newvals = {}
+ for _, v in ipairs(utils.wrap(values)) do
+ if type(v) == "string" then
+ v = v:gsub("%$%((.-)%)", function (w)
+
+ -- is upper?
+ local isupper = false
+ local c = string.char(w:byte())
+ if c >= 'A' and c <= 'Z' then isupper = true end
+
+ -- attempt to get it directly from the configure
+ local r = config.get(w)
+ if not r or type(r) ~= "string" then
+
+ -- attempt to get it from the configure and the lower key
+ w = w:lower()
+ r = config.get(w)
+ if not r or type(r) ~= "string" then
+
+ -- get the other keys
+ if w == "projectdir" then r = xmake._PROJECT_DIR
+ elseif w == "os" then r = platform.os()
+ end
+ end
+ end
+
+ -- upper?
+ if r and type(r) == "string" and isupper then
+ r = r:upper()
+ end
+
+ -- ok?
+ return r
+ end)
+ end
+ table.insert(newvals, v)
+ end
+
+ -- ok?
+ return newvals
+end
+
+-- make configure for the given target_name
+function project._makeconf_for_target(target_name, target)
+
+ -- check
+ assert(target_name and target)
+
+ -- get the target configure file
+ local config_h = target.config_h
+ if not config_h then
+ return true
+ end
+
+ -- translate file path
+ if not path.is_absolute(config_h) then
+ config_h = path.absolute(config_h, xmake._PROJECT_DIR)
+ else
+ config_h = path.translate(config_h)
+ end
+
+ -- the prefix
+ local prefix = target.config_h_prefix or (target_name:upper() .. "_CONFIG")
+
+ -- open the file
+ local file = project._CONFILES[config_h] or io.openmk(config_h)
+ assert(file)
+
+ -- make the head
+ if project._CONFILES[config_h] then file:write("\n") end
+ file:write(string.format("#ifndef %s_H\n", prefix))
+ file:write(string.format("#define %s_H\n", prefix))
+ file:write("\n")
+
+ -- make version
+ if target.version then
+ file:write("// version\n")
+ file:write(string.format("#define %s_VERSION \"%s\"\n", prefix, target.version))
+ local i = 1
+ local m = {"MAJOR", "MINOR", "ALTER"}
+ for v in target.version:gmatch("%d+") do
+ file:write(string.format("#define %s_VERSION_%s %s\n", prefix, m[i], v))
+ i = i + 1
+ if i > 3 then break end
+ end
+ file:write(string.format("#define %s_VERSION_BUILD %s\n", prefix, os.date("%Y%m%d%H%M", os.time())))
+ file:write("\n")
+ end
+
+ -- make the defines
+ local defines = {}
+ if target.defines_h then table.join2(defines, target.defines_h) end
+
+ -- make the undefines
+ local undefines = {}
+ if target.undefines_h then table.join2(undefines, target.undefines_h) end
+
+ -- the options
+ if target.options then
+ for _, name in ipairs(utils.wrap(target.options)) do
+
+ -- get option if be enabled
+ local opt = nil
+ if config.get(name) then opt = config.get("__" .. name) end
+ if nil ~= opt then
+
+ -- get the option defines
+ if opt.defines_h_if_ok then table.join2(defines, opt.defines_h_if_ok) end
+
+ -- get the option undefines
+ if opt.undefines_h_if_ok then table.join2(undefines, opt.undefines_h_if_ok) end
+
+ end
+ end
+ end
+
+ -- make the defines
+ if #defines ~= 0 then
+ file:write("// defines\n")
+ for _, define in ipairs(defines) do
+ file:write(string.format("#define %s 1\n", define:gsub("=", " "):gsub("%$%((.-)%)", function (w) if w == "prefix" then return prefix end end)))
+ end
+ file:write("\n")
+ end
+
+ -- make the undefines
+ if #undefines ~= 0 then
+ file:write("// undefines\n")
+ for _, undefine in ipairs(undefines) do
+ file:write(string.format("#undef %s\n", undefine:gsub("%$%((.-)%)", function (w) if w == "prefix" then return prefix end end)))
+ end
+ file:write("\n")
+ end
+
+ -- make the tail
+ file:write("#endif\n")
+
+ -- cache the file
+ project._CONFILES[config_h] = file
+
+ -- ok
+ return true
+end
+
+-- make the configure file for the given target and dependents
+function project._makeconf_for_target_and_deps(target_name)
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- the target
+ local target = targets[target_name]
+ assert(target)
+
+ -- make configure for the target
+ if not project._makeconf_for_target(target_name, target) then
+ return false
+ end
+
+ -- exists the dependent targets?
+ if target.deps then
+ local deps = utils.wrap(target.deps)
+ for _, dep in ipairs(deps) do
+ if not project._makeconf_for_target_and_deps(dep) then return false end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- make targets from the project file
+function project._make_targets(configs)
+
+ -- check
+ assert(configs and configs._TARGETS)
+
+ -- init
+ project._TARGETS = project._TARGETS or {}
+ local targets = project._TARGETS
+
+ -- make all targets
+ for k, v in pairs(configs._TARGETS) do
+ targets[k] = v
+ end
+
+ -- merge the root configures to all targets
+ for _, target in pairs(targets) do
+
+ -- merge the setted configures
+ for k, v in pairs(configs._SET) do
+ if nil == target[k] then
+ target[k] = v
+ end
+ end
+
+ -- merge the added configures
+ for k, v in pairs(configs._ADD) do
+ if nil == target[k] then
+ target[k] = v
+ else
+ target[k] = table.join(v, target[k])
+ end
+ end
+
+ -- remove repeat values and unwrap it
+ for k, v in pairs(target) 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
+ target[k] = v
+ end
+ end
+
+ -- init mtime for the project file
+ project._MTIMES = project._MTIMES or {}
+ project._MTIMES[path.relative(xmake._PROJECT_FILE, xmake._PROJECT_DIR)] = os.mtime(xmake._PROJECT_FILE)
+
+ -- get the mtimes for configure
+ local mtimes_config = config.get("__mtimes")
+ if mtimes_config then
+
+ -- check for all project files and we need reconfig and rebuild it if them have been modified
+ for file, mtime in pairs(project._MTIMES) do
+
+ -- modified? reconfig and rebuild it
+ local mtime_old = mtimes_config[file]
+ if not mtime_old or mtime > mtime_old then
+ config._RECONFIG = true
+ config.set("__rebuild", true)
+ break
+ end
+ end
+ end
+
+ -- update mtimes
+ config.set("__mtimes", project._MTIMES)
+
+ -- reconfig it? we need reprobe it
+ if config._RECONFIG then
+ project.probe()
+ config.clearup()
+ end
+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(utils.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(utils.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(utils.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(utils.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(utils.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(utils.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(utils.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"))
+
+ -- failed
+ if not ok then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- make option
+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 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
+
+ end
+
+ -- ok
+ return opt
+end
+
+-- make options from the project file
+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
+
+ -- this option need be probed automatically?
+ if config.auto(k) then
+
+ -- make option
+ local o = project._make_option(k, v, cfile, cxxfile, objectfile, targetfile)
+ if o then
+
+ -- enable this option
+ config.set(k, true)
+
+ -- save this option to configure
+ config.set("__" .. k, o)
+
+ else
+
+ -- disable this option
+ config.set(k, false)
+
+ -- clear this option to configure
+ config.set("__" .. k, nil)
+
+ end
+
+ elseif nil == config.get("__" .. k) then
+
+ -- save this option to configure
+ config.set("__" .. k, v)
+ 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
+function project._load_options(file)
+
+ -- check
+ assert(file)
+
+ -- load the project script
+ local script = loadfile(file)
+ if not script then
+ return string.format("load %s failed!", file)
+ end
+
+ -- set the current project file directory
+ project._CURDIR = path.directory(file)
+
+ -- bind the new environment
+ local newenv = {_CONFIGS = {_OPTIONS = {}}}
+ setmetatable(newenv, {__index = function(tbl, key)
+ local val = rawget(tbl, key)
+ if nil == val then val = rawget(_G, key) end
+ if nil == val then return function(...) end end
+ return val
+ end})
+ setfenv(script, newenv)
+
+ -- register import
+ newenv.import = function (module) return project._api_import(newenv, module) end
+
+ -- register interfaces for the condition
+ newenv.os = function (...) return project._api_os(newenv, ...) end
+ newenv.kinds = function (...) return project._api_kinds(newenv, ...) end
+ newenv.modes = function (...) return project._api_modes(newenv, ...) end
+ newenv.plats = function (...) return project._api_plats(newenv, ...) end
+ newenv.archs = function (...) return project._api_archs(newenv, ...) end
+
+ -- register interfaces for the option
+ newenv.set_option = function (...) return project._api_add_option(newenv, ...) end
+ newenv.add_option = function (...) return project._api_add_option(newenv, ...) end
+
+ -- register interfaces for the subproject files
+ newenv.add_subdirs = function (...) return project._api_add_subdirs(newenv, ...) end
+ newenv.add_subfiles = function (...) return project._api_add_subfiles(newenv, ...) end
+
+ -- register interfaces for the functions
+ newenv.add_cfunc = function (...) return project._api_add_cfunc(newenv, ...) end
+ newenv.add_cfuncs = function (...) return project._api_add_cfuncs(newenv, ...) end
+ newenv.add_cxxfunc = function (...) return project._api_add_cxxfunc(newenv, ...) end
+ newenv.add_cxxfuncs = function (...) return project._api_add_cxxfuncs(newenv, ...) end
+
+ -- register interfaces for the package files
+ newenv.add_pkgdirs = function (...) return project._api_add_pkgdirs(newenv, ...) end
+ newenv.add_pkgs = function (...) return project._api_add_subdirs(newenv, ...) end
+
+ -- register interfaces for setting option values
+ local interfaces = { "enable"
+ , "showmenu"
+ , "category"
+ , "warnings"
+ , "optimize"
+ , "languages"
+ , "description"}
+
+ for _, interface in ipairs(interfaces) do
+ newenv["set_option_" .. interface] = function (...) return project._api_set_values(newenv._OPTION, interface, ...) end
+ end
+
+ -- register interfaces for adding option values
+ interfaces = { "links"
+ , "cincludes"
+ , "cxxincludes"
+ , "cfuncs"
+ , "cxxfuncs"
+ , "ctypes"
+ , "cxxtypes"
+ , "cflags"
+ , "cxflags"
+ , "cxxflags"
+ , "ldflags"
+ , "vectorexts"
+ , "defines"
+ , "defines_if_ok"
+ , "defines_h_if_ok"
+ , "undefines"
+ , "undefines_if_ok"
+ , "undefines_h_if_ok"}
+
+ for _, interface in ipairs(interfaces) do
+ newenv["add_option_" .. interface] = function (...) return project._api_add_values(newenv._OPTION, interface, ...) end
+ end
+
+ -- register interfaces for adding option pathes
+ interfaces = { "linkdirs"
+ , "includedirs"}
+
+ for _, interface in ipairs(interfaces) do
+ newenv["add_option_" .. interface] = function (...) return project._api_add_pathes(newenv._OPTION, interface, ...) end
+ end
+
+ -- done the project script
+ local ok, errors = pcall(script)
+ if not ok then
+ return nil, errors
+ end
+
+ -- get the project configure
+ return newenv._CONFIGS
+end
+
+-- only load targets from the project file
+function project._load_targets(file)
+
+ -- check
+ assert(file)
+
+ -- load the project script
+ local script = loadfile(file)
+ if not script then
+ return string.format("load %s failed!", file)
+ end
+
+ -- set the current project file directory
+ project._CURDIR = path.directory(file)
+
+ -- bind the new environment
+ local newenv = {_CONFIGS = {_SET = {}, _ADD = {}, _TARGETS = {}}}
+ setmetatable(newenv, {__index = function(tbl, key)
+ local val = rawget(tbl, key)
+ if nil == val then val = rawget(_G, key) end
+ if nil == val and type(key) == "string" and (key:startswith("add_option") or key:startswith("set_option")) then
+ return function(...) end
+ end
+ return val
+ end})
+ setfenv(script, newenv)
+
+ -- register import
+ newenv.import = function (module) return project._api_import(newenv, module) end
+
+ -- register interfaces for the condition
+ newenv.os = function (...) return project._api_os(newenv, ...) end
+ newenv.kinds = function (...) return project._api_kinds(newenv, ...) end
+ newenv.modes = function (...) return project._api_modes(newenv, ...) end
+ newenv.plats = function (...) return project._api_plats(newenv, ...) end
+ newenv.archs = function (...) return project._api_archs(newenv, ...) end
+ newenv.options = function (...) return project._api_options(newenv, ...) end
+
+ -- register interfaces for the target
+ newenv.set_target = function (...) return project._api_add_target(newenv, ...) end
+ newenv.add_target = function (...) return project._api_add_target(newenv, ...) end
+
+ -- register interfaces for the subproject files
+ newenv.add_subdirs = function (...) return project._api_add_subdirs(newenv, ...) end
+ newenv.add_subfiles = function (...) return project._api_add_subfiles(newenv, ...) end
+
+ -- register interfaces for the functions
+ newenv.add_cfunc = function (...) return project._api_add_cfunc(newenv, ...) end
+ newenv.add_cfuncs = function (...) return project._api_add_cfuncs(newenv, ...) end
+ newenv.add_cxxfunc = function (...) return project._api_add_cxxfunc(newenv, ...) end
+ newenv.add_cxxfuncs = function (...) return project._api_add_cxxfuncs(newenv, ...) end
+
+ -- register interfaces for the package files
+ newenv.add_pkgdirs = function (...) return project._api_add_pkgdirs(newenv, ...) end
+ newenv.add_pkgs = function (...) return project._api_add_subdirs(newenv, ...) end
+
+ -- register interfaces for setting values
+ local interfaces = { "kind"
+ , "config_h_prefix"
+ , "version"
+ , "strip"
+ , "options"
+ , "symbols"
+ , "warnings"
+ , "optimize"
+ , "languages"
+ , "runscript"
+ , "installscript"
+ , "packagescript"}
+
+ for _, interface in ipairs(interfaces) do
+ newenv["set_" .. interface] = function (...) return project._api_set_values(newenv._TARGET or newenv._CONFIGS._SET, interface, ...) end
+ end
+
+ -- register interfaces for setting pathes
+ local interfaces = { "headerdir"
+ , "targetdir"
+ , "objectdir"
+ , "config_h"}
+
+ for _, interface in ipairs(interfaces) do
+ newenv["set_" .. interface] = function (...) return project._api_set_pathes(newenv._TARGET or newenv._CONFIGS._SET, interface, ...) end
+ end
+
+ -- register interfaces for adding values
+ interfaces = { "deps"
+ , "links"
+ , "cflags"
+ , "cxflags"
+ , "cxxflags"
+ , "mflags"
+ , "mxflags"
+ , "mxxflags"
+ , "ldflags"
+ , "shflags"
+ , "options"
+ , "defines"
+ , "undefines"
+ , "defines_h"
+ , "undefines_h"
+ , "languages"
+ , "vectorexts"}
+ for _, interface in ipairs(interfaces) do
+ newenv["add_" .. interface] = function (...) return project._api_add_values(newenv._TARGET or newenv._CONFIGS._ADD, interface, ...) end
+ end
+
+ -- register interfaces for adding pathes
+ interfaces = { "files"
+ , "headers"
+ , "linkdirs"
+ , "includedirs"}
+ for _, interface in ipairs(interfaces) do
+ newenv["add_" .. interface] = function (...) return project._api_add_pathes(newenv._TARGET or newenv._CONFIGS._ADD, interface, ...) end
+ end
+
+ -- done the project script
+ local ok, errors = pcall(script)
+ if not ok then
+ return nil, errors
+ end
+
+ -- get the project configure
+ return newenv._CONFIGS
+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()
+
+ -- load the options from the the project file
+ local configs, errors = project._load_options(xmake._PROJECT_FILE)
+ if not configs then
+ return errors
+ end
+
+ -- make the options from the the project file
+ project._make_options(configs)
+end
+
+-- load the project
+function project.load()
+
+ -- load the targets from the the project file
+ local configs, errors = project._load_targets(xmake._PROJECT_FILE)
+ if not configs then
+ return errors
+ end
+
+ -- make the targets from the the project file
+ project._make_targets(configs)
+end
+
+-- reload the project
+function project.reload()
+
+ -- clear it first
+ project._MTIMES = nil
+ project._TARGETS = nil
+ project._CONFILES = nil
+ project._CURDIR = nil
+
+ -- load it
+ return project.load()
+end
+
+-- dump the current configure
+function project.dump()
+
+ -- check
+ assert(project._TARGETS)
+
+ -- dump
+ if xmake._OPTIONS.verbose then
+ utils.dump(project._TARGETS)
+ end
+
+end
+
+-- make the configure file for the given target
+function project.makeconf(target_name)
+
+ -- init files
+ project._CONFILES = project._CONFILES or {}
+
+ -- the target name
+ if target_name and target_name ~= "all" then
+ -- make configure for the target and dependents
+ if not project._makeconf_for_target_and_deps(target_name) then return false end
+ else
+
+ -- the targets
+ local targets = project.targets()
+ assert(targets)
+
+ -- make configure for the targets
+ for target_name, target in pairs(targets) do
+ if not project._makeconf_for_target(target_name, target) then return false end
+ end
+ end
+
+ -- exit files
+ for _, file in pairs(project._CONFILES) do
+ file:close()
+ end
+ project._CONFILES = nil
+
+ -- ok
+ return true
+end
+
+-- check target
+function project.checktarget(target_name)
+
+ -- the targets
+ local targets = project.targets()
+
+ -- invalid target?
+ if target_name and target_name ~= "all" and targets and not targets[target_name] then
+ utils.error("invalid target: %s!", target_name)
+ return false
+ elseif not target_name then
+ utils.error("no target!")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- get the project menu
+function project.menu()
+
+ -- attempt to load project configure
+ local configs = nil
+ local errors = nil
+ local projectfile = xmake._PROJECT_FILE
+ if projectfile and os.isfile(projectfile) then
+ configs, errors = project._load_options(projectfile)
+ end
+
+ -- failed?
+ if not configs then
+ if errors then utils.error(errors) end
+ return {}
+ end
+
+ -- the options
+ local options = configs._OPTIONS
+ if not options then return {} end
+
+ -- arrange options by category
+ local options_by_category = {}
+ for name, opt in pairs(options) do
+
+ -- make the category
+ local category = "default"
+ if opt.category then category = utils.unwrap(opt.category) end
+ options_by_category[category] = options_by_category[category] or {}
+
+ -- append option to the current category
+ options_by_category[category][name] = opt
+ end
+
+ -- make menu by category
+ local menu = {}
+ for k, opts in pairs(options_by_category) do
+
+ -- insert options
+ local first = true
+ for name, opt in pairs(opts) do
+
+ -- show menu?
+ if opt.showmenu then
+
+ -- the default value
+ local default = "auto"
+ if opt.enable ~= nil then
+ default = utils.unwrap(opt.enable)
+ end
+
+ -- is first?
+ if first then
+
+ -- insert a separator
+ table.insert(menu, {})
+
+ -- not first
+ first = false
+ end
+
+ -- append it
+ if opt.description then
+ table.insert(menu, {nil, name, "kv", default, utils.unwrap(opt.description)})
+ else
+ table.insert(menu, {nil, name, "kv", default, nil})
+ end
+ end
+ end
+ end
+
+ -- ok?
+ return menu
+end
+
+-- return module: project
+return project
diff --git a/xmake/core/base/rule.lua b/xmake/core/base/rule.lua
new file mode 100644
index 000000000..b3dc1825c
--- /dev/null
+++ b/xmake/core/base/rule.lua
@@ -0,0 +1,300 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file rule.lua
+--
+
+-- define module: rule
+local rule = rule 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("base/config")
+local platform = require("platform/platform")
+
+-- get the building log file path
+function rule.logfile()
+
+ -- the logdir
+ local logdir = config.get("buildir") or os.tmpdir()
+ assert(logdir)
+
+ -- get it
+ return path.translate(logdir .. "/.build.log")
+end
+
+-- get the filename from the given name and kind
+function rule.filename(name, kind)
+
+ -- check
+ assert(name and kind)
+
+ -- get format
+ local format = platform.format(kind) or {"", ""}
+
+ -- make it
+ return format[1] .. name .. format[2]
+end
+
+-- get the makefile path
+function rule.makefile()
+
+ -- get the build directory
+ local buildir = config.get("buildir")
+ assert(buildir)
+
+ -- get it
+ return path.translate(buildir .. "/makefile")
+end
+
+-- get configure file for the given target
+function rule.config_h(target)
+
+ -- get the target configure file
+ local config_h = target.config_h
+ if config_h then
+ -- translate file path
+ if not path.is_absolute(config_h) then
+ config_h = path.absolute(config_h, xmake._PROJECT_DIR)
+ else
+ config_h = path.translate(config_h)
+ end
+ end
+
+ -- ok?
+ return config_h
+end
+
+-- get the temporary backup directory for package
+function rule.backupdir(target_name, arch)
+
+ -- the temporary directory
+ local tmpdir = os.tmpdir()
+ assert(tmpdir)
+
+ -- the project name
+ local project_name = path.basename(xmake._PROJECT_DIR)
+ assert(project_name)
+
+ -- make it
+ return string.format("%s/.xmake/%s/pkgfiles/%s/%s", tmpdir, project_name, target_name, arch)
+end
+
+-- get target file for the given target
+function rule.targetfile(target_name, target, buildir)
+
+ -- check
+ assert(target_name and target and target.kind)
+
+ -- the target directory
+ local targetdir = target.targetdir or buildir or config.get("buildir")
+ assert(targetdir and type(targetdir) == "string")
+
+ -- the target file name
+ local filename = rule.filename(target_name, target.kind)
+ assert(filename)
+
+ -- make the target file path
+ return targetdir .. "/" .. filename
+end
+
+-- get object files for the given source files
+function rule.objectdir(target_name, target, buildir)
+
+ -- check
+ assert(target_name and target)
+
+ -- the object directory
+ local objectdir = target.objectdir
+ if not objectdir then
+
+ -- the build directory
+ if not buildir then
+ buildir = config.get("buildir")
+ end
+ assert(buildir)
+
+ -- make the default object directory
+ objectdir = buildir .. "/.objs"
+ end
+
+ -- ok?
+ return objectdir
+end
+
+-- get object files for the given source files
+function rule.objectfiles(target_name, target, sourcefiles, buildir)
+
+ -- check
+ assert(target_name and target and sourcefiles)
+
+ -- the object directory
+ local objectdir = rule.objectdir(target_name, target, buildir)
+ assert(objectdir and type(objectdir) == "string")
+
+ -- make object files
+ local i = 1
+ local objectfiles = {}
+ for _, sourcefile in ipairs(sourcefiles) do
+
+ -- translate: [lib]xxx*.[a|lib] => xxx/*.[o|obj] object file
+ sourcefile = sourcefile:gsub(rule.filename("(%w+)", "static"):gsub("%.", "%%.") .. "$", "%1/*")
+
+ -- make object file
+ local objectfile = string.format("%s/%s/%s/%s", objectdir, target_name, path.directory(sourcefile), rule.filename(path.basename(sourcefile), "object"))
+
+ -- translate path
+ --
+ -- .e.g
+ --
+ -- src/xxx.c
+ -- project/xmake.lua
+ -- build/.objs
+ --
+ -- objectfile: project/build/.objs/xxxx/../../xxx.c will be out of range for objectdir
+ --
+ -- we need replace '..' to '__' in this case
+ --
+ objectfile = (path.translate(objectfile):gsub("%.%.", "__"))
+
+ -- save it
+ objectfiles[i] = objectfile
+ i = i + 1
+
+ end
+
+ -- ok?
+ return objectfiles
+end
+
+-- get the source files from the given target
+function rule.sourcefiles(target)
+
+ -- check
+ assert(target)
+
+ -- no files?
+ if not target.files then
+ return {}
+ end
+
+ -- wrap files first
+ local targetfiles = utils.wrap(target.files)
+
+ -- match files
+ local i = 1
+ local sourcefiles = {}
+ for _, targetfile in ipairs(targetfiles) do
+
+ -- normalize *.[o|obj] filename
+ targetfile = targetfile:gsub("([%w%*]+)%.obj|", rule.filename("%1|", "object"))
+ targetfile = targetfile:gsub("([%w%*]+)%.obj$", rule.filename("%1", "object"))
+ targetfile = targetfile:gsub("([%w%*]+)%.o|", rule.filename("%1|", "object"))
+ targetfile = targetfile:gsub("([%w%*]+)%.o$", rule.filename("%1", "object"))
+
+ -- normalize [lib]*.[a|lib] filename
+ targetfile = targetfile:gsub("([%w%*]+)%.lib|", rule.filename("%1|", "static"))
+ targetfile = targetfile:gsub("([%w%*]+)%.lib$", rule.filename("%1", "static"))
+ targetfile = targetfile:gsub("lib([%w%*]+)%.a|", rule.filename("%1|", "static"))
+ targetfile = targetfile:gsub("lib([%w%*]+)%.a$", rule.filename("%1", "static"))
+
+ -- match source files
+ local files = os.match(targetfile)
+ if #files == 0 then
+ utils.warning("cannot match add_files(\"%s\")", targetfile)
+ end
+
+ -- process source files
+ for _, file in ipairs(files) do
+
+ -- convert to the relative path
+ if path.is_absolute(file) then
+ file = path.relative(file, xmake._PROJECT_DIR)
+ end
+
+ -- save it
+ sourcefiles[i] = file
+ i = i + 1
+
+ end
+ end
+
+ -- remove repeat files
+ sourcefiles = utils.unique(sourcefiles)
+
+ -- ok?
+ return sourcefiles
+end
+
+-- get the header files from the given target
+function rule.headerfiles(target, headerdir)
+
+ -- check
+ assert(target)
+
+ -- no headers?
+ local headers = target.headers
+ if not headers then return end
+
+ -- get the headerdir
+ if not headerdir then headerdir = target.headerdir or config.get("buildir") end
+ assert(headerdir)
+
+ -- get the source pathes and destinate pathes
+ local srcheaders = {}
+ local dstheaders = {}
+ for _, header in ipairs(utils.wrap(headers)) do
+
+ -- get the root directory
+ local rootdir = header:gsub("%(.*%)", ""):gsub("|.*$", "")
+
+ -- remove '(' and ')'
+ local srcpathes = header:gsub("[%(%)]", "")
+ if srcpathes then
+
+ -- get the source pathes
+ srcpathes = os.match(srcpathes)
+ if srcpathes then
+
+ -- add the source headers
+ table.join2(srcheaders, srcpathes)
+
+ -- add the destinate headers
+ for _, srcpath in ipairs(srcpathes) do
+
+ -- the header
+ local dstheader = path.absolute(path.relative(srcpath, rootdir), headerdir)
+ assert(dstheader)
+
+ -- add it
+ table.insert(dstheaders, dstheader)
+ end
+ end
+ end
+ end
+
+ -- ok?
+ return srcheaders, dstheaders
+end
+
+-- return module: rule
+return rule
diff --git a/xmake/core/base/string.lua b/xmake/core/base/string.lua
new file mode 100644
index 000000000..b4be08cfa
--- /dev/null
+++ b/xmake/core/base/string.lua
@@ -0,0 +1,115 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file string.lua
+--
+
+-- define module: string
+local string = string or {}
+
+-- find the last substring with the given pattern
+function string.find_last(self, pattern, plain)
+
+ -- find the last substring
+ local curr = 0
+ repeat
+ local next = self:find(pattern, curr + 1, plain)
+ if next then
+ curr = next
+ end
+ until (not next)
+
+ -- found?
+ if curr > 0 then
+ return curr
+ end
+end
+
+-- split string with the given pattern
+function string.split(self, pattern)
+
+ -- split it
+ local list = {}
+ self:gsub("[^" .. pattern .."]+", function(v) table.insert(list, v) end )
+ return list
+end
+
+-- trim the spaces
+function string.trim(self)
+ return (self:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+-- trim the left spaces
+function string.ltrim(self)
+ return (self:gsub("^%s*", ""))
+end
+
+-- trim the right spaces
+function string.rtrim(self)
+ local n = #self
+ while n > 0 and s:find("^%s", n) do n = n - 1 end
+ return self:sub(1, n)
+end
+
+-- append a substring with a given separator
+function string.append(self, substr, separator)
+
+ -- check
+ assert(self)
+
+ -- not substr? return self
+ if not substr then
+ return self
+ end
+
+ -- append it
+ local s = self
+ if #s == 0 then
+ s = substr
+ else
+ s = string.format("%s%s%s", s, separator or "", substr)
+ end
+
+ -- ok
+ return s
+end
+
+-- encode: ' ', '=', '\"', '<'
+function string.encode(self)
+
+ -- null?
+ if self == nil then return end
+
+ -- done
+ return (self:gsub("[%s=\"<]", function (w) return string.format("%%%x", w:byte()) end))
+end
+
+-- decode: ' ', '=', '\"'
+function string.decode(self)
+
+ -- null?
+ if self == nil then return end
+
+ -- done
+ return (self:gsub("%%(%x%x)", function (w) return string.char(tonumber(w, 16)) end))
+end
+
+
+-- return module: string
+return string
diff --git a/xmake/core/base/table.lua b/xmake/core/base/table.lua
new file mode 100644
index 000000000..52b726412
--- /dev/null
+++ b/xmake/core/base/table.lua
@@ -0,0 +1,99 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file table.lua
+--
+
+-- define module: table
+local table = table or {}
+
+-- join all objects and tables
+function table.join(...)
+
+ -- done
+ local args = {...}
+ local result = {}
+ for _, t in ipairs(args) do
+ if type(t) == "table" then
+ for k, v in pairs(t) do
+ if type(k) == "number" then table.insert(result, v)
+ else result[k] = v end
+ end
+ else
+ table.insert(result, t)
+ end
+ end
+
+ -- ok?
+ return result
+end
+
+-- join all objects and tables to self
+function table.join2(self, ...)
+
+ -- check
+ assert(self and type(self) == "table")
+
+ -- done
+ local args = {...}
+ for _, t in ipairs(args) do
+ if type(t) == "table" then
+ for k, v in pairs(t) do
+ if type(k) == "number" then table.insert(self, v)
+ else self[k] = v end
+ end
+ else
+ table.insert(self, t)
+ end
+ end
+
+ -- ok?
+ return self
+end
+
+-- clear the table
+function table.clear(self)
+
+ -- check
+ assert(self and type(self) == "table")
+
+ -- clear it
+ for k in next, self do
+ rawset(self, k, nil)
+ end
+end
+
+-- copy the table to self
+function table.copy2(self, copied)
+
+ -- check
+ assert(self and copied)
+
+ -- clear self first
+ table.clear(self)
+
+ -- copy it
+ for k, v in pairs(copied) do
+ self[k] = v
+ end
+
+end
+
+-- return module: table
+return table
diff --git a/xmake/core/base/template.lua b/xmake/core/base/template.lua
new file mode 100644
index 000000000..c02b135c3
--- /dev/null
+++ b/xmake/core/base/template.lua
@@ -0,0 +1,77 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file template.lua
+--
+
+-- define module: template
+local template = template or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+
+-- get the language list
+function template.languages()
+
+ -- make list
+ local list = {}
+
+ -- get the language list
+ local languages = os.match(xmake._TEMPLATES_DIR .. "/*", true)
+ if languages then
+ for _, v in ipairs(languages) do
+ table.insert(list, path.basename(v))
+ end
+ end
+
+ -- ok?
+ return list
+end
+
+-- load all templates from the given language
+function template.loadall(language)
+
+ -- check
+ assert(language)
+
+ -- load all templates
+ local modules = {}
+ local templates = os.match(string.format("%s/%s/**/_template.lua", xmake._TEMPLATES_DIR, language))
+ if templates then
+ for _, t in ipairs(templates) do
+ local script = assert(loadfile(t))
+ if script then
+ local module = script()
+ if module then
+ module._DIRECTORY = path.directory(t)
+ table.insert(modules, module)
+ end
+ end
+ end
+ end
+
+ -- ok?
+ return modules
+end
+
+
+-- return module: template
+return template
diff --git a/xmake/core/base/uninstall.lua b/xmake/core/base/uninstall.lua
new file mode 100644
index 000000000..304b73c92
--- /dev/null
+++ b/xmake/core/base/uninstall.lua
@@ -0,0 +1,104 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file uninstall.lua
+--
+
+-- define module: uninstall
+local uninstall = uninstall 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 config = require("base/config")
+local platform = require("platform/platform")
+
+-- uninstall target from the platform script
+function uninstall._done_from_platform(target)
+
+ -- check
+ assert(target)
+
+ -- the platform uninstall script file
+ local uninstallscript = nil
+ local scriptfile = platform.directory() .. "/uninstall.lua"
+ if os.isfile(scriptfile) then
+
+ -- load the uninstall script
+ local script, errors = loadfile(scriptfile)
+ if script then
+ uninstallscript = script()
+ if type(uninstallscript) == "table" and uninstallscript.main then
+ uninstallscript = uninstallscript.main
+ end
+ else
+ utils.error(errors)
+ end
+ end
+
+ -- uninstall it
+ if type(uninstallscript) == "function" then
+ return uninstallscript(target)
+ end
+
+ -- continue
+ return 0
+end
+
+-- uninstall target from the given target configure
+function uninstall._done(target)
+
+ -- check
+ assert(target)
+
+ -- uninstall it from the platform script
+ local ok = uninstall._done_from_platform(target)
+ if ok ~= 0 then return utils.ifelse(ok == 1, true, false) end
+
+ -- ok
+ return true
+end
+
+-- done uninstall from the configure
+function uninstall.done(configs)
+
+ -- check
+ assert(configs)
+
+ -- uninstall targets
+ for _, target in pairs(configs) do
+
+ -- uninstall it
+ if not uninstall._done(target) then
+ -- errors
+ utils.error("uninstall %s failed!", target.name)
+ return false
+ end
+
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: uninstall
+return uninstall
diff --git a/xmake/core/base/utils.lua b/xmake/core/base/utils.lua
new file mode 100644
index 000000000..fd1f053d6
--- /dev/null
+++ b/xmake/core/base/utils.lua
@@ -0,0 +1,258 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file utils.lua
+--
+
+-- define module: utils
+local utils = utils or {}
+
+-- the printf function
+function utils.printf(msg, ...)
+
+ -- check
+ assert(msg)
+
+ -- trace
+ print(string.format(msg, ...))
+end
+
+-- the verbose function
+function utils.verbose(msg, ...)
+
+ if xmake._OPTIONS.verbose then
+
+ -- check
+ assert(msg)
+
+ -- trace
+ print(string.format(msg, ...))
+ end
+end
+
+-- the error function
+function utils.error(msg, ...)
+
+ -- check
+ assert(msg)
+
+ -- trace
+ print("error: " .. string.format(msg, ...))
+end
+
+-- the warning function
+function utils.warning(msg, ...)
+
+ -- check
+ assert(msg)
+
+ -- trace
+ print("warning: " .. string.format(msg, ...))
+end
+
+-- ifelse, a? b : c
+function utils.ifelse(a, b, c)
+ if a then return b else return c end
+end
+
+-- dump object with the level
+function utils._dump_with_level(object, exclude, level)
+
+ -- dump string
+ if type(object) == "string" then
+ io.write(string.format("%q", object))
+ -- dump boolean
+ elseif type(object) == "boolean" then
+ io.write(tostring(object))
+ -- dump number
+ elseif type(object) == "number" then
+ io.write(object)
+ -- dump function
+ elseif type(object) == "function" then
+ io.write("<function>")
+ -- dump table
+ elseif type(object) == "table" then
+
+ -- dump head
+ io.write("\n")
+ for l = 1, level do
+ io.write(" ")
+ end
+ io.write("{\n")
+
+ -- dump body
+ local i = 0
+ for k, v in pairs(object) do
+
+ -- exclude some keys
+ if not exclude or type(k) ~= "string" or not k:find(exclude) then
+
+ -- dump spaces and separator
+ for l = 1, level do
+ io.write(" ")
+ end
+
+ io.write(utils.ifelse(i == 0, " ", ", "))
+
+ -- dump key
+ if type(k) == "string" then
+ io.write(k, " = ")
+ end
+
+ -- dump value
+ if not utils._dump_with_level(v, exclude, level + 1) then
+ return false
+ end
+
+ -- dump newline
+ io.write("\n")
+ i = i + 1
+ end
+ end
+
+ -- dump tail
+ for l = 1, level do
+ io.write(" ")
+ end
+ io.write("}\n")
+ else
+ -- error
+ utils.error("invalid object type: %s", type(object))
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- dump object
+function utils.dump(object, exclude, prefix)
+
+ -- dump prefix
+ if prefix then
+ io.write(prefix)
+ end
+
+ -- dump it
+ utils._dump_with_level(object, exclude, 0)
+
+ -- return it
+ return object
+end
+
+-- unwrap object if be only one
+function utils.unwrap(object)
+
+ -- check
+ assert(object)
+
+ -- unwrap it
+ if type(object) == "table" and table.getn(object) == 1 then
+ for _, v in pairs(object) do
+ return v
+ end
+ end
+
+ -- ok
+ return object
+end
+
+-- wrap object to table
+function utils.wrap(object)
+
+ -- no object?
+ if not object then
+ return {}
+ end
+
+ -- wrap it if not table
+ if type(object) ~= "table" then
+ return {object}
+ end
+
+ -- ok
+ return object
+end
+
+-- remove repeat from the given array
+function utils.unique(array)
+
+ -- check
+ assert(array)
+
+ -- remove repeat
+ if type(array) == "table" then
+
+ -- not only one?
+ if table.getn(array) ~= 1 then
+
+ -- done
+ local exists = {}
+ local unique = {}
+ for _, v in ipairs(array) do
+ if type(v) == "string" then
+ if not exists[v] then
+ exists[v] = true
+ table.insert(unique, v)
+ end
+ else
+ if not exists["\"" .. v .. "\""] then
+ exists["\"" .. v .. "\""] = true
+ table.insert(unique, v)
+ end
+ end
+ end
+
+ -- update it
+ array = unique
+ end
+ end
+
+ -- ok
+ return array
+end
+
+-- call functions
+function utils.call(funcs, pred, ...)
+
+ -- check
+ assert(funcs)
+
+ -- call all
+ for _, func in ipairs(utils.wrap(funcs)) do
+
+ -- check
+ assert(type(func) == "function")
+
+ -- call it
+ local result = func(...)
+
+ -- exists predicate?
+ if pred and type(pred) == "function" then
+ if not pred(name, result) then return false end
+ -- failed?
+ elseif not result then return false end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: utils
+return utils
diff --git a/xmake/core/module/os.lua b/xmake/core/module/os.lua
new file mode 100644
index 000000000..3689086f2
--- /dev/null
+++ b/xmake/core/module/os.lua
@@ -0,0 +1,46 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file os.lua
+--
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+
+-- define module: _os
+local _os = _os or {}
+
+-- cat the given file
+function _os.cat(filepath, linecount)
+
+ -- cat it
+ return io.cat(filepath, linecount)
+end
+
+-- only copy the interfaces of os
+for k, v in pairs(os) do
+ if type(v) == "function" then
+ _os[k] = v
+ end
+end
+
+-- return module: _os
+return _os
+
diff --git a/xmake/core/module/path.lua b/xmake/core/module/path.lua
new file mode 100644
index 000000000..9de905667
--- /dev/null
+++ b/xmake/core/module/path.lua
@@ -0,0 +1,25 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file path.lua
+--
+
+-- return module: path
+return require("base/path")
+
diff --git a/xmake/core/module/project.lua b/xmake/core/module/project.lua
new file mode 100644
index 000000000..f3f726c6f
--- /dev/null
+++ b/xmake/core/module/project.lua
@@ -0,0 +1,73 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file project.lua
+--
+
+-- define module: project
+local project = project or {}
+
+-- load modules
+local rule = require("base/rule")
+local config = require("base/config")
+
+-- get the build directory
+function project.buildir()
+
+ -- get it
+ return config.get("buildir")
+end
+
+-- get the project directory
+function project.projectdir()
+
+ -- get it
+ return xmake._PROJECT_DIR
+end
+
+-- get the log file
+function project.logfile()
+
+ -- get it
+ return rule.logfile()
+end
+
+-- get the current platform
+function project.plat()
+
+ -- get it
+ return config.get("plat")
+end
+
+-- get the current architecture
+function project.arch()
+
+ -- get it
+ return config.get("arch")
+end
+
+-- get the current mode
+function project.mode()
+
+ -- get it
+ return config.get("mode")
+end
+
+-- return module: project
+return project
diff --git a/xmake/core/module/string.lua b/xmake/core/module/string.lua
new file mode 100644
index 000000000..60d3408cf
--- /dev/null
+++ b/xmake/core/module/string.lua
@@ -0,0 +1,24 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file string.lua
+--
+
+-- return module: string
+return require("base/string")
diff --git a/xmake/core/module/utils.lua b/xmake/core/module/utils.lua
new file mode 100644
index 000000000..ab4d2c96f
--- /dev/null
+++ b/xmake/core/module/utils.lua
@@ -0,0 +1,24 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file utils.lua
+--
+
+-- return module: utils
+return require("base/utils")
diff --git a/xmake/core/platform/android/android.lua b/xmake/core/platform/android/android.lua
new file mode 100644
index 000000000..15e3c33a2
--- /dev/null
+++ b/xmake/core/platform/android/android.lua
@@ -0,0 +1,120 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file android.lua
+--
+
+-- define module: android
+local android = android or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+android._HOST = xmake._HOST
+
+-- init os
+android._OS = "android"
+
+-- init architectures
+android._ARCHS = {"armv5te", "armv6", "armv7-a", "armv8-a", "arm64-v8a"}
+
+-- make configure
+function android.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".so"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.as = config.get("as")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- init flags
+ local arch = config.get("arch")
+ if arch:startswith("arm64") then
+ configs.cxflags = {}
+ configs.asflags = {}
+ configs.ldflags = {"-llog"}
+ configs.shflags = {"-llog"}
+ else
+ configs.cxflags = { "-march=" .. arch, "-mthumb"}
+ configs.asflags = { "-march=" .. arch, "-mthumb"}
+ configs.ldflags = { "-march=" .. arch, "-llog", "-mthumb"}
+ configs.shflags = { "-march=" .. arch, "-llog", "-mthumb"}
+ end
+
+ -- add flags for the sdk directory of ndk
+ local ndk = config.get("ndk")
+ local ndk_sdkver = config.get("ndk_sdkver")
+ if ndk and ndk_sdkver then
+ local ndk_sdkdir = path.translate(string.format("%s/platforms/android-%d", ndk, ndk_sdkver))
+ if arch:startswith("arm64") then
+ table.insert(configs.cxflags, string.format("--sysroot=%s/arch-arm64", ndk_sdkdir))
+ table.insert(configs.asflags, string.format("--sysroot=%s/arch-arm64", ndk_sdkdir))
+ table.insert(configs.ldflags, string.format("--sysroot=%s/arch-arm64", ndk_sdkdir))
+ table.insert(configs.shflags, string.format("--sysroot=%s/arch-arm64", ndk_sdkdir))
+ else
+ table.insert(configs.cxflags, string.format("--sysroot=%s/arch-arm", ndk_sdkdir))
+ table.insert(configs.asflags, string.format("--sysroot=%s/arch-arm", ndk_sdkdir))
+ table.insert(configs.ldflags, string.format("--sysroot=%s/arch-arm", ndk_sdkdir))
+ table.insert(configs.shflags, string.format("--sysroot=%s/arch-arm", ndk_sdkdir))
+ end
+ end
+
+end
+
+-- get the option menu for action: xmake config or global
+function android.menu(action)
+
+ -- init config option menu
+ android._MENU_CONFIG = android._MENU_CONFIG or
+ { {}
+ , {nil, "ndk", "kv", nil, "The NDK Directory" }
+ , {nil, "ndk_sdkver", "kv", "auto", "The SDK Version for NDK" }
+ , }
+
+ -- init global option menu
+ android._MENU_GLOBAL = android._MENU_GLOBAL or
+ { {}
+ , {nil, "ndk", "kv", nil, "The NDK Directory" }
+ , {nil, "ndk_sdkver", "kv", "auto", "The SDK Version for NDK" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return android._MENU_CONFIG
+ elseif action == "global" then
+ return android._MENU_GLOBAL
+ end
+end
+
+-- return module: android
+return android
diff --git a/xmake/core/platform/android/prober.lua b/xmake/core/platform/android/prober.lua
new file mode 100644
index 000000000..a6446e0e1
--- /dev/null
+++ b/xmake/core/platform/android/prober.lua
@@ -0,0 +1,269 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "armv7-a")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the sdk version for ndk
+function prober._probe_ndk_sdkver(configs)
+
+ -- ok?
+ local ndk_sdkver = configs.get("ndk_sdkver")
+ if ndk_sdkver then return true end
+
+ -- get the ndk
+ local ndk = configs.get("ndk")
+ if ndk then
+
+ -- match all sdk directories
+ local sdkdirs = os.match(ndk .. "/platforms/android-*", true)
+ if sdkdirs then
+
+ -- get the max version
+ local version_maxn = 0
+ for _, sdkdir in ipairs(sdkdirs) do
+ local filename = path.filename(sdkdir)
+ local version, count = filename:gsub("android%-", "")
+ if count > 0 then
+ version = tonumber(version)
+ if version > version_maxn then version_maxn = version end
+ end
+ end
+
+ -- save the version
+ if version_maxn > 0 then ndk_sdkver = version_maxn end
+ end
+ end
+
+ -- probe ok? update it
+ if type(ndk_sdkver) == "number" and ndk_sdkver > 0 then
+
+ -- save it
+ configs.set("ndk_sdkver", ndk_sdkver)
+
+ -- trace
+ utils.printf("checking for the SDK version of NDK ... %s", string.format("android-%d", ndk_sdkver))
+ else
+
+ -- trace
+ utils.printf("checking for the SDK version of NDK ... no")
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolpath(configs, kind, cross, name, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- attempt to get it from the given cross toolchains
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to get it from the ndk
+ if not toolpath then
+ local ndk = configs.get("ndk")
+ if ndk then
+
+ -- match all toolchains
+ local arch = configs.get("arch")
+ if arch and arch:startswith("arm64") then
+ toolchains = os.match(string.format("%s/toolchains/aarch64-linux-android-**/prebuilt/*/bin/%s%s", ndk, cross, name))
+ else
+ toolchains = os.match(string.format("%s/toolchains/arm-linux-androideabi-**/prebuilt/*/bin/%s%s", ndk, cross, name))
+ end
+
+ -- probe the tool path
+ if toolchains then
+ for _, filepath in ipairs(toolchains) do
+ toolpath = tools.probe(cross .. name, path.directory(filepath))
+ if toolpath then break end
+ end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if toolpath then configs.set(kind, toolpath) end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- failed?
+ if not toolpath and not configs.get("ndk") then
+ utils.error("checking for the NDK directory ... no")
+ utils.error(" - xmake config --ndk=xxx")
+ utils.error("or - xmake global --ndk=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- init prefix
+ local prefix = "arm-linux-androideabi-"
+ local arch = configs.get("arch")
+ if arch and arch:startswith("arm64") then
+ prefix = "aarch64-linux-android-"
+ end
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", prefix, "gcc", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", prefix, "g++", "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", prefix, "gcc", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", prefix, "g++", "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", prefix, "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", prefix, "g++", "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", prefix, "swiftc", "the swift compiler") then return false end
+
+ -- ok
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_ndk_sdkver
+ , prober._probe_toolchains}
+ , nil
+ , config)
+
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_ndk_sdkver}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/iphoneos/iphoneos.lua b/xmake/core/platform/iphoneos/iphoneos.lua
new file mode 100644
index 000000000..f9147945c
--- /dev/null
+++ b/xmake/core/platform/iphoneos/iphoneos.lua
@@ -0,0 +1,141 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file iphoneos.lua
+--
+
+-- define module: iphoneos
+local iphoneos = iphoneos or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+iphoneos._HOST = "macosx"
+
+-- init os
+iphoneos._OS = "ios"
+
+-- init architectures
+iphoneos._ARCHS = {"armv7", "armv7s", "arm64"}
+
+-- make configure
+function iphoneos.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".dylib"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.as = config.get("as")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+ configs.tools.lipo = config.get("lipo")
+
+ -- init target minimal version
+ local target_minver = config.get("target_minver")
+ assert(target_minver)
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then archflags = "-arch " .. arch end
+ configs.cxflags = { archflags, "-miphoneos-version-min=" .. target_minver }
+ configs.mxflags = { archflags, "-miphoneos-version-min=" .. target_minver }
+ configs.asflags = { archflags, "-miphoneos-version-min=" .. target_minver }
+ configs.ldflags = { archflags, "-ObjC", "-lstdc++", "-fobjc-link-runtime", "-miphoneos-version-min=" .. target_minver }
+ configs.shflags = { archflags, "-ObjC", "-lstdc++", "-fobjc-link-runtime", "-miphoneos-version-min=" .. target_minver }
+ if arch then
+ configs.scflags = { string.format("-target %s-apple-ios%s", arch, target_minver) }
+ end
+
+ -- init flags for the xcode sdk directory
+ local xcode_dir = config.get("xcode_dir")
+ local xcode_sdkver = config.get("xcode_sdkver")
+ if xcode_dir and xcode_sdkver then
+
+ -- init flags
+ local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" .. xcode_sdkver .. ".sdk"
+ table.insert(configs.cxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.asflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.mxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.ldflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.shflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.scflags, "-sdk " .. xcode_sdkdir)
+
+ -- save swift link directory
+ config.set("__swift_linkdirs", xcode_dir .. "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos")
+ end
+
+end
+
+-- get the option menu for action: xmake config or global
+function iphoneos.menu(action)
+
+ -- init config option menu
+ iphoneos._MENU_CONFIG = iphoneos._MENU_CONFIG or
+ { {}
+ , {nil, "mm", "kv", nil, "The Objc Compiler" }
+ , {nil, "mxx", "kv", nil, "The Objc++ Compiler" }
+ , {nil, "mflags", "kv", nil, "The Objc Compiler Flags" }
+ , {nil, "mxflags", "kv", nil, "The Objc/c++ Compiler Flags" }
+ , {nil, "mxxflags", "kv", nil, "The Objc++ Compiler Flags" }
+ , {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "The SDK Version for Xcode" }
+ , {nil, "target_minver", "kv", "auto", "The Target Minimal Version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- init global option menu
+ iphoneos._MENU_GLOBAL = iphoneos._MENU_GLOBAL or
+ { {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return iphoneos._MENU_CONFIG
+ elseif action == "global" then
+ return iphoneos._MENU_GLOBAL
+ end
+end
+
+
+-- return module: iphoneos
+return iphoneos
diff --git a/xmake/core/platform/iphoneos/package.lua b/xmake/core/platform/iphoneos/package.lua
new file mode 100644
index 000000000..1e46ddadc
--- /dev/null
+++ b/xmake/core/platform/iphoneos/package.lua
@@ -0,0 +1,76 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file package.lua
+--
+
+-- define module: package
+local package = package or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- package target
+function package.main(target)
+
+ -- check
+ assert(target and target.name)
+
+ -- the count of architectures
+ local count = 0
+ for _, _ in pairs(target.archs) do count = count + 1 end
+ if count < 2 then return 0 end
+
+ -- get the lipo tool
+ local lipo = platform.tool("lipo")
+ if not lipo then return 0 end
+
+ -- make universal info
+ local universal = {}
+ universal.targetdir = rule.backupdir(target.name, "universal")
+ universal.targetfile = rule.targetfile(target.name, target)
+ if not universal.targetdir or not universal.targetfile then return 0 end
+
+ -- make the universal directory
+ os.mkdir(path.directory(string.format("%s/%s", universal.targetdir, universal.targetfile)))
+
+ -- make the lipo command
+ local cmd = lipo .. " -create"
+ for arch, info in pairs(target.archs) do
+ cmd = string.format("%s -arch %s %s/%s", cmd, arch, info.targetdir, info.targetfile)
+ end
+ cmd = string.format("%s -output %s/%s", cmd, universal.targetdir, universal.targetfile)
+
+ -- make the universal target
+ if 0 ~= os.execute(cmd) then return 0 end
+
+ -- ok
+ target.archs.universal = universal
+
+ -- continue
+ return 0
+end
+
+-- return module: package
+return package
diff --git a/xmake/core/platform/iphoneos/prober.lua b/xmake/core/platform/iphoneos/prober.lua
new file mode 100644
index 000000000..0de95c783
--- /dev/null
+++ b/xmake/core/platform/iphoneos/prober.lua
@@ -0,0 +1,310 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "armv7")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the xcode application directory
+function prober._probe_xcode(configs)
+
+ -- get the xcode directory
+ local xcode_dir = configs.get("xcode_dir")
+
+ -- ok?
+ if xcode_dir then return true end
+
+ -- clear it first
+ xcode_dir = nil
+
+ -- attempt to get the default directory
+ if not xcode_dir then
+ if os.isdir("/Applications/Xcode.app") then
+ xcode_dir = "/Applications/Xcode.app"
+ end
+ end
+
+ -- attempt to match the other directories
+ if not xcode_dir then
+ local dirs = os.match("/Applications/Xcode*.app", true)
+ if dirs and table.getn(dirs) ~= 0 then
+ xcode_dir = dirs[1]
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_dir then
+ -- save it
+ configs.set("xcode_dir", xcode_dir)
+
+ -- trace
+ utils.printf("checking for the Xcode application directory ... %s", xcode_dir)
+ else
+ -- failed
+ utils.error("checking for the Xcode application directory ... no")
+ utils.error(" - xmake config --xcode_dir=xxx")
+ utils.error("or - xmake global --xcode_dir=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the xcode sdk version
+function prober._probe_xcode_sdkver(configs)
+
+ -- get the xcode sdk version
+ local xcode_sdkver = configs.get("xcode_sdkver")
+
+ -- ok?
+ if xcode_sdkver then return true end
+
+ -- clear it first
+ xcode_sdkver = nil
+
+ -- attempt to match the directory
+ if not xcode_sdkver then
+ local dirs = os.match(configs.get("xcode_dir") .. "/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS*.sdk", true)
+ if dirs then
+ for _, dir in ipairs(dirs) do
+ xcode_sdkver = string.match(dir, "%d+%.%d+")
+ if xcode_sdkver then break end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_sdkver then
+
+ -- save it
+ configs.set("xcode_sdkver", xcode_sdkver)
+
+ -- trace
+ utils.printf("checking for the Xcode SDK version for %s ... %s", configs.get("plat"), xcode_sdkver)
+ else
+ -- failed
+ utils.error("checking for the Xcode SDK version for %s ... no", configs.get("plat"))
+ utils.error(" - xmake config --xcode_sdkver=xxx")
+ utils.error("or - xmake global --xcode_sdkver=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the target minimal version
+function prober._probe_target_minver(configs)
+
+ -- get the target minimal version
+ local target_minver = configs.get("target_minver")
+
+ -- ok?
+ if target_minver then return true end
+
+ -- init the default target minimal version
+ configs.set("target_minver", "7.0")
+
+ -- trace
+ utils.printf("checking for the target minimal version ... %s", configs.get("target_minver"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "xcrun -sdk iphoneos ", "clang", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "xcrun -sdk iphoneos ", {"clang++", "clang"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "mm", "xcrun -sdk iphoneos ", "clang", "the objc compiler") then return false end
+ if not prober._probe_toolpath(configs, "mxx", "xcrun -sdk iphoneos ", {"clang++", "clang"}, "the objc++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", xmake._CORE_DIR .. "/tools/gas-preprocessor.pl xcrun -sdk iphoneos ", "clang", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "xcrun -sdk iphoneos ", {"clang++", "clang"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "xcrun -sdk iphoneos ", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "xcrun -sdk iphoneos ", {"clang++", "clang"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "xcrun -sdk iphoneos ", "swiftc", "the swift compiler") then return false end
+ if not prober._probe_toolpath(configs, "lipo", "xcrun -sdk iphoneos ", "lipo", "the universal files creater") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_xcode
+ , prober._probe_xcode_sdkver
+ , prober._probe_target_minver
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_xcode
+ , prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/iphonesimulator/iphonesimulator.lua b/xmake/core/platform/iphonesimulator/iphonesimulator.lua
new file mode 100644
index 000000000..4ceeb3eca
--- /dev/null
+++ b/xmake/core/platform/iphonesimulator/iphonesimulator.lua
@@ -0,0 +1,138 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file iphonesimulator.lua
+--
+
+-- define module: iphonesimulator
+local iphonesimulator = iphonesimulator or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+iphonesimulator._HOST = "macosx"
+
+-- init os
+iphonesimulator._OS = "ios"
+
+-- init architectures
+iphonesimulator._ARCHS = {"i386", "x86_64"}
+
+-- make configure
+function iphonesimulator.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".dylib"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- init target minimal version
+ local target_minver = config.get("target_minver")
+ assert(target_minver)
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then archflags = "-arch " .. arch end
+ configs.cxflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.mxflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.asflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.ldflags = { archflags, "-Xlinker -objc_abi_version", "-Xlinker 2 -stdlib=libc++", "-Xlinker -no_implicit_dylibs", "-fobjc-link-runtime", "-mios-simulator-version-min=" .. target_minver }
+ configs.shflags = { archflags, "-Xlinker -objc_abi_version", "-Xlinker 2 -stdlib=libc++", "-Xlinker -no_implicit_dylibs", "-fobjc-link-runtime", "-mios-simulator-version-min=" .. target_minver }
+ if arch then
+ configs.scflags = { string.format("-target %s-apple-ios%s", arch, target_minver) }
+ end
+
+ -- init flags for the xcode sdk directory
+ local xcode_dir = config.get("xcode_dir")
+ local xcode_sdkver = config.get("xcode_sdkver")
+ if xcode_dir and xcode_sdkver then
+
+ -- init flags
+ local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" .. xcode_sdkver .. ".sdk"
+ table.insert(configs.cxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.asflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.mxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.ldflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.shflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.scflags, "-sdk " .. xcode_sdkdir)
+
+ -- save swift link directory
+ config.set("__swift_linkdirs", xcode_dir .. "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator")
+ end
+end
+
+-- get the option menu for action: xmake config or global
+function iphonesimulator.menu(action)
+
+ -- init config option menu
+ iphonesimulator._MENU_CONFIG = iphonesimulator._MENU_CONFIG or
+ { {}
+ , {nil, "mm", "kv", nil, "The Objc Compiler" }
+ , {nil, "mxx", "kv", nil, "The Objc++ Compiler" }
+ , {nil, "mflags", "kv", nil, "The Objc Compiler Flags" }
+ , {nil, "mxflags", "kv", nil, "The Objc/c++ Compiler Flags" }
+ , {nil, "mxxflags", "kv", nil, "The Objc++ Compiler Flags" }
+ , {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "The SDK Version for Xcode" }
+ , {nil, "target_minver", "kv", "auto", "The Target Minimal Version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- init global option menu
+ iphonesimulator._MENU_GLOBAL = iphonesimulator._MENU_GLOBAL or
+ { {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return iphonesimulator._MENU_CONFIG
+ elseif action == "global" then
+ return iphonesimulator._MENU_GLOBAL
+ end
+end
+
+
+-- return module: iphonesimulator
+return iphonesimulator
diff --git a/xmake/core/platform/iphonesimulator/prober.lua b/xmake/core/platform/iphonesimulator/prober.lua
new file mode 100644
index 000000000..a4c69c72a
--- /dev/null
+++ b/xmake/core/platform/iphonesimulator/prober.lua
@@ -0,0 +1,308 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "x86_64")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the xcode application directory
+function prober._probe_xcode(configs)
+
+ -- get the xcode directory
+ local xcode_dir = configs.get("xcode_dir")
+
+ -- ok?
+ if xcode_dir then return true end
+
+ -- clear it first
+ xcode_dir = nil
+
+ -- attempt to get the default directory
+ if not xcode_dir then
+ if os.isdir("/Applications/Xcode.app") then
+ xcode_dir = "/Applications/Xcode.app"
+ end
+ end
+
+ -- attempt to match the other directories
+ if not xcode_dir then
+ local dirs = os.match("/Applications/Xcode*.app", true)
+ if dirs and table.getn(dirs) ~= 0 then
+ xcode_dir = dirs[1]
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_dir then
+ -- save it
+ configs.set("xcode_dir", xcode_dir)
+
+ -- trace
+ utils.printf("checking for the Xcode application directory ... %s", xcode_dir)
+ else
+ -- failed
+ utils.error("checking for the Xcode application directory ... no")
+ utils.error(" - xmake config --xcode_dir=xxx")
+ utils.error("or - xmake global --xcode_dir=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the xcode sdk version
+function prober._probe_xcode_sdkver(configs)
+
+ -- get the xcode sdk version
+ local xcode_sdkver = configs.get("xcode_sdkver")
+
+ -- ok?
+ if xcode_sdkver then return true end
+
+ -- clear it first
+ xcode_sdkver = nil
+
+ -- attempt to match the directory
+ if not xcode_sdkver then
+ local dirs = os.match(configs.get("xcode_dir") .. "/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator*.sdk", true)
+ if dirs then
+ for _, dir in ipairs(dirs) do
+ xcode_sdkver = string.match(dir, "%d+%.%d+")
+ if xcode_sdkver then break end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_sdkver then
+
+ -- save it
+ configs.set("xcode_sdkver", xcode_sdkver)
+
+ -- trace
+ utils.printf("checking for the Xcode SDK version for %s ... %s", configs.get("plat"), xcode_sdkver)
+ else
+ -- failed
+ utils.error("checking for the Xcode SDK version for %s ... no", configs.get("plat"))
+ utils.error(" - xmake config --xcode_sdkver=xxx")
+ utils.error("or - xmake global --xcode_sdkver=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the target minimal version
+function prober._probe_target_minver(configs)
+
+ -- get the target minimal version
+ local target_minver = configs.get("target_minver")
+
+ -- ok?
+ if target_minver then return true end
+
+ -- init the default target minimal version
+ configs.set("target_minver", "7.0")
+
+ -- trace
+ utils.printf("checking for the target minimal version ... %s", configs.get("target_minver"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "xcrun -sdk iphonesimulator ", "clang", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "xcrun -sdk iphonesimulator ", {"clang++", "clang"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "mm", "xcrun -sdk iphonesimulator ", "clang", "the objc compiler") then return false end
+ if not prober._probe_toolpath(configs, "mxx", "xcrun -sdk iphonesimulator ", {"clang++", "clang"}, "the objc++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", "xcrun -sdk iphonesimulator ", "clang", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "xcrun -sdk iphonesimulator ", {"clang++", "clang"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "xcrun -sdk iphonesimulator ", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "xcrun -sdk iphonesimulator ", {"clang++", "clang"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "xcrun -sdk iphonesimulator ", "swiftc", "the swift compiler") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_xcode
+ , prober._probe_xcode_sdkver
+ , prober._probe_target_minver
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_xcode
+ , prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/linux/install.lua b/xmake/core/platform/linux/install.lua
new file mode 100644
index 000000000..870cf5040
--- /dev/null
+++ b/xmake/core/platform/linux/install.lua
@@ -0,0 +1,182 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file install.lua
+--
+
+-- define module: install
+local install = install or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- install target for the library file
+function install._done_library(target)
+
+ -- check
+ assert(target and target.name and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir or "/usr/local"
+ assert(outputdir)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- make the library directory
+ local librarydir = outputdir .. "/lib"
+ if not os.isdir(librarydir) then
+ if not os.mkdir(librarydir) then
+ utils.error("create directory %s failed", librarydir)
+ return -1
+ end
+ end
+
+ -- copy the library file to the library directory
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), string.format("%s/%s", librarydir, path.filename(info.targetfile)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- make the include directory
+ local includedir = outputdir .. "/include"
+ if not os.isdir(includedir) then
+ if not os.mkdir(includedir) then
+ utils.error("create directory %s failed", includedir)
+ return -1
+ end
+ end
+
+ -- copy the config.h to the output directory
+ if info.config_h then
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.config_h), string.format("%s/%s/%s", includedir, target.name, path.filename(info.config_h)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- update the config.h
+ info.config_h = string.format("%s/%s/%s", includedir, target.name, path.filename(info.config_h))
+ end
+
+ -- copy headers
+ if target.headers then
+ local srcheaders, dstheaders = rule.headerfiles(target, includedir)
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ local ok, errors = os.cp(srcheader, dstheader)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ i = i + 1
+ end
+ end
+
+ -- update the headers
+ target.headers = dstheaders
+ end
+
+ -- update the target directory and file
+ info.targetdir = librarydir
+ info.targetfile = path.filename(info.targetfile)
+
+ -- ok
+ return 1
+end
+
+-- install target for the binary file
+function install._done_binary(target)
+
+ -- check
+ assert(target and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir or "/usr/local"
+ assert(outputdir)
+
+ -- make the binary directory
+ local binarydir = outputdir .. "/bin"
+ if not os.isdir(binarydir) then
+ if not os.mkdir(binarydir) then
+ utils.error("create directory %s failed", binarydir)
+ return -1
+ end
+ end
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- copy the binary file to the binary directory
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), binarydir)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- update the target directory and file
+ info.targetdir = binarydir
+ info.targetfile = path.filename(info.targetfile)
+
+ -- ok
+ return 1
+end
+
+-- install target
+function install.main(target)
+
+ -- check
+ assert(target and target.kind)
+
+ -- the install scripts
+ local installscripts =
+ {
+ static = install._done_library
+ , shared = install._done_library
+ , binary = install._done_binary
+ }
+
+ -- install it
+ local installscript = installscripts[target.kind]
+ if installscript then return installscript(target) end
+
+ -- continue
+ return 0
+end
+
+-- return module: install
+return install
diff --git a/xmake/core/platform/linux/linux.lua b/xmake/core/platform/linux/linux.lua
new file mode 100644
index 000000000..406dc5c58
--- /dev/null
+++ b/xmake/core/platform/linux/linux.lua
@@ -0,0 +1,103 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file linux.lua
+--
+
+-- define module: linux
+local linux = linux or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+linux._HOST = "linux"
+
+-- init os
+linux._OS = "linux"
+
+-- init architectures
+linux._ARCHS = {"i386", "x86_64"}
+
+-- make configure
+function linux.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".so"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- cross toolchains?
+ if config.get("cross") then return end
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then
+ if arch == "x86_64" then archflags = "-m64"
+ elseif arch == "i386" then archflags = "-m32"
+ else archflags = "-arch " .. arch
+ end
+ end
+ configs.cxflags = { archflags }
+ configs.mxflags = { archflags }
+ configs.asflags = { archflags }
+ configs.ldflags = { archflags }
+ configs.shflags = { archflags }
+
+ -- init linkdirs and includedirs
+ configs.linkdirs = {"/usr/lib", "/usr/local/lib"}
+ configs.includedirs = {"/usr/include", "/usr/local/include"}
+
+end
+
+-- get the option menu for action: xmake config or global
+function linux.menu(action)
+
+ -- init config option menu
+ linux._MENU_CONFIG = linux._MENU_CONFIG or {}
+
+ -- init global option menu
+ linux._MENU_GLOBAL = linux._MENU_GLOBAL or {}
+
+ -- get the option menu
+ if action == "config" then
+ return linux._MENU_CONFIG
+ elseif action == "global" then
+ return linux._MENU_GLOBAL
+ end
+end
+
+-- return module: linux
+return linux
diff --git a/xmake/core/platform/linux/prober.lua b/xmake/core/platform/linux/prober.lua
new file mode 100644
index 000000000..4e50b13cf
--- /dev/null
+++ b/xmake/core/platform/linux/prober.lua
@@ -0,0 +1,198 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ if configs.get("cross") then
+ configs.set("arch", "none")
+ else
+ configs.set("arch", xmake._ARCH)
+ end
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "", "gcc", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "", {"g++", "gcc"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", "", "gcc", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "", {"g++", "gcc"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "", {"g++", "gcc"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "", "swiftc", "the swift compiler") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/linux/uninstall.lua b/xmake/core/platform/linux/uninstall.lua
new file mode 100644
index 000000000..468692620
--- /dev/null
+++ b/xmake/core/platform/linux/uninstall.lua
@@ -0,0 +1,134 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file uninstall.lua
+--
+
+-- define module: uninstall
+local uninstall = uninstall or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- uninstall target for the library file
+function uninstall._done_library(target)
+
+ -- check
+ assert(target and target.name and target.archs)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- remove the target file
+ local targetfile = info.targetdir .. "/" .. info.targetfile
+ if os.isfile(targetfile) then
+ local ok, errors = os.rm(targetfile)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+
+ -- remove config.h
+ if info.config_h and os.isfile(info.config_h) then
+ local ok, errors = os.rm(info.config_h)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+
+ -- remove headers
+ if target.headers then
+ for _, header in ipairs(target.headers) do
+ if os.isfile(header) then
+ local ok, errors = os.rm(header)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ end
+ end
+
+ -- ok
+ return 1
+end
+
+-- uninstall target for the binary file
+function uninstall._done_binary(target)
+
+ -- check
+ assert(target and target.archs)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- the target file
+ local targetfile = info.targetdir .. "/" .. info.targetfile
+ if not os.isfile(targetfile) then return 1 end
+
+ -- remove the target file
+ local ok, errors = os.rm(targetfile)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- ok
+ return 1
+end
+
+-- uninstall target
+function uninstall.main(target)
+
+ -- check
+ assert(target and target.kind)
+
+ -- the uninstall scripts
+ local uninstallscripts =
+ {
+ static = uninstall._done_library
+ , shared = uninstall._done_library
+ , binary = uninstall._done_binary
+ }
+
+ -- uninstall it
+ local uninstallscript = uninstallscripts[target.kind]
+ if uninstallscript then return uninstallscript(target) end
+
+ -- continue
+ return 0
+end
+
+-- return module: uninstall
+return uninstall
diff --git a/xmake/core/platform/macosx/install.lua b/xmake/core/platform/macosx/install.lua
new file mode 100644
index 000000000..870cf5040
--- /dev/null
+++ b/xmake/core/platform/macosx/install.lua
@@ -0,0 +1,182 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file install.lua
+--
+
+-- define module: install
+local install = install or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- install target for the library file
+function install._done_library(target)
+
+ -- check
+ assert(target and target.name and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir or "/usr/local"
+ assert(outputdir)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- make the library directory
+ local librarydir = outputdir .. "/lib"
+ if not os.isdir(librarydir) then
+ if not os.mkdir(librarydir) then
+ utils.error("create directory %s failed", librarydir)
+ return -1
+ end
+ end
+
+ -- copy the library file to the library directory
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), string.format("%s/%s", librarydir, path.filename(info.targetfile)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- make the include directory
+ local includedir = outputdir .. "/include"
+ if not os.isdir(includedir) then
+ if not os.mkdir(includedir) then
+ utils.error("create directory %s failed", includedir)
+ return -1
+ end
+ end
+
+ -- copy the config.h to the output directory
+ if info.config_h then
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.config_h), string.format("%s/%s/%s", includedir, target.name, path.filename(info.config_h)))
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- update the config.h
+ info.config_h = string.format("%s/%s/%s", includedir, target.name, path.filename(info.config_h))
+ end
+
+ -- copy headers
+ if target.headers then
+ local srcheaders, dstheaders = rule.headerfiles(target, includedir)
+ if srcheaders and dstheaders then
+ local i = 1
+ for _, srcheader in ipairs(srcheaders) do
+ local dstheader = dstheaders[i]
+ if dstheader then
+ local ok, errors = os.cp(srcheader, dstheader)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ i = i + 1
+ end
+ end
+
+ -- update the headers
+ target.headers = dstheaders
+ end
+
+ -- update the target directory and file
+ info.targetdir = librarydir
+ info.targetfile = path.filename(info.targetfile)
+
+ -- ok
+ return 1
+end
+
+-- install target for the binary file
+function install._done_binary(target)
+
+ -- check
+ assert(target and target.archs)
+
+ -- the output directory
+ local outputdir = target.outputdir or "/usr/local"
+ assert(outputdir)
+
+ -- make the binary directory
+ local binarydir = outputdir .. "/bin"
+ if not os.isdir(binarydir) then
+ if not os.mkdir(binarydir) then
+ utils.error("create directory %s failed", binarydir)
+ return -1
+ end
+ end
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- copy the binary file to the binary directory
+ local ok, errors = os.cp(string.format("%s/%s", info.targetdir, info.targetfile), binarydir)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- update the target directory and file
+ info.targetdir = binarydir
+ info.targetfile = path.filename(info.targetfile)
+
+ -- ok
+ return 1
+end
+
+-- install target
+function install.main(target)
+
+ -- check
+ assert(target and target.kind)
+
+ -- the install scripts
+ local installscripts =
+ {
+ static = install._done_library
+ , shared = install._done_library
+ , binary = install._done_binary
+ }
+
+ -- install it
+ local installscript = installscripts[target.kind]
+ if installscript then return installscript(target) end
+
+ -- continue
+ return 0
+end
+
+-- return module: install
+return install
diff --git a/xmake/core/platform/macosx/macosx.lua b/xmake/core/platform/macosx/macosx.lua
new file mode 100644
index 000000000..088a01c18
--- /dev/null
+++ b/xmake/core/platform/macosx/macosx.lua
@@ -0,0 +1,140 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file macosx.lua
+--
+
+-- define module: macosx
+local macosx = macosx or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+macosx._HOST = "macosx"
+
+-- init os
+macosx._OS = "macosx"
+
+-- init architectures
+macosx._ARCHS = {"i386", "x86_64"}
+
+-- make configure
+function macosx.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".dylib"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- init target minimal version
+ local target_minver = config.get("target_minver")
+ assert(target_minver)
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then archflags = "-arch " .. arch end
+ configs.cxflags = { archflags, "-fpascal-strings", "-fmessage-length=0" }
+ configs.mxflags = { archflags, "-fpascal-strings", "-fmessage-length=0" }
+ configs.asflags = { archflags }
+ configs.ldflags = { archflags, "-mmacosx-version-min=" .. target_minver, "-stdlib=libc++", "-lz" }
+ configs.shflags = { archflags, "-mmacosx-version-min=" .. target_minver, "-stdlib=libc++", "-lz" }
+ if arch then
+ configs.scflags = { string.format("-target %s-apple-macosx%s", arch, target_minver) }
+ end
+
+ -- init flags for the xcode sdk directory
+ local xcode_dir = config.get("xcode_dir")
+ local xcode_sdkver = config.get("xcode_sdkver")
+ if xcode_dir and xcode_sdkver then
+
+ -- init flags
+ local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX" .. xcode_sdkver .. ".sdk"
+ table.insert(configs.cxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.asflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.mxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.ldflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.shflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.scflags, "-sdk " .. xcode_sdkdir)
+
+ -- save swift link directory
+ config.set("__swift_linkdirs", xcode_dir .. "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx")
+ end
+
+ -- init linkdirs
+ configs.linkdirs = {"/usr/lib", "/usr/local/lib"}
+
+ -- init includedirs
+ --
+ -- @note
+ -- cannot use configs.includedirs because the swift/objc compiler will compile code failed
+ table.insert(configs.cxflags, "-I/usr/include")
+ table.insert(configs.cxflags, "-I/usr/local/include")
+
+end
+
+-- get the option menu for action: xmake config or global
+function macosx.menu(action)
+
+ -- init config option menu
+ macosx._MENU_CONFIG = macosx._MENU_CONFIG or
+ { {}
+ , {nil, "mm", "kv", nil, "The Objc Compiler" }
+ , {nil, "mxx", "kv", nil, "The Objc++ Compiler" }
+ , {nil, "mflags", "kv", nil, "The Objc Compiler Flags" }
+ , {nil, "mxflags", "kv", nil, "The Objc/c++ Compiler Flags" }
+ , {nil, "mxxflags", "kv", nil, "The Objc++ Compiler Flags" }
+ , {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "The SDK Version for Xcode" }
+ , {nil, "target_minver", "kv", "auto", "The Target Minimal Version" }
+ , }
+
+ -- init global option menu
+ macosx._MENU_GLOBAL = macosx._MENU_GLOBAL or
+ { {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return macosx._MENU_CONFIG
+ elseif action == "global" then
+ return macosx._MENU_GLOBAL
+ end
+end
+
+-- return module: macosx
+return macosx
diff --git a/xmake/core/platform/macosx/prober.lua b/xmake/core/platform/macosx/prober.lua
new file mode 100644
index 000000000..e2571fdd9
--- /dev/null
+++ b/xmake/core/platform/macosx/prober.lua
@@ -0,0 +1,307 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", xmake._ARCH)
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the xcode application directory
+function prober._probe_xcode(configs)
+
+ -- get the xcode directory
+ local xcode_dir = configs.get("xcode_dir")
+
+ -- ok?
+ if xcode_dir then return true end
+
+ -- clear it first
+ xcode_dir = nil
+
+ -- attempt to get the default directory
+ if not xcode_dir then
+ if os.isdir("/Applications/Xcode.app") then
+ xcode_dir = "/Applications/Xcode.app"
+ end
+ end
+
+ -- attempt to match the other directories
+ if not xcode_dir then
+ local dirs = os.match("/Applications/Xcode*.app", true)
+ if dirs and table.getn(dirs) ~= 0 then
+ xcode_dir = dirs[1]
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_dir then
+ -- save it
+ configs.set("xcode_dir", xcode_dir)
+
+ -- trace
+ utils.printf("checking for the Xcode application directory ... %s", xcode_dir)
+ else
+ -- failed
+ utils.error("checking for the Xcode application directory ... no")
+ utils.error(" - xmake config --xcode_dir=xxx")
+ utils.error("or - xmake global --xcode_dir=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the xcode sdk version
+function prober._probe_xcode_sdkver(configs)
+
+ -- get the xcode sdk version
+ local xcode_sdkver = configs.get("xcode_sdkver")
+
+ -- ok?
+ if xcode_sdkver then return true end
+
+ -- clear it first
+ xcode_sdkver = nil
+
+ -- attempt to match the directory
+ if not xcode_sdkver then
+ local dirs = os.match(configs.get("xcode_dir") .. "/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk", true)
+ if dirs then
+ for _, dir in ipairs(dirs) do
+ xcode_sdkver = string.match(dir, "%d+%.%d+")
+ if xcode_sdkver then break end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_sdkver then
+
+ -- save it
+ configs.set("xcode_sdkver", xcode_sdkver)
+
+ -- trace
+ utils.printf("checking for the Xcode SDK version for %s ... %s", configs.get("plat"), xcode_sdkver)
+ else
+ -- failed
+ utils.error("checking for the Xcode SDK version for %s ... no", configs.get("plat"))
+ utils.error(" - xmake config --xcode_sdkver=xxx")
+ utils.error("or - xmake global --xcode_sdkver=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the target minimal version
+function prober._probe_target_minver(configs)
+
+ -- get the target minimal version
+ local target_minver = configs.get("target_minver")
+
+ -- ok?
+ if target_minver then return true end
+
+ -- init the default target minimal version
+ configs.set("target_minver", "10.9")
+
+ -- trace
+ utils.printf("checking for the target minimal version ... %s", configs.get("target_minver"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "xcrun -sdk macosx ", "clang", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "xcrun -sdk macosx ", {"clang++", "clang"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "mm", "xcrun -sdk macosx ", "clang", "the objc compiler") then return false end
+ if not prober._probe_toolpath(configs, "mxx", "xcrun -sdk macosx ", {"clang++", "clang"}, "the objc++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", "xcrun -sdk macosx ", "clang", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "xcrun -sdk macosx ", {"clang++", "clang"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "xcrun -sdk macosx ", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "xcrun -sdk macosx ", {"clang++", "clang"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "xcrun -sdk macosx ", "swiftc", "the swift compiler") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_xcode
+ , prober._probe_xcode_sdkver
+ , prober._probe_target_minver
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_xcode
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/macosx/uninstall.lua b/xmake/core/platform/macosx/uninstall.lua
new file mode 100644
index 000000000..468692620
--- /dev/null
+++ b/xmake/core/platform/macosx/uninstall.lua
@@ -0,0 +1,134 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file uninstall.lua
+--
+
+-- define module: uninstall
+local uninstall = uninstall or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- uninstall target for the library file
+function uninstall._done_library(target)
+
+ -- check
+ assert(target and target.name and target.archs)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- remove the target file
+ local targetfile = info.targetdir .. "/" .. info.targetfile
+ if os.isfile(targetfile) then
+ local ok, errors = os.rm(targetfile)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+
+ -- remove config.h
+ if info.config_h and os.isfile(info.config_h) then
+ local ok, errors = os.rm(info.config_h)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+
+ -- remove headers
+ if target.headers then
+ for _, header in ipairs(target.headers) do
+ if os.isfile(header) then
+ local ok, errors = os.rm(header)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+ end
+ end
+ end
+
+ -- ok
+ return 1
+end
+
+-- uninstall target for the binary file
+function uninstall._done_binary(target)
+
+ -- check
+ assert(target and target.archs)
+
+ -- get target info
+ local info = target.archs[xmake._ARCH] or target.archs["x86_64"] or target.archs["i386"]
+ if not info then return -1 end
+
+ -- check
+ assert(info.targetdir and info.targetfile)
+
+ -- the target file
+ local targetfile = info.targetdir .. "/" .. info.targetfile
+ if not os.isfile(targetfile) then return 1 end
+
+ -- remove the target file
+ local ok, errors = os.rm(targetfile)
+ if not ok then
+ utils.error(errors)
+ return -1
+ end
+
+ -- ok
+ return 1
+end
+
+-- uninstall target
+function uninstall.main(target)
+
+ -- check
+ assert(target and target.kind)
+
+ -- the uninstall scripts
+ local uninstallscripts =
+ {
+ static = uninstall._done_library
+ , shared = uninstall._done_library
+ , binary = uninstall._done_binary
+ }
+
+ -- uninstall it
+ local uninstallscript = uninstallscripts[target.kind]
+ if uninstallscript then return uninstallscript(target) end
+
+ -- continue
+ return 0
+end
+
+-- return module: uninstall
+return uninstall
diff --git a/xmake/core/platform/mingw/mingw.lua b/xmake/core/platform/mingw/mingw.lua
new file mode 100644
index 000000000..7264489b2
--- /dev/null
+++ b/xmake/core/platform/mingw/mingw.lua
@@ -0,0 +1,93 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file mingw.lua
+--
+
+-- define module: mingw
+local mingw = mingw or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+mingw._HOST = xmake._HOST
+
+-- init os
+mingw._OS = "windows"
+
+-- init architectures
+mingw._ARCHS = {"i386", "x86_64"}
+
+-- make configure
+function mingw.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".so"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then
+ if arch == "x86_64" then archflags = "-m64"
+ elseif arch == "i386" then archflags = "-m32"
+ else archflags = "-arch " .. arch
+ end
+ end
+ configs.cxflags = { archflags }
+ configs.asflags = { archflags }
+ configs.ldflags = { archflags }
+ configs.shflags = { archflags }
+
+end
+
+-- get the option menu for action: xmake config or global
+function mingw.menu(action)
+
+ -- init config option menu
+ mingw._MENU_CONFIG = mingw._MENU_CONFIG or {}
+
+ -- init global option menu
+ mingw._MENU_GLOBAL = mingw._MENU_GLOBAL or {}
+
+ -- get the option menu
+ if action == "config" then
+ return mingw._MENU_CONFIG
+ elseif action == "global" then
+ return mingw._MENU_GLOBAL
+ end
+end
+
+-- return module: mingw
+return mingw
diff --git a/xmake/core/platform/mingw/prober.lua b/xmake/core/platform/mingw/prober.lua
new file mode 100644
index 000000000..575e3a7ba
--- /dev/null
+++ b/xmake/core/platform/mingw/prober.lua
@@ -0,0 +1,207 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "i386")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- init the default cross from the current host and architecture
+ local cross = ""
+ local arch = configs.get("arch")
+ if arch then
+ if xmake._HOST == "macosx" and arch == "i386" then
+ cross = "i386-mingw32-"
+ elseif arch == "i386" then
+ cross = "i686-w64-mingw32-"
+ elseif arch == "x86_64" then
+ cross = "x86_64-w64-mingw32-"
+ end
+ end
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", cross, "gcc", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", cross, {"g++", "gcc"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", cross, "gcc", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", cross, {"g++", "gcc"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", cross, "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", cross, {"g++", "gcc"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", cross, "swiftc", "the swift compiler") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/platform.lua b/xmake/core/platform/platform.lua
new file mode 100644
index 000000000..2fc411cbf
--- /dev/null
+++ b/xmake/core/platform/platform.lua
@@ -0,0 +1,385 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file platform.lua
+--
+
+-- define module: platform
+local platform = platform or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local config = require("base/config")
+local global = require("base/global")
+
+-- load prober the given platform directory
+function platform._load_prober(root)
+
+ -- the platform file path
+ local filepath = string.format("%s/prober.lua", root)
+ if os.isfile(filepath) then
+
+ -- load script
+ local script = loadfile(filepath)
+ if script then
+
+ -- load prober
+ local prober = script()
+ if prober then
+
+ -- ok
+ return prober
+ end
+ end
+ end
+end
+
+-- load the given platform from the given root directory
+function platform._load_from(root, plat)
+
+ -- the platform file path
+ local filepath = string.format("%s/platform/%s/%s.lua", root, plat, plat)
+ if os.isfile(filepath) then
+
+ -- load script
+ local script = loadfile(filepath)
+ if script then
+
+ -- load module
+ local module = script()
+ if module then
+
+ -- save directory
+ module._DIRECTORY = path.directory(filepath)
+ assert(module._DIRECTORY)
+
+ -- attempt to load prober
+ module._PROBER = platform._load_prober(module._DIRECTORY)
+
+ -- ok
+ return module
+ end
+ end
+ end
+end
+
+-- load the given platform
+function platform._load(plat)
+
+ -- the module
+ platform._MODULES = platform._MODULES or {}
+ local module = platform._MODULES[plat]
+
+ -- return it directory if ok
+ if module then return module end
+
+ -- attempt to load it from the project configure directory
+ if not module then module = platform._load_from(config.directory(), plat) end
+
+ -- attempt to load it from the global configure directory
+ if not module then module = platform._load_from(global.directory(), plat) end
+
+ -- attempt to load it from the script directory
+ if not module then module = platform._load_from(xmake._CORE_DIR, plat) end
+
+ -- cache it if ok
+ if module then
+ platform._MODULES[plat] = module
+ end
+
+ -- ok?
+ return module
+end
+
+-- get the configure of the given platform
+function platform._configs(plat)
+
+ -- the configure
+ platform._CONFIGS = platform._CONFIGS or {}
+ local configs = platform._CONFIGS[plat]
+
+ -- return it directly if exists
+ if configs then
+ return configs
+ end
+
+ -- load platform
+ local module = platform._load(plat)
+ if module then
+
+ -- init configure
+ platform._CONFIGS[plat]= {}
+ configs = platform._CONFIGS[plat]
+
+ -- make configure
+ module.make(configs)
+ end
+
+ -- ok?
+ return configs
+end
+
+-- get the current platform module
+function platform.module()
+
+ -- load it
+ return platform._load(config.get("plat"))
+end
+
+-- get the current platform module directory
+function platform.directory()
+
+ -- load it
+ local module = platform.module()
+ if module then
+ return module._DIRECTORY
+ end
+end
+
+-- make the current platform configure
+function platform.make()
+
+ -- get the platform
+ local plat = config.get("plat")
+ assert(plat)
+
+ -- make and get the current platform configure
+ return platform._configs(plat)
+end
+
+-- get the platform os
+function platform.os()
+
+ -- get module
+ local module = platform.module()
+ if not module then return end
+
+ -- ok?
+ return module._OS
+end
+
+-- get the given configure
+function platform.get(name)
+
+ -- check
+ assert(platform._CONFIGS)
+
+ -- get the current platform configure
+ local configs = platform._configs(config.get("plat"))
+ if configs then
+ -- get it
+ return configs[name]
+ end
+end
+
+-- get the given tool
+function platform.tool(name)
+
+ -- check
+ assert(name)
+
+ -- get tools
+ local tools = platform.get("tools")
+ if tools then
+ return tools[name]
+ end
+
+end
+
+-- get the given format
+function platform.format(kind)
+
+ -- check
+ assert(kind)
+
+ -- get formats
+ local formats = platform.get("formats")
+ if formats then
+ return formats[kind]
+ end
+
+end
+
+-- dump the platform configure
+function platform.dump()
+
+ -- check
+ assert(platform._CONFIGS)
+
+ -- dump
+ if xmake._OPTIONS.verbose then
+ utils.dump(platform._configs(config.get("plat")))
+ end
+
+end
+
+-- list all platforms
+function platform.plats()
+
+ -- return it directly if exists
+ if platform._PLATS then
+ return platform._PLATS
+ end
+
+ -- make list
+ local list = {}
+
+ -- get the platform list from the project configure directory
+ local plats = os.match(config.directory() .. "/platform/*", true)
+ if plats then
+ for _, v in ipairs(plats) do
+ table.insert(list, path.basename(v))
+ end
+ end
+
+ -- get the platform list from the global configure directory
+ plats = os.match(global.directory() .. "/platform/*", true)
+ if plats then
+ for _, v in ipairs(plats) do
+ table.insert(list, path.basename(v))
+ end
+ end
+
+ -- get the platform list from the script directory
+ plats = os.match(xmake._CORE_DIR .. "/platform/*", true)
+ if plats then
+ for _, v in ipairs(plats) do
+ table.insert(list, path.basename(v))
+ end
+ end
+
+ -- save it
+ platform._PLATS = list
+
+ -- ok
+ return list
+end
+
+-- list all architectures
+function platform.archs(plat)
+
+ -- check
+ assert(plat)
+
+ -- load all platform configs
+ local archs = {}
+ local module = platform._load(plat)
+ if module and module._ARCHS then
+ for _, arch in ipairs(module._ARCHS) do
+ table.insert(archs, arch)
+ end
+ end
+
+ -- ok
+ return archs
+end
+
+-- get the option menu for action: xmake config or global
+function platform.menu(action)
+
+ -- check
+ assert(action)
+
+ -- get all platforms
+ local plats = platform.plats()
+ assert(plats)
+
+ -- load and merge all platform menus
+ local menus = {}
+ local exist = {}
+ for _, plat in ipairs(plats) do
+
+ -- load platform
+ local module = platform._load(plat)
+ if module and module.menu then
+
+ -- get the platform menu
+ local menu = module.menu(action)
+ if menu then
+
+ -- exists options?
+ local exists = false
+ for _, option in ipairs(menu) do
+ local name = option[2]
+ if name and not exist[name] then
+ exists = true
+ break
+ end
+ end
+
+ -- merge it and remove repeat if exists options
+ if exists then
+ -- get the platform menu option
+ for _, option in ipairs(menu) do
+
+ -- merge it and remove repeat
+ local name = option[2]
+ if name then
+ if not exist[name] then
+ table.insert(menus, option)
+ exist[name] = true
+ end
+ else
+ table.insert(menus, option)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ -- get all platform menus
+ return menus
+end
+
+-- probe the platform configure
+function platform.probe(is_global)
+
+ -- probe global
+ if is_global then
+
+ -- get all platforms
+ local plats = platform.plats()
+ assert(plats)
+
+ -- probe all platforms with the current host
+ for _, plat in ipairs(plats) do
+ local module = platform._load(plat)
+ if module and module._PROBER and module._PROBER.global and module._HOST and module._HOST == xmake._HOST then
+ if not module._PROBER.global() then return false end
+ end
+ end
+
+ -- probe config
+ else
+ -- probe it
+ local module = platform.module()
+ if module and module._PROBER and module._PROBER.config then
+ if not module._PROBER.config() then return false end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: platform
+return platform
diff --git a/xmake/core/platform/watchos/package.lua b/xmake/core/platform/watchos/package.lua
new file mode 100644
index 000000000..1e46ddadc
--- /dev/null
+++ b/xmake/core/platform/watchos/package.lua
@@ -0,0 +1,76 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file package.lua
+--
+
+-- define module: package
+local package = package or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local rule = require("base/rule")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- package target
+function package.main(target)
+
+ -- check
+ assert(target and target.name)
+
+ -- the count of architectures
+ local count = 0
+ for _, _ in pairs(target.archs) do count = count + 1 end
+ if count < 2 then return 0 end
+
+ -- get the lipo tool
+ local lipo = platform.tool("lipo")
+ if not lipo then return 0 end
+
+ -- make universal info
+ local universal = {}
+ universal.targetdir = rule.backupdir(target.name, "universal")
+ universal.targetfile = rule.targetfile(target.name, target)
+ if not universal.targetdir or not universal.targetfile then return 0 end
+
+ -- make the universal directory
+ os.mkdir(path.directory(string.format("%s/%s", universal.targetdir, universal.targetfile)))
+
+ -- make the lipo command
+ local cmd = lipo .. " -create"
+ for arch, info in pairs(target.archs) do
+ cmd = string.format("%s -arch %s %s/%s", cmd, arch, info.targetdir, info.targetfile)
+ end
+ cmd = string.format("%s -output %s/%s", cmd, universal.targetdir, universal.targetfile)
+
+ -- make the universal target
+ if 0 ~= os.execute(cmd) then return 0 end
+
+ -- ok
+ target.archs.universal = universal
+
+ -- continue
+ return 0
+end
+
+-- return module: package
+return package
diff --git a/xmake/core/platform/watchos/prober.lua b/xmake/core/platform/watchos/prober.lua
new file mode 100644
index 000000000..1a818dfdf
--- /dev/null
+++ b/xmake/core/platform/watchos/prober.lua
@@ -0,0 +1,310 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "armv7")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the xcode application directory
+function prober._probe_xcode(configs)
+
+ -- get the xcode directory
+ local xcode_dir = configs.get("xcode_dir")
+
+ -- ok?
+ if xcode_dir then return true end
+
+ -- clear it first
+ xcode_dir = nil
+
+ -- attempt to get the default directory
+ if not xcode_dir then
+ if os.isdir("/Applications/Xcode.app") then
+ xcode_dir = "/Applications/Xcode.app"
+ end
+ end
+
+ -- attempt to match the other directories
+ if not xcode_dir then
+ local dirs = os.match("/Applications/Xcode*.app", true)
+ if dirs and table.getn(dirs) ~= 0 then
+ xcode_dir = dirs[1]
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_dir then
+ -- save it
+ configs.set("xcode_dir", xcode_dir)
+
+ -- trace
+ utils.printf("checking for the Xcode application directory ... %s", xcode_dir)
+ else
+ -- failed
+ utils.error("checking for the Xcode application directory ... no")
+ utils.error(" - xmake config --xcode_dir=xxx")
+ utils.error("or - xmake global --xcode_dir=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the xcode sdk version
+function prober._probe_xcode_sdkver(configs)
+
+ -- get the xcode sdk version
+ local xcode_sdkver = configs.get("xcode_sdkver")
+
+ -- ok?
+ if xcode_sdkver then return true end
+
+ -- clear it first
+ xcode_sdkver = nil
+
+ -- attempt to match the directory
+ if not xcode_sdkver then
+ local dirs = os.match(configs.get("xcode_dir") .. "/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS*.sdk", true)
+ if dirs then
+ for _, dir in ipairs(dirs) do
+ xcode_sdkver = string.match(dir, "%d+%.%d+")
+ if xcode_sdkver then break end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_sdkver then
+
+ -- save it
+ configs.set("xcode_sdkver", xcode_sdkver)
+
+ -- trace
+ utils.printf("checking for the Xcode SDK version for %s ... %s", configs.get("plat"), xcode_sdkver)
+ else
+ -- failed
+ utils.error("checking for the Xcode SDK version for %s ... no", configs.get("plat"))
+ utils.error(" - xmake config --xcode_sdkver=xxx")
+ utils.error("or - xmake global --xcode_sdkver=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the target minimal version
+function prober._probe_target_minver(configs)
+
+ -- get the target minimal version
+ local target_minver = configs.get("target_minver")
+
+ -- ok?
+ if target_minver then return true end
+
+ -- init the default target minimal version
+ configs.set("target_minver", "7.0")
+
+ -- trace
+ utils.printf("checking for the target minimal version ... %s", configs.get("target_minver"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "xcrun -sdk watchos ", "clang", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "xcrun -sdk watchos ", {"clang++", "clang"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "mm", "xcrun -sdk watchos ", "clang", "the objc compiler") then return false end
+ if not prober._probe_toolpath(configs, "mxx", "xcrun -sdk watchos ", {"clang++", "clang"}, "the objc++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", xmake._CORE_DIR .. "/tools/gas-preprocessor.pl xcrun -sdk watchos ", "clang", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "xcrun -sdk watchos ", {"clang++", "clang"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "xcrun -sdk watchos ", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "xcrun -sdk watchos ", {"clang++", "clang"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "xcrun -sdk watchos ", "swiftc", "the swift compiler") then return false end
+ if not prober._probe_toolpath(configs, "lipo", "xcrun -sdk watchos ", "lipo", "the universal files creater") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_xcode
+ , prober._probe_xcode_sdkver
+ , prober._probe_target_minver
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_xcode
+ , prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/watchos/watchos.lua b/xmake/core/platform/watchos/watchos.lua
new file mode 100644
index 000000000..9551084f8
--- /dev/null
+++ b/xmake/core/platform/watchos/watchos.lua
@@ -0,0 +1,141 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file watchos.lua
+--
+
+-- define module: watchos
+local watchos = watchos or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+watchos._HOST = "macosx"
+
+-- init os
+watchos._OS = "ios"
+
+-- init architectures
+watchos._ARCHS = {"armv7", "armv7s", "arm64"}
+
+-- make configure
+function watchos.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".dylib"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.as = config.get("as")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+ configs.tools.lipo = config.get("lipo")
+
+ -- init target minimal version
+ local target_minver = config.get("target_minver")
+ assert(target_minver)
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then archflags = "-arch " .. arch end
+ configs.cxflags = { archflags, "-mwatchos-version-min=" .. target_minver }
+ configs.mxflags = { archflags, "-mwatchos-version-min=" .. target_minver }
+ configs.asflags = { archflags, "-mwatchos-version-min=" .. target_minver }
+ configs.ldflags = { archflags, "-ObjC", "-lstdc++", "-fobjc-link-runtime", "-mwatchos-version-min=" .. target_minver }
+ configs.shflags = { archflags, "-ObjC", "-lstdc++", "-fobjc-link-runtime", "-mwatchos-version-min=" .. target_minver }
+ if arch then
+ configs.scflags = { string.format("-target %s-apple-ios%s", arch, target_minver) }
+ end
+
+ -- init flags for the xcode sdk directory
+ local xcode_dir = config.get("xcode_dir")
+ local xcode_sdkver = config.get("xcode_sdkver")
+ if xcode_dir and xcode_sdkver then
+
+ -- init flags
+ local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS" .. xcode_sdkver .. ".sdk"
+ table.insert(configs.cxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.asflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.mxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.ldflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.shflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.scflags, "-sdk " .. xcode_sdkdir)
+
+ -- save swift link directory
+ config.set("__swift_linkdirs", xcode_dir .. "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/watchos")
+ end
+
+end
+
+-- get the option menu for action: xmake config or global
+function watchos.menu(action)
+
+ -- init config option menu
+ watchos._MENU_CONFIG = watchos._MENU_CONFIG or
+ { {}
+ , {nil, "mm", "kv", nil, "The Objc Compiler" }
+ , {nil, "mxx", "kv", nil, "The Objc++ Compiler" }
+ , {nil, "mflags", "kv", nil, "The Objc Compiler Flags" }
+ , {nil, "mxflags", "kv", nil, "The Objc/c++ Compiler Flags" }
+ , {nil, "mxxflags", "kv", nil, "The Objc++ Compiler Flags" }
+ , {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "The SDK Version for Xcode" }
+ , {nil, "target_minver", "kv", "auto", "The Target Minimal Version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- init global option menu
+ watchos._MENU_GLOBAL = watchos._MENU_GLOBAL or
+ { {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return watchos._MENU_CONFIG
+ elseif action == "global" then
+ return watchos._MENU_GLOBAL
+ end
+end
+
+
+-- return module: watchos
+return watchos
diff --git a/xmake/core/platform/watchsimulator/prober.lua b/xmake/core/platform/watchsimulator/prober.lua
new file mode 100644
index 000000000..d33059c36
--- /dev/null
+++ b/xmake/core/platform/watchsimulator/prober.lua
@@ -0,0 +1,308 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+local config = require("base/config")
+local global = require("base/global")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "x86_64")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the xcode application directory
+function prober._probe_xcode(configs)
+
+ -- get the xcode directory
+ local xcode_dir = configs.get("xcode_dir")
+
+ -- ok?
+ if xcode_dir then return true end
+
+ -- clear it first
+ xcode_dir = nil
+
+ -- attempt to get the default directory
+ if not xcode_dir then
+ if os.isdir("/Applications/Xcode.app") then
+ xcode_dir = "/Applications/Xcode.app"
+ end
+ end
+
+ -- attempt to match the other directories
+ if not xcode_dir then
+ local dirs = os.match("/Applications/Xcode*.app", true)
+ if dirs and table.getn(dirs) ~= 0 then
+ xcode_dir = dirs[1]
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_dir then
+ -- save it
+ configs.set("xcode_dir", xcode_dir)
+
+ -- trace
+ utils.printf("checking for the Xcode application directory ... %s", xcode_dir)
+ else
+ -- failed
+ utils.error("checking for the Xcode application directory ... no")
+ utils.error(" - xmake config --xcode_dir=xxx")
+ utils.error("or - xmake global --xcode_dir=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the xcode sdk version
+function prober._probe_xcode_sdkver(configs)
+
+ -- get the xcode sdk version
+ local xcode_sdkver = configs.get("xcode_sdkver")
+
+ -- ok?
+ if xcode_sdkver then return true end
+
+ -- clear it first
+ xcode_sdkver = nil
+
+ -- attempt to match the directory
+ if not xcode_sdkver then
+ local dirs = os.match(configs.get("xcode_dir") .. "/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator*.sdk", true)
+ if dirs then
+ for _, dir in ipairs(dirs) do
+ xcode_sdkver = string.match(dir, "%d+%.%d+")
+ if xcode_sdkver then break end
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if xcode_sdkver then
+
+ -- save it
+ configs.set("xcode_sdkver", xcode_sdkver)
+
+ -- trace
+ utils.printf("checking for the Xcode SDK version for %s ... %s", configs.get("plat"), xcode_sdkver)
+ else
+ -- failed
+ utils.error("checking for the Xcode SDK version for %s ... no", configs.get("plat"))
+ utils.error(" - xmake config --xcode_sdkver=xxx")
+ utils.error("or - xmake global --xcode_sdkver=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the target minimal version
+function prober._probe_target_minver(configs)
+
+ -- get the target minimal version
+ local target_minver = configs.get("target_minver")
+
+ -- ok?
+ if target_minver then return true end
+
+ -- init the default target minimal version
+ configs.set("target_minver", "7.0")
+
+ -- trace
+ utils.printf("checking for the target minimal version ... %s", configs.get("target_minver"))
+
+ -- ok
+ return true
+end
+
+-- probe the make
+function prober._probe_make(configs)
+
+ -- ok?
+ local make = configs.get("make")
+ if make then return true end
+
+ -- probe the make path
+ make = tools.probe("make", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if make then configs.set("make", make) end
+
+ -- trace
+ utils.printf("checking for the make ... %s", utils.ifelse(make, make, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the ccache
+function prober._probe_ccache(configs)
+
+ -- ok?
+ local ccache_enable = configs.get("ccache")
+ if ccache_enable and configs.get("__ccache") then return true end
+
+ -- disable?
+ if type(ccache_enable) == "boolean" and not ccache_enable then
+ configs.set("__ccache", nil)
+ return true
+ end
+
+ -- probe the ccache path
+ local ccache_path = tools.probe("ccache", {"/usr/bin", "/usr/local/bin", "/opt/bin", "/opt/local/bin"})
+
+ -- probe ok? update it
+ if ccache_path then
+ configs.set("ccache", true)
+ configs.set("__ccache", ccache_path)
+ else
+ configs.set("ccache", false)
+ end
+
+ -- trace
+ utils.printf("checking for the ccache ... %s", utils.ifelse(ccache_path, ccache_path, "no"))
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, cross, names, description)
+
+ -- check
+ assert(kind)
+
+ -- get the cross
+ cross = configs.get("cross") or cross
+
+ -- done
+ local toolpath = nil
+ local toolchains = configs.get("toolchains")
+ for _, name in ipairs(utils.wrap(names)) do
+
+ -- attempt to get it from the given cross toolchains
+ if toolchains then
+ toolpath = tools.probe(cross .. (configs.get(kind) or name), toolchains)
+ end
+
+ -- attempt to get it directly from the configure
+ if not toolpath then
+ toolpath = configs.get(kind)
+ end
+
+ -- attempt to run it directly
+ if not toolpath then
+ toolpath = tools.probe(cross .. name)
+ end
+
+ -- probe ok?
+ if toolpath then
+
+ -- update config
+ configs.set(kind, toolpath)
+
+ -- end
+ break
+ end
+
+ end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "xcrun -sdk watchsimulator ", "clang", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "xcrun -sdk watchsimulator ", {"clang++", "clang"}, "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "mm", "xcrun -sdk watchsimulator ", "clang", "the objc compiler") then return false end
+ if not prober._probe_toolpath(configs, "mxx", "xcrun -sdk watchsimulator ", {"clang++", "clang"}, "the objc++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", "xcrun -sdk watchsimulator ", "clang", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "xcrun -sdk watchsimulator ", {"clang++", "clang"}, "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "xcrun -sdk watchsimulator ", "ar", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "xcrun -sdk watchsimulator ", {"clang++", "clang"}, "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "sc", "xcrun -sdk watchsimulator ", "swiftc", "the swift compiler") then return false end
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_xcode
+ , prober._probe_xcode_sdkver
+ , prober._probe_target_minver
+ , prober._probe_make
+ , prober._probe_ccache
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_xcode
+ , prober._probe_make
+ , prober._probe_ccache}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/watchsimulator/watchsimulator.lua b/xmake/core/platform/watchsimulator/watchsimulator.lua
new file mode 100644
index 000000000..a13bfde1e
--- /dev/null
+++ b/xmake/core/platform/watchsimulator/watchsimulator.lua
@@ -0,0 +1,138 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file watchsimulator.lua
+--
+
+-- define module: watchsimulator
+local watchsimulator = watchsimulator or {}
+
+-- load modules
+local config = require("base/config")
+
+-- init host
+watchsimulator._HOST = "macosx"
+
+-- init os
+watchsimulator._OS = "ios"
+
+-- init architectures
+watchsimulator._ARCHS = {"i386", "x86_64"}
+
+-- make configure
+function watchsimulator.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"lib", ".a"}
+ configs.formats.object = {"", ".o"}
+ configs.formats.shared = {"lib", ".dylib"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.ccache = config.get("__ccache")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.mm = config.get("mm")
+ configs.tools.mxx = config.get("mxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.ex = config.get("ar")
+ configs.tools.sc = config.get("sc")
+
+ -- init target minimal version
+ local target_minver = config.get("target_minver")
+ assert(target_minver)
+
+ -- init flags for architecture
+ local archflags = nil
+ local arch = config.get("arch")
+ if arch then archflags = "-arch " .. arch end
+ configs.cxflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.mxflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.asflags = { archflags, "-mios-simulator-version-min=" .. target_minver }
+ configs.ldflags = { archflags, "-Xlinker -objc_abi_version", "-Xlinker 2 -stdlib=libc++", "-Xlinker -no_implicit_dylibs", "-fobjc-link-runtime", "-mios-simulator-version-min=" .. target_minver }
+ configs.shflags = { archflags, "-Xlinker -objc_abi_version", "-Xlinker 2 -stdlib=libc++", "-Xlinker -no_implicit_dylibs", "-fobjc-link-runtime", "-mios-simulator-version-min=" .. target_minver }
+ if arch then
+ configs.scflags = { string.format("-target %s-apple-ios%s", arch, target_minver) }
+ end
+
+ -- init flags for the xcode sdk directory
+ local xcode_dir = config.get("xcode_dir")
+ local xcode_sdkver = config.get("xcode_sdkver")
+ if xcode_dir and xcode_sdkver then
+
+ -- init flags
+ local xcode_sdkdir = xcode_dir .. "/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs/WatchSimulator" .. xcode_sdkver .. ".sdk"
+ table.insert(configs.cxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.asflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.mxflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.ldflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.shflags, "-isysroot " .. xcode_sdkdir)
+ table.insert(configs.scflags, "-sdk " .. xcode_sdkdir)
+
+ -- save swift link directory
+ config.set("__swift_linkdirs", xcode_dir .. "/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/watchsimulator")
+ end
+end
+
+-- get the option menu for action: xmake config or global
+function watchsimulator.menu(action)
+
+ -- init config option menu
+ watchsimulator._MENU_CONFIG = watchsimulator._MENU_CONFIG or
+ { {}
+ , {nil, "mm", "kv", nil, "The Objc Compiler" }
+ , {nil, "mxx", "kv", nil, "The Objc++ Compiler" }
+ , {nil, "mflags", "kv", nil, "The Objc Compiler Flags" }
+ , {nil, "mxflags", "kv", nil, "The Objc/c++ Compiler Flags" }
+ , {nil, "mxxflags", "kv", nil, "The Objc++ Compiler Flags" }
+ , {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {nil, "xcode_sdkver", "kv", "auto", "The SDK Version for Xcode" }
+ , {nil, "target_minver", "kv", "auto", "The Target Minimal Version" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- init global option menu
+ watchsimulator._MENU_GLOBAL = watchsimulator._MENU_GLOBAL or
+ { {}
+ , {nil, "xcode_dir", "kv", "auto", "The Xcode Application Directory" }
+ , {}
+ , {nil, "mobileprovision","kv", "auto", "The Provisioning Profile File" }
+ , {nil, "codesign", "kv", "auto", "The Code Signing Indentity" }
+ , {nil, "entitlements", "kv", "auto", "The Code Signing Entitlements" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return watchsimulator._MENU_CONFIG
+ elseif action == "global" then
+ return watchsimulator._MENU_GLOBAL
+ end
+end
+
+
+-- return module: watchsimulator
+return watchsimulator
diff --git a/xmake/core/platform/windows/prober.lua b/xmake/core/platform/windows/prober.lua
new file mode 100644
index 000000000..40d214efd
--- /dev/null
+++ b/xmake/core/platform/windows/prober.lua
@@ -0,0 +1,300 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file prober.lua
+--
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local global = require("base/global")
+local tools = require("tools/tools")
+local platform = require("platform/platform")
+
+-- define module: prober
+local prober = prober or {}
+
+-- probe the architecture
+function prober._probe_arch(configs)
+
+ -- get the architecture
+ local arch = configs.get("arch")
+
+ -- ok?
+ if arch then return true end
+
+ -- init the default architecture
+ configs.set("arch", "x86")
+
+ -- trace
+ utils.printf("checking for the architecture ... %s", configs.get("arch"))
+
+ -- ok
+ return true
+end
+
+-- probe the vs version
+function prober._probe_vs_version(configs)
+
+ -- get the vs version
+ local vs = configs.get("vs")
+
+ -- ok?
+ if vs then return true end
+
+ -- clear it first
+ vs = nil
+
+ -- make the map table
+ local map =
+ {
+ VS140COMNTOOLS = "2015"
+ , VS120COMNTOOLS = "2013"
+ , VS110COMNTOOLS = "2012"
+ , VS100COMNTOOLS = "2010"
+ , VS90COMNTOOLS = "2008"
+ , VS80COMNTOOLS = "2005"
+ , VS71COMNTOOLS = "2003"
+ , VS70COMNTOOLS = "7.0"
+ , VS60COMNTOOLS = "6.0"
+ , VS50COMNTOOLS = "5.0"
+ , VS42COMNTOOLS = "4.2"
+ }
+
+ -- attempt to get it from the envirnoment variable
+ if not vs then
+ for k, v in pairs(map) do
+ if os.getenv(k) then
+ vs = v
+ break
+ end
+ end
+ end
+
+ -- probe ok? update it
+ if vs then
+ -- save it
+ configs.set("vs", vs)
+
+ -- trace
+ utils.printf("checking for the Microsoft Visual Studio version ... %s", vs)
+ else
+ -- failed
+ utils.error("checking for the Microsoft Visual Studio version ... no")
+ utils.error(" - xmake config --vs=xxx")
+ utils.error("or - xmake global --vs=xxx")
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the vs path
+function prober._probe_vs_path(configs)
+
+ -- ok?
+ if configs.get("__vsenv_path") then return true end
+
+ -- get the vs version
+ local vs = configs.get("vs")
+ assert(vs)
+
+ -- make the map table
+ local map =
+ {
+ ["2015"] = "VS140COMNTOOLS"
+ , ["2013"] = "VS120COMNTOOLS"
+ , ["2012"] = "VS110COMNTOOLS"
+ , ["2010"] = "VS100COMNTOOLS"
+ , ["2008"] = "VS90COMNTOOLS"
+ , ["2005"] = "VS80COMNTOOLS"
+ , ["2003"] = "VS71COMNTOOLS"
+ , ["7.0"] = "VS70COMNTOOLS"
+ , ["6.0"] = "VS60COMNTOOLS"
+ , ["5.0"] = "VS50COMNTOOLS"
+ , ["4.2"] = "VS42COMNTOOLS"
+ }
+
+ -- attempt to get the vs directory from the envirnoment variable
+ local vsdir = map[vs]
+ if vsdir then
+ vsdir = os.getenv(vsdir)
+ end
+ if vsdir then
+ vsdir = vsdir .. "\\..\\.."
+ end
+ if not os.isdir(vsdir) then
+ -- error
+ utils.error("not found %s", vsdir)
+ return false
+ end
+
+ -- the vcvarsall.bat path
+ local vcvarsall = vsdir .. "\\VC\\vcvarsall.bat"
+ if not os.isfile(vcvarsall) then
+ -- error
+ utils.error("not found %s", vcvarsall)
+ return false
+ end
+
+ -- get the temporary directory
+ local tmpdir = os.tmpdir()
+ assert(tmpdir)
+
+ -- make the call(vcvarsall.bat) file
+ local callpath = tmpdir .. "\\call_vcvarsall.bat"
+ local callfile = io.openmk(callpath)
+ assert(callfile)
+
+ -- make call scripts
+ callfile:write("@echo off\n")
+ callfile:write(string.format("call \"%s\" %s > nul\n", vcvarsall, configs.get("arch")))
+ callfile:write("echo return \n")
+ callfile:write("echo { \n")
+ callfile:write("echo path = \"%path%\"\n")
+ callfile:write("echo , lib = \"%lib%\"\n")
+ callfile:write("echo , libpath = \"%libpath%\"\n")
+ callfile:write("echo , include = \"%include%\"\n")
+ callfile:write("echo , devenvdir = \"%devenvdir%\"\n")
+ callfile:write("echo , vsinstalldir = \"%vsinstalldir%\"\n")
+ callfile:write("echo , vcinstalldir = \"%vcinstalldir%\"\n")
+ callfile:write("echo } \n")
+
+ -- close the file
+ callfile:close()
+
+ -- execute the call(vsvars32.bat) file and get all envirnoment variables
+ local cmd = io.popen(callpath)
+ local results = cmd:read("*all")
+ cmd:close()
+
+ -- translate '\' => '\\'
+ results = results:gsub("\\", "\\\\")
+
+ -- get all envirnoment variables
+ local variables = assert(loadstring(results))()
+ if not variables or not variables.path then
+ return false
+ end
+
+ -- save the variables
+ for k, v in pairs(variables) do
+ configs.set("__vsenv_" .. k, v)
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the tool path
+function prober._probe_toolpath(configs, kind, name, description)
+
+ -- check
+ assert(kind)
+
+ -- attempt to get it directly from the configure
+ local toolpath = configs.get(kind)
+ if toolpath then return true end
+
+ -- make cmd
+ local cmd = string.format("%s > %s 2>&1", name, xmake._NULDEV)
+ if kind == "ld" then
+ cmd = string.format("%s nul > %s 2>&1", name, xmake._NULDEV)
+ end
+
+ -- attempt to run it directly first
+ if not toolpath and os.execute(cmd) ~= 1 then
+ toolpath = name
+ end
+
+ -- probe ok? update it
+ if toolpath then configs.set(kind, toolpath) end
+
+ -- trace
+ if toolpath then
+ utils.printf("checking for %s (%s) ... %s", description, kind, path.filename(toolpath))
+ else
+ utils.printf("checking for %s (%s) ... no", description, kind)
+ end
+
+ -- failed?
+ if not toolpath and (kind == "cc" or kind == "ld" or kind == "make") then
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+-- probe the toolchains
+function prober._probe_toolchains(configs)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- done
+ if not prober._probe_toolpath(configs, "cc", "cl.exe", "the c compiler") then return false end
+ if not prober._probe_toolpath(configs, "cxx", "cl.exe", "the c++ compiler") then return false end
+ if not prober._probe_toolpath(configs, "as", "ml.exe", "the assember") then return false end
+ if not prober._probe_toolpath(configs, "ld", "link.exe", "the linker") then return false end
+ if not prober._probe_toolpath(configs, "ar", "link.exe -lib", "the static library linker") then return false end
+ if not prober._probe_toolpath(configs, "sh", "link.exe -dll", "the shared library linker") then return false end
+ if not prober._probe_toolpath(configs, "ex", "lib.exe", "the library extractor") then return false end
+ if not prober._probe_toolpath(configs, "make", "nmake.exe", "the make") then return false end
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok
+ return true
+end
+
+-- probe the project configure
+function prober.config()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_arch
+ , prober._probe_vs_version
+ , prober._probe_vs_path
+ , prober._probe_toolchains}
+ , nil
+ , config)
+end
+
+-- probe the global configure
+function prober.global()
+
+ -- call all probe functions
+ return utils.call( { prober._probe_vs_version
+ , prober._probe_vs_path}
+ , nil
+ , global)
+end
+
+-- return module: prober
+return prober
diff --git a/xmake/core/platform/windows/tools/cl.lua b/xmake/core/platform/windows/tools/cl.lua
new file mode 100644
index 000000000..299960bb8
--- /dev/null
+++ b/xmake/core/platform/windows/tools/cl.lua
@@ -0,0 +1,139 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file cl.lua
+--
+
+-- define module: cl
+local cl = cl or {}
+
+-- load modules
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- init the compiler
+function cl.init(self, name)
+
+ -- save name
+ self.name = name or "cl.exe"
+
+ -- init cxflags
+ self.cxflags = { "-nologo", "-Gd", "-MP4", "-D_MBCS", "-D_CRT_SECURE_NO_WARNINGS"}
+
+ -- init flags map
+ self.mapflags =
+ {
+ -- optimize
+ ["-O0"] = "-Od"
+ , ["-O3"] = "-Ot"
+ , ["-Ofast"] = "-Ox"
+ , ["-fomit-frame-pointer"] = "-Oy"
+
+ -- symbols
+ , ["-g"] = "-Z7"
+ , ["-fvisibility=.*"] = ""
+
+ -- warnings
+ , ["-Wall"] = "-W3" -- = "-Wall" will enable too more warnings
+ , ["-W1"] = "-W1"
+ , ["-W2"] = "-W2"
+ , ["-W3"] = "-W3"
+ , ["-Werror"] = "-WX"
+ , ["%-Wno%-error=.*"] = ""
+ , ["%-fno%-.*"] = ""
+
+ -- vectorexts
+ , ["-mmmx"] = "-arch:MMX"
+ , ["-msse"] = "-arch:SSE"
+ , ["-msse2"] = "-arch:SSE2"
+ , ["-msse3"] = "-arch:SSE3"
+ , ["-mssse3"] = "-arch:SSSE3"
+ , ["-mavx"] = "-arch:AVX"
+ , ["-mavx2"] = "-arch:AVX2"
+ , ["-mfpu=.*"] = ""
+
+ -- language
+ , ["-ansi"] = ""
+ , ["-std=c99"] = "-TP" -- compile as c++ files because msvc only support c89
+ , ["-std=gnu99"] = "-TP" -- compile as c++ files because msvc only support c89
+ , ["-std=.*"] = ""
+
+ -- others
+ , ["-ftrapv"] = ""
+ , ["-fsanitize=address"] = ""
+ }
+
+end
+
+-- make the compiler command
+function cl.command_compile(self, srcfile, objfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s -c %s -Fo%s %s%s", self.name, flags, objfile, srcfile, redirect)
+end
+
+-- make the define flag
+function cl.flag_define(self, define)
+
+ -- make it
+ return "-D" .. define:gsub("\"", "\\\"")
+end
+
+-- make the undefine flag
+function cl.flag_undefine(self, undefine)
+
+ -- make it
+ return "-U" .. undefine
+end
+
+-- make the includedir flag
+function cl.flag_includedir(self, includedir)
+
+ -- make it
+ return "-I" .. includedir
+end
+
+-- the main function
+function cl.main(self, cmd)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: cl
+return cl
diff --git a/xmake/core/platform/windows/tools/lib.lua b/xmake/core/platform/windows/tools/lib.lua
new file mode 100644
index 000000000..1d94152cc
--- /dev/null
+++ b/xmake/core/platform/windows/tools/lib.lua
@@ -0,0 +1,138 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file lib.lua
+--
+
+-- define module: lib
+local lib = lib or {}
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- init the compiler
+function lib.init(self, name)
+
+ -- save name
+ self.name = name or "lib.exe"
+
+end
+
+-- extract the static library to object files
+function lib.extract(self, ...)
+
+ -- check
+ local args = ...
+ assert(#args == 2 and self.name)
+
+ -- get library and object file path
+ local libfile = args[1]
+ local objfile = args[2]
+ assert(libfile and objfile)
+
+ -- get object directory
+ local objdir = path.directory(objfile)
+ if not os.isdir(objdir) then os.mkdir(objdir) end
+ if not os.isdir(objdir) then
+ utils.error("%s not found!", objdir)
+ return false
+ end
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- list object files
+ local file = io.popen(string.format("%s -nologo -list %s", self.name, libfile))
+ if not file then
+ utils.error("extract %s to %s failed!", libfile, objdir)
+ windows.leave()
+ return false
+ end
+
+ -- extrace all object files
+ for line in file:lines() do
+
+ -- is object file?
+ if line:find("%.obj") then
+
+ -- init command
+ local out = path.translate(string.format("%s\\%s", objdir, path.filename(line)))
+
+ -- repeat? rename it
+ if os.isfile(out) then
+ for i = 0, 10 do
+ out = path.translate(string.format("%s\\%d_%s", objdir, i, path.filename(line)))
+ if not os.isfile(out) then break end
+ end
+ end
+
+ -- init command
+ local cmd = string.format("%s -nologo -extract:%s -out:%s %s", self.name, line, out, libfile)
+
+ -- extract it
+ if 0 ~= os.execute(cmd) then
+ utils.error("extract %s to %s failed!", libfile, objdir)
+ windows.leave()
+ return false
+ end
+ end
+ end
+
+ -- exit file
+ file:close()
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok
+ return true
+end
+
+-- the main function
+function lib.main(self, cmd)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: lib
+return lib
diff --git a/xmake/core/platform/windows/tools/link.lua b/xmake/core/platform/windows/tools/link.lua
new file mode 100644
index 000000000..66476fa41
--- /dev/null
+++ b/xmake/core/platform/windows/tools/link.lua
@@ -0,0 +1,128 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file link.lua
+--
+
+-- define module: link
+local link = link or {}
+
+-- load modules
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- init the compiler
+function link.init(self, name)
+
+ -- save name
+ self.name = name or "link.exe"
+
+ -- the architecture
+ local arch = config.get("arch")
+ assert(arch)
+
+ -- init flags for architecture
+ local flags_arch = ""
+ if arch == "x86" then flags_arch = "-machine:x86"
+ elseif arch == "x64" or arch == "amd64" or arch == "x86_amd64" then flags_arch = "-machine:x64"
+ end
+
+ -- init ldflags
+ self.ldflags = { "-nologo"
+ , "-dynamicbase"
+ , "-nxcompat"
+ , flags_arch}
+
+ -- init arflags
+ self.arflags = {"-nologo", flags_arch}
+
+ -- init shflags
+ self.shflags = {"-nologo", flags_arch}
+
+ -- init flags map
+ self.mapflags =
+ {
+ -- strip
+ ["-s"] = ""
+ , ["-S"] = ""
+
+ -- others
+ , ["-ftrapv"] = ""
+ , ["-fsanitize=address"] = ""
+ }
+
+end
+
+-- make the linker command
+function link.command_link(self, objfiles, targetfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ local cmd = string.format("%s %s -out:%s %s%s", self.name, flags, targetfile, objfiles, redirect)
+
+ -- too long?
+ if #cmd > 256 then
+ cmd = string.format("%s%s @<<\n%s -out:%s %s\n<<", self.name, redirect, flags, targetfile, objfiles)
+ end
+
+ -- ok?
+ return cmd
+end
+
+-- make the link flag
+function link.flag_link(self, link)
+
+ -- make it
+ return link .. ".lib"
+end
+
+-- make the linkdir flag
+function link.flag_linkdir(self, linkdir)
+
+ -- make it
+ return "-libpath:" .. linkdir
+end
+
+-- the main function
+function link.main(self, cmd)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: link
+return link
diff --git a/xmake/core/platform/windows/tools/ml.lua b/xmake/core/platform/windows/tools/ml.lua
new file mode 100644
index 000000000..5a6034320
--- /dev/null
+++ b/xmake/core/platform/windows/tools/ml.lua
@@ -0,0 +1,132 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file ml.lua
+--
+
+-- define module: ml
+local ml = ml or {}
+
+-- load modules
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- init the compiler
+function ml.init(self, name)
+
+ -- save name
+ self.name = name or "ml.exe"
+
+ -- init asflags
+ self.asflags = { "-nologo", "-Gd", "-MP4", "-D_MBCS", "-D_CRT_SECURE_NO_WARNINGS"}
+
+ -- init flags map
+ self.mapflags =
+ {
+ -- optimize
+ ["-O0"] = "-Od"
+ , ["-O3"] = "-Ot"
+ , ["-Ofast"] = "-Ox"
+ , ["-fomit-frame-pointer"] = "-Oy"
+
+ -- symbols
+ , ["-g"] = "-Z7"
+ , ["-fvisibility=.*"] = ""
+
+ -- warnings
+ , ["-Wall"] = "-W3" -- = "-Wall" will enable too more warnings
+ , ["-W1"] = "-W1"
+ , ["-W2"] = "-W2"
+ , ["-W3"] = "-W3"
+ , ["-Werror"] = "-WX"
+ , ["%-Wno%-error=.*"] = ""
+
+ -- vectorexts
+ , ["-mmmx"] = "-arch:MMX"
+ , ["-msse"] = "-arch:SSE"
+ , ["-msse2"] = "-arch:SSE2"
+ , ["-msse3"] = "-arch:SSE3"
+ , ["-mssse3"] = "-arch:SSSE3"
+ , ["-mavx"] = "-arch:AVX"
+ , ["-mavx2"] = "-arch:AVX2"
+ , ["-mfpu=.*"] = ""
+
+ -- others
+ , ["-ftrapv"] = ""
+ , ["-fsanitize=address"] = ""
+ }
+
+end
+
+-- make the compiler command
+function ml.command_compile(self, srcfile, objfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s -c %s -Fo%s %s%s", self.name, flags, objfile, srcfile, redirect)
+end
+
+-- make the define flag
+function ml.flag_define(self, define)
+
+ -- make it
+ return "-D" .. define:gsub("\"", "\\\"")
+end
+
+-- make the undefine flag
+function ml.flag_undefine(self, undefine)
+
+ -- make it
+ return "-U" .. undefine
+end
+
+-- make the includedir flag
+function ml.flag_includedir(self, includedir)
+
+ -- make it
+ return "-I" .. includedir
+end
+
+-- the main function
+function ml.main(self, cmd)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: ml
+return ml
diff --git a/xmake/core/platform/windows/tools/nmake.lua b/xmake/core/platform/windows/tools/nmake.lua
new file mode 100644
index 000000000..3dddc7cf2
--- /dev/null
+++ b/xmake/core/platform/windows/tools/nmake.lua
@@ -0,0 +1,74 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file nmake.lua
+--
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- define module: nmake
+local nmake = nmake or {}
+
+-- the init function
+function nmake.init(self, name)
+
+ -- save name
+ self.name = name or "nmake.exe"
+
+ -- is verbose?
+ self._VERBOSE = utils.ifelse(xmake._OPTIONS.verbose, "-v", "")
+
+end
+
+-- the main function
+function nmake.main(self, mkfile, target)
+
+ -- the windows module
+ local windows = platform.module()
+ assert(windows)
+
+ -- enter envirnoment
+ windows.enter()
+
+ -- make command
+ local cmd = nil
+ if mkfile and os.isfile(mkfile) then
+ cmd = string.format("%s /nologo /f %s %s VERBOSE=%s", self.name, mkfile, target or "", self._VERBOSE)
+ else
+ cmd = string.format("%s /nologo %s VERBOSE=%s", self.name, target or "", self._VERBOSE)
+ end
+
+ -- done
+ local ok = os.execute(cmd)
+
+ -- leave envirnoment
+ windows.leave()
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: nmake
+return nmake
diff --git a/xmake/core/platform/windows/windows.lua b/xmake/core/platform/windows/windows.lua
new file mode 100644
index 000000000..794358dc1
--- /dev/null
+++ b/xmake/core/platform/windows/windows.lua
@@ -0,0 +1,144 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file windows.lua
+--
+
+-- define module: windows
+local windows = windows or {}
+
+-- load modules
+local os = require("base/os")
+local config = require("base/config")
+
+-- init host
+windows._HOST = "windows"
+
+-- init os
+windows._OS = "windows"
+
+-- init architectures
+windows._ARCHS = {"x86", "x64", "amd64", "x86_amd64"}
+
+-- enter the given environment
+function windows._enter(name)
+
+ -- check
+ assert(name)
+
+ -- get the pathes for the vs environment
+ local old = nil
+ local new = config.get("__vsenv_" .. name)
+ if new then
+
+ -- get the current pathes
+ old = os.getenv(name) or ""
+
+ -- append the current pathes
+ new = new .. ";" .. old
+
+ -- update the pathes for the environment
+ os.setenv(name, new)
+ end
+
+ -- return the previous environment
+ return old;
+end
+
+-- leave the given environment
+function windows._leave(name, old)
+
+ -- check
+ assert(name)
+
+ -- restore the previous environment
+ if old then
+ os.setenv(name, old)
+ end
+end
+
+-- enter environment
+function windows.enter()
+
+ -- enter the vs environment
+ windows._pathes = windows._enter("path")
+ windows._libs = windows._enter("lib")
+ windows._includes = windows._enter("include")
+ windows._libpathes = windows._enter("libpath")
+
+end
+
+-- leave environment
+function windows.leave()
+
+ -- leave the vs environment
+ windows._leave("path", windows._pathes)
+ windows._leave("lib", windows._libs)
+ windows._leave("include", windows._includes)
+ windows._leave("libpath", windows._libpathes)
+
+end
+-- make configure
+function windows.make(configs)
+
+ -- init the file formats
+ configs.formats = {}
+ configs.formats.static = {"", ".lib"}
+ configs.formats.object = {"", ".obj"}
+ configs.formats.shared = {"", ".dll"}
+ configs.formats.binary = {"", ".exe"}
+
+ -- init the toolchains
+ configs.tools = {}
+ configs.tools.make = config.get("make")
+ configs.tools.cc = config.get("cc")
+ configs.tools.cxx = config.get("cxx")
+ configs.tools.ld = config.get("ld")
+ configs.tools.ar = config.get("ar")
+ configs.tools.sh = config.get("sh")
+ configs.tools.as = config.get("as")
+ configs.tools.ex = config.get("ex")
+end
+
+-- get the option menu for action: xmake config or global
+function windows.menu(action)
+
+ -- init config option menu
+ windows._MENU_CONFIG = windows._MENU_CONFIG or
+ { {}
+ , {nil, "vs", "kv", "auto", "The Microsoft Visual Studio" }
+ , }
+
+ -- init global option menu
+ windows._MENU_GLOBAL = windows._MENU_GLOBAL or
+ { {}
+ , {nil, "vs", "kv", "auto", "The Microsoft Visual Studio" }
+ , }
+
+ -- get the option menu
+ if action == "config" then
+ return windows._MENU_CONFIG
+ elseif action == "global" then
+ return windows._MENU_GLOBAL
+ end
+end
+
+
+-- return module: windows
+return windows
diff --git a/xmake/core/tools/ar.lua b/xmake/core/tools/ar.lua
new file mode 100644
index 000000000..75e63f83d
--- /dev/null
+++ b/xmake/core/tools/ar.lua
@@ -0,0 +1,114 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file ar.lua
+--
+
+-- define module: ar
+local ar = ar or {}
+
+-- load modules
+local utils = require("base/utils")
+local string = require("base/string")
+local config = require("base/config")
+
+-- init the linker
+function ar.init(self, name)
+
+ -- save name
+ self.name = name or "ar"
+
+ -- init arflags
+ self.arflags = { "-crs" }
+
+end
+
+-- make the link command
+function ar.command_link(self, objfiles, targetfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s %s %s %s%s", self.name, flags, targetfile, objfiles, redirect)
+end
+
+-- extract the static library to object files
+function ar.extract(self, ...)
+
+ -- check
+ local args = ...
+ assert(#args == 2 and self.name)
+
+ -- get library and object file path
+ local libfile = args[1]
+ local objfile = args[2]
+ assert(libfile and objfile)
+
+ -- get object directory
+ local objdir = path.directory(objfile)
+ if not os.isdir(objdir) then os.mkdir(objdir) end
+ if not os.isdir(objdir) then
+ utils.error("%s not found!", objdir)
+ return false
+ end
+
+ -- absolute the library path
+ libfile = path.absolute(libfile)
+ assert(libfile)
+
+ -- enter the object directory
+ ok, errors = os.cd(objdir)
+ if not ok then
+ utils.error(errors)
+ return false
+ end
+
+ -- extract it
+ local ok = self:main(string.format("%s -x %s", self.name, libfile))
+ if not ok then
+ utils.error("extract %s to %s failed!", libfile, objdir)
+ return false
+ end
+
+ -- leave the object directory
+ ok, errors = os.cd("-")
+ if not ok then
+ utils.error(errors)
+ return false
+ end
+
+ -- ok
+ return true
+end
+
+
+-- the main function
+function ar.main(self, cmd)
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: ar
+return ar
diff --git a/xmake/core/tools/cat.lua b/xmake/core/tools/cat.lua
new file mode 100644
index 000000000..32fea4e24
--- /dev/null
+++ b/xmake/core/tools/cat.lua
@@ -0,0 +1,43 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file cat.lua
+--
+
+-- define module: cat
+local cat = cat or {}
+
+-- load modules
+local io = require("base/io")
+local os = require("base/os")
+
+-- the main function
+function cat.main(self, ...)
+
+ -- cat all
+ for _, v in ipairs(...) do
+ if os.isfile(v) then io.cat(v) end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: cat
+return cat
diff --git a/xmake/core/tools/clang++.lua b/xmake/core/tools/clang++.lua
new file mode 100644
index 000000000..37352dec4
--- /dev/null
+++ b/xmake/core/tools/clang++.lua
@@ -0,0 +1,38 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file clang.lua
+--
+
+-- load modules
+local gcc = require("tools/gcc")
+
+-- define module: clang++
+local clangxx = clangxx or {}
+
+-- only copy the interfaces of gcc to clang++
+for k, v in pairs(gcc) do
+ if type(v) == "function" then
+ clangxx[k] = v
+ end
+end
+
+-- return module: clang++
+return clangxx
+
diff --git a/xmake/core/tools/clang.lua b/xmake/core/tools/clang.lua
new file mode 100644
index 000000000..280ae73a6
--- /dev/null
+++ b/xmake/core/tools/clang.lua
@@ -0,0 +1,38 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file clang.lua
+--
+
+-- load modules
+local gcc = require("tools/gcc")
+
+-- define module: clang
+local clang = clang or {}
+
+-- only copy the interfaces of gcc to clang
+for k, v in pairs(gcc) do
+ if type(v) == "function" then
+ clang[k] = v
+ end
+end
+
+-- return module: clang
+return clang
+
diff --git a/xmake/core/tools/cp.lua b/xmake/core/tools/cp.lua
new file mode 100644
index 000000000..1b3ba9843
--- /dev/null
+++ b/xmake/core/tools/cp.lua
@@ -0,0 +1,44 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file cp.lua
+--
+
+-- define module: cp
+local cp = cp or {}
+
+-- load modules
+local os = require("base/os")
+
+-- the main function
+function cp.main(self, ...)
+
+ -- cp it
+ local pathes = ...
+ if pathes and table.getn(pathes) == 2 then
+ return os.cp(pathes[1], pathes[2])
+ end
+
+ -- failed
+ return false
+
+end
+
+-- return module: cp
+return cp
diff --git a/xmake/core/tools/dispatcher.lua b/xmake/core/tools/dispatcher.lua
new file mode 100644
index 000000000..d019937ec
--- /dev/null
+++ b/xmake/core/tools/dispatcher.lua
@@ -0,0 +1,80 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file dispatcher.lua
+--
+
+-- define module: dispatcher
+local dispatcher = dispatcher or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local tools = require("tools/tools")
+
+-- the main function
+--
+-- dispatcher toolname toolpath action arguments ...
+function dispatcher.main(self, ...)
+
+ -- check
+ local args = ...
+ assert(#args >= 2)
+
+ -- get tool kind and action name
+ local tool_kind = args[1]
+ local action_name = args[2]
+ assert(tool_kind and action_name)
+
+ -- get the tool
+ local tool = tools.get(tool_kind)
+ if tool then
+
+ -- load action
+ local action = tool[action_name]
+ if action then
+
+ -- init arguments for action
+ local action_args = {}
+ for i = 3, #args do
+ table.insert(action_args, args[i]:decode())
+ end
+
+ -- done action
+ if not action(tool, action_args) then
+ utils.error("run action %s failed!", action_name)
+ assert(false)
+ end
+ else
+ utils.error("load action %s failed!", action_name)
+ assert(false)
+ end
+
+ else
+ assert(false)
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: dispatcher
+return dispatcher
diff --git a/xmake/core/tools/echo.lua b/xmake/core/tools/echo.lua
new file mode 100644
index 000000000..dbfa67426
--- /dev/null
+++ b/xmake/core/tools/echo.lua
@@ -0,0 +1,44 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file echo.lua
+--
+
+-- define module: echo
+local echo = echo or {}
+
+-- load modules
+local io = require("base/io")
+local string = require("base/string")
+
+-- the main function
+function echo.main(self, ...)
+
+ -- echo all
+ for _, v in ipairs(...) do
+ io.write(string.format("%s ", v:decode()))
+ end
+ io.write("\n")
+
+ -- ok
+ return true
+end
+
+-- return module: echo
+return echo
diff --git a/xmake/core/tools/g++.lua b/xmake/core/tools/g++.lua
new file mode 100644
index 000000000..64970b039
--- /dev/null
+++ b/xmake/core/tools/g++.lua
@@ -0,0 +1,38 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file g++.lua
+--
+
+-- load modules
+local gcc = require("tools/gcc")
+
+-- define module: gxx
+local gxx = gxx or {}
+
+-- only copy the interfaces of gcc to g++
+for k, v in pairs(gcc) do
+ if type(v) == "function" then
+ gxx[k] = v
+ end
+end
+
+-- return module: g++
+return gxx
+
diff --git a/xmake/core/tools/gas-preprocessor.pl b/xmake/core/tools/gas-preprocessor.pl
new file mode 100755
index 000000000..98dfe4ad9
--- /dev/null
+++ b/xmake/core/tools/gas-preprocessor.pl
@@ -0,0 +1,1025 @@
+#!/usr/bin/env perl
+# by David Conrad
+# This code is licensed under GPLv2 or later; go to gnu.org to read it
+# (not that it much matters for an asm preprocessor)
+# usage: set your assembler to be something like "perl gas-preprocessor.pl gcc"
+use strict;
+
+# Apple's gas is ancient and doesn't support modern preprocessing features like
+# .rept and has ugly macro syntax, among other things. Thus, this script
+# implements the subset of the gas preprocessor used by x264 and ffmpeg
+# that isn't supported by Apple's gas.
+
+my %canonical_arch = ("aarch64" => "aarch64", "arm64" => "aarch64",
+ "arm" => "arm",
+ "powerpc" => "powerpc", "ppc" => "powerpc");
+
+my %comments = ("aarch64" => '//',
+ "arm" => '@',
+ "powerpc" => '#');
+
+my @gcc_cmd;
+my @preprocess_c_cmd;
+
+my $comm;
+my $arch;
+my $as_type = "apple-gas";
+
+my $fix_unreq = $^O eq "darwin";
+my $force_thumb = 0;
+
+my $arm_cond_codes = "eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo";
+
+my $usage_str = "
+$0\n
+Gas-preprocessor.pl converts assembler files using modern GNU as syntax for
+Apple's ancient gas version or clang's incompatible integrated assembler. The
+conversion is regularly tested for Libav, x264 and vlc. Other projects might
+use different features which are not correctly handled.
+
+Options for this program needs to be separated with ' -- ' from the assembler
+command. Following options are currently supported:
+
+ -help - this usage text
+ -arch - target architecture
+ -as-type - one value out of {{,apple-}{gas,clang},armasm}
+ -fix-unreq
+ -no-fix-unreq
+ -force-thumb - assemble as thumb regardless of the input source
+ (note, this is incomplete and only works for sources
+ it explicitly was tested with)
+";
+
+sub usage() {
+ print $usage_str;
+}
+
+while (@ARGV) {
+ my $opt = shift;
+
+ if ($opt =~ /^-(no-)?fix-unreq$/) {
+ $fix_unreq = $1 ne "no-";
+ } elsif ($opt eq "-force-thumb") {
+ $force_thumb = 1;
+ } elsif ($opt eq "-arch") {
+ $arch = shift;
+ die "unknown arch: '$arch'\n" if not exists $comments{$arch};
+ } elsif ($opt eq "-as-type") {
+ $as_type = shift;
+ die "unknown as type: '$as_type'\n" if $as_type !~ /^((apple-)?(gas|clang)|armasm)$/;
+ } elsif ($opt eq "-help") {
+ usage();
+ exit 0;
+ } elsif ($opt eq "--" ) {
+ @gcc_cmd = @ARGV;
+ } elsif ($opt =~ /^-/) {
+ die "option '$opt' is not known. See '$0 -help' for usage information\n";
+ } else {
+ push @gcc_cmd, $opt, @ARGV;
+ }
+ last if (@gcc_cmd);
+}
+
+if (grep /\.c$/, @gcc_cmd) {
+ # C file (inline asm?) - compile
+ @preprocess_c_cmd = (@gcc_cmd, "-S");
+} elsif (grep /\.[sS]$/, @gcc_cmd) {
+ # asm file, just do C preprocessor
+ @preprocess_c_cmd = (@gcc_cmd, "-E");
+} elsif (grep /-(v|-version|dumpversion)/, @gcc_cmd) {
+ # pass -v/--version along, used during probing. Matching '-v' might have
+ # uninteded results but it doesn't matter much if gas-preprocessor or
+ # the compiler fails.
+ exec(@gcc_cmd);
+} else {
+ die "Unrecognized input filetype";
+}
+if ($as_type eq "armasm") {
+
+ $preprocess_c_cmd[0] = "cpp";
+
+ @preprocess_c_cmd = grep ! /^-nologo$/, @preprocess_c_cmd;
+ # Remove -ignore XX parameter pairs from preprocess_c_cmd
+ my $index = 1;
+ while ($index < $#preprocess_c_cmd) {
+ if ($preprocess_c_cmd[$index] eq "-ignore" and $index + 1 < $#preprocess_c_cmd) {
+ splice(@preprocess_c_cmd, $index, 2);
+ next;
+ }
+ $index++;
+ }
+ if (grep /^-MM$/, @preprocess_c_cmd) {
+ system(@preprocess_c_cmd) == 0 or die "Error running preprocessor";
+ exit 0;
+ }
+}
+
+# if compiling, avoid creating an output file named '-.o'
+if ((grep /^-c$/, @gcc_cmd) && !(grep /^-o/, @gcc_cmd)) {
+ foreach my $i (@gcc_cmd) {
+ if ($i =~ /\.[csS]$/) {
+ my $outputfile = $i;
+ $outputfile =~ s/\.[csS]$/.o/;
+ push(@gcc_cmd, "-o");
+ push(@gcc_cmd, $outputfile);
+ last;
+ }
+ }
+}
+# replace only the '-o' argument with '-', avoids rewriting the make dependency
+# target specified with -MT to '-'
+my $index = 1;
+while ($index < $#preprocess_c_cmd) {
+ if ($preprocess_c_cmd[$index] eq "-o") {
+ $index++;
+ $preprocess_c_cmd[$index] = "-";
+ }
+ $index++;
+}
+
+my $tempfile;
+if ($as_type ne "armasm") {
+ @gcc_cmd = map { /\.[csS]$/ ? qw(-x assembler -) : $_ } @gcc_cmd;
+} else {
+ @preprocess_c_cmd = grep ! /^-c$/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-m/, @preprocess_c_cmd;
+
+ @preprocess_c_cmd = grep ! /^-G/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-W/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-Z/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-fp/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-EHsc$/, @preprocess_c_cmd;
+ @preprocess_c_cmd = grep ! /^-O/, @preprocess_c_cmd;
+
+ @gcc_cmd = grep ! /^-G/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-W/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-Z/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-fp/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-EHsc$/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-O/, @gcc_cmd;
+
+ my @outfiles = grep /\.(o|obj)$/, @gcc_cmd;
+ $tempfile = $outfiles[0].".asm";
+
+ # Remove most parameters from gcc_cmd, which actually is the armasm command,
+ # which doesn't support any of the common compiler/preprocessor options.
+ @gcc_cmd = grep ! /^-D/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-U/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-m/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-M/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-c$/, @gcc_cmd;
+ @gcc_cmd = grep ! /^-I/, @gcc_cmd;
+ @gcc_cmd = map { /\.S$/ ? $tempfile : $_ } @gcc_cmd;
+}
+
+# detect architecture from gcc binary name
+if (!$arch) {
+ if ($gcc_cmd[0] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
+ $arch = $1;
+ } else {
+ # look for -arch flag
+ foreach my $i (1 .. $#gcc_cmd-1) {
+ if ($gcc_cmd[$i] eq "-arch" and
+ $gcc_cmd[$i+1] =~ /(arm64|aarch64|arm|powerpc|ppc)/) {
+ $arch = $1;
+ }
+ }
+ }
+}
+
+# assume we're not cross-compiling if no -arch or the binary doesn't have the arch name
+$arch = qx/arch/ if (!$arch);
+
+die "Unknown target architecture '$arch'" if not exists $canonical_arch{$arch};
+
+$arch = $canonical_arch{$arch};
+$comm = $comments{$arch};
+my $inputcomm = $comm;
+$comm = ";" if $as_type =~ /armasm/;
+
+my %ppc_spr = (ctr => 9,
+ vrsave => 256);
+
+open(INPUT, "-|", @preprocess_c_cmd) || die "Error running preprocessor";
+
+if ($ENV{GASPP_DEBUG}) {
+ open(ASMFILE, ">&STDOUT");
+} else {
+ if ($as_type ne "armasm") {
+ open(ASMFILE, "|-", @gcc_cmd) or die "Error running assembler";
+ } else {
+ open(ASMFILE, ">", $tempfile);
+ }
+}
+
+my $current_macro = '';
+my $macro_level = 0;
+my $rept_level = 0;
+my %macro_lines;
+my %macro_args;
+my %macro_args_default;
+my $macro_count = 0;
+my $altmacro = 0;
+my $in_irp = 0;
+
+my $num_repts;
+my @rept_lines;
+
+my @irp_args;
+my $irp_param;
+
+my @ifstack;
+
+my %symbols;
+
+my @sections;
+
+my %literal_labels; # for ldr <reg>, =<expr>
+my $literal_num = 0;
+my $literal_expr = ".word";
+$literal_expr = ".quad" if $arch eq "aarch64";
+
+my $thumb = 0;
+
+my %thumb_labels;
+my %call_targets;
+my %mov32_targets;
+
+my %neon_alias_reg;
+my %neon_alias_type;
+
+my $temp_label_next = 0;
+my %last_temp_labels;
+my %next_temp_labels;
+
+my %labels_seen;
+
+my %aarch64_req_alias;
+
+if ($force_thumb) {
+ parse_line(".thumb\n");
+}
+
+# pass 1: parse .macro
+# note that the handling of arguments is probably overly permissive vs. gas
+# but it should be the same for valid cases
+while (<INPUT>) {
+ # remove all comments (to avoid interfering with evaluating directives)
+ s/(?<!\\)$inputcomm.*//x;
+ # Strip out windows linefeeds
+ s/\r$//;
+ # Strip out line number comments - armasm can handle them in a separate
+ # syntax, but since the line numbers are off they are only misleading.
+ s/^#\s+(\d+).*// if $as_type =~ /armasm/;
+
+ parse_line($_);
+}
+
+sub eval_expr {
+ my $expr = $_[0];
+ while ($expr =~ /([A-Za-z._][A-Za-z0-9._]*)/g) {
+ my $sym = $1;
+ $expr =~ s/$sym/($symbols{$sym})/ if defined $symbols{$sym};
+ }
+ eval $expr;
+}
+
+sub handle_if {
+ my $line = $_[0];
+ # handle .if directives; apple's assembler doesn't support important non-basic ones
+ # evaluating them is also needed to handle recursive macros
+ if ($line =~ /\.if(n?)([a-z]*)\s+(.*)/) {
+ my $result = $1 eq "n";
+ my $type = $2;
+ my $expr = $3;
+
+ if ($type eq "b") {
+ $expr =~ s/\s//g;
+ $result ^= $expr eq "";
+ } elsif ($type eq "c") {
+ if ($expr =~ /(.*)\s*,\s*(.*)/) {
+ $result ^= $1 eq $2;
+ } else {
+ die "argument to .ifc not recognized";
+ }
+ } elsif ($type eq "") {
+ $result ^= eval_expr($expr) != 0;
+ } elsif ($type eq "eq") {
+ $result = eval_expr($expr) == 0;
+ } elsif ($type eq "lt") {
+ $result = eval_expr($expr) < 0;
+ } else {
+ chomp($line);
+ die "unhandled .if varient. \"$line\"";
+ }
+ push (@ifstack, $result);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub parse_if_line {
+ my $line = $_[0];
+
+ # evaluate .if blocks
+ if (scalar(@ifstack)) {
+ # Don't evaluate any new if statements if we're within
+ # a repetition or macro - they will be evaluated once
+ # the repetition is unrolled or the macro is expanded.
+ if (scalar(@rept_lines) == 0 and $macro_level == 0) {
+ if ($line =~ /\.endif/) {
+ pop(@ifstack);
+ return 1;
+ } elsif ($line =~ /\.elseif\s+(.*)/) {
+ if ($ifstack[-1] == 0) {
+ $ifstack[-1] = !!eval_expr($1);
+ } elsif ($ifstack[-1] > 0) {
+ $ifstack[-1] = -$ifstack[-1];
+ }
+ return 1;
+ } elsif ($line =~ /\.else/) {
+ $ifstack[-1] = !$ifstack[-1];
+ return 1;
+ } elsif (handle_if($line)) {
+ return 1;
+ }
+ }
+
+ # discard lines in false .if blocks
+ foreach my $i (0 .. $#ifstack) {
+ if ($ifstack[$i] <= 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+sub parse_line {
+ my $line = $_[0];
+
+ return if (parse_if_line($line));
+
+ if (scalar(@rept_lines) == 0) {
+ if (/\.macro/) {
+ $macro_level++;
+ if ($macro_level > 1 && !$current_macro) {
+ die "nested macros but we don't have master macro";
+ }
+ } elsif (/\.endm/) {
+ $macro_level--;
+ if ($macro_level < 0) {
+ die "unmatched .endm";
+ } elsif ($macro_level == 0) {
+ $current_macro = '';
+ return;
+ }
+ }
+ }
+
+ if ($macro_level == 0) {
+ if ($line =~ /\.(rept|irp)/) {
+ $rept_level++;
+ } elsif ($line =~ /.endr/) {
+ $rept_level--;
+ }
+ }
+
+ if ($macro_level > 1) {
+ push(@{$macro_lines{$current_macro}}, $line);
+ } elsif (scalar(@rept_lines) and $rept_level >= 1) {
+ push(@rept_lines, $line);
+ } elsif ($macro_level == 0) {
+ expand_macros($line);
+ } else {
+ if ($line =~ /\.macro\s+([\d\w\.]+)\s*(.*)/) {
+ $current_macro = $1;
+
+ # commas in the argument list are optional, so only use whitespace as the separator
+ my $arglist = $2;
+ $arglist =~ s/,/ /g;
+
+ my @args = split(/\s+/, $arglist);
+ foreach my $i (0 .. $#args) {
+ my @argpair = split(/=/, $args[$i]);
+ $macro_args{$current_macro}[$i] = $argpair[0];
+ $argpair[0] =~ s/:vararg$//;
+ $macro_args_default{$current_macro}{$argpair[0]} = $argpair[1];
+ }
+ # ensure %macro_lines has the macro name added as a key
+ $macro_lines{$current_macro} = [];
+
+ } elsif ($current_macro) {
+ push(@{$macro_lines{$current_macro}}, $line);
+ } else {
+ die "macro level without a macro name";
+ }
+ }
+}
+
+sub handle_set {
+ my $line = $_[0];
+ if ($line =~ /\.set\s+(.*),\s*(.*)/) {
+ $symbols{$1} = eval_expr($2);
+ return 1;
+ }
+ return 0;
+}
+
+sub expand_macros {
+ my $line = $_[0];
+
+ # handle .if directives; apple's assembler doesn't support important non-basic ones
+ # evaluating them is also needed to handle recursive macros
+ if (handle_if($line)) {
+ return;
+ }
+
+ if (/\.purgem\s+([\d\w\.]+)/) {
+ delete $macro_lines{$1};
+ delete $macro_args{$1};
+ delete $macro_args_default{$1};
+ return;
+ }
+
+ if ($line =~ /\.altmacro/) {
+ $altmacro = 1;
+ return;
+ }
+
+ if ($line =~ /\.noaltmacro/) {
+ $altmacro = 0;
+ return;
+ }
+
+ $line =~ s/\%([^,]*)/eval_expr($1)/eg if $altmacro;
+
+ # Strip out the .set lines from the armasm output
+ return if (handle_set($line) and $as_type eq "armasm");
+
+ if ($line =~ /\.rept\s+(.*)/) {
+ $num_repts = $1;
+ @rept_lines = ("\n");
+
+ # handle the possibility of repeating another directive on the same line
+ # .endr on the same line is not valid, I don't know if a non-directive is
+ if ($num_repts =~ s/(\.\w+.*)//) {
+ push(@rept_lines, "$1\n");
+ }
+ $num_repts = eval_expr($num_repts);
+ } elsif ($line =~ /\.irp\s+([\d\w\.]+)\s*(.*)/) {
+ $in_irp = 1;
+ $num_repts = 1;
+ @rept_lines = ("\n");
+ $irp_param = $1;
+
+ # only use whitespace as the separator
+ my $irp_arglist = $2;
+ $irp_arglist =~ s/,/ /g;
+ $irp_arglist =~ s/^\s+//;
+ @irp_args = split(/\s+/, $irp_arglist);
+ } elsif ($line =~ /\.irpc\s+([\d\w\.]+)\s*(.*)/) {
+ $in_irp = 1;
+ $num_repts = 1;
+ @rept_lines = ("\n");
+ $irp_param = $1;
+
+ my $irp_arglist = $2;
+ $irp_arglist =~ s/,/ /g;
+ $irp_arglist =~ s/^\s+//;
+ @irp_args = split(//, $irp_arglist);
+ } elsif ($line =~ /\.endr/) {
+ my @prev_rept_lines = @rept_lines;
+ my $prev_in_irp = $in_irp;
+ my @prev_irp_args = @irp_args;
+ my $prev_irp_param = $irp_param;
+ my $prev_num_repts = $num_repts;
+ @rept_lines = ();
+ $in_irp = 0;
+ @irp_args = '';
+
+ if ($prev_in_irp != 0) {
+ foreach my $i (@prev_irp_args) {
+ foreach my $origline (@prev_rept_lines) {
+ my $line = $origline;
+ $line =~ s/\\$prev_irp_param/$i/g;
+ $line =~ s/\\\(\)//g; # remove \()
+ parse_line($line);
+ }
+ }
+ } else {
+ for (1 .. $prev_num_repts) {
+ foreach my $origline (@prev_rept_lines) {
+ my $line = $origline;
+ parse_line($line);
+ }
+ }
+ }
+ } elsif ($line =~ /(\S+:|)\s*([\w\d\.]+)\s*(.*)/ && exists $macro_lines{$2}) {
+ handle_serialized_line($1);
+ my $macro = $2;
+
+ # commas are optional here too, but are syntactically important because
+ # parameters can be blank
+ my @arglist = split(/,/, $3);
+ my @args;
+ my @args_seperator;
+
+ my $comma_sep_required = 0;
+ foreach (@arglist) {
+ # allow arithmetic/shift operators in macro arguments
+ $_ =~ s/\s*(\+|-|\*|\/|<<|>>|<|>)\s*/$1/g;
+
+ my @whitespace_split = split(/\s+/, $_);
+ if (!@whitespace_split) {
+ push(@args, '');
+ push(@args_seperator, '');
+ } else {
+ foreach (@whitespace_split) {
+ #print ("arglist = \"$_\"\n");
+ if (length($_)) {
+ push(@args, $_);
+ my $sep = $comma_sep_required ? "," : " ";
+ push(@args_seperator, $sep);
+ #print ("sep = \"$sep\", arg = \"$_\"\n");
+ $comma_sep_required = 0;
+ }
+ }
+ }
+
+ $comma_sep_required = 1;
+ }
+
+ my %replacements;
+ if ($macro_args_default{$macro}){
+ %replacements = %{$macro_args_default{$macro}};
+ }
+
+ # construct hashtable of text to replace
+ foreach my $i (0 .. $#args) {
+ my $argname = $macro_args{$macro}[$i];
+ my @macro_args = @{ $macro_args{$macro} };
+ if ($args[$i] =~ m/=/) {
+ # arg=val references the argument name
+ # XXX: I'm not sure what the expected behaviour if a lot of
+ # these are mixed with unnamed args
+ my @named_arg = split(/=/, $args[$i]);
+ $replacements{$named_arg[0]} = $named_arg[1];
+ } elsif ($i > $#{$macro_args{$macro}}) {
+ # more args given than the macro has named args
+ # XXX: is vararg allowed on arguments before the last?
+ $argname = $macro_args{$macro}[-1];
+ if ($argname =~ s/:vararg$//) {
+ #print "macro = $macro, args[$i] = $args[$i], args_seperator=@args_seperator, argname = $argname, arglist[$i] = $arglist[$i], arglist = @arglist, args=@args, macro_args=@macro_args\n";
+ #$replacements{$argname} .= ", $args[$i]";
+ $replacements{$argname} .= "$args_seperator[$i] $args[$i]";
+ } else {
+ die "Too many arguments to macro $macro";
+ }
+ } else {
+ $argname =~ s/:vararg$//;
+ $replacements{$argname} = $args[$i];
+ }
+ }
+
+ my $count = $macro_count++;
+
+ # apply replacements as regex
+ foreach (@{$macro_lines{$macro}}) {
+ my $macro_line = $_;
+ # do replacements by longest first, this avoids wrong replacement
+ # when argument names are subsets of each other
+ foreach (reverse sort {length $a <=> length $b} keys %replacements) {
+ $macro_line =~ s/\\$_/$replacements{$_}/g;
+ }
+ if ($altmacro) {
+ foreach (reverse sort {length $a <=> length $b} keys %replacements) {
+ $macro_line =~ s/\b$_\b/$replacements{$_}/g;
+ }
+ }
+ $macro_line =~ s/\\\@/$count/g;
+ $macro_line =~ s/\\\(\)//g; # remove \()
+ parse_line($macro_line);
+ }
+ } else {
+ handle_serialized_line($line);
+ }
+}
+
+sub is_arm_register {
+ my $name = $_[0];
+ if ($name eq "lr" or
+ $name eq "ip" or
+ $name =~ /^[rav]\d+$/) {
+ return 1;
+ }
+ return 0;
+}
+
+sub handle_local_label {
+ my $line = $_[0];
+ my $num = $_[1];
+ my $dir = $_[2];
+ my $target = "$num$dir";
+ if ($dir eq "b") {
+ $line =~ s/$target/$last_temp_labels{$num}/g;
+ } else {
+ my $name = "temp_label_$temp_label_next";
+ $temp_label_next++;
+ push(@{$next_temp_labels{$num}}, $name);
+ $line =~ s/$target/$name/g;
+ }
+ return $line;
+}
+
+sub handle_serialized_line {
+ my $line = $_[0];
+
+ # handle .previous (only with regard to .section not .subsection)
+ if ($line =~ /\.(section|text|const_data)/) {
+ push(@sections, $line);
+ } elsif ($line =~ /\.previous/) {
+ if (!$sections[-2]) {
+ die ".previous without a previous section";
+ }
+ $line = $sections[-2];
+ push(@sections, $line);
+ }
+
+ $thumb = 1 if $line =~ /\.code\s+16|\.thumb/;
+ $thumb = 0 if $line =~ /\.code\s+32|\.arm/;
+
+ # handle ldr <reg>, =<expr>
+ if ($line =~ /(.*)\s*ldr([\w\s\d]+)\s*,\s*=(.*)/ and $as_type ne "armasm") {
+ my $label = $literal_labels{$3};
+ if (!$label) {
+ $label = "Literal_$literal_num";
+ $literal_num++;
+ $literal_labels{$3} = $label;
+ }
+ $line = "$1 ldr$2, $label\n";
+ } elsif ($line =~ /\.ltorg/ and $as_type ne "armasm") {
+ $line .= ".align 2\n";
+ foreach my $literal (keys %literal_labels) {
+ $line .= "$literal_labels{$literal}:\n $literal_expr $literal\n";
+ }
+ %literal_labels = ();
+ }
+
+ # handle GNU as pc-relative relocations for adrp/add
+ if ($line =~ /(.*)\s*adrp([\w\s\d]+)\s*,\s*#?:pg_hi21:([^\s]+)/) {
+ $line = "$1 adrp$2, ${3}\@PAGE\n";
+ } elsif ($line =~ /(.*)\s*add([\w\s\d]+)\s*,([\w\s\d]+)\s*,\s*#?:lo12:([^\s]+)/) {
+ $line = "$1 add$2, $3, ${4}\@PAGEOFF\n";
+ }
+
+ # thumb add with large immediate needs explicit add.w
+ if ($thumb and $line =~ /add\s+.*#([^@]+)/) {
+ $line =~ s/add/add.w/ if eval_expr($1) > 255;
+ }
+
+ # mach-o local symbol names start with L (no dot)
+ $line =~ s/(?<!\w)\.(L\w+)/$1/g;
+
+ # recycle the '.func' directive for '.thumb_func'
+ if ($thumb and $as_type =~ /^apple-/) {
+ $line =~ s/\.func/.thumb_func/x;
+ }
+
+ if ($thumb and $line =~ /^\s*(\w+)\s*:/) {
+ $thumb_labels{$1}++;
+ }
+
+ if ($as_type =~ /^apple-/ and
+ $line =~ /^\s*((\w+\s*:\s*)?bl?x?(..)?(?:\.w)?|\.global)\s+(\w+)/) {
+ my $cond = $3;
+ my $label = $4;
+ # Don't interpret e.g. bic as b<cc> with ic as conditional code
+ if ($cond =~ /|$arm_cond_codes/) {
+ if (exists $thumb_labels{$label}) {
+ print ASMFILE ".thumb_func $label\n";
+ } else {
+ $call_targets{$label}++;
+ }
+ }
+ }
+
+ # @l -> lo16() @ha -> ha16()
+ $line =~ s/,\s+([^,]+)\@l\b/, lo16($1)/g;
+ $line =~ s/,\s+([^,]+)\@ha\b/, ha16($1)/g;
+
+ # move to/from SPR
+ if ($line =~ /(\s+)(m[ft])([a-z]+)\s+(\w+)/ and exists $ppc_spr{$3}) {
+ if ($2 eq 'mt') {
+ $line = "$1${2}spr $ppc_spr{$3}, $4\n";
+ } else {
+ $line = "$1${2}spr $4, $ppc_spr{$3}\n";
+ }
+ }
+
+ if ($line =~ /\.unreq\s+(.*)/) {
+ if (defined $neon_alias_reg{$1}) {
+ delete $neon_alias_reg{$1};
+ delete $neon_alias_type{$1};
+ return;
+ } elsif (defined $aarch64_req_alias{$1}) {
+ delete $aarch64_req_alias{$1};
+ return;
+ }
+ }
+ # old gas versions store upper and lower case names on .req,
+ # but they remove only one on .unreq
+ if ($fix_unreq) {
+ if ($line =~ /\.unreq\s+(.*)/) {
+ $line = ".unreq " . lc($1) . "\n";
+ $line .= ".unreq " . uc($1) . "\n";
+ }
+ }
+
+ if ($line =~ /(\w+)\s+\.(dn|qn)\s+(\w+)(?:\.(\w+))?(\[\d+\])?/) {
+ $neon_alias_reg{$1} = "$3$5";
+ $neon_alias_type{$1} = $4;
+ return;
+ }
+ if (scalar keys %neon_alias_reg > 0 && $line =~ /^\s+v\w+/) {
+ # This line seems to possibly have a neon instruction
+ foreach (keys %neon_alias_reg) {
+ my $alias = $_;
+ # Require the register alias to match as an invididual word, not as a substring
+ # of a larger word-token.
+ if ($line =~ /\b$alias\b/) {
+ $line =~ s/\b$alias\b/$neon_alias_reg{$alias}/g;
+ # Add the type suffix. If multiple aliases match on the same line,
+ # only do this replacement the first time (a vfoo.bar string won't match v\w+).
+ $line =~ s/^(\s+)(v\w+)(\s+)/$1$2.$neon_alias_type{$alias}$3/;
+ }
+ }
+ }
+
+ if ($arch eq "aarch64" or $as_type eq "armasm") {
+ # clang's integrated aarch64 assembler in Xcode 5 does not support .req/.unreq
+ if ($line =~ /\b(\w+)\s+\.req\s+(\w+)\b/) {
+ $aarch64_req_alias{$1} = $2;
+ return;
+ }
+ foreach (keys %aarch64_req_alias) {
+ my $alias = $_;
+ # recursively resolve aliases
+ my $resolved = $aarch64_req_alias{$alias};
+ while (defined $aarch64_req_alias{$resolved}) {
+ $resolved = $aarch64_req_alias{$resolved};
+ }
+ $line =~ s/\b$alias\b/$resolved/g;
+ }
+ }
+ if ($arch eq "aarch64") {
+ # fix missing aarch64 instructions in Xcode 5.1 (beta3)
+ # mov with vector arguments is not supported, use alias orr instead
+ if ($line =~ /^\s*mov\s+(v\d[\.{}\[\]\w]+),\s*(v\d[\.{}\[\]\w]+)\b\s*$/) {
+ $line = " orr $1, $2, $2\n";
+ }
+ # movi 16, 32 bit shifted variant, shift is optional
+ if ($line =~ /^\s*movi\s+(v[0-3]?\d\.(?:2|4|8)[hsHS])\s*,\s*(#\w+)\b\s*$/) {
+ $line = " movi $1, $2, lsl #0\n";
+ }
+ # Xcode 5 misses the alias uxtl. Replace it with the more general ushll.
+ # Clang 3.4 misses the alias sxtl too. Replace it with the more general sshll.
+ if ($line =~ /^\s*(s|u)xtl(2)?\s+(v[0-3]?\d\.[248][hsdHSD])\s*,\s*(v[0-3]?\d\.(?:2|4|8|16)[bhsBHS])\b\s*$/) {
+ $line = " $1shll$2 $3, $4, #0\n";
+ }
+ # clang 3.4 does not automatically use shifted immediates in add/sub
+ if ($as_type eq "clang" and
+ $line =~ /^(\s*(?:add|sub)s?) ([^#l]+)#([\d\+\-\*\/ <>]+)\s*$/) {
+ my $imm = eval $3;
+ if ($imm > 4095 and not ($imm & 4095)) {
+ $line = "$1 $2#" . ($imm >> 12) . ", lsl #12\n";
+ }
+ }
+ if ($ENV{GASPP_FIX_XCODE5}) {
+ if ($line =~ /^\s*bsl\b/) {
+ $line =~ s/\b(bsl)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/;
+ $line =~ s/\b(v[0-3]?\d)\.$3\b/$1/g;
+ }
+ if ($line =~ /^\s*saddl2?\b/) {
+ $line =~ s/\b(saddl2?)(\s+v[0-3]?\d\.(\w+))\b/$1.$3$2/;
+ $line =~ s/\b(v[0-3]?\d)\.\w+\b/$1/g;
+ }
+ if ($line =~ /^\s*dup\b.*\]$/) {
+ $line =~ s/\bdup(\s+v[0-3]?\d)\.(\w+)\b/dup.$2$1/g;
+ $line =~ s/\b(v[0-3]?\d)\.[bhsdBHSD](\[\d\])$/$1$2/g;
+ }
+ }
+ }
+
+ if ($as_type eq "armasm") {
+ # Also replace variables set by .set
+ foreach (keys %symbols) {
+ my $sym = $_;
+ $line =~ s/\b$sym\b/$symbols{$sym}/g;
+ }
+
+ # Handle function declarations and keep track of the declared labels
+ if ($line =~ s/^\s*\.func\s+(\w+)/$1 PROC/) {
+ $labels_seen{$1} = 1;
+ }
+
+ if ($line =~ s/^(\d+)://) {
+ # Convert local labels into unique labels. armasm (at least in
+ # RVCT) has something similar, but still different enough.
+ # By converting to unique labels we avoid any possible
+ # incompatibilities.
+
+ my $num = $1;
+ foreach (@{$next_temp_labels{$num}}) {
+ $line = "$_\n" . $line;
+ }
+ @next_temp_labels{$num} = ();
+ my $name = "temp_label_$temp_label_next";
+ $temp_label_next++;
+ # The matching regexp above removes the label from the start of
+ # the line (which might contain an instruction as well), readd
+ # it on a separate line above it.
+ $line = "$name:\n" . $line;
+ $last_temp_labels{$num} = $name;
+ }
+
+ if ($line =~ s/^(\w+):/$1/) {
+ # Skip labels that have already been declared with a PROC,
+ # labels must not be declared multiple times.
+ return if (defined $labels_seen{$1});
+ $labels_seen{$1} = 1;
+ } elsif ($line !~ /(\w+) PROC/) {
+ # If not a label, make sure the line starts with whitespace,
+ # otherwise ms armasm interprets it incorrectly.
+ $line =~ s/^[\.\w]/\t$&/;
+ }
+
+
+ # Check branch instructions
+ if ($line =~ /(?:^|\n)\s*(\w+\s*:\s*)?(bl?x?(..)?(\.w)?)\s+(\w+)/) {
+ my $instr = $2;
+ my $cond = $3;
+ my $width = $4;
+ my $target = $5;
+ # Don't interpret e.g. bic as b<cc> with ic as conditional code
+ if ($cond !~ /|$arm_cond_codes/) {
+ # Not actually a branch
+ } elsif ($target =~ /(\d+)([bf])/) {
+ # The target is a local label
+ $line = handle_local_label($line, $1, $2);
+ $line =~ s/\b$instr\b/$&.w/ if $width eq "";
+ } elsif (!is_arm_register($target)) {
+ $call_targets{$target}++;
+ }
+ } elsif ($line =~ /^\s*.h?word.*\b\d+[bf]\b/) {
+ while ($line =~ /\b(\d+)([bf])\b/g) {
+ $line = handle_local_label($line, $1, $2);
+ }
+ }
+
+ # ALIGN in armasm syntax is the actual number of bytes
+ if ($line =~ /\.align\s+(\d+)/) {
+ my $align = 1 << $1;
+ $line =~ s/\.align\s(\d+)/ALIGN $align/;
+ }
+ # Convert gas style [r0, :128] into armasm [r0@128] alignment specification
+ $line =~ s/\[([^\[]+),\s*:(\d+)\]/[$1\@$2]/g;
+
+ # armasm treats logical values {TRUE} and {FALSE} separately from
+ # numeric values - logical operators and values can't be intermixed
+ # with numerical values. Evaluate !<number> and (a <> b) into numbers,
+ # let the assembler evaluate the rest of the expressions. This current
+ # only works for cases when ! and <> are used with actual constant numbers,
+ # we don't evaluate subexpressions here.
+
+ # Evaluate !<number>
+ while ($line =~ /!\s*(\d+)/g) {
+ my $val = ($1 != 0) ? 0 : 1;
+ $line =~ s/!(\d+)/$val/;
+ }
+ # Evaluate (a > b)
+ while ($line =~ /\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/) {
+ my $val;
+ if ($2 eq "<") {
+ $val = ($1 < $3) ? 1 : 0;
+ } else {
+ $val = ($1 > $3) ? 1 : 0;
+ }
+ $line =~ s/\(\s*(\d+)\s*([<>])\s*(\d+)\s*\)/$val/;
+ }
+
+ # Change a movw... #:lower16: into a mov32 pseudoinstruction
+ $line =~ s/^(\s*)movw(\s+\w+\s*,\s*)\#:lower16:(.*)$/$1mov32$2$3/;
+ # and remove the following, matching movt completely
+ $line =~ s/^\s*movt\s+\w+\s*,\s*\#:upper16:.*$//;
+
+ if ($line =~ /^\s*mov32\s+\w+,\s*([a-zA-Z]\w*)/) {
+ $mov32_targets{$1}++;
+ }
+
+ # Misc bugs/deficiencies:
+ # armasm seems unable to parse e.g. "vmov s0, s1" without a type
+ # qualifier, thus add .f32.
+ $line =~ s/^(\s+(?:vmov|vadd))(\s+s)/$1.f32$2/;
+ # armasm is unable to parse &0x - add spacing
+ $line =~ s/&0x/& 0x/g;
+ }
+
+ if ($force_thumb) {
+ # Convert register post indexing to a separate add instruction.
+ # This converts e.g. "ldr r0, [r1], r2" into "ldr r0, [r1]",
+ # "add r1, r1, r2".
+ $line =~ s/(ldr|str)\s+(\w+),\s*\[(\w+)\],\s*(\w+)/$1 $2, [$3]\n\tadd $3, $3, $4/g;
+
+ # Convert "mov pc, lr" into "bx lr", since the former only works
+ # for switching from arm to thumb (and only in armv7), but not
+ # from thumb to arm.
+ s/mov\s*pc\s*,\s*lr/bx lr/g;
+
+ # Convert stmdb/ldmia with only one register into a plain str/ldr with post-increment/decrement
+ $line =~ s/stmdb\s+sp!\s*,\s*\{([^,-]+)\}/str $1, [sp, #-4]!/g;
+ $line =~ s/ldmia\s+sp!\s*,\s*\{([^,-]+)\}/ldr $1, [sp], #4/g;
+
+ $line =~ s/\.arm/.thumb/x;
+ }
+
+ # comment out unsupported directives
+ $line =~ s/\.type/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.func/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.endfunc/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.endfunc/ENDP/x if $as_type =~ /armasm/;
+ $line =~ s/\.ltorg/$comm$&/x if $as_type =~ /^(apple-|clang)/;
+ $line =~ s/\.ltorg/LTORG/x if $as_type eq "armasm";
+ $line =~ s/\.size/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.fpu/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.arch/$comm$&/x if $as_type =~ /^(apple-|clang|armasm)/;
+ $line =~ s/\.object_arch/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/.section\s+.note.GNU-stack.*/$comm$&/x if $as_type =~ /^(apple-|armasm)/;
+ $line =~ s/\.hidden/$comm$&/x if $as_type =~ /^(apple-|clang|armasm)/;
+
+ $line =~ s/\.syntax/$comm$&/x if $as_type =~ /armasm/;
+
+ $line =~ s/\.hword/.short/x;
+
+ if ($as_type =~ /^apple-/) {
+ # the syntax for these is a little different
+ $line =~ s/\.global/.globl/x;
+ # also catch .section .rodata since the equivalent to .const_data is .section __DATA,__const
+ $line =~ s/(.*)\.rodata/.const_data/x;
+ $line =~ s/\.int/.long/x;
+ $line =~ s/\.float/.single/x;
+ }
+ if ($as_type eq "armasm") {
+ $line =~ s/\.global/EXPORT/x;
+ $line =~ s/\.int/dcd/x;
+ $line =~ s/\.long/dcd/x;
+ $line =~ s/\.float/dcfs/x;
+ $line =~ s/\.word/dcd/x;
+ $line =~ s/\.short/dcw/x;
+ $line =~ s/\.byte/dcb/x;
+ $line =~ s/\.thumb/THUMB/x;
+ $line =~ s/\.arm/ARM/x;
+ # The alignment in AREA is the power of two, just as .align in gas
+ $line =~ s/\.text/AREA |.text|, CODE, READONLY, ALIGN=2, CODEALIGN/;
+ $line =~ s/(\s*)(.*)\.rodata/$1AREA |.rodata|, DATA, READONLY, ALIGN=5/;
+
+ $line =~ s/fmxr/vmsr/;
+ $line =~ s/fmrx/vmrs/;
+ $line =~ s/fadds/vadd/;
+ }
+
+ # catch unknown section names that aren't mach-o style (with a comma)
+ if ($as_type =~ /apple-/ and $line =~ /.section ([^,]*)$/) {
+ die ".section $1 unsupported; figure out the mach-o section name and add it";
+ }
+
+ print ASMFILE $line;
+}
+
+if ($as_type ne "armasm") {
+ print ASMFILE ".text\n";
+ print ASMFILE ".align 2\n";
+ foreach my $literal (keys %literal_labels) {
+ print ASMFILE "$literal_labels{$literal}:\n $literal_expr $literal\n";
+ }
+
+ map print(ASMFILE ".thumb_func $_\n"),
+ grep exists $thumb_labels{$_}, keys %call_targets;
+} else {
+ map print(ASMFILE "\tIMPORT $_\n"),
+ grep ! exists $labels_seen{$_}, (keys %call_targets, keys %mov32_targets);
+
+ print ASMFILE "\tEND\n";
+}
+
+close(INPUT) or exit 1;
+close(ASMFILE) or exit 1;
+if ($as_type eq "armasm" and ! defined $ENV{GASPP_DEBUG}) {
+ system(@gcc_cmd) == 0 or die "Error running assembler";
+}
+
+END {
+ unlink($tempfile) if defined $tempfile;
+}
+#exit 1
diff --git a/xmake/core/tools/gcc.lua b/xmake/core/tools/gcc.lua
new file mode 100644
index 000000000..ab5e94ccb
--- /dev/null
+++ b/xmake/core/tools/gcc.lua
@@ -0,0 +1,192 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file gcc.lua
+--
+
+-- load modules
+local utils = require("base/utils")
+local table = require("base/table")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- define module: gcc
+local gcc = gcc or {}
+
+-- check the given flag
+function gcc._check(self, flag)
+
+ -- this flag has been checked?
+ self._CHECK = self._CHECK or {}
+ if self._CHECK[flag] then
+ return self._CHECK[flag]
+ end
+
+ -- check it
+ local result = flag
+ if 0 ~= os.execute(string.format("%s %s -S -o %s -xc %s > %s 2>&1", self.name, flag, xmake._NULDEV, xmake._NULDEV, xmake._NULDEV)) then
+ result = ""
+ end
+
+ -- trace
+ utils.verbose("checking for the compiler flags %s ... %s", flag, utils.ifelse(#result ~= 0, "ok", "no"))
+
+ -- save it
+ self._CHECK[flag] = result
+
+ -- ok?
+ return result
+end
+
+-- the init function
+function gcc.init(self, name)
+
+ -- save name
+ self.name = name or "gcc"
+
+ -- init mxflags
+ self.mxflags = { "-fmessage-length=0"
+ , "-pipe"
+ , "-fpascal-strings"
+ , "\"-DIBOutlet=__attribute__((iboutlet))\""
+ , "\"-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))\""
+ , "\"-DIBAction=void)__attribute__((ibaction)\""}
+
+ -- init shflags
+ if name:find("clang") then
+ self.shflags = { "-dynamiclib", "-fPIC" }
+ else
+ self.shflags = { "-shared", "-fPIC" }
+ end
+
+ -- init cxflags for the kind: shared
+ self.shared = {}
+ self.shared.cxflags = {"-fPIC"}
+
+ -- suppress warning for the clang
+ local isclang = false
+ if name:find("clang") then
+ isclang = true
+ self.cxflags = self.cxflags or {}
+ self.mxflags = self.mxflags or {}
+ self.asflags = self.asflags or {}
+ table.join2(self.cxflags, "-Qunused-arguments")
+ table.join2(self.mxflags, "-Qunused-arguments")
+ table.join2(self.asflags, "-Qunused-arguments")
+ end
+
+ -- init flags map
+ self.mapflags =
+ {
+ -- vectorexts
+ ["-mmmx"] = self._check
+ , ["-msse$"] = self._check
+ , ["-msse2"] = self._check
+ , ["-msse3"] = self._check
+ , ["-mssse3"] = self._check
+ , ["-mavx$"] = self._check
+ , ["-mavx2"] = self._check
+ , ["-mfpu=.*"] = self._check
+
+ -- warnings
+ , ["-W1"] = "-Wall"
+ , ["-W2"] = "-Wall"
+ , ["-W3"] = "-Wall"
+
+ -- strip
+ , ["-s"] = utils.ifelse(isclang, "-Wl,-S", "-s")
+ , ["-S"] = utils.ifelse(isclang, "-Wl,-S", "-S")
+
+ -- others
+ , ["-ftrapv"] = self._check
+ , ["-fsanitize=address"] = self._check
+ }
+
+end
+
+-- make the compile command
+function gcc.command_compile(self, srcfile, objfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s -c %s -o %s %s%s", self.name, flags, objfile, srcfile, redirect)
+end
+
+-- make the link command
+function gcc.command_link(self, objfiles, targetfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s -o %s %s %s%s", self.name, targetfile, objfiles, flags, redirect)
+end
+
+-- make the define flag
+function gcc.flag_define(self, define)
+
+ -- make it
+ return "-D" .. define:gsub("\"", "\\\"")
+end
+
+-- make the undefine flag
+function gcc.flag_undefine(self, undefine)
+
+ -- make it
+ return "-U" .. undefine
+end
+
+-- make the includedir flag
+function gcc.flag_includedir(self, includedir)
+
+ -- make it
+ return "-I" .. includedir
+end
+
+-- make the link flag
+function gcc.flag_link(self, link)
+
+ -- make it
+ return "-l" .. link
+end
+
+-- make the linkdir flag
+function gcc.flag_linkdir(self, linkdir)
+
+ -- make it
+ return "-L" .. linkdir
+end
+
+-- the main function
+function gcc.main(self, cmd)
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: gcc
+return gcc
diff --git a/xmake/core/tools/make.lua b/xmake/core/tools/make.lua
new file mode 100644
index 000000000..5d2d1f42b
--- /dev/null
+++ b/xmake/core/tools/make.lua
@@ -0,0 +1,82 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file make.lua
+--
+
+-- load modules
+local os = require("base/os")
+local utils = require("base/utils")
+
+-- define module: make
+local make = make or {}
+
+-- the init function
+function make.init(self, name)
+
+ -- save name
+ self.name = name or "make"
+
+ -- is verbose?
+ self._VERBOSE = utils.ifelse(xmake._OPTIONS.verbose, "-v", "")
+
+end
+
+-- the main function
+function make.main(self, mkfile, target)
+
+ -- enable jobs?
+ local jobs = ""
+ if xmake._OPTIONS.jobs ~= nil then
+ if tonumber(xmake._OPTIONS.jobs) ~= 0 then
+ jobs = "-j" .. xmake._OPTIONS.jobs
+ else
+ jobs = "-j"
+ end
+ end
+
+ -- make command
+ local cmd = nil
+ if mkfile and os.isfile(mkfile) then
+ cmd = string.format("%s -r %s -f %s %s VERBOSE=%s", self.name, jobs, mkfile, target or "", self._VERBOSE)
+ else
+ cmd = string.format("%s -r %s %s VERBOSE=%s", self.name, jobs, target or "", self._VERBOSE)
+ end
+
+ -- done
+ local ok = os.execute(cmd)
+ if ok ~= 0 then
+
+ -- attempt to execute it again for getting the error logs without jobs
+ if mkfile and os.isfile(mkfile) then
+ cmd = string.format("%s -r -f %s %s VERBOSE=%s", self.name, mkfile, target or "", self._VERBOSE)
+ else
+ cmd = string.format("%s -r %s VERBOSE=%s", self.name, target or "", self._VERBOSE)
+ end
+
+ -- done
+ return os.execute(cmd) == 0
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: make
+return make
diff --git a/xmake/core/tools/mkdir.lua b/xmake/core/tools/mkdir.lua
new file mode 100644
index 000000000..9fadb875d
--- /dev/null
+++ b/xmake/core/tools/mkdir.lua
@@ -0,0 +1,46 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file mkdir.lua
+--
+
+-- define module: mkdir
+local mkdir = mkdir or {}
+
+-- load modules
+local os = require("base/os")
+
+-- the main function
+function mkdir.main(self, ...)
+
+ -- mkdir all
+ for _, dir in ipairs(...) do
+ if not os.exists(dir) then
+ if not os.mkdir(dir) then
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: mkdir
+return mkdir
diff --git a/xmake/core/tools/mv.lua b/xmake/core/tools/mv.lua
new file mode 100644
index 000000000..7af2db9ed
--- /dev/null
+++ b/xmake/core/tools/mv.lua
@@ -0,0 +1,43 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file mv.lua
+--
+
+-- define module: mv
+local mv = mv or {}
+
+-- load modules
+local os = require("base/os")
+
+-- the main function
+function mv.main(self, ...)
+
+ -- mv it
+ local pathes = ...
+ if pathes and table.getn(pathes) == 2 then
+ return os.mv(pathes[1], pathes[2])
+ end
+
+ -- failed
+ return false
+end
+
+-- return module: mv
+return mv
diff --git a/xmake/core/tools/rm.lua b/xmake/core/tools/rm.lua
new file mode 100644
index 000000000..47f57e68b
--- /dev/null
+++ b/xmake/core/tools/rm.lua
@@ -0,0 +1,46 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file rm.lua
+--
+
+-- define module: rm
+local rm = rm or {}
+
+-- load modules
+local os = require("base/os")
+
+-- the main function
+function rm.main(self, ...)
+
+ -- rm all
+ for _, file_or_dir in ipairs(...) do
+ if os.exists(file_or_dir) then
+ if not os.rm(file_or_dir) then
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: rm
+return rm
diff --git a/xmake/core/tools/rmdir.lua b/xmake/core/tools/rmdir.lua
new file mode 100644
index 000000000..cea1e28fa
--- /dev/null
+++ b/xmake/core/tools/rmdir.lua
@@ -0,0 +1,46 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file rmdir.lua
+--
+
+-- define module: rmdir
+local rmdir = rmdir or {}
+
+-- load modules
+local os = require("base/os")
+
+-- the main function
+function rmdir.main(self, ...)
+
+ -- rmdir all
+ for _, dir in ipairs(...) do
+ if os.isdir(dir) then
+ if not os.rmdir(dir) then
+ return false
+ end
+ end
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: rmdir
+return rmdir
diff --git a/xmake/core/tools/swiftc.lua b/xmake/core/tools/swiftc.lua
new file mode 100644
index 000000000..39142705f
--- /dev/null
+++ b/xmake/core/tools/swiftc.lua
@@ -0,0 +1,117 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file swiftc.lua
+--
+
+-- load modules
+local utils = require("base/utils")
+local table = require("base/table")
+local string = require("base/string")
+local config = require("base/config")
+local platform = require("platform/platform")
+
+-- define module: swiftc
+local swiftc = swiftc or {}
+
+-- the init function
+function swiftc.init(self, name)
+
+ -- save name
+ self.name = name or "swiftc"
+
+ -- init flags map
+ self.mapflags =
+ {
+ -- symbols
+ ["-fvisibility=hidden"] = ""
+
+ -- warnings
+ , ["-w"] = ""
+ , ["-W.*"] = ""
+
+ -- optimize
+ , ["-O0"] = "-Onone"
+ , ["-Ofast"] = "-Ounchecked"
+ , ["-O.*"] = "-O"
+
+ -- vectorexts
+ , ["-m.*"] = ""
+
+ -- strip
+ , ["-s"] = ""
+ , ["-S"] = ""
+
+ -- others
+ , ["-ftrapv"] = ""
+ , ["-fsanitize=address"] = ""
+ }
+
+ -- init ldflags
+ local swift_linkdirs = config.get("__swift_linkdirs")
+ if swift_linkdirs then
+ self.ldflags = { "-L" .. swift_linkdirs }
+ end
+
+end
+
+-- make the compile command
+function swiftc.command_compile(self, srcfile, objfile, flags, logfile)
+
+ -- redirect
+ local redirect = ""
+ if logfile then redirect = string.format(" > %s 2>&1", logfile) end
+
+ -- make it
+ return string.format("%s -c %s -o %s %s%s", self.name, flags, objfile, srcfile, redirect)
+end
+
+-- make the includedir flag
+function swiftc.flag_includedir(self, includedir)
+
+ -- make it
+ return "-Xcc -I" .. includedir
+end
+
+-- make the define flag
+function swiftc.flag_define(self, define)
+
+ -- make it
+ return "-Xcc -D" .. define:gsub("\"", "\\\"")
+end
+
+-- make the undefine flag
+function swiftc.flag_undefine(self, undefine)
+
+ -- make it
+ return "-Xcc -U" .. undefine
+end
+
+-- the main function
+function swiftc.main(self, cmd)
+
+ -- execute it
+ local ok = os.execute(cmd)
+
+ -- ok?
+ return utils.ifelse(ok == 0, true, false)
+end
+
+-- return module: swiftc
+return swiftc
diff --git a/xmake/core/tools/tools.lua b/xmake/core/tools/tools.lua
new file mode 100644
index 000000000..a61322d3c
--- /dev/null
+++ b/xmake/core/tools/tools.lua
@@ -0,0 +1,222 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file tools.lua
+--
+
+-- define module: tools
+local tools = tools or {}
+
+-- load modules
+local os = require("base/os")
+local path = require("base/path")
+local utils = require("base/utils")
+local string = require("base/string")
+local platform = require("platform/platform")
+
+-- match the tool name
+function tools._match(name, toolname)
+
+ -- match full? ok
+ if name == toolname then return 100 end
+
+ -- match the name for windows? ok
+ if name:find("^" .. toolname .. "%.exe") then return 90 end
+ if name:find(toolname .. "%.exe") then return 85 end
+
+ -- match the last word? ok
+ if name:find(toolname .. "$") then return 80 end
+
+ -- match the partial word? ok
+ if name:find("%-" .. toolname) then return 60 end
+
+ -- contains it? ok
+ if name:find(toolname, 1, true) then return 30 end
+
+ -- not matched
+ return 0
+end
+
+-- find tool from the given root directory and name
+function tools._find_from(root, name)
+
+ -- attempt to get it directly first
+ local filepath = string.format("%s/%s.lua", root, name)
+ if os.isfile(filepath) then
+ return filepath
+ end
+
+ -- make the lower name
+ name = name:lower()
+
+ -- get all tool files
+ local file_ok = nil
+ local score_maxn = 0
+ local files = os.match(string.format("%s/*.lua", root))
+ for _, file in ipairs(files) do
+
+ -- the tool name
+ local toolname = path.basename(file)
+
+ -- found it?
+ if toolname and toolname ~= "tools" then
+
+ -- match score
+ local score = tools._match(name, toolname:lower())
+
+ -- ok?
+ if score >= 100 then return file end
+
+ -- select the file with the max score
+ if score > score_maxn then
+ file_ok = file
+ score_maxn = score
+ end
+ end
+ end
+
+ -- ok?
+ return file_ok
+end
+
+-- probe it's absolute path if exists from the given tool name and root directory
+function tools._probe(root, name)
+
+ -- check
+ assert(root and name)
+
+ -- make the tool path
+ local toolpath = string.format("%s/%s", root, name)
+ toolpath = path.translate(toolpath)
+
+ -- the tool exists? ok
+ if toolpath and os.isfile(toolpath) then
+ return toolpath
+ end
+end
+
+-- find tool from the given name and directory (optional)
+function tools.find(name, root)
+
+ -- check
+ assert(name)
+
+ -- init filename
+ local filepath = nil
+
+ -- only find it from this directory if the given directory exists
+ if root then return tools._find_from(root, name) end
+
+ -- attempt to find it from the current platform directory first
+ if not filepath then filepath = tools._find_from(platform.directory() .. "/tools", name) end
+
+ -- attempt to find it from the script directory
+ if not filepath then filepath = tools._find_from(xmake._CORE_DIR .. "/tools", name) end
+
+ -- ok?
+ return filepath
+end
+
+-- load tool from the given name and directory (optional)
+function tools.load(name, root)
+
+ -- check
+ assert(name)
+
+ -- get it directly from cache dirst
+ tools._TOOLS = tools._TOOLS or {}
+ if tools._TOOLS[name] then
+ return tools._TOOLS[name]
+ end
+
+ -- find the tool file path
+ local toolpath = tools.find(name, root)
+
+ -- not exists?
+ if not toolpath or not os.isfile(toolpath) then
+ return
+ end
+
+ -- load script
+ local script, errors = loadfile(toolpath)
+ if script then
+
+ -- load tool
+ local tool = script()
+
+ -- init tool
+ if tool and tool.init then
+ tool:init(name)
+ end
+
+ -- save tool to the cache
+ tools._TOOLS[name] = tool
+
+ -- ok?
+ return tool
+ else
+ utils.error(errors)
+ utils.error("load %s failed!", toolpath)
+ assert(false)
+ end
+end
+
+-- get the given tool script from the given kind
+function tools.get(kind)
+
+ -- get the tool name
+ local toolname = platform.tool(kind)
+ if not toolname then
+ utils.error("cannot get tool name for %s", kind)
+ return
+ end
+
+ -- load it
+ return tools.load(toolname)
+end
+
+-- probe it's absolute path if exists from the given tool name
+function tools.probe(name, dirs)
+
+ -- check
+ assert(name)
+
+ -- attempt to run it directly first
+ if os.execute(string.format("%s > %s 2>&1", name, xmake._NULDEV)) ~= 0x7f00 then
+ return name
+ end
+
+ -- attempt to get it from the given directories
+ if dirs then
+ for _, dir in ipairs(utils.wrap(dirs)) do
+
+ -- probe it
+ local toolpath = tools._probe(dir, name)
+
+ -- ok?
+ if toolpath and os.execute(string.format("%s > %s 2>&1", toolpath, xmake._NULDEV)) ~= 0x7f00 then
+ return toolpath
+ end
+ end
+ end
+end
+
+
+-- return module: tools
+return tools
diff --git a/xmake/core/tools/verbose.lua b/xmake/core/tools/verbose.lua
new file mode 100644
index 000000000..b1168f29d
--- /dev/null
+++ b/xmake/core/tools/verbose.lua
@@ -0,0 +1,47 @@
+--!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) 2009 - 2015, ruki All rights reserved.
+--
+-- @author ruki
+-- @file verbose.lua
+--
+
+
+-- define module: verbose
+local verbose = verbose or {}
+
+-- load modules
+local io = require("base/io")
+local string = require("base/string")
+
+-- the main function
+function verbose.main(self, ...)
+
+ -- verbose all
+ if xmake._OPTIONS.verbose then
+ for _, v in ipairs(...) do
+ io.write(string.format("%s ", v:decode()))
+ end
+ io.write("\n")
+ end
+
+ -- ok
+ return true
+end
+
+-- return module: verbose
+return verbose