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