premake / premake-core

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

Workspace vpaths overriding project ones #2293

Open UAVXP opened 1 month ago

UAVXP commented 1 month ago

Hello. I have a question about vpaths inheritance.

I want to make a separate (or rather additional) set of vpaths in my project.

This is the project tree:

src_main
    appframework/
...
    public/
        appframework/
            AppFramework.h
            IAppSystem.h
    premake5.lua

src_main/premake5.lua:

workspace "everything"
...
    vpaths {
        ["Header Files"] = { "**.h", "**.hpp" },
        ["Source Files"] = { "**.c", "**.cpp" },
        ["Shaders"] = { "**.fxc", "**.psh", "**.vsh" },
    }
...
    group "Common"
    include "appframework"

And this is what I have in src_main/appframework/premake5.lua:

local prj = project("appframework")
...
    files {
        ...
    }
    vpaths {
        ["Interface"] = "../public/appframework/**.h"
    }

Seems like Premake only considers the main vpaths (from workspace), but not the vpaths from "appframework" project. It puts headers from src_main/public/appframework to a "Header Files" filter in the final ".vcxproj.filters" file, but not "Interface".

How can I accomplish the desired functionality?

UAVXP commented 3 weeks ago

Here's the example project I made to show an issue: premake_vpaths_inheritance.zip

Archive hierarchy:

premake_vpaths_inheritance
    myproject/ - example project folder
    premake5/ - compiled premake-core binaries from https://github.com/premake/premake-core/commit/1a804088d6062814d79f22b292a3f471786d9fe7
    public/ - custom headers for myproject
    premake5.lua

If you want - you can use the latest official Premake build.

premake5.lua:

workspace "everything"

    configurations { "Debug", "Release" }

    vpaths {
        ["Header Files"] = { "**.h", "**.hpp" },
        ["Source Files"] = { "**.c", "**.cpp" },
    }

    group "Common"
    include "myproject"

myproject/premake.lua:

project "myproject"

    language "C++"
    kind "StaticLib"
    targetname "%{prj.name}"
    targetdir "%{cfg.buildcfg}"

    includedirs { "%{wks.location}/public" }

    files {
        "main.cpp",
        "main.h",

        "%{wks.location}/public/public_header.h",
    }

    vpaths {
        ["Interface"] = {

            -- These three does not work
            "%{wks.location}/public/**.h",
            "public/**.h",
            "**.h",

        },
    }

To run: premake5\premake5.exe vs2022

In the resulted myproject/myproject.vcxproj.filters you would see this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\public\public_header.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="main.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
</Project>

as opposed to vpaths settings from myproject/premake5.lua

UAVXP commented 2 weeks ago

No one knows what's going on here? Really? A month has been passed, and not one person replied to this issue

UAVXP commented 2 weeks ago

Also, if I cheat a little and do this in premake5.lua:

function defaultVpaths()
    vpaths {
        ["Header Files"] = { "**.h", "**.hpp" },
        ["Source Files"] = { "**.c", "**.cpp" },
    }
end

workspace "everything"

    configurations { "Debug", "Release" }

    -- vpaths {
        -- ["Header Files"] = { "**.h", "**.hpp" },
        -- ["Source Files"] = { "**.c", "**.cpp" },
    -- }

    group "Common"
    include "myproject"

and this in myproject/premake5.lua:

project "myproject"

    language "C++"
    kind "StaticLib"
    targetname "%{prj.name}"
    targetdir "%{cfg.buildcfg}"

    includedirs { "%{wks.location}/public" }

    files {
        "main.cpp",
        "main.h",

        "%{wks.location}/public/public_header.h",
    }

    defaultVpaths()
    vpaths {
        ["Interface"] = {

            -- These three does not work
            "%{wks.location}/public/**.h",
        --  "public/**.h",
        --  "**.h",

        },
    }

then, for some reason, public/public_header.h filter becomes public and not Interface:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <Filter Include="Source Files">
      <UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier>
    </Filter>
    <Filter Include="Header Files">
      <UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier>
    </Filter>
    <Filter Include="public">
      <UniqueIdentifier>{A4949D15-9036-C8EB-79F1-DB3F65324F3C}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\public\public_header.h">
      <Filter>public</Filter>
    </ClInclude>
    <ClInclude Include="main.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="main.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
</Project>

I don't even know what's going on with vpaths anymore...

UAVXP commented 2 weeks ago

This:

defaultVpaths = {
    ["Header Files"] = { "**.h", "**.hpp" },
    ["Source Files"] = { "**.c", "**.cpp" },
}

