Metacello for complex, productline-like situations?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Metacello for complex, productline-like situations?

Stefan Marr-6
Hi:

(sorry, lengthy mail ahead, non-critical, but might be interesting for people who want to know how metacello get's abused)

I created a configuration with which I am not entirely happy.
The project runs on two of different "platforms" and comes in two different flavors, which requires me to hack a bit to abuse metacello.

While writing this email, I realized that I could use metacello's #for:do: instead of my ad hoc approach, but now I am running into issues that dependencies are not properly resolved.
That is, a package gets loaded before it's dependencies, even though it has been listed 'properly'.

Just a brief introduction into my setting: The "platforms" are either additional packages that provide compiler adaptations, or support code for a special VM.
The two flavors I was mentioning can be simply seen as one being a plain, straightforward implementation, while the other is a version that introduces performance optimizations.

Below, you'll find the ad hoc version of the configuration, as well as the version using #for:do:.
Note, the use of STorVM and IsolateOrNoOpt in the ad hoc version. Both variables are initialized with a symbol, that I then test for. 
Also note, in the ad hoc version, I use the variable platformCore, which makes it a little more concise.

That approach worked, but didn't really look good.
Then I changed it pretty straightforwardly to use #for:do:.
That lost a bit the semantics of STorVM and IsolateOrNoOpt, because the relationship between these attributes is not explicit anymore, but it still reads ok, and was a more or less direct search-and-replace-change. Note further, the platformCore variable could not be used anymore, which leads to a little more code.

But overall, metacello seems to provide the mechanism, without requiring my ad hoc approach.
However, after the change, I am running into trouble.
The package 'O-Languages'  gets loaded before it's requirements, and I am not sure why. I guess, I can't nest stuff as I do. But even switching things around (i.e., pulling the #for:do: blocks outside) does not help.

So, a couple of questions: 
 Has anyone used metacello for similar situations, and if so, what was the preferred solutions?
 Is the way I use #for:do: supported or intended usage?
 And, of course, is the problem I am seeing a bug?

Thanks
Stefan

--------- ad hoc version---------
ConfigurationOfOmni>>configuration: anArrayOfSymbols
" self configuration: #(VM Isolate).
 self configuration: #(ST NoOpt). "
STorVM         := (anArrayOfSymbols intersection: #(VM ST)) first.
IsolateOrNoOpt := (anArrayOfSymbols intersection: #(Isolate NoOpt)) first.

ConfigurationOfOmni>>baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
| platformCore |
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [
spec className: 'ConfigurationOfBenchmarking';
 file: 'ConfigurationOfBenchmarking';
 version: #bleedingEdge;
 repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
STorVM = #ST ifTrue: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb';requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec
repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
STorVM = #ST ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5'; package: 'O-STPrerequisites' ].
STorVM = #VM ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
STorVM = #ST ifTrue: [
platformCore := 'O-ST-Core'.
spec package: 'O-ST-Core'].
STorVM = #VM ifTrue: [
platformCore := 'O-VM-Core'.
spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec requires: {'LRSTM-Model'. platformCore. 'O-Core-Misc'}].
IsolateOrNoOpt = #Isolate ifTrue: [
spec package: 'O-Isolate' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
IsolateOrNoOpt = #NoOpt ifTrue: [
spec package: 'O-NoOpt' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
STorVM = #VM ifTrue: [ spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
    package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
    package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
].
---------adhocversion---------



---------#for:do: version---------
baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [spec className: 'ConfigurationOfBenchmarking';
 file: 'ConfigurationOfBenchmarking';
 version: #bleedingEdge;
 repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
spec for: #ST do: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb'; requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
spec package: 'O-Core-Misc'.
spec for: #ST do: [ 
spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5';
    package: 'O-STPrerequisites' ].
spec for: #VM do: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
spec for: #ST do: [spec package: 'O-ST-Core'].
spec for: #VM do: [spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec for: #ST do: [ spec requires: #('LRSTM-Model' 'O-ST-Core' 'O-Core-Misc') ].
spec for: #VM do: [ spec requires: #('LRSTM-Model' 'O-VM-Core' 'O-Core-Misc') ]].
spec for: #Isolate do: [
spec for: #ST do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
spec for: #VM do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
spec for: #NoOpt do: [
spec for: #ST do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
spec for: #VM do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
spec for: #ST do: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
spec for: #VM do: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
     package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
     package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].

].
---------#for:do:version---------

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 
Reply | Threaded
Open this post in threaded view
|

