Seaside XD image packaging woes

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

Re: Seaside XD image packaging woes

Mariano Peck
Of course, I forgot to attach the app .dat...   they are now..

On Thu, Jul 5, 2018 at 5:07 PM Mariano Martinez Peck <[hidden email]> wrote:
Hi Louis,

I will describe the scenario which we believe is the most comfortable for your case. That is, develop on Windows and then make a XD reduced image for deploying on Linux (Raspbian in your case). This was tested with latest 9.1 ECAP and 32 bits (we still need a few changes for 64 bits). 


-------------------

1) On Windows,  load Server Workbench and Seaside on a development image. You can script it:

 #(
'z.ST: Server Smalltalk (SST) - Seaside Testing'
'z.ST: Server Workbench, Base'
 ) do: [:each | (EmConfigurationMap editionsFor: each) 
first loadWithRequiredMaps 
]. 

1.1) Apply this patch that will be available in next ECAP or Release and its our internal case 63626.

EpOutputStream compile: 'nextPutPointer: anInteger

offset + System vmPointerSize  > bytesSize
ifTrue: [ self writeBytes ].  "Flush the buffer"
reverseEndian
ifTrue: [
longBytes pointerAt: 0 put: anInteger.
1 to: System vmPointerSize do: [ :index |
bytes byteAt: offset + index  put: (longBytes byteAt: System vmPointerSize - index + 1) ] ]
ifFalse: [ 
bytes pointerAt: offset put: anInteger ].
offset := offset + System vmPointerSize'
notifying: Transcript
ifNewAddTo: EpOutputStream controller
categorizeIn: (Array with: 'OVERRIDE').



2) Import and load latest version of SeasideHelloWorld and SeasideHelloWorldPackagingInstructionsApp. The former represents your domain-specific Seaside app (in this case a Hello World). The latter is one possible/easy way to package a Seaside application. It serves as an example and as starting point. This is mostly the only piece you may want to look deeper to adapt it for your own usage.

3) From the main menu, "XD" -> "New Image". Select the feature "Communications - TCP/IP". 

4) Once inside the XD image, open configuration map browser and "Load with Required Maps" the map "zz.Server.AbtSstSeasideFeature"

5) In XD image, go to "Tools" -> "Browse Application Additions", and load latest version of SeasideHelloWorld.  This step simulates what it would be loading your own Seaside app.

6) In XD go to "Tools" -> "Browse Packaged Images" and select the tab "Instructions In Database". You should see SeasideHelloWorldPackagingInstructionsApp. Double click to expand the tree and select AbtXDHelloWorldSeasidePackagingInstructions.

7) Follow the packaging workflow until the end. You should get a seasideHelloWorld.icx, SEASIDEHELLOWORLD.SNP, spusage.es, assocs.es and symbols.es all written. 

8) Move all those files from your Windows to your Linux machine. 

9) On Linux, be sure to have latest ECAP too and start XD image from a console like this (update bold paths and any other info you might need):

 export LANG=en_US.iso88591; export VAST_SANDBOX="/home/mpeck/Instantiations/Vast91EcapB409_Linux"; export LD_LIBRARY_PATH="${VAST_SANDBOX}/bin32";  $LD_LIBRARY_PATH/es  -no_break -msd -mcd -i/mnt/hgfs/Common/Development/Images/91x86-b410-dev/seasideHelloWorldUnix.icx -ini:${VAST_SANDBOX}/image32/abt.ini
 

10) Open a web browser on http://localhost:8888/helloworld 
 
-------------------

I think the resulting behavior is very nice. You can develop on Windows (those that prefer that) and deploy a reduced image in Linux (with full Seaside the .icx is 7MB).

Please, let me know if that works. Unfortunately, I am leaving for vacations on Saturday so I may not be able to be very responsive. 


On Thu, Jul 5, 2018 at 4:26 PM Joachim Tuchel <[hidden email]> wrote:
Lou,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

Joachim





Am Mittwoch, 4. Juli 2018 16:35:44 UTC+2 schrieb Louis LaBrunda:
Hi Joachim and Mariano,
 
In case of XD packaging, however, you end up in a really ugly nightmare trying to do so. I know a few people found ways to do all that stuff like load a Map into the passive image without the Packaged Image Browser, but this is really hard.

If Joachim is referring to what I think he is, I have done this.  Once you have good packaging instructions, I have classes that extend the process to automate running most if not all of it.  I have even added menu items to the popup menu that appears when you right click on an object in an app in the VisualAge Organizer window.  One for headless images and one for GUI images.  The menu items are only enabled if the class is setup to be packaged in this way.  I am willing to share and I think there is an old post of mine in this forum that describers much of the process.  Unfortunately, the classes are very, very much tied to what I what done with the packaged, including renaming, zipping and coping things around on my disk.  It may take quite some refactoring to separate things.  If you are interested, maybe after v9.1 is out the door we can talk about it.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.
[hidden email]


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.
[hidden email]

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.

SeasideHelloWorld.dat (206K) Download Attachment
SeasideHelloWorldPackagingInstructionsApp.dat (222K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Seaside XD image packaging woes

Louis LaBrunda
In reply to this post by jtuchel
Hi Joachim,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

This should go without saying but just to be clear, one needs a good configuration map and working packaging instructions.

I think the method below (a class side extension to #AbtXDSingleImagePackagingInstructions) does most of the work.  There are of course other methods and class that do stuff and hold data.   A lot of it is to make the entire process from packaging to zipping and renaming images and installable msi files (I use to use InstallShield, now it is Advanced Installer) with version numbers, easy for me.  If you find something you don't get or want to know more about, just ask.

The process pauses close to the end to give me a change to run Advanced Installer, then I let it continue to do the zipping and renaming.  I end up with three files, a zip of the image, and msi file and a version log file.  If little has changed (all the DLLs and such are the same) we just deliver the new image to the customer.  I tell you this so that if you see something that doesn't look like packaging, you can probably ignore it because it isn't.

If Instantiations is interested, I'm willing to share.  It will take some work to refactor out the pure packaging part from the rest of my specific use case but I'm willing if they are.

Good luck and have fun.

Lou

buildXDImageAndPackageIt: instructions
"Build an XD Image based upon our sub class and package it."
| devImage imageManager image requiredFeature from toBuild toBin serverName exeManifestPath result xPath binPath |

requiredFeature := AbtBatchFeatureForWs new.
imageManager := EmCrossDevelopmentManagement imageManager.
devImage := EmImageManager currentTarget.
devImage hideWindows: false.

System showBusyCursorWhile: [
image := imageManager
newImage: 'Windows'
hideWindows: false
vmType: 'ES'
bigEndian: false
vmVersion: System vmVersion 
byteCodeVersion: System byteCodeVersion
is64Bit: false.

(image 
platform: AbtBatchNtImageType new;
subsystems: self subSystems;
requiredFeature: requiredFeature;
installRequiredFeature) ifFalse: [image close].

EmSynchronizerManager updateAllTranscriptMenus.
image switchTo.
].

"See #installFeatures comments for info about install features."
System showBusyCursorWhile: [image installFeatures: self installFeatures].
"See #configMap comments for info about what gets loaded."
System showBusyCursorWhile: [self configMap loadWithRequiredMapsAndTracing: true].
"See the sub-class for info about what gets packaged."
System showBusyCursorWhile: [EpPackager packageUsingInstructions: self withProgressMessage: nil].

"At this point we should be packaged and there should be an image on the disk."
"Now we clean things up a bit."
System showBusyCursorWhile: [ | toBeRemoved |
EmImageManager removeCallbacksFor: image passiveImage.
(toBeRemoved := EmSynchronizerManager targetFor: image passiveImage) isNil ifFalse: [
EmSynchronizerManager targetImages remove: toBeRemoved.
EmSynchronizerManager destroyImage: image passiveImage clientData: nil callData: nil.
].

image close.
EmSynchronizerManager updateAllTranscriptMenus.
].

devImage switchTo.

"Get the name of the Service without the extent."
serverName := instructions programName.
"Get the path to the service executable."
exeManifestPath := ((System iniFileGetContentsArray: 'Packaging') at: 'nodialog' ifAbsent: [nil]) asPath directory.
from := exeManifestPath append: 'abtntsrv.exe'.

"Build the path to our bin folder."
xPath := System commandLine first asPath parts.
"Should look something like: ('C:\' 'Program Files (x86)' 'Instantiations' 'VA Smalltalk' '8.6' 'abt.exe')"
binPath := ('%1%2%3%4' bindWith: xPath first with: xPath second with: '\Common Files\Keystone Software Corp\binV' with: (xPath at: 5)) asPath.
"Build the path to where we want to put the service executable (with our name)."
toBuild := instructions buildPath asPath append: (serverName, '.Exe').

"Copy the executable to the build folder."
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the exe to today (keeps the manifest happy)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the exe to the bin folder.  Saves me the trouble"
toBin := binPath append: (serverName, '.Exe').
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"Add .manifest to the exe name and copy the manifest."
from := (from asString, '.manifest') asPath.
toBuild := (toBuild asString, '.manifest') asPath.
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the manifest to today (so I know it got copied)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the manifest to the bin folder."
toBin := (toBin asString, '.manifest') asPath.
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"This is KSC code that gets ready to run the install program (InstallShield) build."
System showBusyCursorWhile: [instructions doExtendedPackagingStage1].
System showBusyCursorWhile: [System message: 'Preform the install program build step and click "OK" when finished.'].
"Now we zip the build so it can be delivered."
System showBusyCursorWhile: [instructions doExtendedPackagingStage2].


 

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

Re: Seaside XD image packaging woes

Louis LaBrunda
In reply to this post by Mariano Peck
Hi Mariano,

Thank you very much for this.  If time permits, I think I'm going to install the latest 9.1 ECAP on Windows and give this a try.

Lou

On Thursday, July 5, 2018 at 4:07:56 PM UTC-4, marianopeck wrote:
Hi Louis,

I will describe the scenario which we believe is the most comfortable for your case. That is, develop on Windows and then make a XD reduced image for deploying on Linux (Raspbian in your case). This was tested with latest 9.1 ECAP and 32 bits (we still need a few changes for 64 bits). 


-------------------

1) On Windows,  load Server Workbench and Seaside on a development image. You can script it:

 #(
'z.ST: Server Smalltalk (SST) - Seaside Testing'
'z.ST: Server Workbench, Base'
 ) do: [:each | (EmConfigurationMap editionsFor: each) 
first loadWithRequiredMaps 
]. 