workspace "everything"

    configurations { "Debug", "Release" }

    -- vpaths {
        -- ["Header Files"] = { "**.h", "**.hpp" },
        -- ["Source Files"] = { "**.c", "**.cpp" },
    -- }

    group "Common"
    include "myproject"
project "myproject"

    language "C++"
    kind "StaticLib"
    targetname "%{prj.name}"
    targetdir "%{cfg.buildcfg}"

    includedirs { "%{wks.location}/public" }

    files {
        "main.cpp",
        "main.h",

        "%{wks.location}/public/public_header.h",
    }

    vpaths {
        defaultVpaths,
        ["Interface"] = {

            -- These three does not work
            "%{wks.location}/public/**.h",
            "%{wks.location}/public/*.h",
            "public/**.h",
            "public/*.h",
            "**.h",
            "*.h",

        },
    }

didn't work either

UAVXP commented 2 weeks ago
function test()
    local arr = {}
    arr["Header Files"] = { "**.h", "**.hpp" }
    arr["Source Files"] = { "**.c", "**.cpp" }
    return arr
end

workspace "everything"

    configurations { "Debug", "Release" }

    -- vpaths {
        -- ["Header Files"] = { "**.h", "**.hpp" },
        -- ["Source Files"] = { "**.c", "**.cpp" },
    -- }

    group "Common"
    include "myproject"
project "myproject"

    language "C++"
    kind "StaticLib"
    targetname "%{prj.name}"
    targetdir "%{cfg.buildcfg}"

    includedirs { "%{wks.location}/public" }

    files {
        "main.cpp",
        "main.h",

        "%{wks.location}/public/public_header.h",
    }

    vpaths {
        test(),

        ["Interface"] = {

            "%{wks.location}/public/**.h",
            "%{wks.location}/public/*.h",
            "public/**.h",
            "public/*.h",
            "**.h",
            "*.h",

        },

        ["Interface/*"] = {

            "%{wks.location}/public/**.h",
            "%{wks.location}/public/*.h",
            "public/**.h",
            "public/*.h",
            "**.h",
            "*.h",

        },

    }

It doesn't work. The myproject.vcxproj.filters file is still the same. I don't even fucking know, and this behavior (and the fact no one actually replied to me) drives me insane.

UAVXP commented 2 weeks ago

@starkos @samsinsane @nickclark2016 Please?

nickclark2016 commented 2 weeks ago

I don't have an answer for you, as I'm not terribly familiar with vpaths in Premake (hence why I didn't answer).

nickclark2016 commented 2 weeks ago

Looking further into your described behavior, this may be a bug.

samsinsane commented 2 weeks ago

No one knows what's going on here? Really? A month has been passed, and not one person replied to this issue

I don't even fucking know, and this behavior (and the fact no one actually replied to me) drives me insane.

You're not entitled to anything from any of us, you need to calm down and be patient. Your urgency is not our priority.


Looking further into your described behavior, this may be a bug.

Not sure I agree, but I'm also not really sure what behaviour you're referring to.

There's two issues that I have seen:

  1. vpaths returns on the first match, which implicitly prioritises a workspace-level vpaths over a project-level one. Given that it's handled like any other API, I would suggest that this is not something that can be fixed without some weird hacks and breaking existing projects that rely on the current functionality.
  2. vpaths "handles" tokens but doesn't actually handle them - %{wks.location} will expand to the action tokens, which in this case is $(SolutionDir) which prevents path matching. Not sure this can be fixed without breaking existing projects that rely on the tokens to be expanded when they are, maybe one of the random token hacks that people keep littering throughout the codebase might work here?

So, to resolve the original issue you can either fix the pathing problems in the function that provides Header Files and Source Files, or move the vpaths to each project. (Edit: I made a mistake in my testing and thought specifying the vpaths after the projects would fix the issue, but it doesn't and I didn't notice that I had the vpaths around the wrong way, my apologies).

UAVXP commented 1 week ago

I was not and am not in any rush, I was just sad and demoralized cause no answers were given, neither positive nor negative or neutral ones. Just emptiness and silence in response for about 1 whole month.

move the vpaths to each project

That's why I used this:

function test()
    local arr = {}
    arr["Header Files"] = { "**.h", "**.hpp" }
    arr["Source Files"] = { "**.c", "**.cpp" }
    return arr
end
    vpaths {
        test(),

        ["Interface"] = {
                ...

This workaround above cannot produce adequate results, even though the "global" vpaths are in the project now (I suppose?).

samsinsane commented 1 week ago

**.h won't match the public directory because the public directory is not inside the myproject directory. The current working directory is changed based on which file is being executed.

Putting the most inclusive patterns first will prevent ["Interface"] from matching anything - you need to put ["Interface"] first as I explained above already.