diff --git a/premake/export-compile-commands/README.md b/premake/export-compile-commands/README.md new file mode 100644 index 000000000..c02d07879 --- /dev/null +++ b/premake/export-compile-commands/README.md @@ -0,0 +1,44 @@ +## Generate compile_commands.json for premake projects + +This module implements [JSON Compilation Database Format +Specification](http://clang.llvm.org/docs/JSONCompilationDatabase.html) for +premake projects. + +Install this module somewhere premake can find it, for example: + +``` +git clone https://github.com/tarruda/premake-export-compile-commands export-compile-commands +``` + +Then put this at the top of your system script(eg: ~/.premake/premake-system.lua): + +```lua +require "export-compile-commands" +``` + +Note that while possible, it is not recommended to put the `require` line in +project-specific premake configuration because the "export-compile-commands" +module will need to be installed everywhere your project is built. + +After the above steps, the "export-compile-commands" action will be available +for your projects: + +``` +premake5 export-compile-commands +``` + +The `export-compile-commands` action will generate one json file per +config/platform combination in each workspace, all under the `compile_commands` +subdirectory. For example, say you have defined `debug` and `release` +configurations with `x32` and `x64` platforms, the output will be something +like: + +``` +Generated WORKSPACE_BUILD_DIR/compile_commands/debug_x32.json... +Generated WORKSPACE_BUILD_DIR/compile_commands/debug_x64.json... +Generated WORKSPACE_BUILD_DIR/compile_commands/release_x32.json... +Generated WORKSPACE_BUILD_DIR/compile_commands/release_x64.json... +``` + +where each file contain the compilation commands for the corresponding +config/platform combo. diff --git a/premake/export-compile-commands/_manifest.lua b/premake/export-compile-commands/_manifest.lua new file mode 100644 index 000000000..707c4325b --- /dev/null +++ b/premake/export-compile-commands/_manifest.lua @@ -0,0 +1,4 @@ +return { + '_preload.lua', + 'export-compile-commands.lua', +} diff --git a/premake/export-compile-commands/_preload.lua b/premake/export-compile-commands/_preload.lua new file mode 100644 index 000000000..9e714742f --- /dev/null +++ b/premake/export-compile-commands/_preload.lua @@ -0,0 +1,3 @@ +return function(cfg) + return _ACTION == 'export-compile-commands' +end diff --git a/premake/export-compile-commands/export-compile-commands.lua b/premake/export-compile-commands/export-compile-commands.lua new file mode 100644 index 000000000..1f87a99a1 --- /dev/null +++ b/premake/export-compile-commands/export-compile-commands.lua @@ -0,0 +1,210 @@ +local p = premake + +p.modules.export_compile_commands = {} +local m = p.modules.export_compile_commands + +local workspace = p.workspace +local project = p.project + +local function esc(s) + s = s:gsub('\\', '\\\\') + s = s:gsub('"', '\\"') + return s +end + +local function esc_table(t) + local res = {} + for k, v in pairs(t) do + table.insert(res, esc(v)) + end + return res +end + +local function quote(s) + return '"' .. esc(s) .. '"' +end + +function m.getToolset(cfg) + return p.tools[cfg.toolset or 'gcc'] +end + +function m.getCommonFlags(prj, cfg) + -- some tools that consumes compile_commands.json have problems with relative include paths + relative = project.getrelative + project.getrelative = function(prj, dir) return dir end + + local toolset = m.getToolset(cfg) + local flags = toolset.getcppflags(cfg) + flags = table.join(flags, toolset.getdefines(cfg.defines)) + flags = table.join(flags, toolset.getundefines(cfg.undefines)) + flags = table.join(flags, toolset.getincludedirs(cfg, cfg.includedirs, cfg.externalincludedirs)) + flags = table.join(flags, toolset.getforceincludes(cfg)) + if project.iscpp(prj) then + flags = table.join(flags, toolset.getcxxflags(cfg)) + elseif project.isc(prj) then + flags = table.join(flags, toolset.getcflags(cfg)) + end + flags = table.join(flags, cfg.buildoptions) + project.getrelative = relative + return flags +end + +function m.getObjectPath(prj, cfg, node) + return path.join(cfg.objdir, path.appendExtension(node.objname, '.o')) +end + +function m.getDependenciesPath(prj, cfg, node) + return path.join(cfg.objdir, path.appendExtension(node.objname, '.d')) +end + +function m.getFileFlags(prj, cfg, node) + return table.join(m.getCommonFlags(prj, cfg), { + '-o', quote(m.getObjectPath(prj, cfg, node)), + '-MF', quote(m.getDependenciesPath(prj, cfg, node)), + '-c', quote(node.abspath) + }) +end + +local function computesystemincludepaths(tool, iscfile) + local cmd = tool .. " -E -v -fsyntax-only " .. (iscfile and '-x c' or '-x c++') .. ' "' .. _MAIN_SCRIPT .. '"' -- Use script as dummy "c" file + local s,e = os.outputof(cmd, "both") + if not s or not e then return {} end + local s = string.match(s, "#include <...> search starts here:\n(.*)End of search list.\n") + local includepaths = {} + for w in string.gmatch(s, " *([^\n]+) *") do + table.insert(includepaths, path.normalize(w)) + end + return includepaths +end + +local systemincludepathscache = {} + +local function getsystemincludepaths(tool, iscfile) + if not systemincludepathscache[tool] then systemincludepathscache[tool] = {} end + local toolcache = systemincludepathscache[tool] + if not toolcache[iscfile] then toolcache[iscfile] = computesystemincludepaths(tool, iscfile) end + return toolcache[iscfile] +end + +local function getsystemflags(tool, iscfile) + return table.implode(getsystemincludepaths(tool, iscfile), ' -isystem \\"', '\\"', '') +end + +local function getlanguageflags(cfg) + local toolset = m.getToolset(cfg) + local compileas = toolset.shared and toolset.shared.compileas + if compileas then + return compileas[cfg.language] or "" + end +end + +function m.generateCompileCommand(prj, cfg, node) + local toolset = m.getToolset(cfg) + local tool = path.iscfile(node.abspath) and 'cc' or 'cxx' + cfg.gccprefix = cfg.gccprefix or "" -- hack to have gcc.gettoolname return non-nil + local tool = toolset.gettoolname(cfg, tool) or tool + local system_flag = getsystemflags(tool, path.iscfile(node.abspath)) + local language_flag = getlanguageflags(cfg) .. " " + return { + directory = prj.location, + file = node.abspath, + command = (tool .. system_flag .. " " .. language_flag .. table.concat(esc_table(m.getFileFlags(prj, cfg, node)), ' ')) + } +end + +function m.includeFile(prj, node, depth) + return path.iscppfile(node.abspath) or path.iscfile(node.abspath) or path.iscppheader(node.abspath) +end + +function m.getProjectCommands(prj, cfg) + local tr = project.getsourcetree(prj) + local cmds = {} + p.tree.traverse(tr, { + onleaf = function(node, depth) + if m.includeFile(prj, node, depth) then + table.insert(cmds, m.generateCompileCommand(prj, cfg, node)) + end + end + }) + return cmds +end + +local function get_architecture() + if jit then + return jit.arch + end + + local handle = io.popen("uname -m 2>/dev/null") + if handle then + local arch = handle:read("*l") + handle:close() + if arch then return arch end + end + + local arch = os.getenv("PROCESSOR_ARCHITECTURE") + if arch then + if arch == "AMD64" or arch == "IA64" then + return "x86_64" + end + return string.lower(arch) + end + + return "x86_64" +end + +function m.onWorkspace(wks) + local cfgCmds = {} + local prjLocs = {} + for prj in workspace.eachproject(wks) do + for cfg in project.eachconfig(prj) do + local cfgKey = string.format('%s', cfg.shortname) + if not cfgCmds[cfgKey] then + cfgCmds[cfgKey] = {} + end + cfgCmds[cfgKey] = table.join(cfgCmds[cfgKey], m.getProjectCommands(prj, cfg)) + if not prjLocs[cfgKey] then + prjLocs[cfgKey] = {} + end + prjLocs[cfgKey].location = prj.location + end + end + for cfgKey,cmds in pairs(cfgCmds) do + local outfile = string.format('%s/compile_commands.json', cfgKey) + p.generate(wks, outfile, function(wks) + p.push('[') + for i = 1, #cmds do + local item = cmds[i] + p.push('{') + p.x('"directory": "%s",', item.directory) + p.x('"file": "%s",', item.file) + p.w('"command": "%s"', item.command) + if i ~= #cmds then + p.pop('},') + else + p.pop('}') + end + end + p.pop(']') + end) + + if cfgKey == "release_" .. get_architecture() then + local source = path.join(prjLocs[cfgKey].location, outfile) + local destination = path.join(os.getcwd(), "compile_commands.json") + os.copyfile(source, destination) + end + end +end + +newaction { + trigger = 'export-compile-commands', + description = 'Export compiler commands in JSON Compilation Database Format', + onWorkspace = m.onWorkspace, + toolset = "clang", + valid_kinds = { "ConsoleApp", "WindowedApp", "Makefile", "SharedLib", "StaticLib", "Utility" }, + valid_languages = { "C", "C++" }, + valid_tools = { + cc = { "gcc", "clang" } + } +} + +return m diff --git a/premake4.lua b/premake4.lua index 6de048a03..f680b7d8e 100644 --- a/premake4.lua +++ b/premake4.lua @@ -587,6 +587,10 @@ function build_link_configuration( package_name, use_ee_icon ) end end + if _OPTIONS["with-text-shaper"] then + defines { "EE_TEXT_SHAPER_ENABLED" } + end + set_ios_config() set_apple_config() build_arch_configuration() diff --git a/premake5.lua b/premake5.lua index 05fecc86f..4e6455bf0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,3 +1,5 @@ +require "premake.export-compile-commands.export-compile-commands" + newoption { trigger = "with-openssl", description = "Enables OpenSSL support ( and disables mbedtls backend )." } newoption { trigger = "with-dynamic-freetype", description = "Dynamic link against freetype." } newoption { trigger = "with-static-eepp", description = "Force to build the demos and tests with eepp compiled statically" } @@ -330,6 +332,10 @@ function build_link_configuration( package_name, use_ee_icon ) end end + if _OPTIONS["with-text-shaper"] then + defines { "EE_TEXT_SHAPER_ENABLED" } + end + cppdialect "C++17" set_ios_config() set_apple_config() diff --git a/src/eepp/system/sys.cpp b/src/eepp/system/sys.cpp index 08a356c39..ed54864b9 100644 --- a/src/eepp/system/sys.cpp +++ b/src/eepp/system/sys.cpp @@ -211,14 +211,15 @@ static std::string GetWindowsArch() { GetSystemInfo( &si ); } - if ( osvi.dwMajorVersion >= 6 ) { - if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ) { - arch = "x64"; - } else if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) { - arch = "x86"; - } - } else { + if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ) { + arch = "x86_64"; + } else if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ) { arch = "x86"; + } else if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64 ) { + arch = "arm64"; + } else if ( si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM ) { + arch = "arm"; } return arch;