summaryrefslogtreecommitdiff
path: root/xmake/modules/package/tools/make.lua
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/modules/package/tools/make.lua')
-rw-r--r--xmake/modules/package/tools/make.lua337
1 files changed, 306 insertions, 31 deletions
diff --git a/xmake/modules/package/tools/make.lua b/xmake/modules/package/tools/make.lua
index cbc58c9e2..12b94d64f 100644
--- a/xmake/modules/package/tools/make.lua
+++ b/xmake/modules/package/tools/make.lua
@@ -15,18 +15,148 @@
-- Copyright (C) 2015-present, TBOOX Open Source Group.
--
-- @author ruki
--- @file make.lua
+-- @file autoconf.lua
--
-- imports
import("core.base.option")
import("core.project.config")
+import("core.tool.linker")
+import("core.tool.compiler")
import("lib.detect.find_tool")
+-- translate paths
+function _translate_paths(package, paths)
+ if paths and is_host("windows") and (package:is_plat("mingw") or package:is_plat("msys") or package:is_plat("cygwin")) then
+ if type(paths) == "string" then
+ return (paths:gsub("\\", "/"))
+ elseif type(paths) == "table" then
+ local result = {}
+ for _, p in ipairs(paths) do
+ table.insert(result, (p:gsub("\\", "/")))
+ end
+ return result
+ end
+ end
+ return paths
+end
+
+-- translate windows bin path
+function _translate_windows_bin_path(bin_path)
+ if bin_path then
+ local argv = os.argv(bin_path)
+ argv[1] = argv[1]:gsub("\\", "/") .. ".exe"
+ return os.args(argv)
+ end
+end
+
+-- map compiler flags
+function _map_compflags(package, langkind, name, values)
+ return compiler.map_flags(langkind, name, values, {target = package})
+end
+
+-- map linker flags
+function _map_linkflags(package, targetkind, sourcekinds, name, values)
+ return linker.map_flags(targetkind, sourcekinds, name, values, {target = package})
+end
+
+-- get configs
+function _get_configs(package, configs)
+
+ -- add prefix
+ local configs = configs or {}
+ table.insert(configs, "--prefix=" .. _translate_paths(package, package:installdir()))
+
+ -- add host for cross-complation
+ if not configs.host and not package:is_plat(os.subhost()) then
+ if package:is_plat("iphoneos") then
+ local triples =
+ {
+ arm64 = "aarch64-apple-darwin",
+ arm64e = "aarch64-apple-darwin",
+ armv7 = "armv7-apple-darwin",
+ armv7s = "armv7s-apple-darwin",
+ i386 = "i386-apple-darwin",
+ x86_64 = "x86_64-apple-darwin"
+ }
+ table.insert(configs, "--host=" .. (triples[package:arch()] or triples.arm64))
+ elseif package:is_plat("android") then
+ -- @see https://developer.android.com/ndk/guides/other_build_systems#autoconf
+ local triples =
+ {
+ ["armv5te"] = "arm-linux-androideabi", -- deprecated
+ ["armv7-a"] = "arm-linux-androideabi", -- deprecated
+ ["armeabi"] = "arm-linux-androideabi", -- removed in ndk r17
+ ["armeabi-v7a"] = "arm-linux-androideabi",
+ ["arm64-v8a"] = "aarch64-linux-android",
+ i386 = "i686-linux-android", -- deprecated
+ x86 = "i686-linux-android",
+ x86_64 = "x86_64-linux-android",
+ mips = "mips-linux-android", -- removed in ndk r17
+ mips64 = "mips64-linux-android" -- removed in ndk r17
+ }
+ table.insert(configs, "--host=" .. (triples[package:arch()] or triples["armeabi-v7a"]))
+ elseif package:is_plat("mingw") then
+ local triples =
+ {
+ i386 = "i686-w64-mingw32",
+ x86_64 = "x86_64-w64-mingw32"
+ }
+ table.insert(configs, "--host=" .. (triples[package:arch()] or triples.i386))
+ elseif package:is_plat("cross") then
+ local host = package:arch()
+ if package:is_arch("arm64") then
+ host = "aarch64"
+ elseif package:is_arch("arm.*") then
+ host = "arm"
+ end
+ host = host .. "-" .. package:targetos()
+ table.insert(configs, "--host=" .. host)
+ end
+ end
+ return configs
+end
+
+-- get cflags from package deps
+function _get_cflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _map_compflags(package, "cxx", "define", fetchinfo.defines))
+ table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "includedir", fetchinfo.includedirs)))
+ table.join2(result, _translate_paths(package, _map_compflags(package, "cxx", "sysincludedir", fetchinfo.sysincludedirs)))
+ end
+ end
+ end
+ return result
+end
+
+-- get ldflags from package deps
+function _get_ldflags_from_packagedeps(package, opt)
+ local result = {}
+ for _, depname in ipairs(opt.packagedeps) do
+ local dep = package:dep(depname)
+ if dep then
+ local fetchinfo = dep:fetch({external = false})
+ if fetchinfo then
+ table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "linkdir", fetchinfo.linkdirs)))
+ table.join2(result, _map_linkflags(package, "binary", {"cxx"}, "link", fetchinfo.links))
+ table.join2(result, _translate_paths(package, _map_linkflags(package, "binary", {"cxx"}, "syslink", fetchinfo.syslinks)))
+ end
+ end
+ end
+ return result
+end
+
-- get the build environments
-function buildenvs(package)
+function buildenvs(package, opt)
+ opt = opt or {}
local envs = {}
- if package:is_plat(os.host()) then
+ local cppflags = {}
+ if package:is_plat(os.subhost()) then
local cflags = table.join(table.wrap(package:config("cxflags")), package:config("cflags"))
local cxxflags = table.join(table.wrap(package:config("cxflags")), package:config("cxxflags"))
local asflags = table.copy(table.wrap(package:config("asflags")))
@@ -37,15 +167,63 @@ function buildenvs(package)
table.insert(asflags, "-m32")
table.insert(ldflags, "-m32")
end
+ table.join2(cflags, opt.cflags)
+ table.join2(cflags, opt.cxflags)
+ table.join2(cxxflags, opt.cxxflags)
+ table.join2(cxxflags, opt.cxflags)
+ table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688
+ table.join2(asflags, opt.asflags)
+ table.join2(ldflags, opt.ldflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cppflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
+ envs.CPPFLAGS = table.concat(cppflags, ' ')
envs.ASFLAGS = table.concat(asflags, ' ')
envs.LDFLAGS = table.concat(ldflags, ' ')
else
- local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags"))
- local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags"))
+ local cflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cflags"))
+ local cxxflags = table.join(table.wrap(package:build_getenv("cxflags")), package:build_getenv("cxxflags"))
+ local asflags = table.copy(table.wrap(package:build_getenv("asflags")))
+ local ldflags = table.copy(table.wrap(package:build_getenv("ldflags")))
+ local shflags = table.copy(table.wrap(package:build_getenv("shflags")))
+ local arflags = table.copy(table.wrap(package:build_getenv("arflags")))
+ local defines = package:build_getenv("defines")
+ local includedirs = package:build_getenv("includedirs")
+ local sysincludedirs = package:build_getenv("sysincludedirs")
+ local links = package:build_getenv("links")
+ local syslinks = package:build_getenv("syslinks")
+ local linkdirs = package:build_getenv("linkdirs")
+ table.join2(cflags, opt.cflags)
+ table.join2(cflags, opt.cxflags)
+ table.join2(cxxflags, opt.cxxflags)
+ table.join2(cxxflags, opt.cxflags)
+ table.join2(cppflags, opt.cppflags) -- @see https://github.com/xmake-io/xmake/issues/1688
+ table.join2(asflags, opt.asflags)
+ table.join2(ldflags, opt.ldflags)
+ table.join2(shflags, opt.shflags)
+ table.join2(cflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cxxflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(cppflags, _get_cflags_from_packagedeps(package, opt))
+ table.join2(ldflags, _get_ldflags_from_packagedeps(package, opt))
+ table.join2(cflags, _map_compflags(package, "c", "define", defines))
+ table.join2(cflags, _map_compflags(package, "c", "includedir", includedirs))
+ table.join2(cflags, _map_compflags(package, "c", "sysincludedir", sysincludedirs))
+ table.join2(asflags, _map_compflags(package, "as", "define", defines))
+ table.join2(asflags, _map_compflags(package, "as", "includedir", includedirs))
+ table.join2(asflags, _map_compflags(package, "as", "sysincludedir", sysincludedirs))
+ table.join2(cxxflags, _map_compflags(package, "cxx", "define", defines))
+ table.join2(cxxflags, _map_compflags(package, "cxx", "includedir", includedirs))
+ table.join2(cxxflags, _map_compflags(package, "cxx", "sysincludedir", sysincludedirs))
+ table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "link", links))
+ table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "syslink", syslinks))
+ table.join2(ldflags, _map_linkflags(package, "binary", {"cxx"}, "linkdir", linkdirs))
+ table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "link", links))
+ table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "syslink", syslinks))
+ table.join2(shflags, _map_linkflags(package, "shared", {"cxx"}, "linkdir", linkdirs))
envs.CC = package:build_getenv("cc")
- envs.CXX = package:build_getenv("cxx")
envs.AS = package:build_getenv("as")
envs.AR = package:build_getenv("ar")
envs.LD = package:build_getenv("ld")
@@ -54,10 +232,39 @@ function buildenvs(package)
envs.RANLIB = package:build_getenv("ranlib")
envs.CFLAGS = table.concat(cflags, ' ')
envs.CXXFLAGS = table.concat(cxxflags, ' ')
- envs.ASFLAGS = table.concat(table.wrap(package:build_getenv("asflags")), ' ')
- envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ')
- envs.LDFLAGS = table.concat(table.wrap(package:build_getenv("ldflags")), ' ')
- envs.SHFLAGS = table.concat(table.wrap(package:build_getenv("shflags")), ' ')
+ envs.CPPFLAGS = table.concat(cppflags, ' ')
+ envs.ASFLAGS = table.concat(asflags, ' ')
+ envs.ARFLAGS = table.concat(arflags, ' ')
+ envs.LDFLAGS = table.concat(ldflags, ' ')
+ envs.SHFLAGS = table.concat(shflags, ' ')
+ if package:is_plat("mingw") then
+ -- fix linker error, @see https://github.com/xmake-io/xmake/issues/574
+ -- libtool: line 1855: lib: command not found
+ envs.ARFLAGS = nil
+ local ld = envs.LD
+ if ld then
+ if ld:endswith("x86_64-w64-mingw32-g++") then
+ envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "x86_64-w64-mingw32-ld")
+ elseif ld:endswith("i686-w64-mingw32-g++") then
+ envs.LD = path.join(path.directory(ld), is_host("windows") and "ld" or "i686-w64-mingw32-ld")
+ end
+ end
+ if is_host("windows") then
+ envs.CC = _translate_windows_bin_path(envs.CC)
+ envs.AS = _translate_windows_bin_path(envs.AS)
+ envs.AR = _translate_windows_bin_path(envs.AR)
+ envs.LD = _translate_windows_bin_path(envs.LD)
+ envs.LDSHARED = _translate_windows_bin_path(envs.LDSHARED)
+ envs.CPP = _translate_windows_bin_path(envs.CPP)
+ envs.RANLIB = _translate_windows_bin_path(envs.RANLIB)
+ end
+ elseif package:is_plat("cross") then
+ -- only for cross-toolchain
+ envs.CXX = package:build_getenv("cxx")
+ if not envs.ARFLAGS or envs.ARFLAGS == "" then
+ envs.ARFLAGS = "-cr"
+ end
+ end
end
local ACLOCAL_PATH = {}
local PKG_CONFIG_PATH = {}
@@ -77,56 +284,111 @@ function buildenvs(package)
end
envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH)
envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH)
- -- some Makefile use ComSpec to detect Windows (e.g. Makefiles generated by Premake) and require this env
- if is_subhost("windows") then
- envs.ComSpec = os.getenv("ComSpec")
- end
+ return envs
+end
+-- get the autogen environments
+function autogen_envs(package, opt)
+ opt = opt or {}
+ local envs = {NOCONFIGURE = "yes"}
+ local ACLOCAL_PATH = {}
+ local PKG_CONFIG_PATH = {}
+ for _, dep in ipairs(package:orderdeps()) do
+ local pkgconfig = path.join(dep:installdir(), "lib", "pkgconfig")
+ if os.isdir(pkgconfig) then
+ table.insert(PKG_CONFIG_PATH, pkgconfig)
+ end
+ pkgconfig = path.join(dep:installdir(), "share", "pkgconfig")
+ if os.isdir(pkgconfig) then
+ table.insert(PKG_CONFIG_PATH, pkgconfig)
+ end
+ local aclocal = path.join(dep:installdir(), "share", "aclocal")
+ if os.isdir(aclocal) then
+ table.insert(ACLOCAL_PATH, aclocal)
+ end
+ end
+ envs.ACLOCAL_PATH = path.joinenv(ACLOCAL_PATH)
+ envs.PKG_CONFIG_PATH = path.joinenv(PKG_CONFIG_PATH)
return envs
end
+-- configure package
+function configure(package, configs, opt)
+
+ -- init options
+ opt = opt or {}
+
+ -- get envs
+ local envs = opt.envs or buildenvs(package, opt)
+
+ -- generate configure file
+ if not os.isfile("configure") then
+ if os.isfile("autogen.sh") then
+ os.vrunv("sh", {"./autogen.sh"}, {envs = autogen_envs(package, opt)})
+ elseif os.isfile("configure.ac") then
+ os.vrunv("sh", {"autoreconf", "--install", "--symlink"}, {envs = autogen_envs(package, opt)})
+ end
+ end
+
+ -- pass configurations
+ local argv = {"./configure"}
+ for name, value in pairs(_get_configs(package, configs)) do
+ value = tostring(value):trim()
+ if value ~= "" then
+ if type(name) == "number" then
+ table.insert(argv, value)
+ else
+ table.insert(argv, "--" .. name .. "=" .. value)
+ end
+ end
+ end
+
+ -- do configure
+ os.vrunv("sh", argv, {envs = envs})
+end
+
-- do make
function make(package, argv, opt)
opt = opt or {}
local program
- local runenvs = opt.envs or buildenvs(package)
if package:is_plat("mingw") and is_subhost("windows") then
local mingw = assert(package:build_getenv("mingw") or package:build_getenv("sdk"), "mingw not found!")
program = path.join(mingw, "bin", "mingw32-make.exe")
else
- local tool = find_tool("make", {envs = runenvs})
+ local tool = find_tool("make")
if tool then
program = tool.program
end
end
assert(program, "make not found!")
- os.vrunv(program, argv, {envs = runenvs, curdir = opt.curdir})
+ os.vrunv(program, argv)
end
-- build package
function build(package, configs, opt)
- -- init options
- opt = opt or {}
+ -- do configure
+ configure(package, configs, opt)
- -- pass configurations
+ -- do make and install
+ opt = opt or {}
local njob = opt.jobs or option.get("jobs") or tostring(os.default_njob())
local argv = {"-j" .. njob}
if option.get("verbose") then
- table.insert(argv, "VERBOSE=1")
+ table.insert(argv, "V=1")
end
- for name, value in pairs(configs) do
- value = tostring(value):trim()
- if value ~= "" then
- if type(name) == "number" then
- table.insert(argv, value)
- else
- table.insert(argv, name .. "=" .. value)
+ if opt.makeconfigs then
+ for name, value in pairs(opt.makeconfigs) do
+ value = tostring(value):trim()
+ if value ~= "" then
+ if type(name) == "number" then
+ table.insert(argv, value)
+ else
+ table.insert(argv, name .. "=" .. value)
+ end
end
end
end
-
- -- do build
make(package, argv, opt)
end
@@ -140,7 +402,20 @@ function install(package, configs, opt)
-- do install
local argv = {"install"}
if option.get("verbose") then
- table.insert(argv, "VERBOSE=1")
+ table.insert(argv, "V=1")
+ end
+ if opt.makeconfigs then
+ for name, value in pairs(opt.makeconfigs) do
+ value = tostring(value):trim()
+ if value ~= "" then
+ if type(name) == "number" then
+ table.insert(argv, value)
+ else
+ table.insert(argv, name .. "=" .. value)
+ end
+ end
+ end
end
make(package, argv, opt)
end
+