--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- -- @author ruki -- @file make.lua -- -- imports import("core.base.option") import("core.project.config") import("lib.detect.find_tool") import("private.utils.toolchain", {alias = "toolchain_utils"}) -- translate bin path function _translate_bin_path(bin_path) if is_host("windows") and bin_path then bin_path = bin_path:gsub("\\", "/") local bin_path_lower = bin_path:lower() if not bin_path_lower:endswith(".exe") and not bin_path_lower:endswith(".cmd") and not bin_path_lower:endswith(".bat") then bin_path = bin_path .. ".exe" end return bin_path end return bin_path end -- get the build environments function buildenvs(package) local envs = {} 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:config("asflags"))) local ldflags = table.copy(table.wrap(package:config("ldflags"))) local shflags = table.copy(table.wrap(package:config("shflags"))) local runtimes = package:runtimes() if runtimes then table.join2(cxxflags, toolchain_utils.map_compflags_for_package(package, "cxx", "runtime", runtimes)) table.join2(ldflags, toolchain_utils.map_linkflags_for_package(package, "binary", {"cxx"}, "runtime", runtimes)) table.join2(shflags, toolchain_utils.map_linkflags_for_package(package, "shared", {"cxx"}, "runtime", runtimes)) end if package:is_plat(os.host()) then if package:is_plat("linux") and package:is_arch("i386") then table.insert(cflags, "-m32") table.insert(cxxflags, "-m32") table.insert(asflags, "-m32") table.insert(ldflags, "-m32") end envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.LDFLAGS = table.concat(ldflags, ' ') envs.SHFLAGS = table.concat(shflags, ' ') else envs.CC = _translate_bin_path(package:build_getenv("cc")) envs.CXX = _translate_bin_path(package:build_getenv("cxx")) envs.AS = _translate_bin_path(package:build_getenv("as")) envs.AR = _translate_bin_path(package:build_getenv("ar")) envs.LD = _translate_bin_path(package:build_getenv("ld")) envs.LDSHARED = _translate_bin_path(package:build_getenv("sh")) envs.CPP = _translate_bin_path(package:build_getenv("cpp")) envs.RANLIB = _translate_bin_path(package:build_getenv("ranlib")) envs.CFLAGS = table.concat(cflags, ' ') envs.CXXFLAGS = table.concat(cxxflags, ' ') envs.ASFLAGS = table.concat(asflags, ' ') envs.ARFLAGS = table.concat(table.wrap(package:build_getenv("arflags")), ' ') envs.LDFLAGS = table.concat(ldflags, ' ') envs.SHFLAGS = table.concat(shflags, ' ') end local ACLOCAL_PATH = {} local PKG_CONFIG_PATH = {} for _, dep in ipairs(package:librarydeps({private = true})) 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 end -- some binary packages contain it too. e.g. libtool for _, dep in ipairs(package:orderdeps()) do 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) -- 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 -- 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}) if tool then program = tool.program end end assert(program, "make not found!") os.vrunv(program, argv or {}, {envs = runenvs, curdir = opt.curdir}) end -- build package function build(package, configs, opt) opt = opt or {} -- pass configurations 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) end end end -- do build make(package, argv, opt) end -- install package function install(package, configs, opt) -- do build opt = opt or {} build(package, configs, opt) -- do install local argv = {"install"} if option.get("verbose") then table.insert(argv, "VERBOSE=1") table.insert(argv, "V=1") end make(package, argv, opt) end