So I discovered Bazel recently and wanted to compile my projects with it (that are using Premake right now).
I want to create a provider for each project that will contain all information about it. Like it defines, dependencies, includes directories, ..., and if it's a binary or a library. To simplify my example I have reduced it to just a little info.
SolutionProjectInfo = provider("", fields = {
'name': "",
'project_type': "",
'srcs': "",
'defines': "",
'include_dirs': ""
})
What I would like to do is to have a rule that will produce a SolutionProjectInfo and make a call to cc_binary.
solution_project = rule(
implementation = _impl_solution_project,
attrs = {
'project_type': attr.string(default = ProjectType.ConsoleApp),
'srcs': attr.label_list(default = [], allow_files = True),
'defines': attr.string_list(default = []),
'include_dirs': attr.string_list(default = [])
},
provides = [SolutionProjectInfo]
)
Right now the implementation of _impl_solution_project is meaningless, cause I can't call cc_binary in a rule.
def _impl_solution_project(ctx):
return [SolutionProjectInfo(
name = ctx.label.name,
project_type = ctx.attr.project_type,
defines = ctx.attr.defines,
include_dirs = ctx.attr.include_dirs,
srcs = ctx.attr.srcs
)]
With that I could have just a BUILD file, in which I make a call to this rule solution_project.
But I have a big problem, I can't make a call to cc_binary in a rule, aka in _impl_solution_project the implementation of my rule solution_project (native.cc_binary can't be called within a rule's implementation).
It seems intended:
How to create a rule from within another rule in Bazel
And if I don't make my call to cc_binary in the function _impl_solution_project, my rule solution_project only generates me an SolutionProjectInfo provider. But I don't understand how I can use this provider to make a call to cc_binary, because I can only access values of a provider in a rule, is that right ?
By having something like :
attrs = {
'project': attr.label(providers = [SolutionProjectInfo])
}
So here is my questions
This questions are independant, I only need one to work
How could make a call to cc_binary in my rule
How could make a call to cc_binary in my rule implementation; Aka make a call to cc_binary in _impl_solution_project of my rule solution_project
What I would like to do is a little bit like the presentation of first-class Macros/Symbolic Macros of future Bazel versions which is not available now.
Symbolic Macros
def _impl_solution_project(ctx):
if ctx.attr.project_type == "ConsoleApp":
native.cc_binary(...)
elif ctx.attr.project_type == "StaticLib":
native.cc_library(...)
...
return [SolutionProjectInfo(
name = ctx.label.name,
project_type = ctx.attr.project_type,
defines = ctx.attr.defines,
include_dirs = ctx.attr.include_dirs,
srcs = ctx.attr.srcs
)]
Here I get an error of:
native.cc_binary can't be called within a rule's implementation
Get values from my provider ouside a rule
How could I get values from my provider outside a rule.
Like doing something like:
solution_project(
name = "EngineCore",
type = "StaticLib"
srcs = glob("/src/**/*.cpp"),
defines = [ "USE_OPENGL" ],
include_dirs = [ "EngineCore/src/" ]
...
)
And then I would have a macro (classic StarLark macro) that make a call to cc_binary or cc_library
# *.bzl
def solution_project_macro(info_provider):
if info_provider.project_type == "ConsoleApp":
native.cc_binary(
name = info_provider.name
...
)
elif info_provider.project_type == "StaticLib":
native.cc_library(...)
# BUILD
solution_project(
name = "EngineCore",
type = "StaticLib"
srcs = glob("/src/**/*.cpp"),
defines = [ "USE_OPENGL" ],
include_dirs = [ "EngineCore/src/" ]
...
)
solution_project_macro(":EngineCore")
Why
The code shown previously is made up, that is why I don't have any repo using this.
But that is what I am aiming for. The goal is to avoid duplication of defines / dependencies / includes directories when working with multiple static libs. Like, for example I have a graphics engine that needs to have the define USE_OPENGL. I want when building the lib to create a provider that stores that define, among include directories and others so when I set this graphics engine as dependencies I don't have to make a duplication of all these defines and flags in generals. Thanks for any help or if you have any other way to do that.