-
-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for crate configuration #673
Conversation
Looks great! A bit of feedback on your open questions:
Yes, and also before
That's an amazing idea. How would conditional dependencies work with GPR files? In tandem with conditional Could this serve in the future to retrieve variants?: Back to earth, I'm unsure about the implementation difficulties, but my gut feeling is that it is reasonably doable. I would delay it though after #323, which should greatly simplify maintenance of all that part. Also the rework could be done with this idea in mind.
I'd go with Ada syntax here, given the users expectations, hence no.
My first impulse is to go for verbatim Ada syntax that you can stitch when generating the files, and no hidden assumptions. For example (also putting in a suggestion for the key naming): # optional, only for new types:
[config.types] # everything after "Type X is". Probably [config.subtypes] would be needed too.
Log_Levels = "(Debug, Warn, Error)"
Buffer_Sizes = "new Integer range 128 .. 1024"
[config.variables] # everything after the colon in a declaration, default included
Buffer_Last = "constant Buffer_Sizes := 0"
Min_Level = "Log_Levels := Debug" # Constant optional?
Foo = 'constant String := "Bar"'
[config.settings] # override values for something existing in [config.variables]
crate.Min_Level = "Warn"
crate.Buffer_Last = "1024" would generate type Log_Levels is (Debug, Warn, Error);
type Buffer_Sizes is new Integer range 128 .. 1024;
Buffer_Last : constant Buffer_Sizes := 0;
Min_Level : Log_Levels := Warn;
Foo : constant String := "Bar"; This way you can also have several vars of the same type, and would not arbitrarily limit the kind of declarations you can use. May be a case of too much liberty though (although we could impose restrictions I guess, e.g. only literals for defaults). Also, IIUC, normally one crate would define the types/defaults, and a dependent would set/override them, right? This means we would need to travel dependencies from leaves to root to properly override all the way up? Or at least detect conflicting settings? |
Thanks Alejandro
Indeed.
That a good question. Since gpr file do not have conditional
I never thought about a command line interface for this.
I just pushed a version that relies more on the TOML syntax. My rationale is that it is better to rely on the TOML library rather than implementing a parser just for this. And I do like the result.
In my opinion this is going too far in complexity.
There is already a detection of conflicting settings. But right now I do not check if a crate only sets variable of its own dependencies, i.e. you can set values for crate you don't depend on. |
I'm not so much concerned with the particular interface, but interested in this being an opportunity to allow packaging different minor variants without resorting to different crates.
OK. Here, I was thinking on how to support easily things like
Different personal perceptions, I guess. To me, closer to Ada is always more attractive. I was thinking in the interim to fully go to something like config.declare = '''
< full Ada declarations >
''' and just parse the type/var names and defaults from there (!). But no matter, if you like what you have.
You're several steps ahead :) |
The code only generates named numbers with the idea that users can define their own types from them. This has to be explained the documentation, but so far I have this comment in the code generation part: -- For Real and Int we do not declare a ranged type such as:
--
-- type Test_Type is range 0 .. 100;
-- Test : constant Test_Type := 50;
--
-- because this would limit the possibilities of users for things
-- such as alignment size, etc. Instead we define named numbers
-- (constant) for the First, Last and actual value of the
-- variable:
Test_First : constant := 0;
Test_Last : constant := 100
Test : constant := 50;
-- User can then define their own types:
type Test_Type is range Config.Test_First .. Config.Test_Last
with Size => 32; With this you can also define
I don't see the benefits of this? What would you generate? |
OK, now I understand. So it's merely definition of constants and the types have to be explicitly written by the user, relying on these constants. Then I would not bother with assuming these constants are going to be used for ranges, and make the user to explicitly define whatever is needed (that is, give one definition for each of My comments were on the assumption that the types would also be generated by Alire. But your idea is certainly simpler and flexible enough. |
I should have started with this.
The range comes from my first experiments in particular with buffer where you don't want negative sizes. So having an upper and lower bounds makes sense, and let the user know as soon as possible that the configuration not valid. I also think that max (and min?) string length would be nice.
|
Thinking again about this, we could change |
@mosteo I will need your help to know where to call It basically has to be called when any of the crate manifests is changed because that could change the variable definitions or settings. |
For the first generation after retrieval of a crate, around here would be the place: alire/src/alire/alire-workspace.adb Line 168 in 23f8d98
Problem is, this won't update the root crate after its manifest is edited, as this is a new necessity. (Until now, manifest edition could only affect dependencies). For regenerating the root crate config, the proper place is around here: alire/src/alire/alire-workspace.adb Line 46 in 23f8d98 Finally, there's the problem of linked crates, which are likely targets for edition. These are currently skipped as they don't need deployment. (Side note: This makes me think that we have a lurking bug around there, as their actions won't ever run.) In any case, to deal with your immediate need, you must check alire/src/alire/alire-workspace.adb Line 77 in 23f8d98
I was thinking the other day (in the context of #633) that a cleaner solution would be to have something like |
It would indeed be interesting to have this kind of mechanism. What about using time-stamps of |
This is happening already for the root manifest (see e.g. alire/src/alire/alire-roots.ads:99). The places I commented that you can place your hooks shouldn't even get called if the manifest hasn't changed. The current assumption is that regular dependencies won't be modified by the user, as they're buried in In any case, this has to be implemented for linked crates. |
23f8d98
to
08290c1
Compare
7a9b5a5
to
42c7b9f
Compare
42c7b9f
to
e72c202
Compare
This is the possibility for crates to define configuration variables that will then generate Ada, C, or GPR files based on the values set by depending crates. For embedded projects where compile optimization and static memory usage are important, it is possible to define sizes of cache buffers or maximum amount of some resources. It allows to enable or disable features at compile time, such as debug logging.
e72c202
to
b9f9746
Compare
@mosteo I think this is ready for review as a first pass. Things we might want to change is having a top level table called [configuration.variables]
test = {type="Boolean"}
[configuration.settings]
lol.test=42 This will also allow extra fields that are going to be useful in the future: [configuration]
output_dir = "config"
disabled=false # Disable the configuration feature for this crate
generate_ada=true
generate_c=false
generate_gpr=true This is the layout I tried when I first started to work on this feature but I couldn't get it to work in the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have had a look through the code to get a general idea of the changes, not much to say as I don't get all the details :). I will play a bit with the feature to see if I have any other suggestions, and will have a go at the configuration
top-level table, but to me it looks okay.
If you prefer, we can merge as is and I can make my changes on a later PR.
This is the possibility for crates to define configuration variables
that will then generate Ada, C, or GPR files based on the values set by
depending crates.
For embedded projects where compile optimization and static memory usage
are important, it is possible to define sizes of cache buffers or
maximum amount of some resources.
It allows to enable or disable features at compile time, such as debug
logging.
Example:
test_config.ads
:Open questions:
case
? e.g.: