premake / premake-core

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

Allow specifying root directory for the project sources #2129

Open vadz opened 1 year ago

vadz commented 1 year ago

For various reasons, I can't have Premake files in the root directory of the project, but have to put it into a subdirectory, let's call it build/premake. This means that even my simplest project definitions look like this:

project "foo"
  kind "StaticLib"
  symbols "On"

  local srcdir = "../../foo/"

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

  includedirs { srcdir .. "include" }

  files {
    srcdir .. "include/foo/bar.h",
    -- a dozen more of them...
    srcdir .. "src/foo/foo.cpp",
    -- and a dozen more of those...
  }

Having to write srcdir .. everywhere is aggravating.

My existing build system allows to do this instead

srcdir ../../foo; // This line makes all the paths relative to this directory.

library foo {
  includedirs = include;

  headers {
    include/foo/foo.h
    ...
  }

  sources {
    src/foo/foo.cpp
    ...
  }

}

and I find this much more convenient.

So I wonder if a similar option could be added to Premake? I'd be willing to implement it, but I'd appreciate any hints about how to do it because I am not sure how to get an option set at the current project level in translate() function which is where, I think, prepending of srcdir should be implemented.

Jarod42 commented 1 year ago

I wonder if os.chdir would do the job. Else I would look at premake.field.kind("path",.

vadz commented 1 year ago

I thought I could use basedir() for this somehow, but I didn't find a way to make it work.

Jarod42 commented 1 year ago

basedir seems indeed a good track.

tritao commented 3 weeks ago

I have the exact same issue on my projects, I want to be able to set a base/src directory that all paths on a project should be relative to. From the description, it seems that basedir would be the API for the job, except it does not seem to affect much.

I have been trying to study what exactly it does, and it seems like it does pretty much the same job as location, except location has preference over it, so if you set location, AFAICT, basedir does not do much.

Here are the relevant references:

oven.lua

function p.workspace.bake(self)
    ...
    self.location = self.location or self.basedir
    context.basedir(self, self.location)
    ...
end

fileconfig.lua

function fileconfig.new(fname, prj)
    ...
    context.basedir(fcfg, prj.location)
    ...
end

context.lua

function context.basedir(ctx, basedir)
    ctx._basedir = basedir or ctx._basedir
    return ctx._basedir
end

premake.lua

function premake.filename(obj, ext)
    local fname = obj.location or obj.basedir
    ...
end

basedir.md

Sets the base directory for a configuration, from with other paths contained by the configuration will be made relative at export time.

We also only have 3 single tests for basedir, all related to detokening.

@samsinsane @Jarod42 Do you know what basedir is supposed to do? Could it be we just need to modify all path fields in a container to take into account basedir?

Jarod42 commented 3 weeks ago

From https://premake.github.io/docs/basedir/

Sets the base directory for a configuration, from with other paths contained by the configuration will be made relative at export time.

So it is not the api you want.

Could it be we just need to modify all path fields in a container to take into account basedir?

I think it is an option to try. but unsure that an API like that is a good idea, as it might also surprise user with "scope"

Following won't "work"

srcdir "../../foo" -- This line makes all the paths relative to this directory.

project "foo"
  includedirs "include"

srcdir "../../foo/include" -- overwrite previous value, so which value is stored in `includedirs`
  headers { "foo/foo.h" }
srcdir "../../foo/src"
  sources { "foo/foo.cpp" }

or if it works, behavior is mostly different than other field...

It is a risky task IMO, (%[path] should also be handled)

tritao commented 3 weeks ago

From https://premake.github.io/docs/basedir/

Sets the base directory for a configuration, from with other paths contained by the configuration will be made relative at export time.

So it is not the api you want.

To be honest, I do not understand what this API really does or is supposed to do, so not going to make any assumptions based on what the docs currently say.

Could it be we just need to modify all path fields in a container to take into account basedir?

I think it is an option to try. but unsure that an API like that is a good idea, as it might also surprise user with "scope"

Following won't "work"

srcdir "../../foo" -- This line makes all the paths relative to this directory.

project "foo"
  includedirs "include"

srcdir "../../foo/include" -- overwrite previous value, so which value is stored in `includedirs`
  headers { "foo/foo.h" }
srcdir "../../foo/src"
  sources { "foo/foo.cpp" }

or if it works, behavior is mostly different than other field...

It is a risky task IMO, (%[path] should also be handled)

Introducing a new srcdir API (or pathsdir, maybe?) would be the easy way to go, it would affect all paths defined for a given scope/container.

To fix the issue you have identified, these paths could have the prefix set whenever you set their values, so changing it mid scope would work as it would take effect right away.

Though I don't really see this issue as too much of a problem, this is an advanced feature anyway, and with proper documentation the behavior (and potential foot guns) can be explained to users.

But I would like to understand what the hell basedir is supposed to do in practice, as I said before if you set location, unless I am missing something, it doesn't seem to do much.