From f785f2039562167ba8cb5838e851d5ee3d872345 Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Wed, 16 Oct 2024 13:47:25 +0100 Subject: [PATCH 1/2] Compute `basedir` at baking time to avoid conflict with `basedir` API. --- src/base/container.lua | 2 +- src/base/oven.lua | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/base/container.lua b/src/base/container.lua index b5ec00a98f..08cb963571 100644 --- a/src/base/container.lua +++ b/src/base/container.lua @@ -78,7 +78,7 @@ self.name = name self.filename = name self.script = _SCRIPT - self.basedir = os.getcwd() + self.cwd = os.getcwd() self.external = false for childClass in container.eachChildClass(class) do diff --git a/src/base/oven.lua b/src/base/oven.lua index 12cb53ec8f..d960926f43 100644 --- a/src/base/oven.lua +++ b/src/base/oven.lua @@ -103,6 +103,7 @@ -- Specify the workspaces's file system location; when path tokens are -- expanded in workspace values, they will be made relative to this. + self.basedir = self.basedir or self.cwd self.location = self.location or self.basedir context.basedir(self, self.location) @@ -238,6 +239,7 @@ -- location. Any path tokens which are expanded in non-path fields -- are made relative to this, ensuring a portable generated project. + self.basedir = self.basedir or self.cwd self.location = self.location or self.basedir context.basedir(self, self.location) @@ -317,6 +319,7 @@ -- location. Any path tokens which are expanded in non-path fields -- are made relative to this, ensuring a portable generated rule. + self.basedir = self.basedir or self.cwd self.location = self.location or self.basedir context.basedir(self, self.location) end From a053949c026d5344c69c18a1f5f9f6ab1f046ccb Mon Sep 17 00:00:00 2001 From: Joao Matos Date: Fri, 11 Oct 2024 16:58:39 +0100 Subject: [PATCH 2/2] Allow using `basedir` as a root base directory for files and paths. --- src/_premake_init.lua | 3 +- src/base/api.lua | 31 ++++++--- src/base/context.lua | 6 +- tests/_tests.lua | 1 + tests/project/test_basedir.lua | 116 +++++++++++++++++++++++++++++++++ tests/project/test_sources.lua | 4 +- website/docs/basedir.md | 38 ++++++++++- 7 files changed, 182 insertions(+), 17 deletions(-) create mode 100644 tests/project/test_basedir.lua diff --git a/src/_premake_init.lua b/src/_premake_init.lua index 6559639d69..34d0a2974e 100644 --- a/src/_premake_init.lua +++ b/src/_premake_init.lua @@ -51,7 +51,8 @@ api.register { name = "basedir", scope = "project", - kind = "path" + kind = "path", + cwdAsBase = true } api.register { diff --git a/src/base/api.lua b/src/base/api.lua index a6864814d8..a26d9df381 100755 --- a/src/base/api.lua +++ b/src/base/api.lua @@ -148,7 +148,8 @@ -- if I have an existing instance, create a new configuration -- block for it so I don't pick up an old filter if instance then - configset.addFilter(instance, {}, os.getcwd()) + local basedir = p.api.scope.current.basedir or os.getcwd() + configset.addFilter(instance, {}, basedir) end -- otherwise, a new instance @@ -163,7 +164,7 @@ -- (recursive call, so needs to be its own function) api._clearContainerChildren(class) - -- active this container, as well as it ancestors + -- active this container, as well as its ancestors if not class.placeholder then api.scope.current = instance end @@ -716,7 +717,8 @@ table.remove(api.scope.global.blocks, i) end - configset.addFilter(api.scope.current, {}, os.getcwd()) + local basedir = p.api.scope.current.basedir or os.getcwd() + configset.addFilter(api.scope.current, {}, basedir) end @@ -802,10 +804,12 @@ premake.field.kind("directory", { paths = true, store = function(field, current, value, processor) - return path.getabsolute(value) + local basedir = p.api.scope.current.basedir or os.getcwd() + return path.getabsolute(value, basedir) end, remove = function(field, current, value, processor) - return path.getabsolute(value) + local basedir = p.api.scope.current.basedir or os.getcwd() + return path.getabsolute(value, basedir) end, compare = function(field, a, b, processor) return (a == b) @@ -829,10 +833,12 @@ premake.field.kind("file", { paths = true, store = function(field, current, value, processor) - return path.getabsolute(value) + local basedir = p.api.scope.current.basedir or os.getcwd() + return path.getabsolute(value, basedir) end, remove = function(field, current, value, processor) - return path.getabsolute(value) + local basedir = p.api.scope.current.basedir or os.getcwd() + return path.getabsolute(value, basedir) end, compare = function(field, a, b, processor) return (a == b) @@ -1087,7 +1093,13 @@ premake.field.kind("path", { paths = true, store = function(field, current, value, processor) - return path.deferredjoin(os.getcwd(), value) + local basedir + if field.cwdAsBase then + basedir = os.getcwd() + else + basedir = p.api.scope.current.basedir or os.getcwd() + end + return path.deferredjoin(basedir, value) end, compare = function(field, a, b, processor) return (a == b) @@ -1152,7 +1164,8 @@ if (type(terms) == "table" and #terms == 1 and terms[1] == "*") or (terms == "*") then terms = nil end - local ok, err = configset.addFilter(api.scope.current, {terms}, os.getcwd()) + local basedir = p.api.scope.current.basedir or os.getcwd() + local ok, err = configset.addFilter(api.scope.current, {terms}, basedir) if not ok then error(err, 2) end diff --git a/src/base/context.lua b/src/base/context.lua index fe0e80f1f8..7ea0cc4174 100644 --- a/src/base/context.lua +++ b/src/base/context.lua @@ -44,12 +44,12 @@ ctx.terms = {} -- This base directory is used when expanding path tokens encountered - -- in non-path value; such values will be made relative to this value + -- in non-path values; such values will be made relative to this value -- so the resulting projects will only contain relative paths. It is -- expected that the creator of the context will set this value using - -- the setbasedir() function. + -- the basedir() function. - ctx._basedir = os.getcwd() + ctx._basedir = cfgset.basedir or os.getcwd() -- when a missing field is requested, fetch it from my config -- set, and then cache the value for future lookups diff --git a/tests/_tests.lua b/tests/_tests.lua index b9aafbb993..daeb9f1442 100644 --- a/tests/_tests.lua +++ b/tests/_tests.lua @@ -29,6 +29,7 @@ return { "workspace/test_objdirs.lua", -- Project object tests + "project/test_basedir.lua", "project/test_config_maps.lua", "project/test_eachconfig.lua", "project/test_getconfig.lua", diff --git a/tests/project/test_basedir.lua b/tests/project/test_basedir.lua new file mode 100644 index 0000000000..19ded087ab --- /dev/null +++ b/tests/project/test_basedir.lua @@ -0,0 +1,116 @@ +-- +-- tests/project/test_basedir.lua +-- Test handling of the projects's basedir field. +-- Copyright (c) 2024 Jason Perkins and the Premake project +-- + + local suite = test.declare("project_basedir") + + +-- +-- Setup and teardown +-- + + local wks, prj + + function suite.setup() + wks = test.createWorkspace() + end + + local function prepare() + prj = test.getproject(wks, 1) + end + + local function get_files() + local cfg = test.getconfig(prj, "Debug") + + local files = {} + for _, file in ipairs(cfg.files) do + table.insert(files, file) + end + + return files + end + + local function get_includedirs() + local cfg = test.getconfig(prj, "Debug") + + local dirs = {} + for _, dir in ipairs(cfg.includedirs) do + table.insert(dirs, dir) + end + + return dirs + end + +-- +-- If no explicit basedir is set, the location should be set to the +-- directory containing the script which defined the project. +-- + + function suite.onNoBaseDir() + prepare() + test.isequal(os.getcwd(), prj.basedir) + end + + +-- +-- If an explicit basedir has been set, use it. +-- + + function suite.onBaseDir() + basedir "base" + prepare() + test.isequal(path.join(os.getcwd(), "base"), prj.basedir) + end + + +-- +-- If multiple basedir are set, make sure the value is overriden correctly. +-- + +function suite.onMultipleBaseDir() + basedir "base0" + basedir "base" + prepare() + test.isequal(path.join(os.getcwd(), "base"), prj.basedir) +end + +-- +-- Files should be set relative to basedir. +-- Tests "file" data kind. +-- + + function suite.onFilesBaseDir() + basedir "base" + files { "test.cpp" } + prepare() + test.isequal({path.join(prj.basedir, "test.cpp")}, get_files()) + end + + +-- +-- Include directories should be set relative to basedir. +-- Tests "directory" data kind. +-- + +function suite.onIncludeDirsBaseDir() + basedir "base" + includedirs { "dir" } + prepare() + test.isequal({path.join(prj.basedir, "dir")}, get_includedirs()) +end + + +-- +-- If the workspace sets a basedir, and the project does not, it should +-- inherit the value from the workspace. +-- + + function suite.projectInheritsWorkspaceBaseDir() + workspace () + basedir "base" + prepare() + -- dbg() + test.isequal(path.join(os.getcwd(), "base"), prj.basedir) + end diff --git a/tests/project/test_sources.lua b/tests/project/test_sources.lua index 84f5ee57ff..a6d9e68707 100644 --- a/tests/project/test_sources.lua +++ b/tests/project/test_sources.lua @@ -19,12 +19,12 @@ local oldcwd function suite.setup() - wks, prj = test.createWorkspace() - -- We change the directory to get nice relative paths oldcwd = os.getcwd() os.chdir(cwd) + wks, prj = test.createWorkspace() + -- Create a token to be used in search paths p.api.register { name = "mytoken", kind = "string", scope = "config" } mytoken "test" diff --git a/website/docs/basedir.md b/website/docs/basedir.md index f0b8da1d79..d149273159 100644 --- a/website/docs/basedir.md +++ b/website/docs/basedir.md @@ -1,4 +1,7 @@ -Sets the base directory for a configuration, from with other paths contained by the configuration will be made relative at export time. +Sets the base directory for a workspace or project, from which other paths contained by the configuration will be made relative to. + +This base directory is also used when expanding path tokens encountered in non-path values. +Such values will be made relative to this value so the resulting projects will only contain relative paths. ```lua basedir ("value") @@ -8,7 +11,7 @@ You do not normally need to set this value, as it is filled in automatically wit ### Parameters ### -`value` is an absolute path, from which other paths contained by the configuration should be made relative. +`value` is an absolute or relative path, from which other paths contained by the configuration should be made relative to. ### Applies To ### @@ -17,3 +20,34 @@ Any configuration. ### Availability ### Premake 4.4 or later. + +### Examples ### + +```lua +workspace "workspace" +basedir "base" +project "project" + files { "file.cpp" } + includedirs { "dir" } +``` + +In this case, files will be generated as `base/file.cpp`, and the include directory as `base/dir`. + + +```lua +basedir "root" +workspace "workspace" +project "project" + basedir "base" + files { "file.cpp" } + includedirs { "dir" } +``` + +This results in the same output, as the project-level `basedir` overrides the workspace-level value. + +```lua +filter { "configurations:Debug" } + includedirs { "%{prj.basedir}" } +``` + +`basedir` can also be used as a token, via for example `%{prj.basedir}` syntax. See the [Tokens](Tokens.md) reference for more details.