From 364912e6c262164774b09b1c8b1aac7e0fcfe2a1 Mon Sep 17 00:00:00 2001 From: Glyn Leine Date: Thu, 14 Dec 2023 14:29:21 +0100 Subject: [PATCH] a whole lotta stuff --- premake/rythe/context.lua | 15 +- premake/rythe/filesystem.lua | 4 + premake/rythe/projects.lua | 286 +++++++++++++++++++++++++++-------- premake/rythe/rythe.lua | 14 +- premake5.lua | 78 +--------- 5 files changed, 245 insertions(+), 152 deletions(-) diff --git a/premake/rythe/context.lua b/premake/rythe/context.lua index b9ec79228..bb2461bc9 100644 --- a/premake/rythe/context.lua +++ b/premake/rythe/context.lua @@ -33,7 +33,7 @@ function context.hasModule(module) return hasFilter(_OPTIONS["modules"], module) end --- Project types are e.g. test, module, application, editor, static-libary, dynamic-library, header-only, util +-- Project types are e.g. test, module, application, editor, libary, header-only, util function context.hasProjectType(projectType) return hasFilter(_OPTIONS["types"], projectType) end @@ -43,23 +43,18 @@ function context.hasProjectGroup(projectGroup) return hasFilter(_OPTIONS["groups"], projectGroup) end --- Links as shared library, but does no runtime reloading +-- Links as shared library function context.linkShared() - return _OPTIONS["shared"] and not (_OPTIONS["dynamic"] or _OPTIONS["static"]) -end - --- Enables runtime module loading, otherwise the same as shared -function context.linkDynamic() - return _OPTIONS["dynamic"] and not _OPTIONS["static"] + return _OPTIONS["shared"] and not _OPTIONS["static"] end -- If no link target is defined, then static is chosen function context.linkStatic() - return _OPTIONS["static"] or not (context.linkShared() or context.linkDynamic()) + return _OPTIONS["static"] or not context.linkShared() end function context.linkTarget() - return context.linkStatic() and "StaticLib" or "SharedLib" + return (context.linkStatic() and "StaticLib") or "SharedLib" end -- Tag to place at the end of a solution name diff --git a/premake/rythe/filesystem.lua b/premake/rythe/filesystem.lua index b0de188b6..86ff9472e 100644 --- a/premake/rythe/filesystem.lua +++ b/premake/rythe/filesystem.lua @@ -25,4 +25,8 @@ function fs.fileName(path) return string.match(path, "([^/\\]+)$") end +function fs.rootName(path) + return string.match(path, "^([^/\\]+)") +end + return fs \ No newline at end of file diff --git a/premake/rythe/projects.lua b/premake/rythe/projects.lua index 0cdd409cd..a5f7d541e 100644 --- a/premake/rythe/projects.lua +++ b/premake/rythe/projects.lua @@ -8,21 +8,64 @@ local buildSettings = rythe.buildSettings local projects = {} +local function folderToProjectType(projectFolder) + if projectFolder == "applications" then + return "application" + elseif projectFolder == "modules" then + return "module" + elseif projectFolder == "libraries" then + return "library" + end + + return projectFolder +end + local function find(projectPath) local projectName = fs.fileName(projectPath) + local projectType = fs.rootName(projectPath) local group = fs.parentPath(projectPath) - - local projectFile = projectPath .. "/project.lua" - if not os.isfile(projectFile) then - projectFile = projectPath .. "/" .. projectName .. ".lua" + local projectTypeLength = string.len(projectType) + 2 + if string.len(group) > projectTypeLength then + group = string.sub(group, projectTypeLength) + else + group = "" + end + + local projectFile = projectPath .. "/.rythe_project" - if not os.isfile(projectFile) then - return nil, group, projectName + return projectFile, group, projectName, folderToProjectType(projectType) +end + +local function projectIdPostfix(projectType) + if projectType == "test" then + return ":test" + elseif projectType == "editor" then + return ":editor" + end + + return "" +end + +local function getProjectId(group, projectName) + return group == "" and projectName or group .. "/" .. projectName +end + +local function findAssembly(assemblyId) + local projectId = string.match(assemblyId, "^([^:]+)") + local projectType = string.sub(assemblyId, string.len(projectId) + 2) + local project = loadedProjects[projectId] + + if projectType == "" then + + if project == nil then + return nil, projectId, nil + else + return project, projectId, project.types[1] end end - return projectFile, group, projectName + return project, projectId, projectType end local function kindName(projectType, config) @@ -38,8 +81,8 @@ local function kindName(projectType, config) else return "ConsoleApp" end - elseif projectType == "static-libary" then - return "SharedLib" + elseif projectType == "library" then + return "StaticLib" elseif projectType == "header-only" then return "SharedItems" elseif projectType == "util" then @@ -49,27 +92,69 @@ local function kindName(projectType, config) end local function projectTypeGroupPrefix(projectType) - if projectType == "test" then - return "tests/" + if projectType == "util" then + return "1 - utils/" + elseif projectType == "application" then + return "2 - applications/" + elseif projectType == "module" then + return "3 - modules/" + elseif projectType == "editor" then + return "4 - editor/" + elseif projectType == "library" or projectType == "header-only" then + return "5 - libraries/" + elseif projectType == "test" then + return "6 - tests/" + end + + assert(false, "Unknown project type: \"" .. projectType .. "\"") +end + +local function projectNamePostfix(projectType) + if projectType == "module" then + return "-module" + elseif projectType == "test" then + return "-test" elseif projectType == "application" then - return "applications/" + return "-application" elseif projectType == "editor" then - return "editor/" + return "-editor" end return "" end -function projects.load(projectPath) - print("Loading project at \"" .. projectPath .. "\"") +local function projectTypeFilesDir(projectType) + if projectType == "test" then + return "/tests/" + elseif projectType == "editor" then + return "/editor/" + end + + return "/src/" +end - local project = loadedProjects[projectPath] +local function isProjectTypeMainType(projectType) + if projectType == "test" then + return false + elseif projectType == "editor" then + return false + end + return true +end + +function projects.load(projectPath) + + local projectFile, group, name, projectType = find(projectPath) + local projectId = getProjectId(group, name) + + local project = loadedProjects[projectId] + if project ~= nil then return project end - local projectFile, group, name = find(projectPath) + print("Loading project at \"" .. projectPath .. "\"") if projectFile == nil then print("Could not find project \"" .. group .. "/" .. name .. "\"") @@ -83,86 +168,153 @@ function projects.load(projectPath) return nil end - assert(project.group == group, "Group folder structure mismatch \"" .. group .. "\" vs \"" .. project.group .. "\"") - assert(project.name == name, "Project name folder structure mismatch \"" .. name .. "\" vs \"" .. project.name .. "\"") - assert(not utils.tableIsEmpty(project.types), "Project must hold an assembly type. (Use the type \"util\" if no source code is required)") + project.group = group + project.name = name + + if project.alias == nil then + project.alias = name + end + + if project.namespace == nil then + project.namespace = name + end + + project.types = { projectType } + + if not utils.tableIsEmpty(project.additional_types) then + project.types = utils.concatTables(project.types, project.additional_types) + end if utils.tableIsEmpty(project.defines) then - project.defines = { "PROJECT_NAME=" .. project.name } + project.defines = { "PROJECT_NAME=" .. project.alias, "PROJECT_FULL_NAME=" .. project.name, "PROJECT_NAMESPACE=" .. project.namespace } else - project.defines = utils.concatTables(project.defines, { "PROJECT_NAME=" .. project.name }) + project.defines[#project.defines +1 ] = "PROJECT_NAME=" .. project.alias + project.defines[#project.defines +1 ] = "PROJECT_FULL_NAME=" .. project.name + project.defines[#project.defines +1 ] = "PROJECT_NAMESPACE=" .. project.namespace end project.src = projectFile project.location = projectPath if project.files == nil then -- files can be an empty table if no files need to be loaded - project.files = { "**.hpp", "**.inl", "**.cpp" } + project.files = { "**" } end - loadedProjects[projectPath] = project + loadedProjects[projectId] = project return project end -local function setupRelease() +local function setupRelease(projectType) filter("configurations:Release") - defines { "NDEBUG" } - optimize("Full") + defines { "NDEBUG" } + optimize("Full") + kind(kindName(projectType, rythe.Configuration.RELEASE)) end -local function setupDevelopment() +local function setupDevelopment(projectType) filter("configurations:Development") - defines { "DEBUG" } - optimize("Debug") - inlining("Explicit") - symbols("On") + defines { "DEBUG" } + optimize("Debug") + inlining("Explicit") + symbols("On") + kind(kindName(projectType, rythe.Configuration.DEVELOPMENT)) end -local function setupDebug() +local function setupDebug(projectType) filter("configurations:Debug") - defines { "DEBUG" } - symbols("On") + defines { "DEBUG" } + symbols("On") + kind(kindName(projectType, rythe.Configuration.DEBUG)) end -function projects.submit(project) +function projects.submit(proj) local configSetup = { [rythe.Configuration.RELEASE] = setupRelease, [rythe.Configuration.DEVELOPMENT] = setupDevelopment, [rythe.Configuration.DEBUG] = setupDebug } - for i, projectType in ipairs(project.types) do - local fullGroupPath = projectTypeGroupPrefix(projectType) .. project.group + for i, projectType in ipairs(proj.types) do + local fullGroupPath = projectTypeGroupPrefix(projectType) .. proj.group local binDir = _ACTION .. "/bin/" + print("Building " .. proj.name .. ": " .. projectType) group(fullGroupPath) - project(project.name) - - location(_ACTION .. "/" .. fullGroupPath) - targetdir(binDir .. fullGroupPath) - objdir(binDir .. "obj") - - if not utils.tableIsEmpty(project.dependencies) then - local libDirs = {} - for i, dep in ipairs(project.dependencies) do - -- something + project(proj.alias .. projectNamePostfix(projectType)) + filename(proj.alias) + location(_ACTION .. "/" .. fullGroupPath) + targetdir(binDir .. fullGroupPath) + objdir(binDir .. "obj") + + local allDeps = proj.dependencies + + if not isProjectTypeMainType(projectType) then + if utils.tableIsEmpty(allDeps) then + allDeps = { getProjectId(proj.group, proj.name) } + else + allDeps = utils.concatTables({ getProjectId(proj.group, proj.name) }, allDeps) + end end - - libdirs(libDirs) - end - architecture(buildSettings.platform) - toolset(buildSettings.toolset) - language("C++") - cppdialect(buildSettings.cppVersion) + if not utils.tableIsEmpty(allDeps) then + local libDirs = {} + local externalIncludeDirs = {} + local depNames = {} + + for i, dep in ipairs(allDeps) do + depProject, depId, depType = findAssembly(dep) + + if depProject ~= nil then + print("\tDependency: " .. depId .. " - " .. depType) + externalIncludeDirs[#externalIncludeDirs + 1] = depProject.location .. "/" .. projectTypeFilesDir(depType) + depNames[#depNames + 1] = depProject.alias .. projectNamePostfix(depType) + else + print("\tDependency \"" .. depId .. "\" was not found") + end + end - defines(project.defines) + dependson(depNames) + externalincludedirs(externalIncludeDirs) + libdirs(libDirs) + end - for i, config in ipairs(rythe.Configuration) do - configSetup[config]() - kind(kindName(projectType, config)) - end + architecture(buildSettings.platform) + toolset(buildSettings.toolset) + language("C++") + cppdialect(buildSettings.cppVersion) + + local allDefines = proj.defines + + if allDefines == nil then + allDefines = {} + end + + for projectId, project in pairs(loadedProjects) do + allDefines[#allDefines + 1] = project.group == "" and string.upper(project.alias) .. "=1" or string.upper(string.gsub(project.group, "[/\\]", "_")) .. "_" .. string.upper(project.alias) .. "=1" + end + + defines(allDefines) + + local filePatterns = {} + for i, pattern in ipairs(proj.files) do + filePatterns[#filePatterns + 1] = proj.location .. projectTypeFilesDir(projectType) .. proj.namespace .. "/" .. pattern + end + + files(filePatterns) + + if not utils.tableIsEmpty(proj.exclude_files) then + local excludePatterns = {} + for i, pattern in ipairs(proj.exclude_files) do + excludePatterns[#excludePatterns + 1] = proj.location .. projectTypeFilesDir(projectType) .. proj.namespace .. "/" .. pattern + end + + removefiles(excludePatterns) + end + + for i, config in pairs(rythe.Configuration) do + configSetup[config](projectType) + end filter("") end @@ -174,16 +326,16 @@ function projects.scan(path) local srcDirs = {} local thirdpartyDirs = {} - for i, dir in ipairs(os.matchdirs(path .. "**/src")) do - if string.find(dir, "third_party") then - thirdpartyDirs[#thirdpartyDirs + 1] = dir + for i, file in ipairs(os.matchfiles(path .. "**/.rythe_project")) do + if string.find(file, "third_party") then + thirdpartyDirs[#thirdpartyDirs + 1] = fs.parentPath(file) else - srcDirs[#srcDirs + 1] = dir + srcDirs[#srcDirs + 1] = fs.parentPath(file) end end for i, dir in ipairs(srcDirs) do - local projectPath = fs.parentPath(dir) + local projectPath = dir local project = projects.load(projectPath) if project ~= nil then @@ -216,6 +368,10 @@ function projects.scan(path) print(message) end end + + for projectId, project in pairs(loadedProjects) do + projects.submit(project) + end end return projects \ No newline at end of file diff --git a/premake/rythe/rythe.lua b/premake/rythe/rythe.lua index 35aa5bf5b..245b2851a 100644 --- a/premake/rythe/rythe.lua +++ b/premake/rythe/rythe.lua @@ -10,7 +10,7 @@ premake.rythe = { buildSettings = { platform = "x86_64", toolset = "clang", - cppVersion = "C++23" + cppVersion = "C++20" } } @@ -18,7 +18,17 @@ local rythe = premake.rythe local projects = dofile("projects.lua") -function rythe.test() +function rythe.configName(config) + local configNames = { + [rythe.Configuration.RELEASE] = "Release", + [rythe.Configuration.DEVELOPMENT] = "Development", + [rythe.Configuration.DEBUG] = "Debug" + } + + return configNames[config] +end + +function rythe.configure() projects.scan("./") end diff --git a/premake5.lua b/premake5.lua index dc75f56b7..b230bbf04 100644 --- a/premake5.lua +++ b/premake5.lua @@ -1,85 +1,13 @@ ---! Rythe Central Build Script for Rythe-Engine ---[[ -authors: Rowan Ramsey, Glyn Leine -copyright: (c) 2023 The Rythe-Team - -Permission is hereby granted, free of charge, to any person obtaining a copy of this -software and associated documentation files (the "Software"), to deal in the Software -without restriction, including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -]]-- - - -function formatEngineModulePath(moduleName) - return string.format("rythe/engine/%s/build-%s.lua", moduleName, moduleName, moduleName) -end - -function formatApplicationPath(moduleName) - return string.format("applications/%s/build-%s.lua", moduleName, moduleName) -end - -function formatExternalProject(projectName) - return string.format("rythe/engine/core/third_party/%s/build-%s.lua",projectName,projectName) -end - -function createProject(groupName,projectName,kindName) - print("Building " .. projectName) - group ("" .. groupName) - project ("" .. projectName) - kind (""..kindName) - location ("src/"..projectName) - architecture "x64" - toolset "clang" - language "C++" - cppdialect "C++20" - targetdir "$(SolutionDir)bin\\lib" - libdirs {"$(SolutionDir)bin\\lib\\"} - objdir "$(SolutionDir)bin\\obj" - defines {"RYTHE_INTERNAL", "PROJECT_NAME="..projectName} - filter "configurations:Debug*" - defines {"DEBUG"} - symbols "On" - targetsuffix "-d" - filter "configurations:Release*" - defines {"NDEBUG"} - optimize "On" - - filter {} - group "" -end - -- root workspace, all sub-project should be included workspace "rythe" - configurations { "Debug64", "Release64" } - --- core module, must not have any dependencies and should be first -include(formatEngineModulePath("core")) -include(formatEngineModulePath("application")) -include(formatEngineModulePath("graphics")) -include(formatEngineModulePath("physics")) -include(formatEngineModulePath("audio")) -include(formatExternalProject("rythe-standard-library")) - -include(formatApplicationPath("sandbox")) -include(formatApplicationPath("rsl_test")) + location(_ACTION) + configurations { "Debug", "Release" } os.chdir(_WORKING_DIR) local r = require("premake/rythe") -r.test() +r.configure() newaction {