--!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") import("core.language.language") -- get macro defines function _get_macro_defines(snippets, extension, opt) -- make an stub source file local sourcefile = os.tmpfile() .. extension io.writefile(sourcefile, table.concat(table.wrap(snippets), "\n")) -- get defines local results = {} local defines = try { function () return os.iorunv(opt.program, table.join(opt.flags or {}, {"-dM", "-E", sourcefile}), {envs = opt.envs}) end } if defines then for _, define in ipairs(defines:split("\n")) do local name = define:match("#define%s+(.-)%s+") if name then results[name] = true end end end os.tryrm(sourcefile) return results end -- set feature with condition function _set_feature(feature, condition) -- init features _g.features = _g.features or {} -- get language kind local langkind = feature:match("^(%w-)_") assert(langkind, "unknown language kind for the feature: %s", feature) -- get source kind from the language kind local sourcekind = language.langkinds()[langkind] assert(sourcekind, "unknown language kind: " .. langkind) -- get extension local extension = table.wrap(language.sourcekinds()[sourcekind])[1] assert(extension, "not supported kind for the feature: %s", feature) -- make snippet local snippet = format([[ #if (%s) # define %s 1 #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 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 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