1.1) Apply this patch that will be available in next ECAP or Release and its our internal case 63626.

EpOutputStream compile: 'nextPutPointer: anInteger

offset + System vmPointerSize  > bytesSize
ifTrue: [ self writeBytes ].  "Flush the buffer"
reverseEndian
ifTrue: [
longBytes pointerAt: 0 put: anInteger.
1 to: System vmPointerSize do: [ :index |
bytes byteAt: offset + index  put: (longBytes byteAt: System vmPointerSize - index + 1) ] ]
ifFalse: [ 
bytes pointerAt: offset put: anInteger ].
offset := offset + System vmPointerSize'
notifying: Transcript
ifNewAddTo: EpOutputStream controller
categorizeIn: (Array with: 'OVERRIDE').



2) Import and load latest version of SeasideHelloWorld and SeasideHelloWorldPackagingInstructionsApp. The former represents your domain-specific Seaside app (in this case a Hello World). The latter is one possible/easy way to package a Seaside application. It serves as an example and as starting point. This is mostly the only piece you may want to look deeper to adapt it for your own usage.

3) From the main menu, "XD" -> "New Image". Select the feature "Communications - TCP/IP". 

4) Once inside the XD image, open configuration map browser and "Load with Required Maps" the map "zz.Server.AbtSstSeasideFeature"

5) In XD image, go to "Tools" -> "Browse Application Additions", and load latest version of SeasideHelloWorld.  This step simulates what it would be loading your own Seaside app.

6) In XD go to "Tools" -> "Browse Packaged Images" and select the tab "Instructions In Database". You should see SeasideHelloWorldPackagingInstructionsApp. Double click to expand the tree and select AbtXDHelloWorldSeasidePackagingInstructions.

7) Follow the packaging workflow until the end. You should get a seasideHelloWorld.icx, SEASIDEHELLOWORLD.SNP, <a href="http://spusage.es" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fspusage.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFNoHxMo6TOOCbaMEXlVFLR6YqnnA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fspusage.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFNoHxMo6TOOCbaMEXlVFLR6YqnnA&#39;;return true;">spusage.es, <a href="http://assocs.es" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fassocs.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNENzbjn6bLaE2YPWmCd9s_VJrSHfw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fassocs.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNENzbjn6bLaE2YPWmCd9s_VJrSHfw&#39;;return true;">assocs.es and <a href="http://symbols.es" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fsymbols.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG7eu_y0QUuJYYod7rRoSQQmjmOCA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fsymbols.es\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG7eu_y0QUuJYYod7rRoSQQmjmOCA&#39;;return true;">symbols.es all written. 

8) Move all those files from your Windows to your Linux machine. 

9) On Linux, be sure to have latest ECAP too and start XD image from a console like this (update bold paths and any other info you might need):

 export LANG=en_US.iso88591; export VAST_SANDBOX="/home/mpeck/Instantiations/Vast91EcapB409_Linux"; export LD_LIBRARY_PATH="${VAST_SANDBOX}/bin32";  $LD_LIBRARY_PATH/es  -no_break -msd -mcd -i/mnt/hgfs/Common/Development/Images/91x86-b410-dev/seasideHelloWorldUnix.icx -ini:${VAST_SANDBOX}/image32/abt.ini
 

10) Open a web browser on <a href="http://localhost:8888/helloworld" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Flocalhost%3A8888%2Fhelloworld\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFsFut5UH_0D7cVJBe5GO4MMK3_kg&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Flocalhost%3A8888%2Fhelloworld\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFsFut5UH_0D7cVJBe5GO4MMK3_kg&#39;;return true;">http://localhost:8888/helloworld 
 
-------------------

I think the resulting behavior is very nice. You can develop on Windows (those that prefer that) and deploy a reduced image in Linux (with full Seaside the .icx is 7MB).

Please, let me know if that works. Unfortunately, I am leaving for vacations on Saturday so I may not be able to be very responsive. 


On Thu, Jul 5, 2018 at 4:26 PM Joachim Tuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="vPy9vumyAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
Lou,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

Joachim





Am Mittwoch, 4. Juli 2018 16:35:44 UTC+2 schrieb Louis LaBrunda:
Hi Joachim and Mariano,
 
In case of XD packaging, however, you end up in a really ugly nightmare trying to do so. I know a few people found ways to do all that stuff like load a Map into the passive image without the Packaged Image Browser, but this is really hard.

If Joachim is referring to what I think he is, I have done this.  Once you have good packaging instructions, I have classes that extend the process to automate running most if not all of it.  I have even added menu items to the popup menu that appears when you right click on an object in an app in the VisualAge Organizer window.  One for headless images and one for GUI images.  The menu items are only enabled if the class is setup to be packaged in this way.  I am willing to share and I think there is an old post of mine in this forum that describers much of the process.  Unfortunately, the classes are very, very much tied to what I what done with the packaged, including renaming, zipping and coping things around on my disk.  It may take quite some refactoring to separate things.  If you are interested, maybe after v9.1 is out the door we can talk about it.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="vPy9vumyAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">va-smalltalk...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="vPy9vumyAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">va-sma...@....
Visit this group at <a href="https://groups.google.com/group/va-smalltalk" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/va-smalltalk&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/va-smalltalk&#39;;return true;">https://groups.google.com/group/va-smalltalk.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.
<a href="javascript:" target="_blank" gdf-obfuscated-mailto="vPy9vumyAgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">mp...@...

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

