Skip to content
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
41 changes: 41 additions & 0 deletions src/base/os.lua
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,47 @@
return result
end

function os.findsubdirheader(headerpath, additionalpaths)
-- headerpath: a partial header file path
-- additionalpaths: required; a string or table of subdirectory paths
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc style is more often the one from os.findlib than os.findheader


if additionalpaths == nil then
error("os.findsubdirheader: additionalpaths is required", 2)
end

local paths = get_library_search_path()

-- replace all /lib and /bin by /include
paths = table.translate(paths, function (p) return p:gsub('[/\\]lib[0-9]*', '/include'):gsub('[/\\]bin', '/include') end)

local userpaths = {}

if type(additionalpaths) == "string" then
userpaths = { additionalpaths }
elseif type(additionalpaths) == "table" then
userpaths = additionalpaths
end

if #userpaths > 0 then
local basepaths = paths
local newpaths = {}
for _, userpath in ipairs(userpaths) do
if path.isabsolute(userpath) then
-- absolute path: search directly, same as os.findheader
table.insert(newpaths, userpath)
else
for _, p in ipairs(basepaths) do
table.insert(newpaths, path.join(p, userpath))
end
end
end
paths = newpaths
end

local result = os.pathsearch(headerpath, table.unpack(paths))
return result
end

--
-- Retrieve the current target operating system ID string.
--
Expand Down
29 changes: 29 additions & 0 deletions tests/base/test_os.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,35 @@
os.findheader("test.h", path.getabsolute("folder/subfolder/include")))
end

function suite.findsubdirheader_provided_relative()
local os_getenv = os.getenv
os.getenv = create_mock_os_getenv({ [get_LD_PATH_variable_name()] = get_surrounded_env_path("folder/subfolder/lib") })

test.isequal(path.getabsolute("folder/subfolder/include/testlib"), os.findsubdirheader("testlib2.h", "testlib"))

os.getenv = os_getenv
end

function suite.findsubdirheader_failure()
test.isfalse(os.findsubdirheader("Knights/who/say/Ni.hpp", "nonexistent"))
end

function suite.findsubdirheader_provided_absolute()
test.isequal(path.getabsolute("folder/subfolder/include"),
os.findsubdirheader("test.h", path.getabsolute("folder/subfolder/include")))
end

function suite.findsubdirheader_mixed_with_empty()
local os_getenv = os.getenv
os.getenv = create_mock_os_getenv({ [get_LD_PATH_variable_name()] = get_surrounded_env_path("folder/subfolder/lib") })

-- "testlib" finds testlib2.h; "" allows test.h to be found in the base include dir
test.isequal(path.getabsolute("folder/subfolder/include/testlib"), os.findsubdirheader("testlib2.h", {"testlib", ""}))
test.isequal(path.getabsolute("folder/subfolder/include"), os.findsubdirheader("test.h", {"testlib", ""}))

os.getenv = os_getenv
end

function suite.findheader_frompath_lib()
local os_getenv = os.getenv
os.getenv = create_mock_os_getenv({ [get_LD_PATH_variable_name()] = get_surrounded_env_path("folder/subfolder/lib") })
Expand Down
1 change: 1 addition & 0 deletions tests/folder/subfolder/include/testlib/testlib2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Only used for presence in tests
10 changes: 9 additions & 1 deletion website/docs/os/os.findheader.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,20 @@ p = os.findheader("headerfile" [, additionalpaths])

`headerfile` is a file name or a the end of a file path to locate.

`additionalpaths` is a string or a table of one or more additional search path.
`additionalpaths` is a string or a table of one or more additional search path. Absolute paths are searched directly; relative paths are resolved against the current working directory.

### Return Value ###

The path containing the header file, if found. Otherwise, nil.

### Example ###

``` lua
os.findheader("stdlib.h") -- e.g. /usr/include
os.findheader("freetype2/ft2build.h") -- e.g. /usr/include
os.findheader("ft2build.h", {"/usr/local/include/freetype2", "/usr/include/freetype2"}) -- e.g. /usr/include/freetype2
```

### Remarks ###
`os.findheader` mostly use the same paths as [[os.findlib]] but replace `/lib` by `/include`.

Expand Down
36 changes: 36 additions & 0 deletions website/docs/os/os.findsubdirheader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Scan the well-known system locations looking for a header file, with support for subdirectory paths.

```lua
p = os.findsubdirheader("headerfile", additionalpaths)
```

### Parameters ###

`headerfile` is a file name or the end of a file path to locate.

`additionalpaths` is a required string or table of one or more subdirectory paths:

- **Relative paths** are joined with every default include search path (cross-join); only the resulting subdirectories are searched.
- **Absolute paths** are searched directly, acting the same behaviour of [[os.findheader]].
- **Empty string `""`** is treated as a path segment that resolves to the base include path itself, so it can be mixed with other entries (e.g. `{"freetype2", ""}` searches both `<base>/freetype2` and `<base>`).

### Return Value ###

The path containing the header file, if found. Otherwise, nil.

### Example ###

``` lua
os.findsubdirheader("ft2build.h", "freetype2") -- e.g. /usr/include/freetype2
os.findsubdirheader("gl.h", {"OpenGL", "GL"}) -- e.g. /usr/include/GL
os.findsubdirheader("ft2build.h", "/your/path/to/freetype2") -- e.g. /your/path/to/freetype2
```

### Remarks ###
Unlike [[os.findheader]], relative paths in `additionalpaths` are resolved against each default search path, allowing discovery of headers in named subdirectories without requiring an absolute path. When `additionalpaths` is non-empty, **only** the specified candidate directories are searched.

`os.findsubdirheader` uses the same base paths as [[os.findheader]], which mostly uses the same paths as [[os.findlib]] but replace `/lib` by `/include`.

### Availability ###

Premake 5.0-beta9 or later.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more beta9 now.

1 change: 1 addition & 0 deletions website/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ module.exports = {
'os/os.execute',
'os/os.executef',
'os/os.findheader',
'os/os.findsubdirheader',
'os/os.findlib',
'os/os.get',
'os/os.getcwd',
Expand Down
Loading