Skip to content

Commit c0187fd

Browse files
committed
Add toolsetpath API for specifying tool executable paths
Introduces a new API function `toolsetpath(toolsetName, toolName, toolPath)` that allows users to specify custom paths for tool executables within their Premake scripts. This provides a mechanism to override the default tool lookup behavior for specific toolsets and tools, offering greater flexibility in build configurations. Changes include: - Registering the `toolsetpaths` field in `_premake_init.lua` to store the custom paths. - Implementing the `toolsetpath` function in `base/api.lua` to process and store the provided paths. - Modifying the `gettoolname` functions in the GCC, Clang, MSVC, SNC, .NET, and Emscripten toolset modules to check for and use paths defined via `toolsetpaths` before falling back to default lookup logic. - Adding tests in the corresponding toolset test files (`tests/tools/`) to verify that the `toolsetpath` setting correctly overrides the default behavior. - Creating a new documentation page (`website/docs/toolsetpath.md`) detailing the API function, its parameters, and usage. - Adding an entry for the new documentation page in the website sidebar (`website/sidebars.js`).
1 parent 88c045b commit c0187fd

17 files changed

+183
-0
lines changed

src/_premake_init.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,14 @@
923923
end,
924924
}
925925

926+
api.register {
927+
name = "toolsetpaths",
928+
scope = "config",
929+
kind = "keyed:keyed:path", -- { toolset_name = { tool_name = path } }
930+
tokens = true,
931+
pathVars = true,
932+
}
933+
926934
api.register {
927935
name = "undefines",
928936
scope = "config",

src/base/api.lua

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,3 +1205,40 @@
12051205
function newoption(opt)
12061206
p.option.add(opt)
12071207
end
1208+
1209+
1210+
---
1211+
-- Set the path for a specific tool within a toolset.
1212+
--
1213+
-- @param toolsetName
1214+
-- The name of the toolset (e.g., "gcc", "clang").
1215+
-- @param toolName
1216+
-- The name of the tool (e.g., "cc", "cxx", "ld").
1217+
-- @param toolPath
1218+
-- The path to the tool executable.
1219+
---
1220+
function toolsetpath(toolsetName, toolName, toolPath)
1221+
local cfg = api.scope.current
1222+
if not cfg then
1223+
error("toolsetpath must be called within a configuration block", 2)
1224+
end
1225+
1226+
-- Get the toolsetpaths field definition
1227+
local field = p.field.get("toolsetpaths")
1228+
if not field then
1229+
error("toolsetpaths field not registered", 2)
1230+
end
1231+
1232+
-- Construct the data table
1233+
local data = {
1234+
[toolsetName] = {
1235+
[toolName] = toolPath
1236+
}
1237+
}
1238+
1239+
-- Store the data using configset.store
1240+
local status, err = configset.store(cfg, field, data)
1241+
if err then
1242+
error(err, 2)
1243+
end
1244+
end

src/tools/clang.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@
350350
}
351351

352352
function clang.gettoolname(cfg, tool)
353+
-- Check toolsetpaths first
354+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
355+
return cfg.toolsetpaths[cfg.toolset][tool]
356+
end
357+
353358
local toolset, version = p.tools.canonical(cfg.toolset or p.CLANG)
354359
local value = clang.tools[tool]
355360
if type(value) == "function" then

src/tools/cosmocc.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@ cosmocc.tools = {
2323
}
2424

2525
function cosmocc.gettoolname(cfg, tool)
26+
-- Check toolsetpaths first
27+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
28+
return cfg.toolsetpaths[cfg.toolset][tool]
29+
end
30+
2631
return cosmocc.tools[tool]
2732
end

src/tools/dotnet.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@
255255
--
256256

257257
function dotnet.gettoolname(cfg, tool)
258+
-- Check toolsetpaths first
259+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
260+
return cfg.toolsetpaths[cfg.toolset][tool]
261+
end
262+
258263
local compilers = {
259264
msnet = "csc",
260265
mono = "mcs",

src/tools/emcc.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ emcc.tools = {
2222
-- flags correctly to emcc builds.
2323
emcc.shared.profile = nil
2424
emcc.ldflags.profile = nil
25+
emcc.getsharedlibarg = function(cfg) return "" end
2526

2627
function emcc.gettoolname(cfg, tool)
28+
-- Check toolsetpaths first
29+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
30+
return cfg.toolsetpaths[cfg.toolset][tool]
31+
end
32+
2733
return emcc.tools[tool]
2834
end

src/tools/gcc.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,11 @@
706706
}
707707

708708
function gcc.gettoolname(cfg, tool)
709+
-- Check toolsetpaths first
710+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
711+
return cfg.toolsetpaths[cfg.toolset][tool]
712+
end
713+
709714
local toolset, version = p.tools.canonical(cfg.toolset or p.GCC)
710715
if toolset == p.tools.gcc and version ~= nil then
711716
version = "-" .. version

src/tools/msc.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,11 @@
479479
--
480480

481481
function msc.gettoolname(cfg, tool)
482+
-- Check toolsetpaths first
483+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
484+
return cfg.toolsetpaths[cfg.toolset][tool]
485+
end
486+
482487
return nil
483488
end
484489

src/tools/snc.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
}
140140

141141
function snc.gettoolname(cfg, tool)
142+
-- Check toolsetpaths first
143+
if cfg.toolsetpaths and cfg.toolsetpaths[cfg.toolset] and cfg.toolsetpaths[cfg.toolset][tool] then
144+
return cfg.toolsetpaths[cfg.toolset][tool]
145+
end
146+
142147
local names = snc.tools[cfg.architecture] or snc.tools[cfg.system] or {}
143148
return names[tool]
144149
end