Re: Seaside XD image packaging woes

Mariano Peck


On Fri, Jul 6, 2018 at 10:49 AM Louis LaBrunda <[hidden email]> wrote:
Hi Mariano,

Thank you very much for this.  If time permits, I think I'm going to install the latest 9.1 ECAP on Windows and give this a try.


Excellent! Let us know how it goes. 

BTW, as you know, you can do the same procedure but doing everything on Linux too. I mean, you can still create the Unix XD from within Linux. I put the Windows development image in the workflow because I thought it was the most comfortable. But both paths should work :)


Lou

On Thursday, July 5, 2018 at 4:07:56 PM UTC-4, marianopeck wrote:
Hi Louis,

I will describe the scenario which we believe is the most comfortable for your case. That is, develop on Windows and then make a XD reduced image for deploying on Linux (Raspbian in your case). This was tested with latest 9.1 ECAP and 32 bits (we still need a few changes for 64 bits). 


-------------------

1) On Windows,  load Server Workbench and Seaside on a development image. You can script it:

 #(
'z.ST: Server Smalltalk (SST) - Seaside Testing'
'z.ST: Server Workbench, Base'
 ) do: [:each | (EmConfigurationMap editionsFor: each) 
first loadWithRequiredMaps 
]. 

1.1) Apply this patch that will be available in next ECAP or Release and its our internal case 63626.

EpOutputStream compile: 'nextPutPointer: anInteger

offset + System vmPointerSize  > bytesSize
ifTrue: [ self writeBytes ].  "Flush the buffer"
reverseEndian
ifTrue: [
longBytes pointerAt: 0 put: anInteger.
1 to: System vmPointerSize do: [ :index |
bytes byteAt: offset + index  put: (longBytes byteAt: System vmPointerSize - index + 1) ] ]
ifFalse: [ 
bytes pointerAt: offset put: anInteger ].
offset := offset + System vmPointerSize'
notifying: Transcript
ifNewAddTo: EpOutputStream controller
categorizeIn: (Array with: 'OVERRIDE').



2) Import and load latest version of SeasideHelloWorld and SeasideHelloWorldPackagingInstructionsApp. The former represents your domain-specific Seaside app (in this case a Hello World). The latter is one possible/easy way to package a Seaside application. It serves as an example and as starting point. This is mostly the only piece you may want to look deeper to adapt it for your own usage.

3) From the main menu, "XD" -> "New Image". Select the feature "Communications - TCP/IP". 

4) Once inside the XD image, open configuration map browser and "Load with Required Maps" the map "zz.Server.AbtSstSeasideFeature"

5) In XD image, go to "Tools" -> "Browse Application Additions", and load latest version of SeasideHelloWorld.  This step simulates what it would be loading your own Seaside app.

6) In XD go to "Tools" -> "Browse Packaged Images" and select the tab "Instructions In Database". You should see SeasideHelloWorldPackagingInstructionsApp. Double click to expand the tree and select AbtXDHelloWorldSeasidePackagingInstructions.

7) Follow the packaging workflow until the end. You should get a seasideHelloWorld.icx, SEASIDEHELLOWORLD.SNP, spusage.es, assocs.es and symbols.es all written. 

8) Move all those files from your Windows to your Linux machine. 

9) On Linux, be sure to have latest ECAP too and start XD image from a console like this (update bold paths and any other info you might need):

 export LANG=en_US.iso88591; export VAST_SANDBOX="/home/mpeck/Instantiations/Vast91EcapB409_Linux"; export LD_LIBRARY_PATH="${VAST_SANDBOX}/bin32";  $LD_LIBRARY_PATH/es  -no_break -msd -mcd -i/mnt/hgfs/Common/Development/Images/91x86-b410-dev/seasideHelloWorldUnix.icx -ini:${VAST_SANDBOX}/image32/abt.ini
 

10) Open a web browser on http://localhost:8888/helloworld 
 
-------------------

I think the resulting behavior is very nice. You can develop on Windows (those that prefer that) and deploy a reduced image in Linux (with full Seaside the .icx is 7MB).

Please, let me know if that works. Unfortunately, I am leaving for vacations on Saturday so I may not be able to be very responsive. 


On Thu, Jul 5, 2018 at 4:26 PM Joachim Tuchel <[hidden email]> wrote:
Lou,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

Joachim





Am Mittwoch, 4. Juli 2018 16:35:44 UTC+2 schrieb Louis LaBrunda:
Hi Joachim and Mariano,
 
In case of XD packaging, however, you end up in a really ugly nightmare trying to do so. I know a few people found ways to do all that stuff like load a Map into the passive image without the Packaged Image Browser, but this is really hard.

If Joachim is referring to what I think he is, I have done this.  Once you have good packaging instructions, I have classes that extend the process to automate running most if not all of it.  I have even added menu items to the popup menu that appears when you right click on an object in an app in the VisualAge Organizer window.  One for headless images and one for GUI images.  The menu items are only enabled if the class is setup to be packaged in this way.  I am willing to share and I think there is an old post of mine in this forum that describers much of the process.  Unfortunately, the classes are very, very much tied to what I what done with the packaged, including renaming, zipping and coping things around on my disk.  It may take quite some refactoring to separate things.  If you are interested, maybe after v9.1 is out the door we can talk about it.

Lou

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.
[hidden email]

--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.


--
Mariano Martinez Peck
Software Engineer, Instantiations Inc.
[hidden email]

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

Re: Seaside XD image packaging woes

jtuchel
In reply to this post by Louis LaBrunda
Louis,

thanks for sharing. This is hilarious: it seems all I need is just a handful of method calls to make things happen automatically. Most of the magic seems to be #switchTo and teh configuration of the passive image. Can't believe I didn't find out myself ;-) The relevant part is mostly the first few lines until "devImage switchTo", anything after that is highly individual for projects.

Our current process is highly efficient and involves a prepared "Master image" with a clean passive image for Linux and our Packaging instructions preloaded. The image is write-protected on the file system. All we need to do is fire it up (easy with Environments these days), load two config maps and click through the packaged image browser. It just takes 3 minutes to create our (ca 5.3 MB sized) production image, but automating it would be so much nicer. You still have to think at work, and I'd like to eliminate that ;-)
Especially if we can also include the upload to the servers and stuff to make it a fully automated end-to-end solution.

This will probably be my thing to look for for next Sunday afternoon ;-)

Again: thanks a lot for sharing!

Joachim





Am Freitag, 6. Juli 2018 15:46:18 UTC+2 schrieb Louis LaBrunda:
Hi Joachim,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

This should go without saying but just to be clear, one needs a good configuration map and working packaging instructions.