Re: Metacello for complex, productline-like situations?

Dale Henrichs-3
Stef,

I just started taking a look at your two alternatives and I've noticed that the fordo option is using nest #for:do: blocks inside the #common block and I'm curious if that's intentional or not. There is also additional nesting within #Isolate and #NoOpt ... The sematics for nested #for:do: is to trigger a block when all of the #for:do: attributes  are present in the attribute list.

I would expect attribute lists like the following to be used to trigger different combinations of packages:

  #( #common #Isolate #ST)
  #( #common #NoOpt #ST)

Also I'm curious what your load use case looks like, especially in the #for:do: case ... typically the list of attributes used for resolving the #for:do: blocks is based on image attributes and the absence or presence of an attribute is calculated in a #customProjectAttributes method. Right now I don't see how you plan to conditionally set the attributes for a project....

I just noted that you are using a nested #for:do: inside a package spec:

    spec
      package: 'O-Languages'
      with: [
        spec
          for: #'ST'
          do: [ spec requires: #('LRSTM-Model' 'O-ST-Core' 'O-Core-Misc') ].
        spec
          for: #'VM'
          do: [ spec requires: #('LRSTM-Model' 'O-VM-Core' 'O-Core-Misc') ] ].
    spec

which _should_ have signalled an error (but obviously doesn't ... #for:do: should only be nested directly inside other #for:do: statements). You should express the above like the following:

    spec package: 'O-Languages' with: [
      spec requires: #('LRSTM-Model'  'O-Core-Misc') ]].
    spec
      for: #'ST'
      do: [
        spec package: 'O-Languages' with: [ spec requires: #( 'O-ST-Core' ) ]].
    spec
      for: #'VM'
      do: [
        spec package: 'O-Languages' with: [ spec requires: #( 'O-VM-Core') ]].

Maybe this will address your dependency problem? Since the required packages inside the# for:do:

Dale

From: "Stefan Marr" <[hidden email]>
To: [hidden email]
Sent: Monday, June 17, 2013 11:47:24 AM
Subject: [Metacello] Metacello for complex, productline-like situations?

Hi:

(sorry, lengthy mail ahead, non-critical, but might be interesting for people who want to know how metacello get's abused)

I created a configuration with which I am not entirely happy.
The project runs on two of different "platforms" and comes in two different flavors, which requires me to hack a bit to abuse metacello.

While writing this email, I realized that I could use metacello's #for:do: instead of my ad hoc approach, but now I am running into issues that dependencies are not properly resolved.
That is, a package gets loaded before it's dependencies, even though it has been listed 'properly'.

Just a brief introduction into my setting: The "platforms" are either additional packages that provide compiler adaptations, or support code for a special VM.
The two flavors I was mentioning can be simply seen as one being a plain, straightforward implementation, while the other is a version that introduces performance optimizations.

Below, you'll find the ad hoc version of the configuration, as well as the version using #for:do:.
Note, the use of STorVM and IsolateOrNoOpt in the ad hoc version. Both variables are initialized with a symbol, that I then test for. 
Also note, in the ad hoc version, I use the variable platformCore, which makes it a little more concise.

That approach worked, but didn't really look good.
Then I changed it pretty straightforwardly to use #for:do:.
That lost a bit the semantics of STorVM and IsolateOrNoOpt, because the relationship between these attributes is not explicit anymore, but it still reads ok, and was a more or less direct search-and-replace-change. Note further, the platformCore variable could not be used anymore, which leads to a little more code.

But overall, metacello seems to provide the mechanism, without requiring my ad hoc approach.
However, after the change, I am running into trouble.
The package 'O-Languages'  gets loaded before it's requirements, and I am not sure why. I guess, I can't nest stuff as I do. But even switching things around (i.e., pulling the #for:do: blocks outside) does not help.

So, a couple of questions: 
 Has anyone used metacello for similar situations, and if so, what was the preferred solutions?
 Is the way I use #for:do: supported or intended usage?
 And, of course, is the problem I am seeing a bug?

Thanks
Stefan

--------- ad hoc version---------
ConfigurationOfOmni>>configuration: anArrayOfSymbols
" self configuration: #(VM Isolate).
 self configuration: #(ST NoOpt). "
STorVM         := (anArrayOfSymbols intersection: #(VM ST)) first.
IsolateOrNoOpt := (anArrayOfSymbols intersection: #(Isolate NoOpt)) first.

ConfigurationOfOmni>>baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
| platformCore |
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [
spec className: 'ConfigurationOfBenchmarking';
 file: 'ConfigurationOfBenchmarking';
 version: #bleedingEdge;
 repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
STorVM = #ST ifTrue: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb';requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec
repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
STorVM = #ST ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5'; package: 'O-STPrerequisites' ].
STorVM = #VM ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
STorVM = #ST ifTrue: [
platformCore := 'O-ST-Core'.
spec package: 'O-ST-Core'].
STorVM = #VM ifTrue: [
platformCore := 'O-VM-Core'.
spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec requires: {'LRSTM-Model'. platformCore. 'O-Core-Misc'}].
IsolateOrNoOpt = #Isolate ifTrue: [
spec package: 'O-Isolate' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
IsolateOrNoOpt = #NoOpt ifTrue: [
spec package: 'O-NoOpt' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
STorVM = #VM ifTrue: [ spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
    package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
    package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
].
---------adhocversion---------



---------#for:do: version---------
baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [spec className: 'ConfigurationOfBenchmarking';
 file: 'ConfigurationOfBenchmarking';
 version: #bleedingEdge;
 repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
spec for: #ST do: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb'; requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
spec package: 'O-Core-Misc'.
spec for: #ST do: [ 
spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5';
    package: 'O-STPrerequisites' ].
spec for: #VM do: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
spec for: #ST do: [spec package: 'O-ST-Core'].
spec for: #VM do: [spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec for: #ST do: [ spec requires: #('LRSTM-Model' 'O-ST-Core' 'O-Core-Misc') ].
spec for: #VM do: [ spec requires: #('LRSTM-Model' 'O-VM-Core' 'O-Core-Misc') ]].
spec for: #Isolate do: [
spec for: #ST do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
spec for: #VM do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
spec for: #NoOpt do: [
spec for: #ST do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
spec for: #VM do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
spec for: #ST do: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
spec for: #VM do: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
     package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
     package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].

].
---------#for:do:version---------

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 
Reply | Threaded
Open this post in threaded view
|

Re: Metacello for complex, productline-like situations?

Diego Lont-2
<base href="x-msg://8412/">Stef,

Maybe you would like to view your configuration in GTMetaceller. It is a tool I wrote in Moose with glamour and is now part of the Glamour tools. To load it in a Pharo image you need to install the Glamour tools, that also loads the Glamour core.

Gofer new
package: 'ConfigurationOfGToolkit';
load.
(Smalltalk at: #ConfigurationOfGToolkit) project load: #'development'.

(Smalltalk at: #GTMetaceller) open

There is a warning, but that is in another tool, so you can ignore that. There are also some pictures in it, they will be enabled if you also load roassal (that is not included by default using the configuration).

One of the features is that it allows you to see what packages would be loaded in the image for what version, creating a faster feedback loop. I wrote it to be able to modify my configurations more easy.

If you lack features, or run into bugs: please let me know. I support this tool, as much as my time allows me.

Diego

On Jun 17, 2013, at 9:44 PM, Dale K. Henrichs wrote:

Stef,

I just started taking a look at your two alternatives and I've noticed that the fordo option is using nest #for:do: blocks inside the #common block and I'm curious if that's intentional or not. There is also additional nesting within #Isolate and #NoOpt ... The sematics for nested #for:do: is to trigger a block when all of the #for:do: attributes  are present in the attribute list. 

I would expect attribute lists like the following to be used to trigger different combinations of packages:

  #( #common #Isolate #ST) 
  #( #common #NoOpt #ST)

Also I'm curious what your load use case looks like, especially in the #for:do: case ... typically the list of attributes used for resolving the #for:do: blocks is based on image attributes and the absence or presence of an attribute is calculated in a #customProjectAttributes method. Right now I don't see how you plan to conditionally set the attributes for a project.... 

I just noted that you are using a nested #for:do: inside a package spec:

    spec
      package: 'O-Languages'
      with: [ 
        spec
          for: #'ST'
          do: [ spec requires: #('LRSTM-Model' 'O-ST-Core' 'O-Core-Misc') ].
        spec
          for: #'VM'
          do: [ spec requires: #('LRSTM-Model' 'O-VM-Core' 'O-Core-Misc') ] ].
    spec

which _should_ have signalled an error (but obviously doesn't ... #for:do: should only be nested directly inside other #for:do: statements). You should express the above like the following:

    spec package: 'O-Languages' with: [
      spec requires: #('LRSTM-Model'  'O-Core-Misc') ]].
    spec
      for: #'ST'
      do: [
        spec package: 'O-Languages' with: [ spec requires: #( 'O-ST-Core' ) ]].
    spec
      for: #'VM'
      do: [
        spec package: 'O-Languages' with: [ spec requires: #( 'O-VM-Core') ]].

Maybe this will address your dependency problem? Since the required packages inside the# for:do:

Dale

From: "Stefan Marr" <[hidden email]>
To: [hidden email]
Sent: Monday, June 17, 2013 11:47:24 AM
Subject: [Metacello] Metacello for complex, productline-like situations?

Hi:

(sorry, lengthy mail ahead, non-critical, but might be interesting for people who want to know how metacello get's abused)

I created a configuration with which I am not entirely happy.
The project runs on two of different "platforms" and comes in two different flavors, which requires me to hack a bit to abuse metacello.

While writing this email, I realized that I could use metacello's #for:do: instead of my ad hoc approach, but now I am running into issues that dependencies are not properly resolved.
That is, a package gets loaded before it's dependencies, even though it has been listed 'properly'.

Just a brief introduction into my setting: The "platforms" are either additional packages that provide compiler adaptations, or support code for a special VM.
The two flavors I was mentioning can be simply seen as one being a plain, straightforward implementation, while the other is a version that introduces performance optimizations.

Below, you'll find the ad hoc version of the configuration, as well as the version using #for:do:.
Note, the use of STorVM and IsolateOrNoOpt in the ad hoc version. Both variables are initialized with a symbol, that I then test for. 
Also note, in the ad hoc version, I use the variable platformCore, which makes it a little more concise.

That approach worked, but didn't really look good.
Then I changed it pretty straightforwardly to use #for:do:.
That lost a bit the semantics of STorVM and IsolateOrNoOpt, because the relationship between these attributes is not explicit anymore, but it still reads ok, and was a more or less direct search-and-replace-change. Note further, the platformCore variable could not be used anymore, which leads to a little more code.

But overall, metacello seems to provide the mechanism, without requiring my ad hoc approach.
However, after the change, I am running into trouble.
The package 'O-Languages'  gets loaded before it's requirements, and I am not sure why. I guess, I can't nest stuff as I do. But even switching things around (i.e., pulling the #for:do: blocks outside) does not help.

So, a couple of questions: 
 Has anyone used metacello for similar situations, and if so, what was the preferred solutions?
 Is the way I use #for:do: supported or intended usage?
 And, of course, is the problem I am seeing a bug?

Thanks
Stefan

--------- ad hoc version---------
ConfigurationOfOmni>>configuration: anArrayOfSymbols
" self configuration: #(VM Isolate).
  self configuration: #(ST NoOpt). "
STorVM         := (anArrayOfSymbols intersection: #(VM ST)) first.
IsolateOrNoOpt := (anArrayOfSymbols intersection: #(Isolate NoOpt)) first.

ConfigurationOfOmni>>baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
| platformCore |
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [
spec className: 'ConfigurationOfBenchmarking';
  file: 'ConfigurationOfBenchmarking';
  version: #bleedingEdge;
  repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
STorVM = #ST ifTrue: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb';requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec
repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
STorVM = #ST ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5'; package: 'O-STPrerequisites' ].
STorVM = #VM ifTrue: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
STorVM = #ST ifTrue: [
platformCore := 'O-ST-Core'.
spec package: 'O-ST-Core'].
STorVM = #VM ifTrue: [
platformCore := 'O-VM-Core'.
spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec requires: {'LRSTM-Model'. platformCore. 'O-Core-Misc'}].
IsolateOrNoOpt = #Isolate ifTrue: [
spec package: 'O-Isolate' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
IsolateOrNoOpt = #NoOpt ifTrue: [
spec package: 'O-NoOpt' with: [ spec requires: {'O-Languages'. platformCore. 'O-Tests'} ].
STorVM = #ST ifTrue: [ spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
STorVM = #VM ifTrue: [ spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
STorVM = #ST ifTrue: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
STorVM = #VM ifTrue: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
     package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
     package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
].
---------adhocversion---------



---------#for:do: version---------
baseline04: spec
<version: '0.4-baseline'>

spec for: #'common' do: [
spec blessing: #'baseline'.
spec package: 'RoarVM' with: [ spec repository: 'http://ss3.gemstone.com/ss/RoarVM'].
spec project: 'Benchmarking' with: [spec className: 'ConfigurationOfBenchmarking';
  file: 'ConfigurationOfBenchmarking';
  version: #bleedingEdge;
  repository: 'http://smalltalkhub.com/mc/StefanMarr/SMark/main' ].
spec for: #ST do: [
spec package: 'AST-Core'     with: [ spec repository: 'http://www.squeaksource.com/rb'].
spec package: 'AST-Semantic' with: [spec repository: 'http://www.squeaksource.com/rb'; requires: #('AST-Core')].
spec package: 'AST-Compiler' with: [ spec repository: 'http://source.lukas-renggli.ch/helvetia']].

spec repository: 'http://ss3.gemstone.com/ss/Omni';
package: 'ClojureST';
package: 'O-Base-Compat';
package: 'O-Base-Overrides'.
spec package: 'O-Core-Misc'.
spec for: #ST do: [ 
spec package: 'O-Core-Misc' with: 'O-Core-Misc.WithOwner-StefanMarr.5';
     package: 'O-STPrerequisites' ].
spec for: #VM do: [ spec package: 'O-Core-Misc' with: 'O-Core-Misc.NoOwner-StefanMarr.5'].
spec package: 'O-Core-Reflection';
package: 'O-Benchmarks' with: [ spec requires: #('Benchmarking')];
package: 'O-CLBG-Compatibility'.
spec for: #ST do: [spec package: 'O-ST-Core'].
spec for: #VM do: [spec package: 'O-VM-Core'].
spec package: 'O-Languages' with: [
spec for: #ST do: [ spec requires: #('LRSTM-Model' 'O-ST-Core' 'O-Core-Misc') ].
spec for: #VM do: [ spec requires: #('LRSTM-Model' 'O-VM-Core' 'O-Core-Misc') ]].
spec for: #Isolate do: [
spec for: #ST do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-Isolate' with: [ spec requires: #('O-ST-Core' 'O-Isolate') ]].
spec for: #VM do: [
spec package: 'O-Isolate'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-Isolate' with: [ spec requires: #('O-VM-Core' 'O-Isolate') ]]].
spec for: #NoOpt do: [
spec for: #ST do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-ST-Core' 'O-Tests') ].
spec package: 'O-ST-NoOpt' with: [ spec requires: #('O-ST-Core' 'O-NoOpt') ].
spec for: #VM do: [
spec package: 'O-NoOpt'    with: [ spec requires: #('O-Languages' 'O-VM-Core' 'O-Tests') ].
spec package: 'O-VM-NoOpt' with: [ spec requires: #('O-VM-Core' 'O-NoOpt') ]]]].

spec package: 'O-Tests' with: [ spec requires: #('ClojureST' 'O-Core-Misc' 'O-Languages')].
spec for: #ST do: [ spec package: 'O-ST-Tests' with: [ spec requires: #('O-Core-Misc')]].
spec for: #VM do: [ spec package: 'O-VM-Tests' with: [ spec requires: #('O-Core-Misc' 'O-Tests')]].

"AmbientTalkST"
spec package: 'AmbientTalkST-Tests' with: [spec requires: #('O-Core-Misc' 'O-Languages')];
     package: 'AmbientTalkST-Ost-Tests' with: [ spec requires: #('O-Core-Misc')];
     package: 'AmbientTalkST-Benchmarks' with: [ spec requires: #('O-CLBG-Compatibility' 'Benchmarking')].
"LRSTM packages"
spec package: 'LRSTM-Model'          with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'].
spec package: 'LRSTM-Benchmarks' with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].
spec package: 'LRSTM-Tests'           with: [spec repository: 'http://ss3.gemstone.com/ss/LRSTM'. spec requires: #('LRSTM-Model')].

].
---------#for:do:version---------

-- 
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 

-- 
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to[hidden email].
For more options, visit https://groups.google.com/groups/opt_out.    

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 
Reply | Threaded
Open this post in threaded view
|

Re: Metacello for complex, productline-like situations?

Stefan Marr-6
In reply to this post by Dale Henrichs-3
Hi Dale:

On Monday, June 17, 2013 9:44:16 PM UTC+2, Dale wrote:
I just started taking a look at your two alternatives and I've noticed that the fordo option is using nest #for:do: blocks inside the #common block and I'm curious if that's intentional or not. There is also additional nesting within #Isolate and #NoOpt ... The sematics for nested #for:do: is to trigger a block when all of the #for:do: attributes  are present in the attribute list.

I would expect attribute lists like the following to be used to trigger different combinations of packages:

  #( #common #Isolate #ST)
  #( #common #NoOpt #ST)

Yes, the nesting was intentional, but your notation is probably also working.
The configuration needs to be able to set up all 4 possible combinations, i.e., #(ST Isolate), #(ST NoOpt), #(VM Isolate), and #(VM NoOpt).
 
Also I'm curious what your load use case looks like, especially in the #for:do: case ... typically the list of attributes used for resolving the #for:do: blocks is based on image attributes and the absence or presence of an attribute is calculated in a #customProjectAttributes method. Right now I don't see how you plan to conditionally set the attributes for a project.... 

Indeed, my use case requires user input. The user (that is me at the moment) choses which of the 4 possible configurations is desired. Like in a normal product line, where you want to have a certain set of features in the final product.
 
I just noted that you are using a nested #for:do: inside a package spec:

Ok, thanks. I tried to fix that, but unfortunately, it didn't make a difference.
The dependencies were still not properly resolved. Guess, I would need to debug that... Well, for now, I'll give in and use my previous approach.
If I find some spare time, I'll try to look what's actually going wrong.

Thanks
Stefan

PS: Diego, thanks for pointing out the tool, but I hadn't had a chance yet to look at it.

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.
 
 
Reply | Threaded
Open this post in threaded view
|

Re: Metacello for complex, productline-like situations?

Dale Henrichs-3



From: "Stefan Marr" <[hidden email]>
To: [hidden email]
Sent: Monday, July 1, 2013 7:43:23 AM
Subject: Re: [Metacello] Metacello for complex, productline-like situations?

Hi Dale:

On Monday, June 17, 2013 9:44:16 PM UTC+2, Dale wrote:
I just started taking a look at your two alternatives and I've noticed that the fordo option is using nest #for:do: blocks inside the #common block and I'm curious if that's intentional or not. There is also additional nesting within #Isolate and #NoOpt ... The sematics for nested #for:do: is to trigger a block when all of the #for:do: attributes  are present in the attribute list.

I would expect attribute lists like the following to be used to trigger different combinations of packages:

  #( #common #Isolate #ST)
  #( #common #NoOpt #ST)

Yes, the nesting was intentional, but your notation is probably also working.
The configuration needs to be able to set up all 4 possible combinations, i.e., #(ST Isolate), #(ST NoOpt), #(VM Isolate), and #(VM NoOpt).
Sounds reasonable...
 
Also I'm curious what your load use case looks like, especially in the #for:do: case ... typically the list of attributes used for resolving the #for:do: blocks is based on image attributes and the absence or presence of an attribute is calculated in a #customProjectAttributes method. Right now I don't see how you plan to conditionally set the attributes for a project.... 

Indeed, my use case requires user input. The user (that is me at the moment) choses which of the 4 possible configurations is desired. Like in a normal product line, where you want to have a certain set of features in the final product.
Ah...makes sense, now:)
 
I just noted that you are using a nested #for:do: inside a package spec:

Ok, thanks. I tried to fix that, but unfortunately, it didn't make a difference.
The dependencies were still not properly resolved. Guess, I would need to debug that... Well, for now, I'll give in and use my previous approach.
If I find some spare time, I'll try to look what's actually going wrong.
I'd like to see your new specification ... I could have sworn that I set up a config to test as opposed to eyeballing it, so I'd be interested in doing the debugging myself:) Especially that now I understand your use case ...

Dale

--
You received this message because you are subscribed to the Google Groups "Metacello" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/groups/opt_out.