tests/tools/test_clang.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@
4848
test.isequal("windres-16", clang.gettoolname(cfg, "rc"))
4949
end
5050

51+
--
52+
-- Verify that toolsetpath overrides the default tool name.
53+
--
54+
function suite.toolsetpathOverridesDefault()
55+
toolset "clang"
56+
toolsetpath("clang", "cc", "/path/to/my/custom/clang")
57+
prepare()
58+
test.isequal("/path/to/my/custom/clang", clang.gettoolname(cfg, "cc"))
59+
end
60+
5161
--
5262
-- Check Mac OS X deployment target flags
5363
--

tests/tools/test_dotnet.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@
4545
test.isequal("csc", dotnet.gettoolname(cfg, "csc"))
4646
end
4747

48+
--
49+
-- Verify that toolsetpath overrides the default tool name.
50+
--
51+
function suite.toolsetpathOverridesDefault()
52+
toolset "dotnet"
53+
toolsetpath("dotnet", "csc", "/path/to/my/custom/csc")
54+
prepare()
55+
test.isequal("/path/to/my/custom/csc", dotnet.gettoolname(cfg, "csc"))
56+
end
57+
4858

4959
--
5060
-- Check support for the `csversion` API

tests/tools/test_emcc.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,13 @@ function suite.tools_onWASM64()
4646
test.isequal("wasm64", cfg.architecture)
4747
end
4848

49+
--
50+
-- Verify that toolsetpath overrides the default tool name.
51+
--
52+
function suite.toolsetpathOverridesDefault()
53+
toolset "emcc"
54+
toolsetpath("emcc", "cc", "/path/to/my/custom/emcc")
55+
prepare()
56+
test.isequal("/path/to/my/custom/emcc", emcc.gettoolname(cfg, "cc"))
57+
end
58+

tests/tools/test_gcc.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@
6666
test.isequal("windres-16", gcc.gettoolname(cfg, "rc"))
6767
end
6868

69+
--
70+
-- Verify that toolsetpath overrides the default tool name.
71+
--
72+
function suite.toolsetpathOverridesDefault()
73+
toolset "gcc"
74+
toolsetpath("gcc", "cc", "/path/to/my/custom/gcc")
75+
prepare()
76+
test.isequal("/path/to/my/custom/gcc", gcc.gettoolname(cfg, "cc"))
77+
end
78+
6979
--
7080
-- By default, the -MMD -MP are used to generate dependencies.
7181
--

tests/tools/test_msc.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@
2626
end
2727

2828

29+
--
30+
-- Verify that toolsetpath overrides the default tool name.
31+
--
32+
function suite.toolsetpathOverridesDefault()
33+
toolset "msc"
34+
toolsetpath("msc", "cc", "C:/path/to/my/custom/cl.exe")
35+
prepare()
36+
test.isequal("C:/path/to/my/custom/cl.exe", msc.gettoolname(cfg, "cc"))
37+
end
38+
2939
--
3040
-- Check the optimization flags.
3141
--

tests/tools/test_snc.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@
4545
test.isnil(snc.gettoolname(cfg, "ar"))
4646
end
4747

48+
--
49+
-- Verify that toolsetpath overrides the default tool name.
50+
--
51+
function suite.toolsetpathOverridesDefault()
52+
toolset "snc"
53+
toolsetpath("snc", "cc", "/path/to/my/custom/snc_cc")
54+
prepare()
55+
test.isequal("/path/to/my/custom/snc_cc", snc.gettoolname(cfg, "cc"))
56+
end
57+
4858

4959
--
5060
-- By default, the -MMD -MP are used to generate dependencies.

website/docs/toolsetpath.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Specifies the path to a specific tool executable for a given toolset. This allows overriding the default tool lookup behavior of Premake.
2+
3+
```lua
4+
toolsetpath(toolsetName, toolName, toolPath)
5+
```
6+
7+
### Parameters
8+
9+
`toolsetName`
10+
: The name of the toolset (e.g., `"gcc"`, `"clang"`, `"msc"`).
11+
12+
`toolName`
13+
: The name of the tool within the toolset (e.g., `"cc"` for C compiler, `"cxx"` for C++ compiler, `"ld"` for linker, `"ar"` for archiver).
14+
15+
`toolPath`
16+
: The absolute or relative path to the tool executable.
17+
18+
### Applies To
19+
20+
Project configurations.
21+
22+
### Example
23+
24+
```lua
25+
project "MyProject"
26+
kind "ConsoleApp"
27+
language "C++"
28+
system "Linux"
29+
30+
configuration "Release"
31+
toolset "gcc"
32+
-- Specify a custom path for the GCC C++ compiler
33+
toolsetpath("gcc", "cxx", "/opt/my_custom_gcc/bin/g++")
34+
35+
configuration "Debug"
36+
toolset "clang"
37+
-- Specify a custom path for the Clang C compiler
38+
toolsetpath("clang", "cc", "/usr/local/clang-15/bin/clang")
39+
```
40+
41+
In this example, the `toolsetpath` function is used to specify custom paths for the C++ compiler in the "Release" configuration (using GCC) and the C compiler in the "Debug" configuration (using Clang).

website/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ module.exports = {
271271
'thumbmode',
272272
'toolchainversion',
273273
'toolset',
274+
'toolsetpath',
274275
'toolsversion',
275276
'undefines',
276277
'usage',

0 commit comments

Comments
 (0)