I think the method below (a class side extension to #AbtXDSingleImagePackagingInstructions) does most of the work.  There are of course other methods and class that do stuff and hold data.   A lot of it is to make the entire process from packaging to zipping and renaming images and installable msi files (I use to use InstallShield, now it is Advanced Installer) with version numbers, easy for me.  If you find something you don't get or want to know more about, just ask.

The process pauses close to the end to give me a change to run Advanced Installer, then I let it continue to do the zipping and renaming.  I end up with three files, a zip of the image, and msi file and a version log file.  If little has changed (all the DLLs and such are the same) we just deliver the new image to the customer.  I tell you this so that if you see something that doesn't look like packaging, you can probably ignore it because it isn't.

If Instantiations is interested, I'm willing to share.  It will take some work to refactor out the pure packaging part from the rest of my specific use case but I'm willing if they are.

Good luck and have fun.

Lou

buildXDImageAndPackageIt: instructions
"Build an XD Image based upon our sub class and package it."
| devImage imageManager image requiredFeature from toBuild toBin serverName exeManifestPath result xPath binPath |

requiredFeature := AbtBatchFeatureForWs new.
imageManager := EmCrossDevelopmentManagement imageManager.
devImage := EmImageManager currentTarget.
devImage hideWindows: false.

System showBusyCursorWhile: [
image := imageManager
newImage: 'Windows'
hideWindows: false
vmType: 'ES'
bigEndian: false
vmVersion: System vmVersion 
byteCodeVersion: System byteCodeVersion
is64Bit: false.

(image 
platform: AbtBatchNtImageType new;
subsystems: self subSystems;
requiredFeature: requiredFeature;
installRequiredFeature) ifFalse: [image close].

EmSynchronizerManager updateAllTranscriptMenus.
image switchTo.
].

"See #installFeatures comments for info about install features."
System showBusyCursorWhile: [image installFeatures: self installFeatures].
"See #configMap comments for info about what gets loaded."
System showBusyCursorWhile: [self configMap loadWithRequiredMapsAndTracing: true].
"See the sub-class for info about what gets packaged."
System showBusyCursorWhile: [EpPackager packageUsingInstructions: self withProgressMessage: nil].

"At this point we should be packaged and there should be an image on the disk."
"Now we clean things up a bit."
System showBusyCursorWhile: [ | toBeRemoved |
EmImageManager removeCallbacksFor: image passiveImage.
(toBeRemoved := EmSynchronizerManager targetFor: image passiveImage) isNil ifFalse: [
EmSynchronizerManager targetImages remove: toBeRemoved.
EmSynchronizerManager destroyImage: image passiveImage clientData: nil callData: nil.
].

image close.
EmSynchronizerManager updateAllTranscriptMenus.
].

devImage switchTo.

"Get the name of the Service without the extent."
serverName := instructions programName.
"Get the path to the service executable."
exeManifestPath := ((System iniFileGetContentsArray: 'Packaging') at: 'nodialog' ifAbsent: [nil]) asPath directory.
from := exeManifestPath append: 'abtntsrv.exe'.

"Build the path to our bin folder."
xPath := System commandLine first asPath parts.
"Should look something like: ('C:\' 'Program Files (x86)' 'Instantiations' 'VA Smalltalk' '8.6' 'abt.exe')"
binPath := ('%1%2%3%4' bindWith: xPath first with: xPath second with: '\Common Files\Keystone Software Corp\binV' with: (xPath at: 5)) asPath.
"Build the path to where we want to put the service executable (with our name)."
toBuild := instructions buildPath asPath append: (serverName, '.Exe').

"Copy the executable to the build folder."
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the exe to today (keeps the manifest happy)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the exe to the bin folder.  Saves me the trouble"
toBin := binPath append: (serverName, '.Exe').
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"Add .manifest to the exe name and copy the manifest."
from := (from asString, '.manifest') asPath.
toBuild := (toBuild asString, '.manifest') asPath.
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the manifest to today (so I know it got copied)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the manifest to the bin folder."
toBin := (toBin asString, '.manifest') asPath.
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"This is KSC code that gets ready to run the install program (InstallShield) build."
System showBusyCursorWhile: [instructions doExtendedPackagingStage1].
System showBusyCursorWhile: [System message: 'Preform the install program build step and click "OK" when finished.'].
"Now we zip the build so it can be delivered."
System showBusyCursorWhile: [instructions doExtendedPackagingStage2].


 

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

Re: Seaside XD image packaging woes

Louis LaBrunda
Hi Joachim,

On Tuesday, July 10, 2018 at 4:52:42 AM UTC-4, Joachim Tuchel wrote:
Louis,

thanks for sharing. This is hilarious: it seems all I need is just a handful of method calls to make things happen automatically. Most of the magic seems to be #switchTo and the configuration of the passive image. Can't believe I didn't find out myself ;-) The relevant part is mostly the first few lines until "devImage switchTo", anything after that is highly individual for projects.

You are very welcome.  Sometimes it is something so simple that our brains just skip over it.
 
Our current process is highly efficient and involves a prepared "Master image" with a clean passive image for Linux and our Packaging instructions preloaded. The image is write-protected on the file system. All we need to do is fire it up (easy with Environments these days), load two config maps and click through the packaged image browser. It just takes 3 minutes to create our (ca 5.3 MB sized) production image, but automating it would be so much nicer. You still have to think at work, and I'd like to eliminate that ;-)
Especially if we can also include the upload to the servers and stuff to make it a fully automated end-to-end solution.

I have some classes that hold information about the back end of the process, like what to zip together, how to rename things with version number in the name and where to put things, so I'm sure you can do the same to meet your needs.  As I think I said, I add menu items to start the process, if you (or anyone) needs help with that I will dig it out.

 
This will probably be my thing to look for for next Sunday afternoon ;-)

Good luck.
 
Lou

P.S.  Once I discovered configuration maps I was hooked.  I have two (at least, especially for headless programs) configuration maps for each application (program) one for packaging and one for development.  Defining the one for packaging is the hardest and most critical.  Getting the section of required maps right is the trouble spot.  First you need to have the prerequisites right.  That is greatly helped by the Application Manager.  I'm thinking that the prerequisite information can be used help define the required maps.  I'm going to play with this over the next few days.


Again: thanks a lot for sharing!

Joachim





Am Freitag, 6. Juli 2018 15:46:18 UTC+2 schrieb Louis LaBrunda:
Hi Joachim,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

This should go without saying but just to be clear, one needs a good configuration map and working packaging instructions.

