ProjectBuilder.st
author Claus Gittinger <cg@exept.de>
Tue, 28 Jan 2014 21:48:47 +0100
changeset 3072 117522ff72bc
parent 3043 457d1202c86b
child 3127 f28722d20fbb
permissions -rw-r--r--
class: Tools::ProjectBuilder
changed: #makeWithOutputTo:errorTo:
     1 "
     2  COPYRIGHT (c) 2009 by eXept Software AG
     3               All Rights Reserved
     4 
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    11 "
    12 "{ Package: 'stx:libtool2' }"
    13 
    14 "{ NameSpace: Tools }"
    15 
    16 Object subclass:#ProjectBuilder
    17 	instanceVariableNames:'package projectDefinitionClass sourceCodeManager buildDirectory
    18 		myWorkingDirectory mySTXTopDirectory myTopDirectory outputStream
    19 		makeExeOnly makeQuick usedCompiler stdOut stdErr isQuickBuild
    20 		isLocalBuild'
    21 	classVariableNames:'PreviousBuildDirectory'
    22 	poolDictionaries:''
    23 	category:'System-Support-Projects'
    24 !
    25 
    26 !ProjectBuilder class methodsFor:'documentation'!
    27 
    28 copyright
    29 "
    30  COPYRIGHT (c) 2009 by eXept Software AG
    31               All Rights Reserved
    32 
    33  This software is furnished under a license and may be used
    34  only in accordance with the terms of that license and with the
    35  inclusion of the above copyright notice.   This software may not
    36  be provided or otherwise made available to, or used by, any
    37  other person.  No title to or ownership of the software is
    38  hereby transferred.
    39 "
    40 ! !
    41 
    42 !ProjectBuilder class methodsFor:'accessing'!
    43 
    44 previousBuildDirectory
    45     ^ PreviousBuildDirectory
    46 !
    47 
    48 previousBuildDirectory:something
    49     PreviousBuildDirectory := something.
    50 ! !
    51 
    52 !ProjectBuilder class methodsFor:'examples'!
    53 
    54 example1
    55     Smalltalk loadPackage:'stx:projects/helloWorldApp' asAutoloaded:true.
    56 
    57     self new
    58         package:'stx:projects/helloWorldApp';
    59         build
    60 !
    61 
    62 example2
    63     |builder|
    64 
    65     Smalltalk loadPackage:'stx:clients/Demos/foxCalcApplication' asAutoloaded:true.
    66 
    67     builder := self new.
    68     builder 
    69         package:'stx:clients/Demos/foxCalcApplication';
    70         build.
    71 
    72     UserPreferences fileBrowserClass openOnDirectory:builder packageBuildDirectory.
    73 
    74     "Modified: / 03-09-2012 / 19:23:53 / cg"
    75 ! !
    76 
    77 !ProjectBuilder class methodsFor:'queries'!
    78 
    79 defaultUsedCompiler
    80     |compiler|
    81 
    82     (compiler := UserPreferences current usedCompilerForBuild) notNil ifTrue:[
    83         ^ compiler
    84     ].
    85 
    86     ^ ParserFlags usedCompiler
    87 !
    88 
    89 listOfPossibleCompilers
    90     OperatingSystem isMSWINDOWSlike ifTrue:[
    91         OperatingSystem getLoginName = 'cg' ifTrue:[
    92             ^ #(
    93                 'bcc'   "/ OK
    94                 'vc'    "/ almost OK
    95                 'lcc'   "/ experimental, but only free for non-commercial work
    96                 'tcc'   "/ experimental; limited but free
    97                 'mingw' "/ experimental; free
    98              )
    99         ].
   100         ^ #('bcc' 'vc' 'mingw' )
   101     ].
   102     ^ #('gcc')
   103 
   104     "Created: / 21-01-2012 / 14:04:15 / cg"
   105 !
   106 
   107 suiteNameOfCompiler:usedCompiler
   108     usedCompiler = 'bcc' ifTrue:[
   109         ^ 'Borland C-Compiler'.
   110     ].
   111     usedCompiler = 'vc' ifTrue:[
   112         ^ 'Microsoft Visual C Compiler'.
   113     ].
   114     usedCompiler = 'lcc' ifTrue:[
   115         ^ 'LCC C-Compiler'.
   116     ].
   117     usedCompiler = 'tcc' ifTrue:[
   118         ^ 'Tiny C-Compiler'.
   119     ].
   120     usedCompiler = 'gcc' ifTrue:[
   121         ^ 'GNU C-Compiler'.
   122     ].
   123     usedCompiler = 'mingw' ifTrue:[
   124         ^ 'MINGW GNU C-Compiler'.
   125     ].
   126     self halt:'unknown compiler'.
   127 
   128     ^ 'C-Compiler'.
   129 
   130     "Created: / 06-09-2012 / 15:58:33 / cg"
   131 ! !
   132 
   133 !ProjectBuilder methodsFor:'accessing'!
   134 
   135 buildDirectory
   136     ^ buildDirectory
   137 !
   138 
   139 buildDirectory:something
   140     buildDirectory := something.
   141 !
   142 
   143 isLocalBuild
   144     ^ isLocalBuild ? false
   145 !
   146 
   147 isLocalBuild:aBoolean
   148     "create a files without going through the source code manager"
   149 
   150     isLocalBuild := aBoolean.
   151 !
   152 
   153 isQuickBuild
   154     ^ isQuickBuild ? false
   155 !
   156 
   157 isQuickBuild:aBoolean
   158     "skips creation of header files, and copying of support files, if possible
   159      to speedup a build. Use with care."
   160 
   161     isQuickBuild := aBoolean.
   162 !
   163 
   164 makeExeOnly
   165     ^ (makeExeOnly ? false)
   166 !
   167 
   168 makeExeOnly:aBoolean
   169     makeExeOnly := aBoolean.
   170 !
   171 
   172 makeQuick
   173     ^ (makeQuick ? false)
   174 !
   175 
   176 makeQuick:aBoolean
   177     makeQuick := aBoolean.
   178 !
   179 
   180 package:aPackageIDOrSymbol
   181     package := aPackageIDOrSymbol asPackageId.
   182 !
   183 
   184 packageBuildDirectory
   185     "the directoray, where the deployable binary is created (xxxSetup.exe)"
   186 
   187     ^ buildDirectory / (package asPackageId module) / (package asPackageId directory)
   188 !
   189 
   190 projectDefinitionClass:something
   191     projectDefinitionClass := something.
   192 !
   193 
   194 suffixForHeaderFiles
   195     ^ OperatingSystem isUNIXlike ifTrue:['.H'] ifFalse:['.STH']
   196 !
   197 
   198 usedCompilerForBuild:something
   199     usedCompiler := something.
   200 
   201     "Created: / 22-01-2012 / 10:50:48 / cg"
   202 ! !
   203 
   204 !ProjectBuilder methodsFor:'building'!
   205 
   206 build
   207     "/ intermediate - this will move into a commonly used utility class
   208     "/ (where all the project code support will be collected).
   209 
   210     |makeOutput|
   211 
   212     makeOutput := TextStream on:(Text new:10000).
   213     self buildWithColorizedOutputTo:makeOutput.
   214 
   215     TextView openWith:makeOutput contents.
   216 !
   217 
   218 buildWithColorizedOutputTo:makeOutput
   219     "/ intermediate - this will move into a commonly used utility class
   220     "/ (where all the project code support will be collected).
   221 
   222     |lock|
   223 
   224     lock := Semaphore forMutualExclusion.
   225 
   226     stdErr := ActorStream new
   227                     nextPutBlock:[:char |
   228                         lock critical:[
   229                             makeOutput 
   230                                 withEmphasis:{#backgroundColor->Color red. #color->Color white.}
   231                                 do:[makeOutput nextPut:char].
   232                         ]
   233                     ];
   234                     nextPutAllBlock:[:string |
   235                         lock critical:[          
   236                             makeOutput
   237                                 withEmphasis:{#backgroundColor->Color red. #color->Color white.}
   238                                 do:[makeOutput nextPutAll:string].
   239                         ]
   240                     ].
   241     stdOut := ActorStream new
   242                     nextPutBlock:[:char |
   243                         lock critical:[
   244                             makeOutput nextPut:char.
   245                         ]
   246                     ];
   247                     nextPutAllBlock:[:string |
   248                         lock critical:[         
   249                             makeOutput nextPutAll:string.
   250                         ]
   251                     ].
   252 
   253     self buildWithOutputTo:stdOut errorTo:stdErr.
   254 
   255     "Modified: / 06-09-2012 / 16:15:50 / cg"
   256 !
   257 
   258 buildWithOutputTo:stdOutArg errorTo:stdErrArg
   259     "/ intermediate - this will move into a commonly used utility class
   260     "/ (where all the project code support will be collected).
   261 
   262     |module directory|
   263 
   264     projectDefinitionClass := ProjectDefinition definitionClassForPackage:package.
   265     projectDefinitionClass isNil ifTrue:[
   266         self error:('Missing ProjectDefinition class for "',package asString,'"')
   267     ].
   268 
   269     "/ ensure that everything is loaded...
   270     projectDefinitionClass loadAsAutoloaded:false.
   271     projectDefinitionClass loadExtensions.
   272     projectDefinitionClass loadAllClassesAsAutoloaded:false.
   273 
   274     module := package module.
   275     directory := package directory.
   276 
   277     buildDirectory isNil ifTrue:[
   278         buildDirectory := PreviousBuildDirectory ifNil:[ UserPreferences current buildDirectory ].
   279         buildDirectory isNil ifTrue:[
   280             buildDirectory := Filename tempDirectory construct:'stx_build'.
   281         ].
   282     ].
   283     buildDirectory := buildDirectory asFilename.
   284 
   285     "/ self validateBuildDirectoryIsPresent.
   286 
   287     PreviousBuildDirectory := buildDirectory.
   288 
   289     "/ UserPreferences current localBuild:true
   290     (self isLocalBuild or:[UserPreferences current localBuild]) ifFalse:[
   291         SourceCodeManager notNil ifTrue:[
   292             sourceCodeManager := SourceCodeManagerUtilities sourceCodeManagerFor:projectDefinitionClass.
   293         ]
   294     ].
   295     sourceCodeManager := nil.
   296 
   297     myTopDirectory := 
   298         Smalltalk packagePath 
   299             detect:[:aPath |
   300                 (aPath asFilename / 'stx' / 'include') exists
   301                 and: [ (aPath asFilename / 'stx' / 'rules') exists ]]
   302             ifNone:nil.       
   303     myTopDirectory isNil ifTrue:[
   304         self error:('Cannot figure out my top directory (where stx/include and stx/rules are)')
   305     ].
   306     myTopDirectory := myTopDirectory asFilename.
   307     mySTXTopDirectory := myTopDirectory / 'stx'.
   308 
   309     self makeQuick ifFalse:[
   310         self setupBuildDirectory.
   311         self activityNotification:'Generating stc directory...'.
   312         self copySTCDirectoryForBuild.
   313     ].
   314     self activityNotification:'Generating source files...'.
   315     self generateSourceFiles.
   316     self makeQuick ifFalse:[
   317         self activityNotification:'Copying dlls for linkage...'.
   318         self copyDLLsForLinkage.
   319         self activityNotification:'Copying support files for compilation and linkage...'.
   320         self copySupportFilesForCompilation.
   321         self copySupportFilesForLinkage.
   322         self copyStartupFilesFromSmalltalk.
   323     ].
   324     self activityNotification:'Executing make...'.
   325     self makeWithOutputTo:stdOut errorTo:stdErr.
   326 
   327     "Modified: / 04-09-2012 / 00:49:52 / cg"
   328 ! !
   329 
   330 !ProjectBuilder methodsFor:'building/private'!
   331 
   332 copyDLLsForLinkage
   333     |targetBuildDir preRequisites dllRelativeSourcePathes dllRelativeDestPathes|
   334 
   335     targetBuildDir := buildDirectory / package module / package directory.
   336 
   337     preRequisites := projectDefinitionClass allPreRequisites.
   338     OperatingSystem isUNIXlike ifTrue:[
   339         "For now: unix Makefiles require some libs implicitely..."
   340         preRequisites := preRequisites union:#(
   341                                #'stx:goodies/refactoryBrowser/parser'
   342                                #'stx:libtool'
   343                             ).
   344     ].
   345 
   346     preRequisites do:[:eachPackageToFileout |
   347         |packageId packageDef packageModule packageDirectory packageTargetDir
   348          dllSource dllSourceDir libraryName dllRelativePathSource 
   349          dllRelativePathDest objDirSource objDirDest alternativeObjDirSource|
   350 
   351         packageId := eachPackageToFileout asPackageId.
   352         packageModule := packageId module.
   353         packageDirectory := packageId directory.
   354         packageTargetDir := (buildDirectory / packageModule / packageDirectory) recursiveMakeDirectory.
   355 
   356         packageDef := packageId projectDefinitionClass.
   357         libraryName := packageDef libraryName.
   358 
   359         "/ mhmh - take them from my tree or from the projects/smalltalk execution directory ??
   360         dllSourceDir := myTopDirectory / packageModule / packageDirectory.
   361 
   362         OperatingSystem isMSWINDOWSlike ifTrue:[
   363             objDirDest := self objDirForUsedCompiler:usedCompiler.
   364             objDirSource := objDirDest.
   365 "/            "/ use visual-c files for tcc linkage
   366 "/            usedCompiler = 'tcc' ifTrue:[
   367 "/                objDirSource := self objDirForUsedCompiler:'vc'.
   368 "/            ] ifFalse:[
   369 "/                objDirSource := objDirDest
   370 "/            ].
   371             (dllSourceDir / objDirSource / (libraryName, '.dll')) exists ifFalse:[
   372                 alternativeObjDirSource := self objDirForUsedCompiler:'vc'.
   373                 (dllSourceDir / alternativeObjDirSource / (libraryName, '.dll')) exists ifTrue:[
   374                     objDirSource := alternativeObjDirSource.
   375                     stdErr nextPutLine:(('Warning: using alternative %1 from %2 (%3 version)...' 
   376                                                 bindWith:libraryName 
   377                                                 with:alternativeObjDirSource 
   378                                                 with:(self class suiteNameOfCompiler:'vc'))
   379                                             emphasizeAllWith:(#color -> Color red darkened)).
   380                 ] ifFalse:[
   381                     alternativeObjDirSource := self objDirForUsedCompiler:'bcc'.
   382                     (dllSourceDir / alternativeObjDirSource / (libraryName, '.dll')) exists ifTrue:[
   383                         objDirSource := alternativeObjDirSource.
   384                         stdErr nextPutLine:('Warning: using alternative %1 from %2 (%3 version)...' 
   385                                     bindWith:libraryName 
   386                                     with:alternativeObjDirSource 
   387                                     with:(self class suiteNameOfCompiler:'bcc')).
   388                     ]
   389                 ].
   390             ].
   391 
   392 "/            dllRelativePath := objDir,'/',(libraryName,'.dll').
   393 "/            (dllSourceDir / dllRelativePath) exists 
   394             dllRelativeSourcePathes := Array with:(objDirSource,'\', libraryName, '.dll').
   395             dllRelativeDestPathes := Array with:(objDirDest,'\', libraryName, '.dll').
   396         ] ifFalse:[
   397             dllRelativeSourcePathes := Array with:(libraryName,'.so').
   398             dllRelativeDestPathes := Array with:(libraryName, '.so').
   399             (packageModule = 'stx' and:[packageDirectory = 'libview']) ifTrue:[
   400                 dllRelativeSourcePathes := dllRelativeSourcePathes copyWith:('XWorkstation.so').
   401                 dllRelativeDestPathes := dllRelativeDestPathes copyWith:'XWorkstation.so'.
   402                 dllRelativeSourcePathes := dllRelativeSourcePathes copyWith:('GLXWorkstation.so').
   403                 dllRelativeDestPathes := dllRelativeDestPathes copyWith:'GLXWorkstation.so'.
   404             ].
   405         ].
   406         dllRelativeSourcePathes with:dllRelativeDestPathes do:[:dllRelativeSourcePath :dllRelativeDestPath|
   407             |source dest|
   408 
   409             source := dllSourceDir / dllRelativeSourcePath.
   410             source exists ifFalse:[
   411                 self activityNotification:'   skip missing file: ',source pathName.
   412             ] ifTrue:[
   413                 dest := packageTargetDir / dllRelativeDestPath.
   414                 (dest exists not
   415                  or:[source fileSize ~= dest fileSize
   416                  or:[source modificationTime >= dest modificationTime
   417                  "/ or:[ ((dllSourceDir / dllRelativePath) sameContentsAs:(packageTargetDir / dllRelativePath)) not ]
   418                 ]]) ifTrue:[
   419                     Transcript showCR:'updating ',dllRelativeDestPath.
   420                     dest directory recursiveMakeDirectory.
   421                     source copyTo:dest.    
   422                     self activityNotification:'    ',dest pathName
   423                 ] ifFalse:[
   424                     Transcript showCR:'already up-to-date: ',dllRelativeDestPath.
   425                 ]
   426             ]
   427         ].
   428     ].
   429 
   430     "Modified: / 06-09-2012 / 16:19:29 / cg"
   431 !
   432 
   433 copyDirectory:relativepath
   434     "/ need rules in stx
   435     ((Smalltalk projectDirectoryForPackage:'stx') asFilename construct:relativepath)
   436         recursiveCopyTo:(buildDirectory construct:'stx').
   437 !
   438 
   439 copyDirectoryForBuild:subdir
   440     |targetDir targetFile|
   441 
   442     targetDir := buildDirectory / 'stx' / subdir.
   443     targetDir exists ifFalse:[
   444         targetDir makeDirectory.
   445     ] ifTrue:[
   446         self isQuickBuild ifTrue:[^ self]
   447     ].
   448     (mySTXTopDirectory / subdir) directoryContentsAsFilenamesDo:[:eachFile |
   449         eachFile isDirectory ifFalse:[
   450             targetFile := targetDir / eachFile baseName.
   451             (targetFile exists not
   452             or:[ targetFile modificationTime < eachFile modificationTime ]) ifTrue:[
   453                 self activityNotification:'copying ',eachFile pathName,'...'.
   454                 eachFile copyTo:(targetDir construct:eachFile baseName)
   455             ]
   456         ].
   457     ].
   458     self activityNotification:nil
   459 !
   460 
   461 copyResourcesForPackage:aPackage
   462     |module directory myPackageDirectory rsrcDir stylesDir|
   463 
   464     module := aPackage asPackageId module.
   465     directory := aPackage asPackageId directory.
   466 
   467     myPackageDirectory := myTopDirectory / module / directory.
   468 
   469     (rsrcDir := myPackageDirectory / 'resources' ) exists ifTrue:[
   470         rsrcDir recursiveCopyTo:(buildDirectory / module / directory)
   471     ].
   472     (stylesDir := myPackageDirectory / 'styles' ) exists ifTrue:[
   473         stylesDir recursiveCopyTo:(buildDirectory / module / directory)
   474     ].
   475 !
   476 
   477 copySTCDirectoryForBuild
   478     "copy stc files to the build directory"
   479 
   480     |targetDir stc files|
   481 
   482     targetDir := buildDirectory / 'stx' / 'stc'.
   483     targetDir exists ifFalse:[ targetDir makeDirectory ].
   484 
   485     stc := OperatingSystem isMSWINDOWSlike 
   486                 ifTrue:[ 'stc.exe' ]
   487                 ifFalse:[ 'stc' ].
   488 
   489     files := #( ) copyWith:stc.
   490 
   491     files do:[:eachFile |
   492         |sourceFile targetFile|
   493 
   494         sourceFile := mySTXTopDirectory / 'stc' / eachFile.
   495         targetFile := targetDir / eachFile.
   496         (targetFile exists not
   497         or:[ targetFile modificationTime < sourceFile modificationTime ]) ifTrue:[
   498             self activityNotification:'copying ',sourceFile pathName,'...'.
   499             sourceFile copyTo:targetFile
   500         ].
   501     ].
   502 
   503     OperatingSystem isUNIXlike ifTrue:[
   504         (targetDir / 'stc') makeExecutableForAll    
   505     ].
   506 
   507     self activityNotification:nil
   508 
   509     "Modified (comment): / 04-09-2012 / 00:49:19 / cg"
   510 !
   511 
   512 copyStartupFilesFromSmalltalk
   513     "copy additional smalltalk startup files to the build directory"
   514 
   515     (buildDirectory / 'stx' / 'projects/smalltalk' ) exists ifFalse:[
   516         (buildDirectory / 'stx' / 'projects/smalltalk' ) recursiveMakeDirectory.
   517     ].
   518 
   519     #( 
   520         'keyboard.rc' 
   521         'keyboardMacros.rc' 
   522         'display.rc' 
   523         'd_win32.rc'
   524         'host.rc' 
   525         'h_win32.rc'  
   526         'smalltalk.rc'  
   527         'private.rc'  
   528     ) do:[:fn |
   529         (myTopDirectory / 'stx' / 'projects/smalltalk' / fn)
   530             copyTo: (buildDirectory / 'stx' / 'projects/smalltalk' / fn)
   531     ].
   532 
   533     (myTopDirectory / 'stx' / 'doc/online/english/LICENCE_STX.html')
   534             copyTo: (buildDirectory / 'stx' / 'projects/smalltalk' / 'LICENCE_STX.html').
   535 
   536     "Modified (comment): / 04-09-2012 / 00:48:47 / cg"
   537 !
   538 
   539 copySupportFilesForCompilation
   540     "copy the tcc compiler to the build directory"
   541 
   542     |files|
   543 
   544     files := #().
   545 
   546     OperatingSystem isMSWINDOWSlike ifTrue:[
   547         files := files , #( 
   548                         'librun/genDate.com' 
   549                     ).
   550         usedCompiler = 'tcc' ifTrue:[
   551             files := files , #( 
   552                         'support/tcc'
   553                     ).
   554         ].
   555     ] ifFalse:[
   556         files := files , #( 
   557                         "/ 'librun/genDate'   -- not needed on unix (done via script)
   558                         'configurations/myConf' 
   559                         'configurations/vendorConf' 
   560                         'configurations/conf.inc' 
   561                         'configurations/COMMON' 
   562                     ).
   563     ].
   564 
   565     files do:[:relativePath |
   566         (mySTXTopDirectory / relativePath) exists ifTrue:[
   567             ((buildDirectory / 'stx' / relativePath) exists
   568             and:[ (mySTXTopDirectory / relativePath) fileSize = (buildDirectory / 'stx' / relativePath) fileSize
   569             and:[ (mySTXTopDirectory / relativePath) modificationTime < (buildDirectory / 'stx' / relativePath) modificationTime
   570             "/ and:[ (mySTXTopDirectory / dllRelativePath) sameContentsAs:(targetBuildDir / dllRelativePath) ]
   571             ]]) ifFalse:[
   572                 (buildDirectory / 'stx' / relativePath) directory recursiveMakeDirectory.    
   573                 (mySTXTopDirectory / relativePath) isDirectory ifTrue:[
   574                     (mySTXTopDirectory / relativePath) recursiveCopyTo:(buildDirectory / 'stx' / relativePath) directory.    
   575                 ] ifFalse:[
   576                     (mySTXTopDirectory / relativePath) copyTo:(buildDirectory / 'stx' / relativePath) directory.    
   577                 ]
   578             ]
   579         ] ifFalse:[
   580             self error:'Missing file or directory: ',relativePath printString mayProceed:true.
   581         ].
   582     ].
   583 
   584     "Created: / 04-09-2012 / 00:47:49 / cg"
   585 !
   586 
   587 copySupportFilesForLinkage
   588     "copy additional files which are req'd for linkage to the build directory"
   589 
   590     |files|
   591 
   592     OperatingSystem isMSWINDOWSlike ifTrue:[
   593         files := #( 
   594                     'librun/genDate.com'
   595                     'librun/main.c'
   596                     'projects/smalltalk/stx_16x16.ico'
   597                     'projects/smalltalk/stx_32x32.ico'
   598                     'projects/smalltalk/stx_splash.bmp'
   599                  ).
   600 
   601         usedCompiler = 'bcc' ifTrue:[
   602             files := files , #( 
   603                         'librun/objbc/librun.dll'
   604                         'support/win32/borland/cs3245.dll' 
   605                         'support/win32/X11.dll'
   606                         'support/win32/Xext.dll'
   607                         'lib/bc/librun.lib'
   608                         'lib/bc/cs32i.lib'
   609                     ).
   610         ].
   611         usedCompiler = 'vc' ifTrue:[
   612             files := files , #( 
   613                         'librun/objvc/librun.dll'
   614                         'lib/vc/librun.lib'
   615                     ).
   616         ].
   617         usedCompiler = 'tcc' ifTrue:[
   618             files := files , #( 
   619                         'librun/objvc/librun.dll'   "/ linkage is against vc version!!
   620                         'lib/vc/librun.lib'
   621                     ).
   622         ].
   623         usedCompiler = 'lcc' ifTrue:[
   624             files := files , #( 
   625                         'librun/objvc/librun.dll'   "/ linkage is against vc version!!
   626                         'lib/vc/librun.lib'
   627                     ).
   628         ].
   629         usedCompiler = 'mingw' ifTrue:[
   630             files := files , #( 
   631                         'librun/objmingw/librun.dll'   "/ linkage is against vc version!!
   632                         'lib/mingw/librun.lib'
   633                     ).
   634         ].
   635     ] ifFalse:[
   636         files := #(
   637                     'librun/main.c'
   638                     'librun/librun.so'
   639                 )
   640     ].
   641     files := files asOrderedCollection.
   642 
   643     OperatingSystem isMSWINDOWSlike ifTrue:[
   644         projectDefinitionClass applicationIconFileName notNil ifTrue:[
   645             files add:('projects/smalltalk/',projectDefinitionClass applicationIconFileName,'.ico')
   646         ].
   647         projectDefinitionClass splashFileName notNil ifTrue:[
   648             files add:('projects/smalltalk/',projectDefinitionClass splashFileName,'.bmp')
   649         ].
   650     ].
   651 
   652     files do:[:relativePath |
   653         (mySTXTopDirectory / relativePath) exists ifTrue:[
   654             ((buildDirectory / 'stx' / relativePath) exists
   655             and:[ (mySTXTopDirectory / relativePath) fileSize = (buildDirectory / 'stx' / relativePath) fileSize
   656             and:[ (mySTXTopDirectory / relativePath) modificationTime < (buildDirectory / 'stx' / relativePath) modificationTime
   657             "/ and:[ (mySTXTopDirectory / dllRelativePath) sameContentsAs:(targetBuildDir / dllRelativePath) ]
   658             ]]) ifFalse:[
   659                 (buildDirectory / 'stx' / relativePath) directory recursiveMakeDirectory.
   660                 (mySTXTopDirectory / relativePath) copyTo:(buildDirectory / 'stx' / relativePath).    
   661             ]
   662         ] ifFalse:[
   663 "/ does not really help: objbc/librun.lib does not work with MSVC and vice versa...
   664 "/            ((relativePath = 'librun/objvc/librun.dll')
   665 "/            and:[ (mySTXTopDirectory / 'librun/objbc/librun.dll') exists ])ifTrue:[
   666 "/                stdErr nextPutLine:('Warning: using alternative librun from objbc (Borland version)...'). 
   667 "/                (buildDirectory / 'stx' / relativePath) directory recursiveMakeDirectory.
   668 "/                (mySTXTopDirectory / 'librun/objbc/librun.dll') copyTo:(buildDirectory / 'stx' / relativePath).    
   669 "/            ] ifFalse:[
   670 "/                ((relativePath = 'librun/objbc/librun.dll')
   671 "/                and:[ (mySTXTopDirectory / 'librun/objvc/librun.dll') exists ])ifTrue:[
   672 "/                    stdErr nextPutLine:('Warning: using alternative librun from objvc (MSVC version)...'). 
   673 "/                    (buildDirectory / 'stx' / relativePath) directory recursiveMakeDirectory.
   674 "/                    (mySTXTopDirectory / 'librun/objvc/librun.dll') copyTo:(buildDirectory / 'stx' / relativePath).    
   675 "/                ] ifFalse:[
   676                     self error:'Missing file: ',relativePath printString mayProceed:true.
   677 "/                ]
   678 "/            ]
   679         ].
   680     ].
   681 
   682     "Modified: / 05-09-2012 / 16:26:25 / cg"
   683 !
   684 
   685 createHeaderFileFor:aClass in:packageTargetDir
   686     |instVarList classInstVarList classVarList bindings superclassFilename
   687      template file newContents oldContents|
   688 
   689     instVarList := StringCollection new.
   690     aClass instVarNames do:[:v |
   691         instVarList add:('OBJ %1;' bindWith:v)
   692     ].
   693     classInstVarList := StringCollection new.
   694     aClass class instVarNames do:[:v |
   695     "/ (v includes:$_) ifTrue:[self halt].
   696         classInstVarList add:('OBJ %1;' bindWith:v)
   697     ].
   698     classVarList := StringCollection new.
   699     aClass classVarNames do:[:v |
   700         classVarList add:('extern OBJ %1_%2;' bindWith:aClass name with:v)
   701     ].
   702 
   703     bindings := Dictionary new.
   704     bindings at:'ClassName' put:aClass name. 
   705     aClass superclass isNil ifTrue:[
   706         bindings at:'SuperclassName' put:'-'. 
   707         bindings at:'SuperclassFileInclude' put:''.
   708     ] ifFalse:[
   709         bindings at:'SuperclassName' put:aClass superclass name. 
   710         bindings at:'SuperclassFileName' put:(superclassFilename := Smalltalk fileNameForClass:aClass superclass).
   711         bindings at:'SuperclassFileInclude' put:('#include "%1.STH"' bindWith:superclassFilename).
   712     ].
   713     bindings at:'InstVarList' put:instVarList asString. 
   714     bindings at:'ClassVarList' put:classVarList asString. 
   715     bindings at:'ClassInstVarList' put:classInstVarList asString. 
   716 
   717     template := 
   718 '/* This file was generated by ProjectBuilder. */
   719 /* !!!!!!!! Do not change by hand !!!!!!!! */
   720 
   721 /* Class: %(ClassName) */
   722 /* Superclass: %(SuperclassName) */
   723 
   724 %(SuperclassFileInclude)
   725 
   726 /* INDIRECTGLOBALS */
   727 #ifdef _HEADER_INST_
   728 %(InstVarList)
   729 #endif /* _HEADER_INST_ */
   730 
   731 #ifdef _HEADER_CLASS_
   732 %(ClassVarList)
   733 #endif /* _HEADER_CLASS_ */
   734 
   735 #ifdef _HEADER_CLASSINST_
   736 %(ClassInstVarList)
   737 #endif /* _HEADER_CLASSINST_ */
   738 '.
   739     newContents := template bindWithArguments:bindings.
   740     file := packageTargetDir asFilename / ((Smalltalk fileNameForClass:aClass),(self suffixForHeaderFiles)).
   741     (file exists not
   742     or:[ (oldContents := file contents) ~= newContents ]) ifTrue:[
   743         file contents: newContents.
   744     ].
   745 
   746     "Modified: / 15-08-2011 / 14:58:46 / cg"
   747 !
   748 
   749 generateBuildSupportFilesByFilingOutIn:packageTargetDir forDefinitionClass:projectDefinitionClass
   750     |fullPathName|
   751 
   752     projectDefinitionClass forEachFileNameAndGeneratedContentsDo:[:fileName :fileContents |
   753         fullPathName := packageTargetDir construct:fileName.
   754         fullPathName directory exists ifFalse:[
   755             "take care for files like 'autopackage/default.apspec'"
   756             fullPathName directory makeDirectory.
   757         ].
   758         (fullPathName exists
   759          and:[ fullPathName contents = fileContents ]) ifFalse:[
   760             fullPathName contents:fileContents.
   761         ].
   762     ].    
   763 !
   764 
   765 generateSourceFiles
   766     (self isLocalBuild not and:[ sourceCodeManager notNil ])  ifTrue:[
   767         "/ check out / generate files there
   768         self generateSourceFilesByCheckingOutUsing:sourceCodeManager
   769     ] ifFalse:[
   770         "/ local build
   771         "/ fileout the project
   772         self generateSourceFilesByFilingOut
   773     ]
   774 !
   775 
   776 generateSourceFilesByCheckingOutUsing:aSourceCodeManager
   777     "/ will no longer be needed/supported
   778 
   779     |repository stxRepository module directory|
   780 
   781     self breakPoint:#cg.
   782 
   783     "/ check out / generate files there
   784     repository := (aSourceCodeManager repositoryNameForModule:module) ifNil:[aSourceCodeManager repositoryName].
   785     stxRepository := aSourceCodeManager repositoryName.
   786 
   787     (buildDirectory construct:'stx') exists ifFalse:[
   788         (module ~= 'stx') ifTrue:[
   789             OperatingSystem
   790                 executeCommand:('cvs -d ',stxRepository,' co stx')
   791                 inputFrom:nil
   792                 outputTo:Transcript
   793                 errorTo:Transcript
   794                 inDirectory:buildDirectory
   795                 onError:[:status| self error:'cvs update stx failed'].
   796         ].
   797     ].
   798 
   799     ((buildDirectory construct:module) construct:'CVS') exists ifFalse:[
   800         OperatingSystem
   801             executeCommand:('cvs -d ',repository,' co -l ',directory)
   802             inputFrom:nil
   803             outputTo:Transcript
   804             errorTo:Transcript
   805             inDirectory:buildDirectory
   806             onError:[:status| self error:'cvs update failed'].
   807     ].
   808     OperatingSystem
   809         executeCommand:'cvs upd -d'
   810         inputFrom:nil
   811         outputTo:Transcript
   812         errorTo:Transcript
   813         inDirectory:(buildDirectory construct:module)
   814         onError:[:status| self error:'cvs update failed'].
   815 self halt.
   816 
   817     "Modified: / 29-12-2011 / 14:02:56 / cg"
   818 !
   819 
   820 generateSourceFilesByFilingOut
   821     "/ local build
   822     "/ fileout the project
   823 
   824     (package module ~= 'stx') ifTrue:[
   825         (buildDirectory / package module) makeDirectory.
   826     ].
   827 
   828     "/ file out the package(s) which are to be built
   829     ((Array with:package))
   830     do:[:eachPackageToFileout |
   831         |packageId packageModule packageDirectory packageTargetDir packageDef extSource|
   832 
   833         packageId := eachPackageToFileout asPackageId.
   834         packageModule := packageId module.
   835         packageDirectory := packageId directory.
   836         packageTargetDir := (buildDirectory / packageModule / packageDirectory) recursiveMakeDirectory.
   837 
   838         packageDef := packageId projectDefinitionClass.
   839         (packageDef compiled_classNames_common ,
   840         packageDef compiled_classNamesForPlatform) do:[:eachClassName |
   841             |cls fileName newSource|
   842 
   843             cls := Smalltalk classNamed:eachClassName.
   844             self assert:cls isLoaded.
   845             fileName := (Smalltalk fileNameForClass:cls),'.st'.
   846             fileName := packageTargetDir asFilename construct:fileName.
   847             fileName exists ifTrue:[
   848                 newSource := String streamContents:[:s | cls fileOutOn:s withTimeStamp:false].
   849                 newSource = fileName contentsAsString ifFalse:[
   850                     fileName contents:newSource
   851                 ].
   852             ] ifFalse:[
   853                 cls fileOutIn:packageTargetDir withTimeStamp:false
   854             ].
   855         ].
   856 
   857         packageDef hasExtensionMethods ifTrue:[
   858             extSource := 
   859                 String streamContents:[:s |
   860                     s nextPutAll:('"{ Package: ''%1'' }" !!\\' bindWith:packageDef package) withCRs.
   861 
   862                     packageDef extensionMethods do:[:eachMethod |
   863                         eachMethod mclass fileOutMethod:eachMethod on:s
   864                     ].
   865                 ].
   866             extSource isWideString ifTrue:[
   867                 extSource := ( '"{ Encoding: utf8 }"' , Character cr asString, Character cr asString, extSource).
   868                 extSource := extSource utf8Encoded.
   869             ].
   870             (packageTargetDir asFilename construct:'extensions.st') contents:extSource
   871         ].
   872 
   873 "/        (Smalltalk allClassesInPackage:eachPackageToFileout) do:[:cls |
   874 "/            cls isPrivate ifFalse:[
   875 "/                cls isLoaded ifFalse:[
   876 "/                    self halt.
   877 "/                    cls autoload.
   878 "/                ].
   879 "/                cls fileOutIn:packageTargetDir
   880 "/            ]
   881 "/        ].
   882         self generateBuildSupportFilesByFilingOutIn:packageTargetDir forDefinitionClass:projectDefinitionClass.
   883     ].
   884     self makeQuick ifFalse:[
   885         "/ generate header files and build support files
   886         "/ in prerequisite packages...
   887         (projectDefinitionClass allPreRequisites)
   888         do:[:eachPackageToFileout |
   889             |packageId packageDef packageModule packageDirectory packageTargetDir|
   890 
   891             packageId := eachPackageToFileout asPackageId.
   892             packageModule := packageId module.
   893             packageDirectory := packageId directory.
   894             packageTargetDir := (buildDirectory / packageModule / packageDirectory) recursiveMakeDirectory.
   895 
   896             packageDef := packageId projectDefinitionClass.
   897             (packageDef compiled_classNames_common ,
   898             packageDef compiled_classNamesForPlatform) do:[:eachClassName |
   899                 |cls|
   900 
   901                 cls := Smalltalk classNamed:eachClassName.
   902                 "/ self assert:cls isLoaded.
   903                 cls isNil ifTrue:[
   904                     stdErr nextPutLine:('Missing class: ',eachClassName, ' (not present in system. Warning only:subclasses of it will not be compiled)').
   905                 ] ifFalse:[
   906                     cls isLoaded ifTrue:[    
   907                         self createHeaderFileFor:cls in:packageTargetDir
   908                     ]
   909                 ].
   910             ].
   911             self copyResourcesForPackage:eachPackageToFileout.
   912             self generateBuildSupportFilesByFilingOutIn:packageTargetDir forDefinitionClass:packageDef.
   913             (packageTargetDir / '.NOSOURCE') contents:'existence of this file suppresses compilation of st files'.
   914         ].
   915     ].
   916 
   917 "/    stx_libbasic2 preRequisitesForBuilding#(#'stx:libbasic')
   918 !
   919 
   920 makeCommandOfCompiler:usedCompiler
   921     usedCompiler = 'bcc' ifTrue:[ 
   922         ^ 'bmake'.
   923     ].
   924     usedCompiler = 'vc' ifTrue:[ 
   925         ^ 'vcmake'. "/ compilerFlag := '-DUSEVC' 
   926     ].
   927     usedCompiler = 'lcc' ifTrue:[ 
   928         ^ 'lccmake'. "/ compilerFlag := '-DUSELCC' 
   929     ].
   930     usedCompiler = 'tcc' ifTrue:[ 
   931         ^ 'tccmake'. "/ compilerFlag := '-DUSELCC' 
   932     ].
   933     usedCompiler = 'mingw' ifTrue:[ 
   934         ^ 'mingwmake'.  "/ compilerFlag := '-DUSEMINGW' 
   935     ].
   936     true "usedCompiler = 'gcc'" ifTrue:[ 
   937         ^ 'make'.       "/ compilerFlag := '-DUSEGCC' 
   938     ].
   939     self error:'unknown compiler specified'.
   940 
   941     "Created: / 03-09-2012 / 19:46:07 / cg"
   942 !
   943 
   944 makeWithOutputTo:stdOut errorTo:stdErr
   945     |module directory makeCommand forceArg|
   946 
   947     module := package module.
   948     directory := package directory.
   949 
   950     makeCommand := ParserFlags makeCommand.
   951     usedCompiler isNil ifTrue:[
   952         usedCompiler := ParserFlags usedCompiler.
   953     ].
   954     makeCommand := self makeCommandOfCompiler:usedCompiler.
   955     forceArg := ''.
   956     
   957     "/ makeCommand := makeCommand, ' TOP=', mySTXTopDirectory pathName.
   958 
   959     OperatingSystem isUNIXlike ifTrue:[
   960         forceArg := ' FORCE='.
   961 
   962         "/ generate the makefile first
   963         self activityNotification:('sh %1/rules/stmkmf (in %2)' 
   964                     bindWith:mySTXTopDirectory pathName    
   965                     with:(buildDirectory / module / directory)).
   966         OperatingSystem
   967             executeCommand:('sh %1/rules/stmkmf' bindWith:mySTXTopDirectory pathName)
   968             inputFrom:nil
   969             outputTo:stdOut
   970             errorTo:stdErr
   971             inDirectory:(buildDirectory / module / directory)
   972             onError:[:status | self error:'make failed'].
   973     ].
   974 
   975     projectDefinitionClass isLibraryDefinition ifTrue:[
   976         "/ generate the library
   977         self activityNotification:(makeCommand,' classLibRule').
   978         OperatingSystem
   979             executeCommand:(makeCommand,' classLibRule',forceArg)
   980             inputFrom:nil
   981             outputTo:stdOut
   982             errorTo:stdErr
   983             inDirectory:(buildDirectory / module / directory)
   984             onError:[:status | self error:'make failed'].
   985     ] ifFalse:[
   986         (self makeExeOnly) ifTrue:[
   987             self activityNotification:(makeCommand,' exe').
   988             OperatingSystem
   989                 "/ generate the executable
   990                 executeCommand:(makeCommand,' exe',forceArg)
   991                 inputFrom:nil
   992                 outputTo:stdOut
   993                 errorTo:stdErr
   994                 inDirectory:(buildDirectory / module / directory)
   995                 onError:[:status | self error:'make failed'].
   996 
   997         ] ifFalse:[
   998             "/ generate the self-installable package
   999             self activityNotification:(makeCommand,' ALL_NP').
  1000             OperatingSystem
  1001                 executeCommand:(makeCommand,' ALL_NP')
  1002                 inputFrom:nil
  1003                 outputTo:stdOut
  1004                 errorTo:stdErr
  1005                 inDirectory:(buildDirectory / module / directory)
  1006                 onError:[:status | self error:'make failed'].
  1007         ]
  1008     ]
  1009 
  1010     "Modified: / 28-01-2014 / 21:48:07 / cg"
  1011 !
  1012 
  1013 objDirForUsedCompiler
  1014     ^ self objDirForUsedCompiler:usedCompiler
  1015 
  1016     "Created: / 20-08-2012 / 17:01:13 / cg"
  1017 !
  1018 
  1019 objDirForUsedCompiler:usedCompiler
  1020     usedCompiler = 'gcc' ifTrue:[^ 'obj'].      "/ unix case
  1021 
  1022     usedCompiler = 'bcc' ifTrue:[^ 'objbc'].
  1023     usedCompiler = 'vc' ifTrue:[^ 'objvc'].
  1024     usedCompiler = 'tcc' ifTrue:[^ 'objtcc'].
  1025     usedCompiler = 'lcc' ifTrue:[^ 'objlcc'].
  1026     usedCompiler = 'mingw' ifTrue:[^ 'objmingw'].
  1027     self halt:'please add compiler here'.
  1028     ^ 'objbc'
  1029 
  1030     "Created: / 03-09-2012 / 19:55:34 / cg"
  1031 !
  1032 
  1033 recursiveCopyDirectoryForBuild:subdir
  1034     |targetDir|
  1035 
  1036     targetDir := buildDirectory / 'stx' / subdir.
  1037     targetDir exists ifFalse:[
  1038         targetDir makeDirectory.
  1039     ].
  1040     (mySTXTopDirectory / subdir) directoryContentsAsFilenamesDo:[:eachFile |
  1041         eachFile recursiveCopyTo:(targetDir construct:eachFile baseName)
  1042     ].
  1043     self activityNotification:nil
  1044 !
  1045 
  1046 setupBuildDirectory
  1047     self activityNotification:('Building in %1' bindWith:buildDirectory pathName).
  1048 
  1049     buildDirectory exists ifFalse:[
  1050         buildDirectory recursiveMakeDirectory.
  1051     ].
  1052     (buildDirectory / 'stx') exists ifFalse:[
  1053         (buildDirectory / 'stx') makeDirectory.
  1054     ].
  1055 
  1056     self copyDirectoryForBuild:'include'.
  1057     self copyDirectoryForBuild:'rules'.
  1058 
  1059     OperatingSystem isUNIXlike ifTrue:[
  1060         self recursiveCopyDirectoryForBuild:'configurations'.
  1061     ]
  1062 !
  1063 
  1064 validateBuildDirectoryIsPresent
  1065 
  1066     ^ self.
  1067 
  1068 "/    [
  1069 "/        |default directoryIsOKForMe stc |
  1070 "/
  1071 "/        default := (buildDirectory ?
  1072 "/                          PreviousBuildDirectory)
  1073 "/                          ifNil:[ UserPreferences current buildDirectory].
  1074 "/
  1075 "/        buildDirectory := Dialog requestDirectoryName:'Temporary Work-ROOT for build:'
  1076 "/                                 default:default.
  1077 "/
  1078 "/        buildDirectory isEmptyOrNil ifTrue:[^ self].
  1079 "/        buildDirectory := buildDirectory asFilename.
  1080 "/        directoryIsOKForMe := true.
  1081 "/
  1082 "/        buildDirectory exists ifFalse:[
  1083 "/            Dialog warn:(self classResources string:'Work directory %1 does not exist.' with:buildDirectory).
  1084 "/            directoryIsOKForMe := false.
  1085 "/        ] ifTrue:[
  1086 "/            (buildDirectory construct:'stx') exists ifFalse:[
  1087 "/                Dialog warn:(self classResources stringWithCRs:'Work directory must contain an stx subDirectory,\which contains (at least) the stc and include subdirectories.').
  1088 "/                directoryIsOKForMe := false.
  1089 "/            ] ifTrue:[
  1090 "/                stc := (OperatingSystem isMSDOSlike) ifTrue:['stc.exe'] ifFalse:['stc'].
  1091 "/                (((buildDirectory construct:'stx')construct:'stc')construct:stc) exists ifFalse:[
  1092 "/                    Dialog warn:(self classResources stringWithCRs:'Work directory must contain an stc compiler in the stx/stc subDirectory.').
  1093 "/                    directoryIsOKForMe := false.
  1094 "/                ].
  1095 "/                ((buildDirectory construct:'stx')construct:'include') exists ifFalse:[
  1096 "/                    Dialog warn:(self classResources stringWithCRs:'Work directory must have had a make run before (for include files to exists).').
  1097 "/                    directoryIsOKForMe := false.
  1098 "/                ].
  1099 "/            ]
  1100 "/        ].
  1101 "/        directoryIsOKForMe
  1102 "/    ] whileFalse
  1103 ! !
  1104 
  1105 !ProjectBuilder class methodsFor:'documentation'!
  1106 
  1107 version
  1108     ^ '$Header$'
  1109 !
  1110 
  1111 version_CVS
  1112     ^ '$Header$'
  1113 ! !
  1114