premake / premake-core

Premake
https://premake.github.io/
BSD 3-Clause "New" or "Revised" License
3.21k stars 618 forks source link

forced slash replacement #41

Open tbasnoopy opened 9 years ago

tbasnoopy commented 9 years ago

prerequisites

premake5.lua

local qt_bin_path = "C:/dev/mx/v1/dep/qt/qt_33_x64_bin"

solution "myTestSln"
  location "testfiles/sln"

  platforms "x64"
  configurations "release"
  project "myTestPrj1"
    kind "Utility"
    files (qt_bin_path.."/bin/QtDeclarative_sofistik33_x64_4.dll")

    filter "files:**/*.dll"
      buildmessage ([[%{file.name} (copy)]])
      buildcommands [[xcopy /y "%{file.path:gsub("/","\\")}" "bla"]]
      buildoutputs ("bla")
    filter "*"

Problem The resulting path can be an absolute and all "\" in the path are replaced by "/". There is - afaik - no possibility to change the slashes and not all Windows tools - like xcopy - can handle paths with "/".

Cause If premake is detecting absolute paths in non path variables, they are replaced by relative paths. This is not possible all the time (not sure but here can be a bug, too). It's never possible on Windows system where files are placed over different Partitions (C:\; D:).

detoken.lua:66

local isAbs = path.isabsolute(result)
if isAbs and not field.paths and basedir then
  result = path.getrelative(basedir, result)
end

The path.getrelative function calls path.normalize which replaces all the "\" to "/". This is not the system specification but required for further processing in premake.

path_normalize.c:30

if (ch == '\\') {
  ch = '/';
}

possible Solution Allow avoiding path fixing.

detoken.lua:66

local isAbs = path.isabsolute(result)
if type(result) == "string" and result:find("!$") then
  result = result:match("(.-)!$"):gsub("/","\\")
elseif isAbs and not field.paths and basedir then
  result = path.getrelative(basedir, result)
end

premake5.lua (part replacement)

buildcommands [[xcopy /y "%{file.path.."!"}" "bla"]]

Or is there a way I didn't see?

starkos commented 9 years ago

A couple of things mixed up here; let's use this ticket to address the path separators and open another for the relative path logic if needed.

Premake specifies that all paths should use forward slashes, so let's take that as a given, and that path.normalize() is doing the right thing.

Translating separators in commands can sometimes be an issue even when you are not using tokens, e.g. trying to launch an executable on a relative path across different platforms. So ideally a more general solution would be best.

One solution similar to yours is to wrap it with a path.translate(), like your gsub(). We could make a shortcut for it and place it in the token environment, so maybe do something like:

buildcommands [[xcopy /y "%{T(file.path)}" "bla"]]

That helper could even have a bit of additional logic to try to determine which separator is appropriate for the target.

Makefiles are tricky because they can technically target multiple platforms now. But we can punt and just use the target OS until someone wants to tackle that fully.

starkos commented 9 years ago

Oh, and an example of the relative executable would be

buildcommands [[%{T("../bin/cg")} "bla"]]
tbasnoopy commented 9 years ago

No need for another ticket for relative path logic from my side.

How can we detect which separator is appropriate for the target platform?

I've written a short test:

function T(p)
  return p:gsub("/","\\")
end

buildcommands [[xcopy /y "%{T(file.path)}" "bla"]],

But this doesn't work. I didn't take an exact look on that but i think the same logic (detoken.lua:66) which breaks my gsub is breaking this, too.

If we want to avoid this issue we have to change this function (detoken.lua:66) in some way. But I think i do not understand how you think this should happen.

starkos commented 9 years ago

How can we detect which separator is appropriate for the target platform?

os.is("windows") should do it.

I'm a little concerned about building this into the token expander since we don't necessarily know the context in which the path is being used? I don't have a great solution off the top of my head.

TurkeyMan commented 9 years ago

xbox, xbox360, xbone all use windows slash too...

tbasnoopy commented 9 years ago

I meant something like an cool api call: system_get_path_seperator. But I think there is no system comprehensive call.

@starkos : Which case could be a problem? In the most cases the path is good... or not. But I have not clue which cases can occur.

Jarod42 commented 1 month ago

https://premake.github.io/docs/Tokens/#path-in-commands %[..] handles path in commands string.