I think the method below (a class side extension to #AbtXDSingleImagePackagingInstructions) does most of the work.  There are of course other methods and class that do stuff and hold data.   A lot of it is to make the entire process from packaging to zipping and renaming images and installable msi files (I use to use InstallShield, now it is Advanced Installer) with version numbers, easy for me.  If you find something you don't get or want to know more about, just ask.

The process pauses close to the end to give me a change to run Advanced Installer, then I let it continue to do the zipping and renaming.  I end up with three files, a zip of the image, and msi file and a version log file.  If little has changed (all the DLLs and such are the same) we just deliver the new image to the customer.  I tell you this so that if you see something that doesn't look like packaging, you can probably ignore it because it isn't.

If Instantiations is interested, I'm willing to share.  It will take some work to refactor out the pure packaging part from the rest of my specific use case but I'm willing if they are.

Good luck and have fun.

Lou

buildXDImageAndPackageIt: instructions
"Build an XD Image based upon our sub class and package it."
| devImage imageManager image requiredFeature from toBuild toBin serverName exeManifestPath result xPath binPath |

requiredFeature := AbtBatchFeatureForWs new.
imageManager := EmCrossDevelopmentManagement imageManager.
devImage := EmImageManager currentTarget.
devImage hideWindows: false.

System showBusyCursorWhile: [
image := imageManager
newImage: 'Windows'
hideWindows: false
vmType: 'ES'
bigEndian: false
vmVersion: System vmVersion 
byteCodeVersion: System byteCodeVersion
is64Bit: false.

(image 
platform: AbtBatchNtImageType new;
subsystems: self subSystems;
requiredFeature: requiredFeature;
installRequiredFeature) ifFalse: [image close].

EmSynchronizerManager updateAllTranscriptMenus.
image switchTo.
].

"See #installFeatures comments for info about install features."
System showBusyCursorWhile: [image installFeatures: self installFeatures].
"See #configMap comments for info about what gets loaded."
System showBusyCursorWhile: [self configMap loadWithRequiredMapsAndTracing: true].
"See the sub-class for info about what gets packaged."
System showBusyCursorWhile: [EpPackager packageUsingInstructions: self withProgressMessage: nil].

"At this point we should be packaged and there should be an image on the disk."
"Now we clean things up a bit."
System showBusyCursorWhile: [ | toBeRemoved |
EmImageManager removeCallbacksFor: image passiveImage.
(toBeRemoved := EmSynchronizerManager targetFor: image passiveImage) isNil ifFalse: [
EmSynchronizerManager targetImages remove: toBeRemoved.
EmSynchronizerManager destroyImage: image passiveImage clientData: nil callData: nil.
].

image close.
EmSynchronizerManager updateAllTranscriptMenus.
].

devImage switchTo.

"Get the name of the Service without the extent."
serverName := instructions programName.
"Get the path to the service executable."
exeManifestPath := ((System iniFileGetContentsArray: 'Packaging') at: 'nodialog' ifAbsent: [nil]) asPath directory.
from := exeManifestPath append: 'abtntsrv.exe'.

"Build the path to our bin folder."
xPath := System commandLine first asPath parts.
"Should look something like: ('C:\' 'Program Files (x86)' 'Instantiations' 'VA Smalltalk' '8.6' 'abt.exe')"
binPath := ('%1%2%3%4' bindWith: xPath first with: xPath second with: '\Common Files\Keystone Software Corp\binV' with: (xPath at: 5)) asPath.
"Build the path to where we want to put the service executable (with our name)."
toBuild := instructions buildPath asPath append: (serverName, '.Exe').

"Copy the executable to the build folder."
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the exe to today (keeps the manifest happy)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the exe to the bin folder.  Saves me the trouble"
toBin := binPath append: (serverName, '.Exe').
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"Add .manifest to the exe name and copy the manifest."
from := (from asString, '.manifest') asPath.
toBuild := (toBuild asString, '.manifest') asPath.
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the manifest to today (so I know it got copied)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the manifest to the bin folder."
toBin := (toBin asString, '.manifest') asPath.
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"This is KSC code that gets ready to run the install program (InstallShield) build."
System showBusyCursorWhile: [instructions doExtendedPackagingStage1].
System showBusyCursorWhile: [System message: 'Preform the install program build step and click "OK" when finished.'].
"Now we zip the build so it can be delivered."
System showBusyCursorWhile: [instructions doExtendedPackagingStage2].


 

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

Re: Seaside XD image packaging woes

Richard Sargent
Administrator
On Tuesday, July 10, 2018 at 6:23:40 AM UTC-7, Louis LaBrunda wrote:
Hi Joachim,

On Tuesday, July 10, 2018 at 4:52:42 AM UTC-4, Joachim Tuchel wrote:
Louis,

thanks for sharing. This is hilarious: it seems all I need is just a handful of method calls to make things happen automatically. Most of the magic seems to be #switchTo and the configuration of the passive image. Can't believe I didn't find out myself ;-) The relevant part is mostly the first few lines until "devImage switchTo", anything after that is highly individual for projects.

You are very welcome.  Sometimes it is something so simple that our brains just skip over it.
 
Our current process is highly efficient and involves a prepared "Master image" with a clean passive image for Linux and our Packaging instructions preloaded. The image is write-protected on the file system. All we need to do is fire it up (easy with Environments these days), load two config maps and click through the packaged image browser. It just takes 3 minutes to create our (ca 5.3 MB sized) production image, but automating it would be so much nicer. You still have to think at work, and I'd like to eliminate that ;-)
Especially if we can also include the upload to the servers and stuff to make it a fully automated end-to-end solution.

I have some classes that hold information about the back end of the process, like what to zip together, how to rename things with version number in the name and where to put things, so I'm sure you can do the same to meet your needs.  As I think I said, I add menu items to start the process, if you (or anyone) needs help with that I will dig it out.

 
This will probably be my thing to look for for next Sunday afternoon ;-)

Good luck.
 
Lou

P.S.  Once I discovered configuration maps I was hooked.  I have two (at least, especially for headless programs) configuration maps for each application (program) one for packaging and one for development.  Defining the one for packaging is the hardest and most critical.  Getting the section of required maps right is the trouble spot.  First you need to have the prerequisites right.  That is greatly helped by the Application Manager.  I'm thinking that the prerequisite information can be used help define the required maps.  I'm going to play with this over the next few days.

Hi Lou,

Can you clarify this a bit? When you describe two configuration maps, are they organized as superset and subset? i.e. does the development map have the application map as a required map and so it, by itself, only loads development tools and such?

By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that.




Again: thanks a lot for sharing!

Joachim





Am Freitag, 6. Juli 2018 15:46:18 UTC+2 schrieb Louis LaBrunda:
Hi Joachim,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

This should go without saying but just to be clear, one needs a good configuration map and working packaging instructions.

I think the method below (a class side extension to #AbtXDSingleImagePackagingInstructions) does most of the work.  There are of course other methods and class that do stuff and hold data.   A lot of it is to make the entire process from packaging to zipping and renaming images and installable msi files (I use to use InstallShield, now it is Advanced Installer) with version numbers, easy for me.  If you find something you don't get or want to know more about, just ask.

The process pauses close to the end to give me a change to run Advanced Installer, then I let it continue to do the zipping and renaming.  I end up with three files, a zip of the image, and msi file and a version log file.  If little has changed (all the DLLs and such are the same) we just deliver the new image to the customer.  I tell you this so that if you see something that doesn't look like packaging, you can probably ignore it because it isn't.

If Instantiations is interested, I'm willing to share.  It will take some work to refactor out the pure packaging part from the rest of my specific use case but I'm willing if they are.

Good luck and have fun.

Lou

buildXDImageAndPackageIt: instructions
"Build an XD Image based upon our sub class and package it."
| devImage imageManager image requiredFeature from toBuild toBin serverName exeManifestPath result xPath binPath |

requiredFeature := AbtBatchFeatureForWs new.
imageManager := EmCrossDevelopmentManagement imageManager.
devImage := EmImageManager currentTarget.
devImage hideWindows: false.

System showBusyCursorWhile: [
image := imageManager
newImage: 'Windows'
hideWindows: false
vmType: 'ES'
bigEndian: false
vmVersion: System vmVersion 
byteCodeVersion: System byteCodeVersion
is64Bit: false.

(image 
platform: AbtBatchNtImageType new;
subsystems: self subSystems;
requiredFeature: requiredFeature;
installRequiredFeature) ifFalse: [image close].

EmSynchronizerManager updateAllTranscriptMenus.
image switchTo.
].

"See #installFeatures comments for info about install features."
System showBusyCursorWhile: [image installFeatures: self installFeatures].
"See #configMap comments for info about what gets loaded."
System showBusyCursorWhile: [self configMap loadWithRequiredMapsAndTracing: true].
"See the sub-class for info about what gets packaged."
System showBusyCursorWhile: [EpPackager packageUsingInstructions: self withProgressMessage: nil].

"At this point we should be packaged and there should be an image on the disk."
"Now we clean things up a bit."
System showBusyCursorWhile: [ | toBeRemoved |
EmImageManager removeCallbacksFor: image passiveImage.
(toBeRemoved := EmSynchronizerManager targetFor: image passiveImage) isNil ifFalse: [
EmSynchronizerManager targetImages remove: toBeRemoved.
EmSynchronizerManager destroyImage: image passiveImage clientData: nil callData: nil.
].

image close.
EmSynchronizerManager updateAllTranscriptMenus.
].

devImage switchTo.

"Get the name of the Service without the extent."
serverName := instructions programName.
"Get the path to the service executable."
exeManifestPath := ((System iniFileGetContentsArray: 'Packaging') at: 'nodialog' ifAbsent: [nil]) asPath directory.
from := exeManifestPath append: 'abtntsrv.exe'.

"Build the path to our bin folder."
xPath := System commandLine first asPath parts.
"Should look something like: ('C:\' 'Program Files (x86)' 'Instantiations' 'VA Smalltalk' '8.6' 'abt.exe')"
binPath := ('%1%2%3%4' bindWith: xPath first with: xPath second with: '\Common Files\Keystone Software Corp\binV' with: (xPath at: 5)) asPath.
"Build the path to where we want to put the service executable (with our name)."
toBuild := instructions buildPath asPath append: (serverName, '.Exe').

"Copy the executable to the build folder."
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the exe to today (keeps the manifest happy)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the exe to the bin folder.  Saves me the trouble"
toBin := binPath append: (serverName, '.Exe').
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"Add .manifest to the exe name and copy the manifest."
from := (from asString, '.manifest') asPath.
toBuild := (toBuild asString, '.manifest') asPath.
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the manifest to today (so I know it got copied)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the manifest to the bin folder."
toBin := (toBin asString, '.manifest') asPath.
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"This is KSC code that gets ready to run the install program (InstallShield) build."
System showBusyCursorWhile: [instructions doExtendedPackagingStage1].
System showBusyCursorWhile: [System message: 'Preform the install program build step and click "OK" when finished.'].
"Now we zip the build so it can be delivered."
System showBusyCursorWhile: [instructions doExtendedPackagingStage2].


 

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

Re: Seaside XD image packaging woes

Seth Berman
"By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that."
- Seems reasonable...I'll make a case for 9.2 backlog

-- Seth

On Wednesday, July 11, 2018 at 1:52:11 PM UTC-4, Richard Sargent wrote:
On Tuesday, July 10, 2018 at 6:23:40 AM UTC-7, Louis LaBrunda wrote:
Hi Joachim,

On Tuesday, July 10, 2018 at 4:52:42 AM UTC-4, Joachim Tuchel wrote:
Louis,

thanks for sharing. This is hilarious: it seems all I need is just a handful of method calls to make things happen automatically. Most of the magic seems to be #switchTo and the configuration of the passive image. Can't believe I didn't find out myself ;-) The relevant part is mostly the first few lines until "devImage switchTo", anything after that is highly individual for projects.

You are very welcome.  Sometimes it is something so simple that our brains just skip over it.
 
Our current process is highly efficient and involves a prepared "Master image" with a clean passive image for Linux and our Packaging instructions preloaded. The image is write-protected on the file system. All we need to do is fire it up (easy with Environments these days), load two config maps and click through the packaged image browser. It just takes 3 minutes to create our (ca 5.3 MB sized) production image, but automating it would be so much nicer. You still have to think at work, and I'd like to eliminate that ;-)
Especially if we can also include the upload to the servers and stuff to make it a fully automated end-to-end solution.

I have some classes that hold information about the back end of the process, like what to zip together, how to rename things with version number in the name and where to put things, so I'm sure you can do the same to meet your needs.  As I think I said, I add menu items to start the process, if you (or anyone) needs help with that I will dig it out.

 
This will probably be my thing to look for for next Sunday afternoon ;-)

