ToolApplicationModel subclass:#ApplicationBuilder
instanceVariableNames:'task shellView'
classVariableNames:'Aspects'
poolDictionaries:''
category:'Interface-Smalltalk'
!
!ApplicationBuilder class methodsFor:'documentation'!
documentation
"
The Application Builder of ST/X allows you to build ST/X-applications by following steps:
0. Clobber the target directory of the application
1. Generation of the h-file with symbols
2. Generation of the c-file with modules
3. Compilation of the modules init file
4. Compilation of the startup C-file
5. Defining of the symbolic links to the libraries
6. Linking of the libraries to the application
7. Defining of the symbolic links to the resources
[instance variables:]
task <Process> task of the running build
shellView <ShellView> shell view for outputing the build results
[class variables:]
Aspects <IdentityDictionary> aspects of the settings
[start with:]
ApplicationBuilder open
[see also:]
LibraryBuilder
[author:]
Thomas Zwick, eXept Software AG
"
! !
!ApplicationBuilder class methodsFor:'help specs'!
helpSpec
"This resource specification was automatically generated
by the UIHelpTool of ST/X."
"Do not manually edit this!! If it is corrupted,
the UIHelpTool may not be able to read the specification."
"
UIHelpTool openOnClass:ApplicationBuilder
"
<resource: #help>
^super helpSpec addPairsFrom:#(
#applicationLinkDefines
'Opens a dialog to define the link defines for the application.'
#applicationName
'Name of the application.'
#build
'Starts the process of building the application.'
#buildDate
'Build date of the application.'
#configuration
'Configuration information of the application.'
#libraryDirectory
'Directory of the ST/X libraries.'
#start
'Start the build application.'
#startupCFile
'Startup C-file of ST/X for the application.'
#startupFile
'Startup C-file of ST/X for the application.'
#startupMessage
'Startup message consisting of the class name and the selector name.'
#startupModule
'Startup module of ST/X for the application.'
#stop
'Stops the process of application building.'
#stxLibraries
'List of the ST/X library names.'
#symlinkBitmaps
'Create symbolic links to the bitmaps of ST/X.'
#symlinkRCFiles
'Create symbolic links to the RC-files of ST/X.'
#symlinkResources
'Create symbolic links to the resources of ST/X.'
#symlinkSources
'Create symbolic links to the sources of ST/X.'
#systemLibaries
'Libraries of the operating system needed by the application.'
#targetDirectory
'Target directory of the application.'
#topDirectory
'Top directory of ST/X.'
#userLibraries
'Libraries of the user wanted to add to the application.'
)
! !
!ApplicationBuilder class methodsFor:'interface specs'!
windowSpec
"This resource specification was automatically generated
by the UIPainter of ST/X."
"Do not manually edit this!! If it is corrupted,
the UIPainter may not be able to read the specification."
"
UIPainter new openOnClass:ApplicationBuilder andSelector:#windowSpec
ApplicationBuilder new openInterface:#windowSpec
ApplicationBuilder open
"
<resource: #canvas>
^
#(#FullSpec
#window:
#(#WindowSpec
#name: 'Application Builder'
#layout: #(#LayoutFrame 37 0 199 0 536 0 658 0)
#label: 'Application Builder'
#min: #(#Point 420 220)
#max: #(#Point 1152 900)
#bounds: #(#Rectangle 37 199 537 659)
#menu: #menu
#usePreferredExtent: false
)
#component:
#(#SpecCollection
#collection:
#(
#(#ViewSpec
#name: 'Box1'
#layout: #(#LayoutFrame 0 0.0 0 0 0 1.0 288 0)
#component:
#(#SpecCollection
#collection:
#(
#(#ViewSpec
#name: 'Box2'
#layout: #(#LayoutFrame 0 0.0 0 0.0 -148 1.0 2 1.0)
#component:
#(#SpecCollection
#collection:
#(
#(#LabelSpec
#name: 'applicationNameLabel'
#layout: #(#AlignmentOrigin 147 0 15 0 1 0.5)
#label: 'Application Name:'
#adjust: #right
)
#(#InputFieldSpec
#name: 'applicationNameField'
#layout: #(#LayoutFrame 150 0 4 0 0 1 26 0)
#activeHelpKey: #applicationName
#model: #applicationName
)
#(#LabelSpec
#name: 'startupMessageLabel'
#layout: #(#AlignmentOrigin 147 0 39 0 1 0.5)
#label: 'Startup Message:'
#adjust: #right
)
#(#InputFieldSpec
#name: 'startupMessageField'
#layout: #(#LayoutFrame 150 0 28 0 0 1.0 50 0)
#activeHelpKey: #startupMessage
#model: #startupMessage
)
#(#LabelSpec
#name: 'buildDateLabel'
#layout: #(#AlignmentOrigin 147 0 63 0 1 0.5)
#label: 'Build Date:'
#adjust: #right
)
#(#InputFieldSpec
#name: 'buildDateField'
#layout: #(#LayoutFrame 150 0 52 0 0 1.0 74 0)
#activeHelpKey: #buildDate
#model: #buildDate
)
#(#LabelSpec
#name: 'configurationLabel'
#layout: #(#AlignmentOrigin 147 0 87 0 1 0.5)
#label: 'Configuration:'
#adjust: #right
)
#(#InputFieldSpec
#name: 'configurationField'
#layout: #(#LayoutFrame 150 0 76 0 0 1.0 98 0)
#activeHelpKey: #configuration
#model: #configuration
)
#(#DividerSpec
#name: 'divider1'
#layout: #(#LayoutFrame 0 0 102 0 0 1 105 0)
)
#(#ActionButtonSpec
#name: 'targetDirectoryButton'
#layout: #(#LayoutFrame 4 0 109 0 147 0 133 0)
#label: 'Target Directory:'
#model: #doSelectDirectory:
#actionValue: 'Target'
)
#(#InputFieldSpec
#name: 'targetDirectoryField'
#layout: #(#LayoutFrame 150 0 109 0 0 1.0 131 0)
#activeHelpKey: #targetDirectory
#model: #targetDirectory
)
#(#ActionButtonSpec
#name: 'topDirectoryButton'
#layout: #(#LayoutFrame 4 0 133 0 147 0 157 0)
#label: 'Top Directory:'
#model: #doSelectDirectory:
#actionValue: 'Top'
)
#(#InputFieldSpec
#name: 'topDirectoryField'
#layout: #(#LayoutFrame 150 0 133 0 0 1.0 155 0)
#activeHelpKey: #topDirectory
#model: #topDirectory
)
#(#ActionButtonSpec
#name: 'libraryDirectoryButton'
#layout: #(#LayoutFrame 4 0 157 0 147 0 181 0)
#label: 'Library Directory:'
#model: #doSelectDirectory:
#actionValue: 'Library'
)
#(#InputFieldSpec
#name: 'libraryDirectoryField'
#layout: #(#LayoutFrame 150 0 157 0 0 1.0 179 0)
#activeHelpKey: #libraryDirectory
#model: #libraryDirectory
)
#(#ActionButtonSpec
#name: 'startupCFileButton'
#layout: #(#LayoutFrame 4 0 181 0 147 0 205 0)
#label: 'Startup C-File:'
#model: #doSelectCFile:
#actionValue: 'StartupCFile'
)
#(#InputFieldSpec
#name: 'startupCFileField'
#layout: #(#LayoutFrame 150 0 181 0 0 1.0 203 0)
#activeHelpKey: #startupModule
#model: #startupCFile
)
#(#DividerSpec
#name: 'divider2'
#layout: #(#LayoutFrame 0 0.0 208 0 0 1.0 211 0)
)
#(#LabelSpec
#name: 'stxLibraryButton'
#layout: #(#LayoutFrame 4 0 215 0 147 0 239 0)
#label: 'ST/X Libraries:'
)
#(#ComboBoxSpec
#name: 'stxLibrariesComboBox'
#layout: #(#LayoutFrame 150 0 216 0 0 1 238 0)
#activeHelpKey: #stxLibraries
#model: #stxLibrary
#immediateAccept: false
#acceptOnTab: false
#comboList: #stxLibraries
)
#(#ActionButtonSpec
#name: 'systemLibrariesButton'
#layout: #(#LayoutFrame 4 0 239 0 147 0 263 0)
#label: 'System Libraries:'
#model: #doSelectLibrary:
#actionValue: 'SystemLibrary'
)
#(#ComboBoxSpec
#name: 'systemLibrariesComboBox'
#layout: #(#LayoutFrame 150 0 240 0 0 1 262 0)
#activeHelpKey: #systemLibaries
#model: #systemLibrary
#immediateAccept: false
#acceptOnTab: false
#comboList: #systemLibraries
)
#(#ActionButtonSpec
#name: 'userLibrariesButton'
#layout: #(#LayoutFrame 4 0 263 0 147 0 287 0)
#label: 'User Libraries:'
#model: #doSelectLibrary:
#actionValue: 'UserLibrary'
)
#(#ComboBoxSpec
#name: 'userLibrariesComboBox'
#layout: #(#LayoutFrame 150 0 264 0 0 1 286 0)
#activeHelpKey: #userLibraries
#model: #userLibrary
#immediateAccept: false
#acceptOnTab: false
#comboList: #userLibraries
)
)
)
)
#(#ViewSpec
#name: 'Box3'
#layout: #(#LayoutFrame -134 1 0 0.0 0 1.0 0 1.0)
#component:
#(#SpecCollection
#collection:
#(
#(#FramedBoxSpec
#name: 'FramedBox'
#layout: #(#LayoutFrame -4 0.0 0 0.0 0 1.0 -98 1.0)
#component:
#(#SpecCollection
#collection:
#(
#(#CheckBoxSpec
#name: 'linkRCFilesCheckBox'
#layout: #(#LayoutFrame 12 0 24 0 12 1 46 0)
#activeHelpKey: #symlinkRCFiles
#model: #linkRCFiles
#label: 'RC-Files'
)
#(#CheckBoxSpec
#name: 'linkResourcesCheckBox'
#layout: #(#LayoutFrame 12 0 48 0 12 1 70 0)
#activeHelpKey: #symlinkResources
#model: #linkResources
#label: 'Resources'
)
#(#CheckBoxSpec
#name: 'linkSourcesCheckBox'
#layout: #(#LayoutFrame 12 0 72 0 12 1 94 0)
#activeHelpKey: #symlinkSources
#model: #linkSources
#label: 'Sources'
)
#(#CheckBoxSpec
#name: 'linkBitmapsCheckBox'
#layout: #(#LayoutFrame 12 0 96 0 12 1 118 0)
#activeHelpKey: #symlinkBitmaps
#model: #linkBitmaps
#label: 'Bitmaps'
)
)
)
#label: 'Symbolic Links'
#labelPosition: #topLeft
)
#(#VerticalPanelViewSpec
#name: 'VerticalPanel'
#layout: #(#LayoutFrame 0 0.0 -90 1 -6 1.0 0 1.0)
#component:
#(#SpecCollection
#collection:
#(
#(#ActionButtonSpec
#name: 'buildButton'
#activeHelpKey: #build
#label: 'Build'
#model: #doBuild
#extent: #(#Point 128 28)
)
#(#ActionButtonSpec
#name: 'stopButton'
#activeHelpKey: #stop
#label: 'Stop'
#model: #doStop
#extent: #(#Point 128 28)
)
#(#ActionButtonSpec
#name: 'Button1'
#activeHelpKey: #start
#label: 'Start'
#model: #doStart
#extent: #(#Point 128 28)
)
)
)
#horizontalLayout: #fit
#verticalLayout: #fit
#horizontalSpace: 3
#verticalSpace: 3
)
)
)
)
#(#DividerSpec
#name: 'Separator1'
#layout: #(#LayoutFrame -144 1 0 0.0 -138 1 0 1.0)
#orientation: #vertical
)
)
)
)
#(#DividerSpec
#name: 'Separator2'
#layout: #(#LayoutFrame 0 0.0 290 0 0 1.0 293 0)
)
#(#SubCanvasSpec
#name: 'SubCanvas'
#layout: #(#LayoutFrame 0 0.0 296 0 0 1.0 -26 1)
#hasHorizontalScrollBar: false
#hasVerticalScrollBar: false
#clientHolder: #shellView
)
#(#UISubSpecification
#name: 'windowSpecForInfoBar'
#layout: #(#LayoutFrame 0 0.0 -24 1 0 1.0 0 1.0)
#majorKey: #ToolApplicationModel
#minorKey: #windowSpecForInfoBar
)
)
)
)
! !
!ApplicationBuilder class methodsFor:'menu specs'!
menu
"This resource specification was automatically generated
by the MenuEditor of ST/X."
"Do not manually edit this!! If it is corrupted,
the MenuEditor may not be able to read the specification."
"
MenuEditor new openOnClass:ApplicationBuilder andSelector:#menu
(Menu new fromLiteralArrayEncoding:(ApplicationBuilder menu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#label: 'File'
#submenu:
#(#Menu
#(
#(#MenuItem
#label: 'Build'
#value: #doBuild
#activeHelpKey: #build
)
#(#MenuItem
#label: 'Stop'
#value: #doStop
#activeHelpKey: #stop
)
#(#MenuItem
#label: 'Start'
#value: #doStart
#activeHelpKey: #start
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Exit'
#value: #closeRequest
#activeHelpKey: #fileExit
)
) nil
nil
)
)
#(#MenuItem
#label: 'Settings'
#submenu:
#(#Menu
#(
#(#MenuItem
#label: 'Target Directory...'
#value: #doSelectDirectory:
#activeHelpKey: #targetDirectory
#argument: 'Target'
)
#(#MenuItem
#label: 'Top Directory...'
#value: #doSelectDirectory:
#activeHelpKey: #topDirectory
#argument: 'Top'
)
#(#MenuItem
#label: 'Library Directory...'
#value: #doSelectDirectory:
#activeHelpKey: #libraryDirectory
#argument: 'Library'
)
#(#MenuItem
#label: 'Startup C-File...'
#value: #doSelectCFile:
#activeHelpKey: #startupCFile
#argument: 'StartupCFile'
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'System Libraries...'
#value: #doSelectLibrary:
#activeHelpKey: #systemLibaries
#argument: 'SystemLibrary'
)
#(#MenuItem
#label: 'User Libraries...'
#value: #doSelectLibrary:
#activeHelpKey: #userLibraries
#argument: 'UserLibrary'
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Application Link Defines...'
#value: #doDefineApplicationLinkDefines
#activeHelpKey: #applicationLinkDefines
)
#(#MenuItem
#label: '-'
)
#(#MenuItem
#label: 'Fonts'
#submenuChannel: #menuFont
)
) nil
nil
)
)
#(#MenuItem
#label: 'Help'
#startGroup: #right
#submenuChannel: #menuHelp
)
) nil
nil
)
! !
!ApplicationBuilder methodsFor:'actions'!
doBuild
"builds the application by doing following tasks:
0. Clobber the target directory of the application
1. Generation of the h-file with symbols
2. Generation of the c-file with modules
3. Compilation of the modules init file
4. Compilation of the startup C-file
5. Creating of the symbolic links to the libraries
6. Linking of the libraries to the application
7. Creating of the symbolic links to the resources
"
|dir compilerPath compilerFlags block0 block1 block2 block3 block4 block5 block6 block7 priority|
task notNil ifTrue: [self warn: 'There is already a build running!!'].
self inform: 'Starting building of application...' asBoldText.
(dir := self getApplicationDirectory) isNil
ifTrue: [^self warn: 'Could not create application directory!!'].
shellView directory: dir.
(compilerPath := ByteCodeCompiler ccPath, ' ') isNil
ifTrue: [^self warn:'Define first a system compiler!!'].
compilerFlags := self getCompilerFlags.
block0 :=
[
self inform: 'Clobbering the target directory...'.
self clobberTargetDirectory: dir.
task := nil
].
block1 :=
[
self inform: 'Starting generation of the h-file with symbols...'.
self generateHFileWithSymbolsIn: dir.
(dir asFilename construct: 'symbols.h') exists
ifTrue: [task := nil]
ifFalse: [self warn:'Could not generate the h-file with symbols!!']
].
block2 :=
[
self inform: 'Starting generation of the C-file with modules...'.
self generateCFileWithModulesIn: dir.
(dir asFilename construct: 'modulList.c') exists
ifTrue: [task := nil]
ifFalse: [self warn:'Could not generate the C-file with libraries!!']
].
block3 :=
[
self inform: 'Starting compilation of the modules init file...'.
self compileModulListFileWith: compilerPath, compilerFlags inDirectory: dir.
(dir asFilename construct: 'modulList.o') exists
ifTrue: [task := nil]
ifFalse: [self warn:'Could not compile the modules file!!']
].
block4 :=
[
((Aspects at: #startupCFile) value asFilename) exists
ifFalse: [task := nil. self warn: 'Defined startup C-file not found!!'].
self inform: 'Starting compilation of the startup C-file...'.
self compileStartupCFileWith: compilerPath, compilerFlags inDirectory: dir.
(dir asFilename construct: 'main.o') exists
ifTrue: [task := nil]
ifFalse: [self warn:'Could not compile the startup C-file!!']
].
block5 :=
[
self inform: 'Starting defining of the symbolic links to the libraries...'.
self createSymbolicLinksToTheLibrariesIn: dir.
task := nil.
].
block6 :=
[
self inform: 'Starting linking of the libraries to the application...'.
self linkLibrariesToTheApplicationIn: dir.
(dir asFilename construct: (Aspects at: #applicationName) value) exists
ifTrue: [task := nil]
ifFalse: [self warn:'Could not build the application!!']
].
block7 :=
[
self inform: 'Starting linking of the resources...'.
self createSymbolicLinksToTheResourcesIn: dir.
task := nil.
].
priority := Processor userBackgroundPriority.
task := block0 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block1 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block2 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block3 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block4 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block5 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block6 forkAt: priority.
task addExitAction:
[
task isNil ifTrue:
[
task := block7 forkAt: priority.
task addExitAction:
[
task := nil.
self inform: 'Application build.' asBoldText.
Display beep.
]
]
]
]
]
]
]
]
]
]
]
]
]
]
]
!
doDefineApplicationLinkDefines
"opens a dialog for defining the application defines"
|box|
box := EnterBox new.
box label: 'Application Link Defines'.
box initialText: (Aspects at: #applicationLinkDefines) value.
box showAtPointer.
box accepted
ifTrue:
[
(Aspects at: #applicationLinkDefines) value: box contents
].
box destroy
!
doSelectCFile: whichFile
"opens a FileSelectionBrowser in order to select C-file"
|currentFile selectedFile|
currentFile := Aspects at: whichFile asLowercaseFirst asSymbol.
((selectedFile := FileSelectionBrowser
request: 'Select Your ', whichFile, ' File'
fileName: currentFile value
inDirectory: currentFile value
withFileFilters: #('*.c')) notNil and:
[selectedFile asFilename exists and: [selectedFile asFilename isDirectory not]])
ifTrue: [currentFile value: selectedFile]
!
doSelectDirectory: whichDir
"opens a FileSelectionBrowser in order to select directory"
|currentDir selectedDir|
currentDir := Aspects at: (whichDir asLowercaseFirst, 'Directory') asSymbol.
((selectedDir := FileSelectionBrowser
request: 'Select Your ', whichDir, ' Directory'
fileName: nil
inDirectory: currentDir value
withFileFilters: #('*.*o')) notNil and:
[selectedDir asFilename exists and: [selectedDir asFilename isDirectory]])
ifTrue: [currentDir value: selectedDir. shellView executeCommand: 'cd ', selectedDir]
!
doSelectLibrary: whichFile
"opens a FileSelectionBrowser in order to select library"
|currentFile selectedFile|
currentFile := Aspects at: whichFile asLowercaseFirst asSymbol.
((selectedFile := FileSelectionBrowser
request: 'Select Your ', whichFile, ' File'
fileName: currentFile value
inDirectory: currentFile value
withFileFilters: #('*.*o' '*.a')) notNil and:
[selectedFile asFilename exists and: [selectedFile asFilename isDirectory not]])
ifTrue: [currentFile value: selectedFile]
!
doStart
"starts the build application"
|dir|
self doStop.
(dir := self getApplicationDirectory) isNil
ifTrue: [^self warn: 'Application directory does not exists!!'].
shellView directory: dir.
shellView executeCommand: (Aspects at: #applicationName) value.
!
doStop
"terminates the task of the current build"
task notNil ifTrue: [task removeAllExitActions. task terminate].
task := nil.
shellView executeCommand: 'clear'.
self inform: ''
! !
!ApplicationBuilder methodsFor:'aspects'!
aspectFor:aKey
"returns an aspect at aKey"
^Aspects at: aKey ifAbsent: [super aspectFor:aKey]
!
aspectsAt: aKey putFirst: anObject
"puts firstly anObject as ValueHolder at aKey and returns it"
^Aspects at: aKey ifAbsent: [Aspects at: aKey put: anObject asValue]
!
shellView
"returns a shell view"
shellView isNil ifTrue: [shellView := ShellView new. shellView directory: (Aspects at: #topDirectory) value].
^shellView
! !
!ApplicationBuilder methodsFor:'building'!
clobberTargetDirectory: dir
"clobbers the target directory of the application"
self executeCommand: 'rm -r *' inDirectory: dir
!
compileModulListFileWith: ccPathAndFlags inDirectory: dir
"compiles the C-file with the list of the module names"
|command|
command := ccPathAndFlags , ' -c -fPIC -O6 -fomit-frame-pointer -m486 -DDEBUG -Di386 modulList.c'.
self executeCommand: command inDirectory: dir
!
compileStartupCFileWith: ccPathAndFlags inDirectory: dir
"compiles the startup file with passing startup class, startup selector, configuration string, and build date"
|startUpClass cls startUpSelector startupFile command|
startUpClass := ((Aspects at: #startupMessage) value upTo: $ ) asSymbol.
(cls := Smalltalk at: startUpClass) isNil ifTrue: [^self warn: 'Defined class not found in system!!'].
startUpSelector := ((Aspects at: #startupMessage) value copy reverse upTo: $ ) reverse asSymbol.
(cls respondsTo: startUpSelector) ifFalse: [^self warn: 'Defined class does not respond to the defined selector!!'].
startupFile := (Aspects at: #startupCFile) value asFilename.
startupFile copyTo: (startupFile := dir asFilename construct: (Aspects at: #startupCFile) value asFilename baseName).
command := ccPathAndFlags , ' -o main.o -c -O -O6 -fomit-frame-pointer -m486 -DDEBUG -Di386 ',
'-DSTARTUP_CLASS="\"', startUpClass, '\"" ',
'-DSTARTUP_SELECTOR="\"', startUpSelector, '\"" ',
'-DCONFIGURATION_STRING="\"', (Aspects at: #configuration) value, '\"" ',
'-DBUILD_DATE="\"', (Aspects at: #buildDate) value, '\"" ',
startupFile name.
self executeCommand: command inDirectory: dir
!
compileStartupFileWith: ccPathAndFlags inDirectory: dir
"compiles the startup file with passing startup class, startup selector, configuration string, and build date"
|startUpClass cls startUpSelector startupFile command|
startUpClass := ((Aspects at: #startupMessage) value upTo: $ ) asSymbol.
(cls := Smalltalk at: startUpClass) isNil ifTrue: [^self warn: 'Defined class not found in system!!'].
startUpSelector := ((Aspects at: #startupMessage) value copy reverse upTo: $ ) reverse asSymbol.
(cls respondsTo: startUpSelector) ifFalse: [^self warn: 'Defined class does not respond to the defined selector!!'].
startupFile := (Aspects at: #startupModule) value asFilename.
startupFile copyTo: (startupFile := dir asFilename construct: (Aspects at: #startupModule) value asFilename baseName).
command := ccPathAndFlags , ' -o main.o -c -O -O6 -fomit-frame-pointer -m486 -DDEBUG -Di386 ',
'-DSTARTUP_CLASS="\"', startUpClass, '\"" ',
'-DSTARTUP_SELECTOR="\"', startUpSelector, '\"" ',
'-DCONFIGURATION_STRING="\"', (Aspects at: #configuration) value, '\"" ',
'-DBUILD_DATE="\"', (Aspects at: #buildDate) value, '\"" ',
startupFile name.
self executeCommand: command inDirectory: dir
!
createSymbolicLinksToTheLibrariesIn: dir
"creates the symbolic links to the libraries"
self getLibraryFileNames value do:
[:libPath|
self executeCommand: 'ln -s ', libPath , ' ', libPath asFilename head inDirectory: dir
]
!
createSymbolicLinksToTheResourcesIn: dir
"creates the symbolic links to the resources"
(Aspects at: #linkRCFiles) value
ifTrue:
[
self executeCommand:
'ln -s ',
((Aspects at: #libraryDirectory) value asFilename construct: '*.rc') name, ' ',
(Aspects at: #targetDirectory) value inDirectory: dir.
].
(Aspects at: #linkResources) value
ifTrue:
[
self executeCommand:
'cp -r -d ',
((Aspects at: #libraryDirectory) value asFilename construct: 'resources') name, ' ',
(Aspects at: #targetDirectory) value inDirectory: dir.
].
(Aspects at: #linkSources) value
ifTrue:
[
self executeCommand:
'cp -r -d ',
((Aspects at: #libraryDirectory) value asFilename construct: 'source') name, ' ',
(Aspects at: #targetDirectory) value inDirectory: dir.
].
(Aspects at: #linkBitmaps) value
ifTrue:
[
self executeCommand:
'cp -r -d ',
((Aspects at: #libraryDirectory) value asFilename construct: 'bitmaps') name, ' ',
(Aspects at: #targetDirectory) value inDirectory: dir.
].
!
executeCommand: aCommand inDirectory: dir
"executes aCommand in directory dir; put aCommand and the result into the shell view"
|outStream|
shellView directory: dir.
shellView append: shellView getDirectoryTextString, ' ', aCommand.
outStream:= PipeStream readingFrom: aCommand errorDisposition:#inline inDirectory: dir.
[
outStream canReadWithoutBlocking
ifTrue:
[
outStream readWait.
shellView append: shellView getDirectoryTextString, ' ',
(Text string: (outStream upTo: Character cr) color: Color red).
].
] doWhile:[outStream atEnd not].
outStream close
!
generateCFileWithModulesIn: dir
"generates a C-file with the modules in directory dir"
|selectionOfLibraries|
selectionOfLibraries := self getModuleNames.
self executeCommand: 'echo "#include <stcIntern.h>" > modulList.c' inDirectory: dir.
self executeCommand: 'echo "typedef void (*vf)();" >> modulList.c' inDirectory: dir.
selectionOfLibraries do:
[:lib|
self executeCommand: 'echo "extern void _', lib, '_Init();" >> modulList.c' inDirectory: dir.
].
self executeCommand: 'echo "static vf modules[] = {" >> modulList.c' inDirectory: dir.
selectionOfLibraries do:
[:lib|
self executeCommand: 'echo "_', lib, '_Init," >> modulList.c' inDirectory: dir.
].
self executeCommand: 'echo "(vf)0};" >> modulList.c' inDirectory: dir.
self executeCommand: 'echo "vf *__modules__ = modules;" >> modulList.c' inDirectory: dir
!
generateHFileWithSymbolsIn: dir
"generates a H-file with the symbols in directory dir"
|symbolsFile realInc|
ByteCodeCompiler stcCompilationIncludes asArrayOfSubstrings do:
[:inc|
realInc := inc readStream.
realInc upTo: $/.
realInc := '/', realInc upToEnd.
(symbolsFile := realInc asFilename construct: 'symbols.stc') exists
ifTrue:
[
self executeCommand: 'echo "char *__symbols[] = {" > symbols.h' inDirectory: dir.
self executeCommand: 'sed ''s/^/"/'' < ', symbolsFile name,' | sed ''s/$/",/'' | sed ''s/\\/\\\\/g'' >> symbols.h' inDirectory: dir.
self executeCommand: 'echo "0 };" >> symbols.h' inDirectory: dir.
]
].
^nil
!
inform: aString
"outputs aString via shell view as information"
shellView commandInputField contents: aString
!
linkLibrariesToTheApplicationIn: dir
"links the libraries to the application"
|appName command|
appName := (Aspects at: #applicationName) value.
command := ByteCodeCompiler ccPath,
' ', (Aspects at: #applicationLinkDefines) value, ' ',
' -o ' , appName,
' modulList.o main.o ',
((Aspects at: #libraryDirectory) value asFilename construct: 'librun', ObjectFileLoader sharedLibraryExtension) name, ' ',
((self getLibraryFileNames, (Aspects at: #systemLibraries) value) asStringCollection asStringWith: $ ).
self executeCommand: command inDirectory: dir
! !
!ApplicationBuilder methodsFor:'change & update'!
update:something with:aParameter from:changedObject
"updates the combo boxes with the library names and the module names"
|library libraries|
(changedObject == (Aspects at: #stxLibrary))
ifTrue:
[
libraries := (Aspects at: #stxLibraries) value.
(Aspects at: #stxLibrary) value size = 0 ifTrue: [libraries remove: (Aspects at: #oldSTXLibrary) value ifAbsent: nil].
(Aspects at: #oldSTXLibrary) value: (library := (Aspects at: #stxLibrary) value).
(libraries includes: library) not &
library notEmpty
ifTrue:
[
libraries addFirst: library
]
].
(changedObject == (Aspects at: #systemLibrary))
ifTrue:
[
libraries := (Aspects at: #systemLibraries) value.
(Aspects at: #systemLibrary) value size = 0 ifTrue: [libraries remove: (Aspects at: #oldSystemLibrary) value ifAbsent: nil].
(Aspects at: #oldSystemLibrary) value: (library := (Aspects at: #systemLibrary) value).
(libraries includes: library) not &
library notEmpty
ifTrue:
[
libraries addFirst: library
]
].
(changedObject == (Aspects at: #userLibrary))
ifTrue:
[
libraries := (Aspects at: #userLibraries) value.
(Aspects at: #userLibrary) value size = 0 ifTrue: [libraries remove: (Aspects at: #oldUserLibrary) value ifAbsent: nil].
(Aspects at: #oldUserLibrary) value: (library := (Aspects at: #userLibrary) value).
(libraries includes: library) not &
library notEmpty
ifTrue:
[
libraries addFirst: library
]
].
! !
!ApplicationBuilder methodsFor:'initialization'!
initialize
"initialize all aspects"
|homeDir|
super initialize.
Aspects := Aspects ? IdentityDictionary new.
homeDir := Filename homeDirectory asFilename.
self aspectsAt: #applicationName putFirst: 'application'.
self aspectsAt: #startupMessage putFirst: 'Smalltalk start'.
self aspectsAt: #startupCFile putFirst: (homeDir construct: 'stx/librun/main.c') name.
self aspectsAt: #topDirectory putFirst: (homeDir construct: 'stx') name.
self aspectsAt: #targetDirectory putFirst: (homeDir construct: 'stx/projects/application') name.
self aspectsAt: #libraryDirectory putFirst: (homeDir construct: 'stx/projects/smalltalk') name.
self aspectsAt: #stxLibraries putFirst:
(ObjectMemory binaryModuleInfo collect: [:binMoInfo| (binMoInfo name copy reverse upTo: $ ) reverse]) asSortedCollection.
self aspectsAt: #systemLibraries putFirst: ObjectFileLoader searchedLibraries.
self aspectsAt: #userLibraries putFirst: OrderedCollection new.
Aspects at: #buildDate put: Date today printString, ' ', Time now printString.
self aspectsAt: #configuration putFirst: Smalltalk configuration.
self aspectsAt: #linkRCFiles putFirst: true.
self aspectsAt: #linkResources putFirst: true.
self aspectsAt: #linkSources putFirst: true.
self aspectsAt: #linkBitmaps putFirst: true.
(Aspects at: #stxLibrary put: ((Aspects at: #stxLibraries) value at: 1 ifAbsent: '') asValue) addDependent: self.
(Aspects at: #systemLibrary put: ((Aspects at: #systemLibraries) value at: 1 ifAbsent: '') asValue) addDependent: self.
(Aspects at: #userLibrary put: ((Aspects at: #userLibraries) value at: 1 ifAbsent: '') asValue) addDependent: self.
self aspectsAt: #oldSTXLibrary putFirst: (Aspects at: #stxLibrary) value.
self aspectsAt: #oldSystemLibrary putFirst: (Aspects at: #systemLibrary) value.
self aspectsAt: #oldUserLibrary putFirst: (Aspects at: #userLibrary) value.
self aspectsAt: #applicationLinkDefines putFirst: '-L/usr/X11/lib -Llib -Lbinary -L. -L/usr/local/lib -L/usr/lib -L/lib -lm -ldl -lXext -lX11'.
! !
!ApplicationBuilder methodsFor:'queries'!
getApplicationDirectory
"returns the directory of the application; if not present, create it"
|appDir|
(appDir := (Aspects at: #targetDirectory) value asFilename) exists ifFalse:[appDir makeDirectory].
(appDir isReadable and:[appDir isWritable]) ifFalse: [^nil].
^appDir name
!
getCompilerFlags
"returns the defines of the OS and the compiler flags of the ByteCodeCompiler"
|compilerFlags|
compilerFlags := OperatingSystem getOSDefine ? ''.
ByteCodeCompiler stcCompilationDefines notNil
ifTrue:[compilerFlags := compilerFlags , ' ' , ByteCodeCompiler stcCompilationDefines].
ByteCodeCompiler stcCompilationIncludes notNil
ifTrue:[compilerFlags := compilerFlags , ' ' , ByteCodeCompiler stcCompilationIncludes].
ByteCodeCompiler ccCompilationOptions notNil
ifTrue:[compilerFlags := compilerFlags , ' ' , ByteCodeCompiler ccCompilationOptions].
^compilerFlags
!
getLibraryFileNames
"returns the complete file names of the system and the user libraries"
|libraryFileNames|
libraryFileNames := OrderedCollection new.
(Aspects at: #stxLibraries) value do:
[:lib|
|abbrevLib libPath|
abbrevLib := lib.
lib = 'GLXWorkstation' ifTrue: [abbrevLib := 'GLXWorkstat'].
lib = 'XWorkstation' ifTrue: [abbrevLib := 'XWorkstat' ].
lib = 'ObjectFileLoader' ifTrue: [abbrevLib := 'ObjFLoader' ].
(libPath := (Aspects at: #libraryDirectory) value asFilename construct: abbrevLib, ObjectFileLoader sharedLibraryExtension) exists
ifTrue: [libraryFileNames add: libPath name]
].
^libraryFileNames, (Aspects at: #userLibraries) value
!
getModuleNames
"returns the module names of the system and the user libraries"
|moduleNames|
moduleNames := OrderedCollection new.
(Aspects at: #userLibraries) value do:
[:lib|
lib asFilename exists ifTrue: [moduleNames add: (lib asFilename baseName upTo: $.)]
].
^(Aspects at: #stxLibraries) value, moduleNames
! !
!ApplicationBuilder methodsFor:'startup / release'!
closeRequest
"close request; before closing stop the running build, then release the dependents of all aspects"
self doStop.
Aspects do: [:aspect| aspect release].
super closeRequest
! !
!ApplicationBuilder class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libtool/ApplicationBuilder.st,v 1.1 1998-03-31 18:22:48 tz Exp $'
! !