Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using basedir as a root base directory for files and paths. #2303

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/_premake_init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
api.register {
name = "basedir",
scope = "project",
kind = "path"
kind = "path",
cwdAsBase = true
}

api.register {
Expand Down
31 changes: 22 additions & 9 deletions src/base/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/base/container.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/base/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/base/oven.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/_tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
116 changes: 116 additions & 0 deletions tests/project/test_basedir.lua
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions tests/project/test_sources.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
38 changes: 36 additions & 2 deletions website/docs/basedir.md
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -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 ###

Expand All @@ -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.