--!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 features.lua -- -- imports import("cfeatures") import("cxxfeatures") -- get macro defines function _get_macro_defines(snippets, extension, opt) -- make an stub source file local sourcefile = os.tmpfile() .. extension local objectfile = sourcefile .. ".obj" local binaryfile = sourcefile .. ".exe" io.writefile(sourcefile, "#include \n\nint main(int argc, char** argv)\n{\n" .. table.concat(table.wrap(snippets), "\n") .. "\nreturn 0;\n}\n") -- get defines local results = {} local defines = try { function () os.runv(opt.program, table.join(opt.flags or {}, {"-nologo", "-Fo" .. objectfile, sourcefile, "-link", "-out:" .. binaryfile}), {envs = opt.envs}) return os.iorunv(binaryfile, {}, {envs = opt.envs}) end } if defines then for _, define in ipairs(defines:split("\n")) do results[define] = true end end -- remove files os.tryrm(sourcefile) os.tryrm(objectfile) os.tryrm(binaryfile) return results end -- set feature with condition function _set_feature(feature, condition) -- init features _g.features = _g.features or {} -- get feature kind local kind = feature:match("^(%w-)_") assert(kind, "unknown kind for the feature: %s", feature) -- init language extensions _g.extensions = _g.extensions or {c = ".c", cxx = ".cpp", objc = ".m", objcxx = ".mm"} -- get extension local extension = _g.extensions[kind] assert(extension, "not supported kind for the feature: %s", feature) -- make snippet local snippet = format([[ #if (%s) printf("%s\n"); #endif]], condition, feature) -- init features with the given extension local features = _g.features[extension] or {} _g.features[extension] = features -- set feature and snippet features[feature] = snippet end -- set features function set_features(features) for feature, condition in pairs(features) do _set_feature(feature, condition) end end -- check features function check_features(opt) -- check features with all extensions opt = opt or {} local results = {} for extension, features in pairs(_g.features) do -- make snippets local snippets = {} for _, snippet in pairs(features) do table.insert(snippets, snippet) end -- get defines local defines = _get_macro_defines(snippets, extension, opt) -- check features for feature, _ in pairs(features) do if defines[feature] then results[feature] = true end end end -- ok? return results end -- get features -- -- @param opt the argument options, e.g. {toolname = "", program = "", programver = "", flags = {}} -- -- @return the features -- function main(opt) -- set features for c set_features(cfeatures()) -- set features for c++ set_features(cxxfeatures()) -- check features return check_features(opt) end