Good luck.
 
Lou

P.S.  Once I discovered configuration maps I was hooked.  I have two (at least, especially for headless programs) configuration maps for each application (program) one for packaging and one for development.  Defining the one for packaging is the hardest and most critical.  Getting the section of required maps right is the trouble spot.  First you need to have the prerequisites right.  That is greatly helped by the Application Manager.  I'm thinking that the prerequisite information can be used help define the required maps.  I'm going to play with this over the next few days.

Hi Lou,

Can you clarify this a bit? When you describe two configuration maps, are they organized as superset and subset? i.e. does the development map have the application map as a required map and so it, by itself, only loads development tools and such?

By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that.




Again: thanks a lot for sharing!

Joachim





Am Freitag, 6. Juli 2018 15:46:18 UTC+2 schrieb Louis LaBrunda:
Hi Joachim,

I've done that for "normal" packaging of a GUI application: menu item in the Transcript, loads the code and packages. Also, we've triggered builds using jenkins, including running sUnit tests. So it is perfectly doable, even if the APIs are undocumented.

However, I miserably failed trying something similar for XD Packaging. How to create a passive image, how to load into it etc. ? I finally gave up...

I'd love to see code snippets that help me get further with this because we mainly XD package these days...

This should go without saying but just to be clear, one needs a good configuration map and working packaging instructions.

