├── LICENSE ├── README.md ├── _manifest.lua ├── _preload.lua ├── androidmk.lua ├── androidmk_api.lua ├── androidmk_project.lua └── androidmk_solution.lua /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2015-2019, Bastien Brunnenstein 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # premake-androidmk 2 | 3 | Application.mk & Android.mk generator for Premake5. 4 | 5 | This module requires the latest premake version to work (5.0.0 alpha5). 6 | 7 | 8 | ## Android.mk API 9 | 10 | Note : All the fields starting with `ndk` are solution-wide, but filters can be applied. 11 | 12 | ***** 13 | 14 | `ndkabi` : ABI targets 15 | 16 | Supported values : 17 | Wanted ABIs separated by spaces (e.g. `"armeabi x86 mips"`) 18 | * `armeabi` 19 | * `armeabi-v7a` 20 | * `arm64-v8a` 21 | * `x86` 22 | * `x86_64` 23 | * `mips` 24 | * `mips64` 25 | 26 | Or one of : 27 | * `default` 28 | * `all` 29 | 30 | ***** 31 | 32 | `ndkplatform` : Android API version 33 | 34 | Supported values : 35 | * `default` 36 | * `android-3` 37 | * `android-4` 38 | * `android-5` 39 | * `android-8` 40 | * `android-9` 41 | * `android-12` 42 | * `android-13` 43 | * `android-14` 44 | * `android-15` 45 | * `android-16` 46 | * `android-17` 47 | * `android-18` 48 | * `android-19` 49 | * `android-21` 50 | 51 | ***** 52 | 53 | `ndkstl` : Standard library 54 | 55 | Supported values : 56 | * `default` 57 | * `libstdc++` 58 | * `gabi++_static` 59 | * `gabi++_shared` 60 | * `stlport_static` 61 | * `stlport_shared` 62 | * `gnustl_static` 63 | * `gnustl_shared` 64 | * `c++_static` 65 | * `c++_shared` 66 | 67 | ***** 68 | 69 | `ndktoolchainversion` : Android toolchain version 70 | 71 | Supported values : 72 | * `default` 73 | * `4.8` 74 | * `4.9` 75 | * `clang` 76 | * `clang3.4` 77 | * `clang3.5` 78 | 79 | ***** 80 | 81 | `amk_includes` : Include existing Android.mk files 82 | 83 | Supported values : List of files 84 | 85 | ***** 86 | 87 | `amk_importmodules` : Import Android.mk modules 88 | 89 | Supported values : List of strings 90 | 91 | ***** 92 | 93 | `amk_staticlinks` and `amk_sharedlinks` : Link libs from included Android.mk files and imported modules 94 | 95 | Supported values : List of libraries 96 | 97 | If you want to link to system libraries or other projects in the solution, use `links` instead. 98 | 99 | 100 | 101 | ## Premake API support 102 | 103 | Most functions should work as expected. 104 | Some limitations apply, for example you cannot change the output folder. 105 | 106 | `system` and `architecture` are completely ignored. 107 | 108 | You cannot do per ABI filtering yet, but it's technically doable. 109 | 110 | Some useful working commands : 111 | 112 | `rtti "On"` : Enable RTTI 113 | 114 | `exceptionhandling "On"` : Enable C++ exceptions 115 | 116 | `flags { "C++11" }` : Enable C++11 117 | 118 | `optimize "Off"` or `"Debug"` : Enable debug mode (must be used solution-wide) 119 | 120 | Symbols are always enabled, use ndk-gdb to debug. 121 | 122 | 123 | ## Sample code 124 | 125 | ```lua 126 | require "androidmk" -- Adjust path if needed 127 | 128 | solution "MySolution" 129 | configurations { "Debug", "Release" } 130 | language "C++" 131 | 132 | location "android/jni" -- Generate files in android project jni folder (recommended) 133 | 134 | ndkabi "all" 135 | ndkplatform "android-12" 136 | 137 | filter "configurations:Release" 138 | optimize "On" 139 | filter "configurations:Debug" 140 | optimize "Debug" 141 | 142 | 143 | project "MyProject" 144 | kind "SharedLib" 145 | includedirs "SDL2/include" 146 | files { 147 | "src/*.cpp", 148 | "SDL2/src/main/android/SDL_android_main.c", 149 | } 150 | 151 | links { 152 | "GLESv1_CM", 153 | "GLESv2", 154 | "log", 155 | } 156 | 157 | amk_includes { 158 | "SDL2/Android.mk", 159 | } 160 | 161 | amk_sharedlinks { 162 | "SDL2", 163 | } 164 | ``` 165 | 166 | 167 | It is recommended to create an Application.mk file including your generated one : 168 | 169 | File android/jni/Application.mk : 170 | ``` 171 | include $(call my-dir)/MySolution_Application.mk 172 | ``` 173 | 174 | 175 | Generate command (in android folder) : 176 | `ndk-build PM5_CONFIG=debug -j` 177 | 178 | Use your own deploy command, mine is : 179 | `ant debug` 180 | 181 | Debug command : 182 | `ndk-gdb-py --gnumake-flag PM5_CONFIG=debug` 183 | -------------------------------------------------------------------------------- /_manifest.lua: -------------------------------------------------------------------------------- 1 | return { 2 | "_preload.lua", 3 | "androidmk.lua", 4 | "androidmk_project.lua", 5 | "androidmk_solution.lua", 6 | "androidmk_api.lua", 7 | } 8 | -------------------------------------------------------------------------------- /_preload.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- _preload.lua 3 | -- Generator for ndk-build makefiles 4 | -- Author : Bastien Brunnenstein 5 | -- 6 | 7 | premake.extensions.androidmk = premake.extensions.androidmk or {} 8 | local androidmk = premake.extensions.androidmk 9 | local make = premake.make 10 | 11 | 12 | androidmk.CONFIG_OPTION = "PM5_CONFIG" 13 | 14 | 15 | newaction { 16 | trigger = "androidmk", 17 | shortname = "Android.mk", 18 | description = "Generate Android.mk files for Android NDK", 19 | 20 | valid_kinds = { 21 | premake.STATICLIB, 22 | premake.SHAREDLIB, 23 | }, 24 | 25 | valid_languages = { "C", "C++" }, 26 | 27 | 28 | onSolution = function(sln) 29 | premake.escaper(make.esc) 30 | premake.generate(sln, androidmk.slnApplicationFile(sln), androidmk.generate_applicationmk) 31 | premake.generate(sln, androidmk.slnAndroidFile(sln), androidmk.generate_androidmk) 32 | end, 33 | 34 | onProject = function(prj) 35 | premake.escaper(make.esc) 36 | premake.generate(prj, androidmk.prjFile(prj), androidmk.generate_projectmk) 37 | end, 38 | 39 | onCleanSolution = function(sln) 40 | premake.clean.file(sln, androidmk.slnApplicationFile(sln)) 41 | premake.clean.file(sln, androidmk.slnAndroidFile(sln)) 42 | end, 43 | 44 | onCleanProject = function(prj) 45 | premake.clean.file(prj, androidmk.prjFile(prj)) 46 | end 47 | } 48 | -------------------------------------------------------------------------------- /androidmk.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- androidmk.lua 3 | -- Generator for ndk-build makefiles 4 | -- Author : Bastien Brunnenstein 5 | -- 6 | 7 | premake.extensions.androidmk = premake.extensions.androidmk or {} 8 | local androidmk = premake.extensions.androidmk 9 | 10 | include "_preload.lua" 11 | 12 | 13 | function androidmk.slnApplicationFile(sln) 14 | return sln.name .."_Application.mk" 15 | end 16 | 17 | function androidmk.slnAndroidFile(sln) 18 | return sln.name .."_Android.mk" 19 | end 20 | 21 | 22 | function androidmk.prjFile(prj) 23 | return prj.name ..".mk" 24 | end 25 | 26 | 27 | androidmk.ldflags = { 28 | flags = { 29 | --LinkTimeOptimization = "-flto", 30 | } 31 | } 32 | 33 | androidmk.cflags = { 34 | flags = { 35 | FatalCompileWarnings = "-Werror", 36 | ShadowedVariables = "-Wshadow", 37 | UndefinedIdentifiers = "-Wundef", 38 | --LinkTimeOptimization = "-flto", 39 | }, 40 | warnings = { 41 | Extra = "-Wall -Wextra", 42 | Off = "-w", 43 | } 44 | } 45 | 46 | androidmk.cppflags = { 47 | flags = { 48 | ["C++11"] = "-std=c++11", 49 | ["C++14"] = "-std=c++14", 50 | } 51 | } 52 | 53 | 54 | include "androidmk_api.lua" 55 | include "androidmk_solution.lua" 56 | include "androidmk_project.lua" 57 | -------------------------------------------------------------------------------- /androidmk_api.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- androidmk_api.lua 3 | -- API for Android.mk generator 4 | -- Author : Bastien Brunnenstein 5 | -- 6 | 7 | local api = premake.api 8 | 9 | 10 | -- More info: https://developer.android.com/ndk/guides/abis.html 11 | api.register { 12 | name = "ndkabi", 13 | scope = "config", 14 | kind = "string", 15 | allowed = function(value) 16 | local usedAbis = {} 17 | local validAbis = { 18 | "default", 19 | "armeabi", 20 | "armeabi-v7a", 21 | "arm64-v8a", 22 | "x86", 23 | "x86_64", 24 | "mips", 25 | "mips64", 26 | "all" 27 | } 28 | 29 | for _, v in ipairs(string.explode(value, ' ')) do 30 | if v ~= "" then 31 | if not table.contains(validAbis, v) then 32 | error("ndkabi : "..v.." is not a valid abi") 33 | end 34 | table.insert(usedAbis, v) 35 | end 36 | end 37 | 38 | if #usedAbis == 0 then 39 | error("ndkabi : Invalid parameter") 40 | end 41 | 42 | if table.contains(usedAbis, "all") then 43 | return "all" 44 | else 45 | return table.implode(usedAbis, '', '', ' ') 46 | end 47 | end 48 | } 49 | 50 | -- More info: https://developer.android.com/ndk/guides/stable_apis.html 51 | api.register { 52 | name = "ndkplatform", 53 | scope = "config", 54 | kind = "string", 55 | allowed = { 56 | "default", 57 | "android-3", 58 | "android-4", 59 | "android-5", 60 | "android-8", 61 | "android-9", 62 | "android-12", 63 | "android-13", 64 | "android-14", 65 | "android-15", 66 | "android-16", 67 | "android-17", 68 | "android-18", 69 | "android-19", 70 | "android-21", 71 | }, 72 | } 73 | 74 | -- More info: https://developer.android.com/ndk/guides/cpp-support.html#runtimes 75 | api.register { 76 | name = "ndkstl", 77 | scope = "config", 78 | kind = "string", 79 | allowed = { 80 | "default", 81 | "libstdc++", 82 | "gabi++_static", 83 | "gabi++_shared", 84 | "stlport_static", 85 | "stlport_shared", 86 | "gnustl_static", 87 | "gnustl_shared", 88 | "c++_static", 89 | "c++_shared", 90 | }, 91 | } 92 | 93 | api.register { 94 | name = "ndktoolchainversion", 95 | scope = "config", 96 | kind = "string", 97 | allowed = { 98 | "default", 99 | "4.8", 100 | "4.9", 101 | "clang", 102 | "clang3.4", 103 | "clang3.5", 104 | }, 105 | } 106 | 107 | -- Allows to add existing Android.mk projects 108 | api.register { 109 | name = "amk_includes", 110 | scope = "project", 111 | kind = "list:file", 112 | tokens = true, 113 | } 114 | 115 | api.register { 116 | name = "amk_importmodules", 117 | scope = "project", 118 | kind = "list:string", 119 | tokens = true, 120 | } 121 | 122 | -- Links from includes and imports 123 | api.register { 124 | name = "amk_staticlinks", 125 | scope = "config", 126 | kind = "list:string", 127 | } 128 | 129 | api.register { 130 | name = "amk_sharedlinks", 131 | scope = "config", 132 | kind = "list:string", 133 | } 134 | -------------------------------------------------------------------------------- /androidmk_project.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- androidmk_project.lua 3 | -- Generator for Android.mk project files 4 | -- Author : Bastien Brunnenstein 5 | -- 6 | 7 | local androidmk = premake.extensions.androidmk 8 | local make = premake.make 9 | local project = premake.project 10 | 11 | local p = premake 12 | 13 | 14 | function androidmk.generate_projectmk(prj) 15 | premake.eol("\n") 16 | 17 | androidmk.prjHeader(prj) 18 | 19 | -- Prepare the list of files 20 | local rootFiles, cfgFiles = androidmk.prepareSrcFiles(prj) 21 | androidmk.prjSrcFiles(rootFiles) 22 | 23 | for cfg in project.eachconfig(prj) do 24 | p.w('') 25 | p.x('ifeq ($(%s),%s)', androidmk.CONFIG_OPTION, cfg.shortname) 26 | 27 | androidmk.prjIncludes(prj, cfg) 28 | androidmk.prjCppFeatures(prj, cfg) 29 | androidmk.prjCfgSrcFiles(cfgFiles[cfg]) 30 | androidmk.prjDependencies(prj, cfg) 31 | androidmk.prjLdFlags(prj, cfg) 32 | androidmk.prjCFlags(prj, cfg) 33 | 34 | -- Always last 35 | androidmk.prjKind(prj, cfg) 36 | 37 | p.w('endif') 38 | end 39 | end 40 | 41 | 42 | function androidmk.prjHeader(prj) 43 | p.w('LOCAL_PATH := $(call my-dir)') 44 | p.w('include $(CLEAR_VARS)') 45 | p.w('LOCAL_MODULE := %s', prj.name) 46 | if prj.targetname then 47 | p.w('LOCAL_MODULE_FILENAME := %s', prj.targetname) 48 | end 49 | p.w('') 50 | end 51 | 52 | function androidmk.prjKind(prj, cfg) 53 | if cfg.kind == premake.STATICLIB then 54 | p.w(' include $(BUILD_STATIC_LIBRARY)') 55 | 56 | else -- cfg.kind == premake.SHAREDLIB 57 | p.w(' include $(BUILD_SHARED_LIBRARY)') 58 | 59 | end 60 | end 61 | 62 | 63 | function androidmk.prjIncludes(prj, cfg) 64 | if cfg.includedirs then 65 | p.w(' LOCAL_C_INCLUDES := %s', 66 | table.implode( 67 | table.translate( 68 | table.translate(cfg.includedirs, 69 | function(d) 70 | return "$(LOCAL_PATH)/"..project.getrelative(prj, d) 71 | end) 72 | , p.esc) 73 | , '', '', ' ')) 74 | end 75 | end 76 | 77 | function androidmk.prjCppFeatures(prj, cfg) 78 | local features = {} 79 | 80 | if cfg.rtti == p.ON then 81 | table.insert(features, "rtti") 82 | end 83 | 84 | if cfg.exceptionhandling == p.ON then 85 | table.insert(features, "exceptions") 86 | end 87 | 88 | if #features > 0 then 89 | p.w(' LOCAL_CPP_FEATURES := %s', table.implode(features, '', '', ' ')) 90 | end 91 | end 92 | 93 | function androidmk.prepareSrcFiles(prj) 94 | local root = {} 95 | local configs = {} 96 | for cfg in project.eachconfig(prj) do 97 | configs[cfg] = {} 98 | end 99 | 100 | local tr = project.getsourcetree(prj) 101 | premake.tree.traverse(tr, { 102 | onleaf = function(node, depth) 103 | -- Figure out what configurations contain this file 104 | local incfg = {} 105 | local inall = true 106 | for cfg in project.eachconfig(prj) do 107 | local filecfg = premake.fileconfig.getconfig(node, cfg) 108 | if filecfg and not filecfg.flags.ExcludeFromBuild then 109 | incfg[cfg] = filecfg 110 | else 111 | inall = false 112 | end 113 | end 114 | 115 | -- Allow .arm, .neon and .arm.neon files 116 | if not path.iscppfile(node.abspath) and 117 | path.getextension(node.abspath) ~= "arm" and 118 | path.getextension(node.abspath) ~= "neon" then 119 | return 120 | end 121 | 122 | local filename = project.getrelative(prj, node.abspath) 123 | 124 | -- If this file exists in all configurations, write it to 125 | -- the project's list of files, else add to specific cfgs 126 | if inall then 127 | table.insert(root, filename) 128 | else 129 | for cfg in project.eachconfig(prj) do 130 | if incfg[cfg] then 131 | table.insert(configs[cfg], filename) 132 | end 133 | end 134 | end 135 | 136 | end 137 | }) 138 | 139 | return root, configs 140 | end 141 | 142 | function androidmk.prjSrcFiles(files) 143 | p.w('LOCAL_SRC_FILES := %s', table.implode(table.translate(files, p.esc), '', '', ' ')) 144 | end 145 | 146 | function androidmk.prjCfgSrcFiles(files) 147 | if #files > 0 then 148 | p.w(' LOCAL_SRC_FILES += %s', table.implode(table.translate(files, p.esc), '', '', ' ')) 149 | end 150 | end 151 | 152 | function androidmk.prjDependencies(prj, cfg) 153 | local staticdeps = {} 154 | local shareddeps = {} 155 | 156 | local dependencies = premake.config.getlinks(cfg, "dependencies", "object") 157 | for _, dep in ipairs(dependencies) do 158 | if dep.kind == premake.STATICLIB then 159 | table.insert(staticdeps, dep.filename) 160 | else 161 | table.insert(shareddeps, dep.filename) 162 | end 163 | end 164 | 165 | for _, v in ipairs(cfg.amk_staticlinks) do 166 | table.insert(staticdeps, v) 167 | end 168 | for _, v in ipairs(cfg.amk_sharedlinks) do 169 | table.insert(shareddeps, v) 170 | end 171 | 172 | if #staticdeps > 0 then 173 | p.w(' LOCAL_STATIC_LIBRARIES := %s', table.implode(staticdeps, '', '', ' ')) 174 | end 175 | 176 | if #shareddeps > 0 then 177 | p.w(' LOCAL_SHARED_LIBRARIES := %s', table.implode(shareddeps, '', '', ' ')) 178 | end 179 | end 180 | 181 | function androidmk.prjLdFlags(prj, cfg) 182 | -- LDLIBS 183 | local flags = {} 184 | 185 | for _, dir in ipairs(premake.config.getlinks(cfg, "system", "directory")) do 186 | table.insert(flags, '-L' .. premake.quoted(dir)) 187 | end 188 | 189 | for _, name in ipairs(premake.config.getlinks(cfg, "system", "basename")) do 190 | table.insert(flags, "-l" .. name) 191 | end 192 | 193 | if #flags > 0 then 194 | p.w(' LOCAL_LDLIBS := %s', table.implode(table.translate(flags, p.esc), '', '', ' ')) 195 | end 196 | 197 | --LDFLAGS 198 | flags = premake.config.mapFlags(cfg, androidmk.ldflags) 199 | 200 | for _, opt in ipairs(cfg.linkoptions) do 201 | table.insert(flags, opt) 202 | end 203 | 204 | if #flags > 0 then 205 | p.w(' LOCAL_LDFLAGS := %s', table.implode(table.translate(flags, p.esc), '', '', ' ')) 206 | end 207 | end 208 | 209 | function androidmk.prjCFlags(prj, cfg) 210 | local flags = premake.config.mapFlags(cfg, androidmk.cflags) 211 | 212 | -- Defines 213 | for _, def in ipairs(cfg.defines) do 214 | table.insert(flags, '-D' .. def) 215 | end 216 | 217 | -- Warnings 218 | for _, enable in ipairs(cfg.enablewarnings) do 219 | table.insert(flags, '-W' .. enable) 220 | end 221 | for _, disable in ipairs(cfg.disablewarnings) do 222 | table.insert(flags, '-Wno-' .. disable) 223 | end 224 | for _, fatal in ipairs(cfg.fatalwarnings) do 225 | table.insert(flags, '-Werror=' .. fatal) 226 | end 227 | 228 | -- Build options 229 | for _, opt in ipairs(cfg.buildoptions) do 230 | table.insert(flags, opt) 231 | end 232 | 233 | if #flags > 0 then 234 | p.w(' LOCAL_CFLAGS := %s', table.implode(table.translate(flags, p.esc), '', '', ' ')) 235 | end 236 | 237 | 238 | local cppflags = premake.config.mapFlags(cfg, androidmk.cppflags) 239 | 240 | if #cppflags > 0 then 241 | p.w(' LOCAL_CPPFLAGS := %s', table.implode(table.translate(cppflags, p.esc), '', '', ' ')) 242 | end 243 | end 244 | -------------------------------------------------------------------------------- /androidmk_solution.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- androidmk_solution.lua 3 | -- Generator for Application.mk and Android.mk solution files 4 | -- Author : Bastien Brunnenstein 5 | -- 6 | 7 | local androidmk = premake.extensions.androidmk 8 | local solution = premake.solution 9 | local project = premake.project 10 | local make = premake.make 11 | 12 | local p = premake 13 | 14 | 15 | function androidmk.generate_applicationmk(sln) 16 | premake.eol("\n") 17 | 18 | androidmk.slnBuildScript(sln) 19 | 20 | p.w('PM5_HELP := true') 21 | 22 | for cfg in solution.eachconfig(sln) do 23 | p.w('') 24 | p.x('ifeq ($(%s),%s)', androidmk.CONFIG_OPTION, cfg.shortname) 25 | 26 | androidmk.slnOptim(sln, cfg) 27 | androidmk.slnAbi(sln, cfg) 28 | androidmk.slnPlatform(sln, cfg) 29 | androidmk.slnStl(sln, cfg) 30 | androidmk.slnToolchainVersion(sln, cfg) 31 | 32 | p.w(' PM5_HELP := false') 33 | p.w('endif') 34 | end 35 | 36 | androidmk.slnPremakeHelp(sln) 37 | end 38 | 39 | function androidmk.generate_androidmk(sln) 40 | premake.eol("\n") 41 | local curpath = 'SOLUTION_'..sln.name:upper()..'_PATH' 42 | p.w('%s := $(call my-dir)', curpath) 43 | p.w('') 44 | 45 | for prj in solution.eachproject(sln) do 46 | local prjpath = premake.filename(prj, androidmk.prjFile(prj)) 47 | local prjrelpath = path.getrelative(sln.location, prjpath) 48 | p.x('include $(%s)/%s', curpath, prjrelpath) 49 | end 50 | 51 | for cfg in solution.eachconfig(sln) do 52 | local existingmklist = {} 53 | local moduleslist = {} 54 | 55 | -- Agregate existing Android.mk files for each project per configuration 56 | for prj in solution.eachproject(sln) do 57 | for prjcfg in project.eachconfig(prj) do 58 | if prjcfg.shortname == cfg.shortname then 59 | for _, mkpath in ipairs(prj.amk_includes) do 60 | local mkrelpath = path.getrelative(sln.location, mkpath) 61 | if not table.contains(existingmklist, mkrelpath) then 62 | table.insert(existingmklist, mkrelpath) 63 | end 64 | end 65 | for _, mod in ipairs(prj.amk_importmodules) do 66 | if not table.contains(moduleslist, mod) then 67 | table.insert(moduleslist, mod) 68 | end 69 | end 70 | end 71 | end 72 | end 73 | 74 | if #existingmklist > 0 or #moduleslist > 0 then 75 | p.w('') 76 | p.x('ifeq ($(%s),%s)', androidmk.CONFIG_OPTION, cfg.shortname) 77 | for _, mkpath in ipairs(existingmklist) do 78 | p.x(' include $(%s)/%s', curpath, mkpath) 79 | end 80 | for _, mod in ipairs(moduleslist) do 81 | p.x(' $(call import-module,%s)', mod) 82 | end 83 | p.w('endif') 84 | end 85 | end 86 | end 87 | 88 | 89 | function androidmk.slnBuildScript(sln) 90 | p.x('APP_BUILD_SCRIPT := $(call my-dir)/%s', androidmk.slnAndroidFile(sln)) 91 | end 92 | 93 | function androidmk.slnPremakeHelp(sln) 94 | p.w('') 95 | p.w('ifeq ($(PM5_HELP),true)') 96 | 97 | p.w(' $(info )') 98 | p.w(' $(info Usage:)') 99 | p.w(' $(info $() ndk-build %s=)', androidmk.CONFIG_OPTION) 100 | p.w(' $(info )') 101 | p.w(' $(info CONFIGURATIONS:)') 102 | for cfg in solution.eachconfig(sln) do 103 | p.w(' $(info $() %s)', cfg.shortname) 104 | end 105 | 106 | p.w(' $(info )') 107 | p.w(' $(info For more ndk-build options, see https://developer.android.com/ndk/guides/ndk-build.html)') 108 | p.w(' $(info )') 109 | 110 | p.w(' $(error Set %s and try again)', androidmk.CONFIG_OPTION) 111 | p.w('endif') 112 | end 113 | 114 | 115 | -- Function to make sure that an option in a given config is the same for every project 116 | -- Additionnaly, replace "default" with "nil" 117 | local function agregateOption(sln, cfg, option) 118 | local first = true 119 | local val 120 | for prj in solution.eachproject(sln) do 121 | for prjcfg in project.eachconfig(prj) do 122 | if prjcfg.shortname == cfg.shortname then 123 | if first then 124 | first = false 125 | val = prjcfg[option] 126 | else 127 | if prjcfg[option] ~= val then 128 | error("Value for "..option.." must be the same on every project for configuration "..cfg.longname.." in solution "..sln.name) 129 | end 130 | end 131 | end 132 | end 133 | end 134 | if val == "default" then 135 | return nil 136 | end 137 | return val 138 | end 139 | 140 | function androidmk.slnOptim(sln, cfg) 141 | local optim = agregateOption(sln, cfg, "optimize") 142 | if optim == p.OFF or optim == "Debug" then 143 | p.w(' APP_OPTIM := debug') 144 | elseif optim ~= nil then 145 | p.w(' APP_OPTIM := release') 146 | end 147 | end 148 | 149 | function androidmk.slnAbi(sln, cfg) 150 | local abi = agregateOption(sln, cfg, "ndkabi") 151 | if abi then 152 | p.w(' APP_ABI := %s', abi) 153 | end 154 | end 155 | 156 | function androidmk.slnPlatform(sln, cfg) 157 | local plat = agregateOption(sln, cfg, "ndkplatform") 158 | if plat then 159 | p.w(' APP_PLATFORM := %s', plat) 160 | end 161 | end 162 | 163 | function androidmk.slnStl(sln, cfg) 164 | local stl = agregateOption(sln, cfg, "ndkstl") 165 | if stl then 166 | p.w(' APP_STL := %s', stl) 167 | end 168 | end 169 | 170 | function androidmk.slnToolchainVersion(sln, cfg) 171 | local toolchain = agregateOption(sln, cfg, "ndktoolchainversion") 172 | if toolchain then 173 | p.w(' NDK_TOOLCHAIN_VERSION := %s', toolchain) 174 | end 175 | end 176 | --------------------------------------------------------------------------------