Skip to content

Commit a053949

Browse files
committed
Allow using basedir as a root base directory for files and paths.
1 parent f785f20 commit a053949

File tree

7 files changed

+182
-17
lines changed

7 files changed

+182
-17
lines changed

src/_premake_init.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
api.register {
5252
name = "basedir",
5353
scope = "project",
54-
kind = "path"
54+
kind = "path",
55+
cwdAsBase = true
5556
}
5657

5758
api.register {

src/base/api.lua

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@
148148
-- if I have an existing instance, create a new configuration
149149
-- block for it so I don't pick up an old filter
150150
if instance then
151-
configset.addFilter(instance, {}, os.getcwd())
151+
local basedir = p.api.scope.current.basedir or os.getcwd()
152+
configset.addFilter(instance, {}, basedir)
152153
end
153154

154155
-- otherwise, a new instance
@@ -163,7 +164,7 @@
163164
-- (recursive call, so needs to be its own function)
164165
api._clearContainerChildren(class)
165166

166-
-- active this container, as well as it ancestors
167+
-- active this container, as well as its ancestors
167168
if not class.placeholder then
168169
api.scope.current = instance
169170
end
@@ -716,7 +717,8 @@
716717
table.remove(api.scope.global.blocks, i)
717718
end
718719

719-
configset.addFilter(api.scope.current, {}, os.getcwd())
720+
local basedir = p.api.scope.current.basedir or os.getcwd()
721+
configset.addFilter(api.scope.current, {}, basedir)
720722
end
721723

722724

@@ -802,10 +804,12 @@
802804
premake.field.kind("directory", {
803805
paths = true,
804806
store = function(field, current, value, processor)
805-
return path.getabsolute(value)
807+
local basedir = p.api.scope.current.basedir or os.getcwd()
808+
return path.getabsolute(value, basedir)
806809
end,
807810
remove = function(field, current, value, processor)
808-
return path.getabsolute(value)
811+
local basedir = p.api.scope.current.basedir or os.getcwd()
812+
return path.getabsolute(value, basedir)
809813
end,
810814
compare = function(field, a, b, processor)
811815
return (a == b)
@@ -829,10 +833,12 @@
829833
premake.field.kind("file", {
830834
paths = true,
831835
store = function(field, current, value, processor)
832-
return path.getabsolute(value)
836+
local basedir = p.api.scope.current.basedir or os.getcwd()
837+
return path.getabsolute(value, basedir)
833838
end,
834839
remove = function(field, current, value, processor)
835-
return path.getabsolute(value)
840+
local basedir = p.api.scope.current.basedir or os.getcwd()
841+
return path.getabsolute(value, basedir)
836842
end,
837843
compare = function(field, a, b, processor)
838844
return (a == b)
@@ -1087,7 +1093,13 @@
10871093
premake.field.kind("path", {
10881094
paths = true,
10891095
store = function(field, current, value, processor)
1090-
return path.deferredjoin(os.getcwd(), value)
1096+
local basedir
1097+
if field.cwdAsBase then
1098+
basedir = os.getcwd()
1099+
else
1100+
basedir = p.api.scope.current.basedir or os.getcwd()
1101+
end
1102+
return path.deferredjoin(basedir, value)
10911103
end,
10921104
compare = function(field, a, b, processor)
10931105
return (a == b)
@@ -1152,7 +1164,8 @@
11521164
if (type(terms) == "table" and #terms == 1 and terms[1] == "*") or (terms == "*") then
11531165
terms = nil
11541166
end
1155-
local ok, err = configset.addFilter(api.scope.current, {terms}, os.getcwd())
1167+
local basedir = p.api.scope.current.basedir or os.getcwd()
1168+
local ok, err = configset.addFilter(api.scope.current, {terms}, basedir)
11561169
if not ok then
11571170
error(err, 2)
11581171
end

src/base/context.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@
4444
ctx.terms = {}
4545

4646
-- This base directory is used when expanding path tokens encountered
47-
-- in non-path value; such values will be made relative to this value
47+
-- in non-path values; such values will be made relative to this value
4848
-- so the resulting projects will only contain relative paths. It is
4949
-- expected that the creator of the context will set this value using
50-
-- the setbasedir() function.
50+
-- the basedir() function.
5151

52-
ctx._basedir = os.getcwd()
52+
ctx._basedir = cfgset.basedir or os.getcwd()
5353

5454
-- when a missing field is requested, fetch it from my config
5555
-- set, and then cache the value for future lookups

tests/_tests.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ return {
2929
"workspace/test_objdirs.lua",
3030

3131
-- Project object tests
32+
"project/test_basedir.lua",
3233
"project/test_config_maps.lua",
3334
"project/test_eachconfig.lua",
3435
"project/test_getconfig.lua",

tests/project/test_basedir.lua

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
--
2+
-- tests/project/test_basedir.lua
3+
-- Test handling of the projects's basedir field.
4+
-- Copyright (c) 2024 Jason Perkins and the Premake project
5+
--
6+
7+
local suite = test.declare("project_basedir")
8+
9+
10+
--
11+
-- Setup and teardown
12+
--
13+
14+
local wks, prj
15+
16+
function suite.setup()
17+
wks = test.createWorkspace()
18+
end
19+
20+
local function prepare()
21+
prj = test.getproject(wks, 1)
22+
end
23+
24+
local function get_files()
25+
local cfg = test.getconfig(prj, "Debug")
26+
27+
local files = {}
28+
for _, file in ipairs(cfg.files) do
29+
table.insert(files, file)
30+
end
31+
32+
return files
33+
end
34+
35+
local function get_includedirs()
36+
local cfg = test.getconfig(prj, "Debug")
37+
38+
local dirs = {}
39+
for _, dir in ipairs(cfg.includedirs) do
40+
table.insert(dirs, dir)
41+
end
42+
43+
return dirs
44+
end
45+
46+
--
47+
-- If no explicit basedir is set, the location should be set to the
48+
-- directory containing the script which defined the project.
49+
--
50+
51+
function suite.onNoBaseDir()
52+
prepare()
53+
test.isequal(os.getcwd(), prj.basedir)
54+
end
55+
56+
57+
--
58+
-- If an explicit basedir has been set, use it.
59+
--
60+
61+
function suite.onBaseDir()
62+
basedir "base"
63+
prepare()
64+
test.isequal(path.join(os.getcwd(), "base"), prj.basedir)
65+
end
66+
67+
68+
--
69+
-- If multiple basedir are set, make sure the value is overriden correctly.
70+
--
71+
72+
function suite.onMultipleBaseDir()
73+
basedir "base0"
74+
basedir "base"
75+
prepare()
76+
test.isequal(path.join(os.getcwd(), "base"), prj.basedir)
77+
end
78+
79+
--
80+
-- Files should be set relative to basedir.
81+
-- Tests "file" data kind.
82+
--
83+
84+
function suite.onFilesBaseDir()
85+
basedir "base"
86+
files { "test.cpp" }
87+
prepare()
88+
test.isequal({path.join(prj.basedir, "test.cpp")}, get_files())
89+
end
90+
91+
92+
--
93+
-- Include directories should be set relative to basedir.
94+
-- Tests "directory" data kind.
95+
--
96+
97+
function suite.onIncludeDirsBaseDir()
98+
basedir "base"
99+
includedirs { "dir" }
100+
prepare()
101+
test.isequal({path.join(prj.basedir, "dir")}, get_includedirs())
102+
end
103+
104+
105+
--
106+
-- If the workspace sets a basedir, and the project does not, it should
107+
-- inherit the value from the workspace.
108+
--
109+
110+
function suite.projectInheritsWorkspaceBaseDir()
111+
workspace ()
112+
basedir "base"
113+
prepare()
114+
-- dbg()
115+
test.isequal(path.join(os.getcwd(), "base"), prj.basedir)
116+
end

tests/project/test_sources.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
local oldcwd
2020

2121
function suite.setup()
22-
wks, prj = test.createWorkspace()
23-
2422
-- We change the directory to get nice relative paths
2523
oldcwd = os.getcwd()
2624
os.chdir(cwd)
2725

26+
wks, prj = test.createWorkspace()
27+
2828
-- Create a token to be used in search paths
2929
p.api.register { name = "mytoken", kind = "string", scope = "config" }
3030
mytoken "test"

website/docs/basedir.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
Sets the base directory for a configuration, from with other paths contained by the configuration will be made relative at export time.
1+
Sets the base directory for a workspace or project, from which other paths contained by the configuration will be made relative to.
2+
3+
This base directory is also used when expanding path tokens encountered in non-path values.
4+
Such values will be made relative to this value so the resulting projects will only contain relative paths.
25

36
```lua
47
basedir ("value")
@@ -8,7 +11,7 @@ You do not normally need to set this value, as it is filled in automatically wit
811

912
### Parameters ###
1013

11-
`value` is an absolute path, from which other paths contained by the configuration should be made relative.
14+
`value` is an absolute or relative path, from which other paths contained by the configuration should be made relative to.
1215

1316
### Applies To ###
1417

@@ -17,3 +20,34 @@ Any configuration.
1720
### Availability ###
1821

1922
Premake 4.4 or later.
23+
24+
### Examples ###
25+
26+
```lua
27+
workspace "workspace"
28+
basedir "base"
29+
project "project"
30+
files { "file.cpp" }
31+
includedirs { "dir" }
32+
```
33+
34+
In this case, files will be generated as `base/file.cpp`, and the include directory as `base/dir`.
35+
36+
37+
```lua
38+
basedir "root"
39+
workspace "workspace"
40+
project "project"
41+
basedir "base"
42+
files { "file.cpp" }
43+
includedirs { "dir" }
44+
```
45+
46+
This results in the same output, as the project-level `basedir` overrides the workspace-level value.
47+
48+
```lua
49+
filter { "configurations:Debug" }
50+
includedirs { "%{prj.basedir}" }
51+
```
52+
53+
`basedir` can also be used as a token, via for example `%{prj.basedir}` syntax. See the [Tokens](Tokens.md) reference for more details.

0 commit comments

Comments
 (0)