I think the method below (a class side extension to #AbtXDSingleImagePackagingInstructions) does most of the work.  There are of course other methods and class that do stuff and hold data.   A lot of it is to make the entire process from packaging to zipping and renaming images and installable msi files (I use to use InstallShield, now it is Advanced Installer) with version numbers, easy for me.  If you find something you don't get or want to know more about, just ask.

The process pauses close to the end to give me a change to run Advanced Installer, then I let it continue to do the zipping and renaming.  I end up with three files, a zip of the image, and msi file and a version log file.  If little has changed (all the DLLs and such are the same) we just deliver the new image to the customer.  I tell you this so that if you see something that doesn't look like packaging, you can probably ignore it because it isn't.

If Instantiations is interested, I'm willing to share.  It will take some work to refactor out the pure packaging part from the rest of my specific use case but I'm willing if they are.

Good luck and have fun.

Lou

buildXDImageAndPackageIt: instructions
"Build an XD Image based upon our sub class and package it."
| devImage imageManager image requiredFeature from toBuild toBin serverName exeManifestPath result xPath binPath |

requiredFeature := AbtBatchFeatureForWs new.
imageManager := EmCrossDevelopmentManagement imageManager.
devImage := EmImageManager currentTarget.
devImage hideWindows: false.

System showBusyCursorWhile: [
image := imageManager
newImage: 'Windows'
hideWindows: false
vmType: 'ES'
bigEndian: false
vmVersion: System vmVersion 
byteCodeVersion: System byteCodeVersion
is64Bit: false.

(image 
platform: AbtBatchNtImageType new;
subsystems: self subSystems;
requiredFeature: requiredFeature;
installRequiredFeature) ifFalse: [image close].

EmSynchronizerManager updateAllTranscriptMenus.
image switchTo.
].

"See #installFeatures comments for info about install features."
System showBusyCursorWhile: [image installFeatures: self installFeatures].
"See #configMap comments for info about what gets loaded."
System showBusyCursorWhile: [self configMap loadWithRequiredMapsAndTracing: true].
"See the sub-class for info about what gets packaged."
System showBusyCursorWhile: [EpPackager packageUsingInstructions: self withProgressMessage: nil].

"At this point we should be packaged and there should be an image on the disk."
"Now we clean things up a bit."
System showBusyCursorWhile: [ | toBeRemoved |
EmImageManager removeCallbacksFor: image passiveImage.
(toBeRemoved := EmSynchronizerManager targetFor: image passiveImage) isNil ifFalse: [
EmSynchronizerManager targetImages remove: toBeRemoved.
EmSynchronizerManager destroyImage: image passiveImage clientData: nil callData: nil.
].

image close.
EmSynchronizerManager updateAllTranscriptMenus.
].

devImage switchTo.

"Get the name of the Service without the extent."
serverName := instructions programName.
"Get the path to the service executable."
exeManifestPath := ((System iniFileGetContentsArray: 'Packaging') at: 'nodialog' ifAbsent: [nil]) asPath directory.
from := exeManifestPath append: 'abtntsrv.exe'.

"Build the path to our bin folder."
xPath := System commandLine first asPath parts.
"Should look something like: ('C:\' 'Program Files (x86)' 'Instantiations' 'VA Smalltalk' '8.6' 'abt.exe')"
binPath := ('%1%2%3%4' bindWith: xPath first with: xPath second with: '\Common Files\Keystone Software Corp\binV' with: (xPath at: 5)) asPath.
"Build the path to where we want to put the service executable (with our name)."
toBuild := instructions buildPath asPath append: (serverName, '.Exe').

"Copy the executable to the build folder."
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the exe to today (keeps the manifest happy)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the exe to the bin folder.  Saves me the trouble"
toBin := binPath append: (serverName, '.Exe').
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"Add .manifest to the exe name and copy the manifest."
from := (from asString, '.manifest') asPath.
toBuild := (toBuild asString, '.manifest') asPath.
result := from copyToNew: toBuild.
result isCfsError ifTrue: [^self copyOf: from to: toBuild failed: result].
"Change the date on the manifest to today (so I know it got copied)."
result := CfsFileDescriptor touch: toBuild asString.
result isCfsError ifTrue: [^self touchOf: toBuild failed: result].

"Then copy the manifest to the bin folder."
toBin := (toBin asString, '.manifest') asPath.
result := toBuild copyToNew: toBin.
result isCfsError ifTrue: [^self copyOf: toBuild to: toBin failed: result].

"This is KSC code that gets ready to run the install program (InstallShield) build."
System showBusyCursorWhile: [instructions doExtendedPackagingStage1].
System showBusyCursorWhile: [System message: 'Preform the install program build step and click "OK" when finished.'].
"Now we zip the build so it can be delivered."
System showBusyCursorWhile: [instructions doExtendedPackagingStage2].


 

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

Re: Seaside XD image packaging woes

Louis LaBrunda
In reply to this post by Richard Sargent
Hi Richard,

I'm snipping a lot of the previous posts out, in the hope that it makes this less confusing, snip...

Can you clarify this a bit? When you describe two configuration maps, are they organized as superset and subset? i.e. does the development map have the application map as a required map and so it, by itself, only loads development tools and such?

 Yes, all the development maps have their application map as a required map.  As I map have said somewhere, I often hose images during testing, so I want an easy way to start with a "clean image" barely more than the abt.icx image from Instantiations.  I keep separate images for each program.  There are applications that are shared amongst programs and therefor loaded into each image but that applications that define the program kind of own each image.
 
By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that.

Interesting.  Given my use of added menu items, I'm not sure it would save me much.

Below is the code snippet I have been playing with to aid in the making of the "Required Maps" section of a configuration map.  It is a bit of a hack and kinda slow but it is a start at what I am trying to do.  You enter the applications you want to load with the map first.  To try it, replace "mapName := #KscNonVisual." with the name of the map you are building and execute the code in a workspace.  The code looks at the applications you want to load and gets their prerequisites, it then finds those applications in existing maps and then displays the required maps in the transcript.  I haven't gotten to the point of trying to see if there are maps that load other maps and therefor could replace a number of required maps with one map.  If this is helpful and can be perfected, I think it could be called via a menu item and maybe put the required maps right in the new map.

Any ideas of how to make it better or whatever are welcome.

Lou


| mapName map allMapsByAppName prerequisites requiredApplicationsByName requiredMapsByAppName requiredMaps appsThatCanBeRemoved |
mapName := #KscNonVisual.
map := (EmConfigurationMap editionsFor: mapName) first.
requiredApplicationsByName := LookupTable new.
map applicationNames do: [:an | requiredApplicationsByName at: an asSymbol put: (System globalNamespace classAt: an)].
" requiredApplicationsByName inspect."
allMapsByAppName := LookupTable new.
EmConfigurationMap configurationMapNames do: [:mn | allMapsByAppName at: mn asSymbol put: (EmConfigurationMap editionsFor: mn) first].
" allMapsByAppName inspect."
prerequisites := Set new.
requiredApplicationsByName values do: [:app |
prerequisites addAll: (app allPrerequisites collect: [:p | p name]).
].
prerequisites := prerequisites asOrderedCollection.
" prerequisites inspect."

requiredMapsByAppName := LookupTable new.
appsThatCanBeRemoved := OrderedCollection new.
prerequisites do: [:an | | appName |
appName := an asString.
allMapsByAppName keysAndValuesDo: [:mName :m |
(mName ~= mapName) ifTrue: [
(m applicationNames includes: appName) ifTrue: [
(requiredApplicationsByName includesKey: an) ifTrue: [appsThatCanBeRemoved add: an] ifFalse: [requiredMapsByAppName at: an put: m].
].
].
].
].
" requiredMapsByAppName inspect.
appsThatCanBeRemoved inspect."
Transcript cr; cr.
appsThatCanBeRemoved notEmpty ifTrue: [
Transcript show: 'The following apps can be removed from the map as they can be included by "Required Maps".'; cr.
Transcript show: 'If you remove it, run this again to get the correct "Required Maps".'; cr; cr.
appsThatCanBeRemoved do: [:an | Transcript tab; show: an; cr].
].

Transcript cr; cr; show: 'Required Maps:'; cr; cr.
requiredMaps := requiredMapsByAppName values asSet asOrderedCollection.
requiredMaps do: [:m | Transcript tab; show: m name; cr].
Transcript cr; cr.





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

Re: Seaside XD image packaging woes

Richard Sargent
Administrator
On Wednesday, July 11, 2018 at 12:24:30 PM UTC-7, Louis LaBrunda wrote:
Hi Richard,

I'm snipping a lot of the previous posts out, in the hope that it makes this less confusing, snip...

Can you clarify this a bit? When you describe two configuration maps, are they organized as superset and subset? i.e. does the development map have the application map as a required map and so it, by itself, only loads development tools and such?

 Yes, all the development maps have their application map as a required map.  As I map have said somewhere, I often hose images during testing, so I want an easy way to start with a "clean image" barely more than the abt.icx image from Instantiations.  I keep separate images for each program.  There are applications that are shared amongst programs and therefor loaded into each image but that applications that define the program kind of own each image.

Good. That's what I thought (and expected!).


 
By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that.

Interesting.  Given my use of added menu items, I'm not sure it would save me much.

Yes. The use of abt.cnf is not for generating a configuration map, but automating building an image "from scratch" or using a CI tool for automatically packaging the application, running the test suite, etc.

(That "CI tool" can be as simple as a scheduled batch job or even a one off command invocation.)


Below is the code snippet I have been playing with to aid in the making of the "Required Maps" section of a configuration map.  It is a bit of a hack and kinda slow but it is a start at what I am trying to do.  You enter the applications you want to load with the map first.  To try it, replace "mapName := #KscNonVisual." with the name of the map you are building and execute the code in a workspace.  The code looks at the applications you want to load and gets their prerequisites, it then finds those applications in existing maps and then displays the required maps in the transcript.  I haven't gotten to the point of trying to see if there are maps that load other maps and therefor could replace a number of required maps with one map.  If this is helpful and can be perfected, I think it could be called via a menu item and maybe put the required maps right in the new map.

Any ideas of how to make it better or whatever are welcome.

Lou


| mapName map allMapsByAppName prerequisites requiredApplicationsByName requiredMapsByAppName requiredMaps appsThatCanBeRemoved |
mapName := #KscNonVisual.
map := (EmConfigurationMap editionsFor: mapName) first.
requiredApplicationsByName := LookupTable new.
map applicationNames do: [:an | requiredApplicationsByName at: an asSymbol put: (System globalNamespace classAt: an)].
" requiredApplicationsByName inspect."
allMapsByAppName := LookupTable new.
EmConfigurationMap configurationMapNames do: [:mn | allMapsByAppName at: mn asSymbol put: (EmConfigurationMap editionsFor: mn) first].
" allMapsByAppName inspect."
prerequisites := Set new.
requiredApplicationsByName values do: [:app |
prerequisites addAll: (app allPrerequisites collect: [:p | p name]).
].
prerequisites := prerequisites asOrderedCollection.
" prerequisites inspect."

requiredMapsByAppName := LookupTable new.
appsThatCanBeRemoved := OrderedCollection new.
prerequisites do: [:an | | appName |
appName := an asString.
allMapsByAppName keysAndValuesDo: [:mName :m |
(mName ~= mapName) ifTrue: [
(m applicationNames includes: appName) ifTrue: [
(requiredApplicationsByName includesKey: an) ifTrue: [appsThatCanBeRemoved add: an] ifFalse: [requiredMapsByAppName at: an put: m].
].
].
].
].
" requiredMapsByAppName inspect.
appsThatCanBeRemoved inspect."
Transcript cr; cr.
appsThatCanBeRemoved notEmpty ifTrue: [
Transcript show: 'The following apps can be removed from the map as they can be included by "Required Maps".'; cr.
Transcript show: 'If you remove it, run this again to get the correct "Required Maps".'; cr; cr.
appsThatCanBeRemoved do: [:an | Transcript tab; show: an; cr].
].

Transcript cr; cr; show: 'Required Maps:'; cr; cr.
requiredMaps := requiredMapsByAppName values asSet asOrderedCollection.
requiredMaps do: [:m | Transcript tab; show: m name; cr].
Transcript cr; cr.





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

Re: Seaside XD image packaging woes

Louis LaBrunda
Hi,

On Wednesday, July 11, 2018 at 3:54:25 PM UTC-4, Richard Sargent wrote:
On Wednesday, July 11, 2018 at 12:24:30 PM UTC-7, Louis LaBrunda wrote:
Hi Richard,

I'm snipping a lot of the previous posts out, in the hope that it makes this less confusing, snip...

Can you clarify this a bit? When you describe two configuration maps, are they organized as superset and subset? i.e. does the development map have the application map as a required map and so it, by itself, only loads development tools and such?

 Yes, all the development maps have their application map as a required map.  As I map have said somewhere, I often hose images during testing, so I want an easy way to start with a "clean image" barely more than the abt.icx image from Instantiations.  I keep separate images for each program.  There are applications that are shared amongst programs and therefor loaded into each image but that applications that define the program kind of own each image.

Good. That's what I thought (and expected!).


 
By the way, one can use abt.cnf for automating builds. It's a little tricky and I seemed to have purged my examples. :-(
This is one of those areas I wish was controlled by a command line parameter rather than hard-coded. Perhaps one day, Seth and gang will improve that.

Interesting.  Given my use of added menu items, I'm not sure it would save me much.

Yes. The use of abt.cnf is not for generating a configuration map, but automating building an image "from scratch" or using a CI tool for automatically packaging the application, running the test suite, etc.

I know, I meant I have menu items that build the image from scratch and package it.  I just right click on the class and click the menu item (one for XD and one for GUI).
 
(That "CI tool" can be as simple as a scheduled batch job or even a one off command invocation.)


Below is the code snippet I have been playing with to aid in the making of the "Required Maps" section of a configuration map.  It is a bit of a hack and kinda slow but it is a start at what I am trying to do.  You enter the applications you want to load with the map first.  To try it, replace "mapName := #KscNonVisual." with the name of the map you are building and execute the code in a workspace.  The code looks at the applications you want to load and gets their prerequisites, it then finds those applications in existing maps and then displays the required maps in the transcript.  I haven't gotten to the point of trying to see if there are maps that load other maps and therefor could replace a number of required maps with one map.  If this is helpful and can be perfected, I think it could be called via a menu item and maybe put the required maps right in the new map.

Any ideas of how to make it better or whatever are welcome.

Lou


| mapName map allMapsByAppName prerequisites requiredApplicationsByName requiredMapsByAppName requiredMaps appsThatCanBeRemoved |
mapName := #KscNonVisual.
map := (EmConfigurationMap editionsFor: mapName) first.
requiredApplicationsByName := LookupTable new.
map applicationNames do: [:an | requiredApplicationsByName at: an asSymbol put: (System globalNamespace classAt: an)].
" requiredApplicationsByName inspect."
allMapsByAppName := LookupTable new.
EmConfigurationMap configurationMapNames do: [:mn | allMapsByAppName at: mn asSymbol put: (EmConfigurationMap editionsFor: mn) first].
" allMapsByAppName inspect."
prerequisites := Set new.
requiredApplicationsByName values do: [:app |
prerequisites addAll: (app allPrerequisites collect: [:p | p name]).
].
prerequisites := prerequisites asOrderedCollection.
" prerequisites inspect."

requiredMapsByAppName := LookupTable new.
appsThatCanBeRemoved := OrderedCollection new.
prerequisites do: [:an | | appName |
appName := an asString.
allMapsByAppName keysAndValuesDo: [:mName :m |
(mName ~= mapName) ifTrue: [
(m applicationNames includes: appName) ifTrue: [
(requiredApplicationsByName includesKey: an) ifTrue: [appsThatCanBeRemoved add: an] ifFalse: [requiredMapsByAppName at: an put: m].
].
].
].
].
" requiredMapsByAppName inspect.
appsThatCanBeRemoved inspect."
Transcript cr; cr.
appsThatCanBeRemoved notEmpty ifTrue: [
Transcript show: 'The following apps can be removed from the map as they can be included by "Required Maps".'; cr.
Transcript show: 'If you remove it, run this again to get the correct "Required Maps".'; cr; cr.
appsThatCanBeRemoved do: [:an | Transcript tab; show: an; cr].
].

Transcript cr; cr; show: 'Required Maps:'; cr; cr.
requiredMaps := requiredMapsByAppName values asSet asOrderedCollection.
requiredMaps do: [:m | Transcript tab; show: m name; cr].
Transcript cr; cr.





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

Re: Seaside XD image packaging woes

Louis LaBrunda
In reply to this post by Louis LaBrunda
 Hi Everyone,

Below is the latest version of my experiment.  This one displays less in the Transcript and actually replaces the *Required Maps* so be careful.  If you have required maps that you know are required (like your own maps) put them in the *Required Maps* section, then run this code (don't forget to replace the map name).  You should also start with an image that has everything that you need loaded.  The resultant *Required Maps* should keep your maps first.  Any maps included by your starter *Required Maps* should not be duplicated by this new code.  You may have to play with the order of the maps that are added.  You do that by starting with a clean image with little loaded, then load the map with its required maps.  Check the loading for errors that should show you that a map is being loaded too soon and move it down in the list.

If anyone tries this, please let me know what you think.

Lou


| mapName map allMapsByAppName prerequisites requiredApplicationsByName requiredMapsByAppName requiredMaps appsThatCanBeRemoved |
mapName := #KscNonVisualDev.
map := (EmConfigurationMap editionsFor: mapName) first.
requiredApplicationsByName := LookupTable new.
map applicationNames do: [:an | requiredApplicationsByName at: an asSymbol put: (System globalNamespace classAt: an)].
" requiredApplicationsByName inspect."
allMapsByAppName := LookupTable new.
EmConfigurationMap configurationMapNames do: [:mn | allMapsByAppName at: mn asSymbol put: (EmConfigurationMap editionsFor: mn) first].
" allMapsByAppName inspect."
prerequisites := Set new.
requiredApplicationsByName values do: [:app |
prerequisites addAll: (app allPrerequisites collect: [:p | p name]).
].
prerequisites := prerequisites asOrderedCollection.
" prerequisites inspect."

requiredMapsByAppName := LookupTable new.
appsThatCanBeRemoved := OrderedCollection new.
prerequisites do: [:an | | appName |
appName := an asString.
allMapsByAppName keysAndValuesDo: [:mName :m |
(mName ~= mapName) ifTrue: [
(m applicationNames includes: appName) ifTrue: [
(requiredApplicationsByName includesKey: an) ifTrue: [appsThatCanBeRemoved add: an] ifFalse: [requiredMapsByAppName at: an put: m].
].
].
].
].
" requiredMapsByAppName inspect.
appsThatCanBeRemoved inspect."

requiredMaps :=  requiredMapsByAppName values asSet asOrderedCollection.
requiredMaps abrRemoveAll: map requiredMaps.
map requiredMaps do: [:rm |
requiredMaps abrRemoveAll: rm allPossibleRequiredMaps.
].

" requiredMaps addAllFirst: map requiredMaps."
" requiredMaps inspect."
map addRequiredMapsAsLast: requiredMaps for: 'true'.


Transcript cr; cr.
appsThatCanBeRemoved notEmpty ifTrue: [
Transcript show: 'The following apps can be removed from the map as they can be included by *Required Maps*.'; cr.
Transcript show: 'If you remove it, run this again to get the correct *Required Maps*.'; cr; cr.
appsThatCanBeRemoved do: [:an | Transcript tab; show: an; cr].
].



--
You received this message because you are subscribed to the Google Groups "VA Smalltalk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/va-smalltalk.
For more options, visit https://groups.google.com/d/optout.
12