ProjectBuilder.st
author Claus Gittinger <cg@exept.de>
Mon, 05 Aug 2013 21:17:05 +0200
changeset 3041 380d18b00312
parent 3006 741e3e2f0270
child 3042 7022b69410ab
permissions -rw-r--r--
class: Tools::ProjectBuilder
changed: #copyDLLsForLinkage
     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 default 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 generateSourceFiles
   750     (self isLocalBuild not and:[ sourceCodeManager notNil ])  ifTrue:[
   751         "/ check out / generate files there
   752         self generateSourceFilesByCheckingOutUsing:sourceCodeManager
   753     ] ifFalse:[
   754         "/ local build
   755         "/ fileout the project
   756         self generateSourceFilesByFilingOut
   757     ]
   758 !
   759 
   760 generateSourceFilesByCheckingOutUsing:aSourceCodeManager
   761     "/ will no longer be needed/supported
   762 
   763     |repository stxRepository module directory|
   764 
   765     self breakPoint:#cg.
   766 
   767     "/ check out / generate files there
   768     repository := (aSourceCodeManager repositoryNameForModule:module) ifNil:[aSourceCodeManager repositoryName].
   769     stxRepository := aSourceCodeManager repositoryName.
   770 
   771     (buildDirectory construct:'stx') exists ifFalse:[
   772         (module ~= 'stx') ifTrue:[
   773             OperatingSystem
   774                 executeCommand:('cvs -d ',stxRepository,' co stx')
   775                 inputFrom:nil
   776                 outputTo:Transcript
   777                 errorTo:Transcript
   778                 inDirectory:buildDirectory
   779                 onError:[:status| self error:'cvs update stx failed'].
   780         ].
   781     ].
   782 
   783     ((buildDirectory construct:module) construct:'CVS') exists ifFalse:[
   784         OperatingSystem
   785             executeCommand:('cvs -d ',repository,' co -l ',directory)
   786             inputFrom:nil
   787             outputTo:Transcript
   788             errorTo:Transcript
   789             inDirectory:buildDirectory
   790             onError:[:status| self error:'cvs update failed'].
   791     ].
   792     OperatingSystem
   793         executeCommand:'cvs upd -d'
   794         inputFrom:nil
   795         outputTo:Transcript
   796         errorTo:Transcript
   797         inDirectory:(buildDirectory construct:module)
   798         onError:[:status| self error:'cvs update failed'].
   799 self halt.
   800 
   801     "Modified: / 29-12-2011 / 14:02:56 / cg"
   802 !
   803 
   804 generateSourceFilesByFilingOut
   805     "/ local build
   806     "/ fileout the project
   807 
   808     |fullPathName|
   809 
   810     (package module ~= 'stx') ifTrue:[
   811         (buildDirectory / package module) makeDirectory.
   812     ].
   813 
   814     "/ file out the package(s) which are to be built
   815     ((Array with:package))
   816     do:[:eachPackageToFileout |
   817         |packageId packageModule packageDirectory packageTargetDir packageDef extSource|
   818 
   819         packageId := eachPackageToFileout asPackageId.
   820         packageModule := packageId module.
   821         packageDirectory := packageId directory.
   822         packageTargetDir := (buildDirectory / packageModule / packageDirectory) recursiveMakeDirectory.
   823 
   824         packageDef := packageId projectDefinitionClass.
   825         (packageDef compiled_classNames_common ,
   826         packageDef compiled_classNamesForPlatform) do:[:eachClassName |
   827             |cls fileName newSource|
   828 
   829             cls := Smalltalk classNamed:eachClassName.
   830             self assert:cls isLoaded.
   831             fileName := (Smalltalk fileNameForClass:cls),'.st'.
   832             fileName := packageTargetDir asFilename construct:fileName.
   833             fileName exists ifTrue:[
   834                 newSource := String streamContents:[:s | cls fileOutOn:s withTimeStamp:false].
   835                 newSource = fileName contentsAsString ifFalse:[
   836                     fileName contents:newSource
   837                 ].
   838             ] ifFalse:[
   839                 cls fileOutIn:packageTargetDir withTimeStamp:false
   840             ].
   841         ].
   842 
   843         packageDef hasExtensionMethods ifTrue:[
   844             extSource := 
   845                 String streamContents:[:s |
   846                     s nextPutAll:('"{ Package: ''%1'' }" !!\\' bindWith:packageDef package) withCRs.
   847 
   848                     packageDef extensionMethods do:[:eachMethod |
   849                         eachMethod mclass fileOutMethod:eachMethod on:s
   850                     ].
   851                 ].
   852             extSource isWideString ifTrue:[
   853                 extSource := ( '"{ Encoding: utf8 }"' , Character cr asString, Character cr asString, extSource).
   854                 extSource := extSource utf8Encoded.
   855             ].
   856             (packageTargetDir asFilename construct:'extensions.st') contents:extSource
   857         ].
   858 
   859 "/        (Smalltalk allClassesInPackage:eachPackageToFileout) do:[:cls |
   860 "/            cls isPrivate ifFalse:[
   861 "/                cls isLoaded ifFalse:[
   862 "/                    self halt.
   863 "/                    cls autoload.
   864 "/                ].
   865 "/                cls fileOutIn:packageTargetDir
   866 "/            ]
   867 "/        ].
   868 
   869         projectDefinitionClass forEachFileNameAndGeneratedContentsDo:[:fileName :fileContents |
   870             fullPathName := packageTargetDir construct:fileName.
   871             fullPathName directory exists ifFalse:[
   872                 "take care for files like 'autopackage/default.apspec'"
   873                 fullPathName directory makeDirectory.
   874             ].
   875             (fullPathName exists
   876              and:[ fullPathName contents = fileContents ]) ifFalse:[
   877                 fullPathName contents:fileContents.
   878             ].
   879         ].    
   880     ].
   881     self makeQuick ifFalse:[
   882         "/ generate header files in prerequisite packages...
   883         (projectDefinitionClass allPreRequisites)
   884         do:[:eachPackageToFileout |
   885             |packageId packageDef packageModule packageDirectory packageTargetDir|
   886 
   887             packageId := eachPackageToFileout asPackageId.
   888             packageModule := packageId module.
   889             packageDirectory := packageId directory.
   890             packageTargetDir := (buildDirectory / packageModule / packageDirectory) recursiveMakeDirectory.
   891 
   892             packageDef := packageId projectDefinitionClass.
   893             (packageDef compiled_classNames_common ,
   894             packageDef compiled_classNamesForPlatform) do:[:eachClassName |
   895                 |cls|
   896 
   897                 cls := Smalltalk classNamed:eachClassName.
   898                 "/ self assert:cls isLoaded.
   899                 cls isNil ifTrue:[
   900                     stdErr nextPutLine:('Missing class: ',eachClassName, ' (not present in system. Warning only:subclasses of it will not be compiled)').
   901                 ] ifFalse:[
   902                     cls isLoaded ifTrue:[    
   903                         self createHeaderFileFor:cls in:packageTargetDir
   904                     ]
   905                 ].
   906             ].
   907             self copyResourcesForPackage:eachPackageToFileout.
   908         ].
   909     ].
   910 
   911 "/    stx_libbasic2 preRequisitesForBuilding#(#'stx:libbasic')
   912 !
   913 
   914 makeCommandOfCompiler:usedCompiler
   915     usedCompiler = 'bcc' ifTrue:[ 
   916         ^ 'bmake'.
   917     ].
   918     usedCompiler = 'vc' ifTrue:[ 
   919         ^ 'vcmake'. "/ compilerFlag := '-DUSEVC' 
   920     ].
   921     usedCompiler = 'lcc' ifTrue:[ 
   922         ^ 'lccmake'. "/ compilerFlag := '-DUSELCC' 
   923     ].
   924     usedCompiler = 'tcc' ifTrue:[ 
   925         ^ 'tccmake'. "/ compilerFlag := '-DUSELCC' 
   926     ].
   927     usedCompiler = 'mingw' ifTrue:[ 
   928         ^ 'mingwmake'.  "/ compilerFlag := '-DUSEMINGW' 
   929     ].
   930     true "usedCompiler = 'gcc'" ifTrue:[ 
   931         ^ 'make'.       "/ compilerFlag := '-DUSEGCC' 
   932     ].
   933     self error:'unknown compiler specified'.
   934 
   935     "Created: / 03-09-2012 / 19:46:07 / cg"
   936 !
   937 
   938 makeWithOutputTo:stdOut errorTo:stdErr
   939     |module directory makeCommand|
   940 
   941     module := package module.
   942     directory := package directory.
   943 
   944     makeCommand := ParserFlags makeCommand.
   945     usedCompiler isNil ifTrue:[
   946         usedCompiler := ParserFlags usedCompiler.
   947     ].
   948     makeCommand := self makeCommandOfCompiler:usedCompiler.
   949 
   950     "/ makeCommand := makeCommand, ' TOP=', mySTXTopDirectory pathName.
   951 
   952     OperatingSystem isUNIXlike ifTrue:[
   953         "/ generate the makefile first
   954         self activityNotification:('sh %1/rules/stmkmf (in %2)' 
   955                     bindWith:mySTXTopDirectory pathName    
   956                     with:(buildDirectory / module / directory)).
   957         OperatingSystem
   958             executeCommand:('sh %1/rules/stmkmf' bindWith:mySTXTopDirectory pathName)
   959             inputFrom:nil
   960             outputTo:stdOut
   961             errorTo:stdErr
   962             inDirectory:(buildDirectory / module / directory)
   963             onError:[:status | self error:'make failed'].
   964     ].
   965 
   966     projectDefinitionClass isLibraryDefinition ifTrue:[
   967         "/ generate the library
   968         self activityNotification:(makeCommand,' classLibRule').
   969         OperatingSystem
   970             executeCommand:(makeCommand,' classLibRule FORCE=')
   971             inputFrom:nil
   972             outputTo:stdOut
   973             errorTo:stdErr
   974             inDirectory:(buildDirectory / module / directory)
   975             onError:[:status | self error:'make failed'].
   976     ] ifFalse:[
   977         (self makeExeOnly) ifTrue:[
   978             self activityNotification:(makeCommand,' exe').
   979             OperatingSystem
   980                 "/ generate the executable
   981                 executeCommand:(makeCommand,' exe FORCE=')
   982                 inputFrom:nil
   983                 outputTo:stdOut
   984                 errorTo:stdErr
   985                 inDirectory:(buildDirectory / module / directory)
   986                 onError:[:status | self error:'make failed'].
   987 
   988         ] ifFalse:[
   989             "/ generate the self-installable package
   990             self activityNotification:(makeCommand,' ALL_NP').
   991             OperatingSystem
   992                 executeCommand:(makeCommand,' ALL_NP')
   993                 inputFrom:nil
   994                 outputTo:stdOut
   995                 errorTo:stdErr
   996                 inDirectory:(buildDirectory / module / directory)
   997                 onError:[:status | self error:'make failed'].
   998         ]
   999     ]
  1000 
  1001     "Modified: / 03-09-2012 / 19:47:15 / cg"
  1002     "Modified (comment): / 06-09-2012 / 16:22:38 / cg"
  1003 !
  1004 
  1005 objDirForUsedCompiler
  1006     ^ self objDirForUsedCompiler:usedCompiler
  1007 
  1008     "Created: / 20-08-2012 / 17:01:13 / cg"
  1009 !
  1010 
  1011 objDirForUsedCompiler:usedCompiler
  1012     usedCompiler = 'gcc' ifTrue:[^ 'obj'].      "/ unix case
  1013 
  1014     usedCompiler = 'bcc' ifTrue:[^ 'objbc'].
  1015     usedCompiler = 'vc' ifTrue:[^ 'objvc'].
  1016     usedCompiler = 'tcc' ifTrue:[^ 'objtcc'].
  1017     usedCompiler = 'lcc' ifTrue:[^ 'objlcc'].
  1018     usedCompiler = 'mingw' ifTrue:[^ 'objmingw'].
  1019     self halt:'please add compiler here'.
  1020     ^ 'objbc'
  1021 
  1022     "Created: / 03-09-2012 / 19:55:34 / cg"
  1023 !
  1024 
  1025 recursiveCopyDirectoryForBuild:subdir
  1026     |targetDir|
  1027 
  1028     targetDir := buildDirectory / 'stx' / subdir.
  1029     targetDir exists ifFalse:[
  1030         targetDir makeDirectory.
  1031     ].
  1032     (mySTXTopDirectory / subdir) directoryContentsAsFilenamesDo:[:eachFile |
  1033         eachFile recursiveCopyTo:(targetDir construct:eachFile baseName)
  1034     ].
  1035     self activityNotification:nil
  1036 !
  1037 
  1038 setupBuildDirectory
  1039     self activityNotification:('Building in %1' bindWith:buildDirectory pathName).
  1040 
  1041     buildDirectory exists ifFalse:[
  1042         buildDirectory recursiveMakeDirectory.
  1043     ].
  1044     (buildDirectory / 'stx') exists ifFalse:[
  1045         (buildDirectory / 'stx') makeDirectory.
  1046     ].
  1047 
  1048     self copyDirectoryForBuild:'include'.
  1049     self copyDirectoryForBuild:'rules'.
  1050 
  1051     OperatingSystem isUNIXlike ifTrue:[
  1052         self recursiveCopyDirectoryForBuild:'configurations'.
  1053     ]
  1054 !
  1055 
  1056 validateBuildDirectoryIsPresent
  1057 
  1058     ^ self.
  1059 
  1060 "/    [
  1061 "/        |default directoryIsOKForMe stc |
  1062 "/
  1063 "/        default := (buildDirectory ?
  1064 "/                          PreviousBuildDirectory)
  1065 "/                          ifNil:[ UserPreferences current buildDirectory].
  1066 "/
  1067 "/        buildDirectory := Dialog requestDirectoryName:'Temporary Work-ROOT for build:'
  1068 "/                                 default:default.
  1069 "/
  1070 "/        buildDirectory isEmptyOrNil ifTrue:[^ self].
  1071 "/        buildDirectory := buildDirectory asFilename.
  1072 "/        directoryIsOKForMe := true.
  1073 "/
  1074 "/        buildDirectory exists ifFalse:[
  1075 "/            Dialog warn:(self classResources string:'Work directory %1 does not exist.' with:buildDirectory).
  1076 "/            directoryIsOKForMe := false.
  1077 "/        ] ifTrue:[
  1078 "/            (buildDirectory construct:'stx') exists ifFalse:[
  1079 "/                Dialog warn:(self classResources stringWithCRs:'Work directory must contain an stx subDirectory,\which contains (at least) the stc and include subdirectories.').
  1080 "/                directoryIsOKForMe := false.
  1081 "/            ] ifTrue:[
  1082 "/                stc := (OperatingSystem isMSDOSlike) ifTrue:['stc.exe'] ifFalse:['stc'].
  1083 "/                (((buildDirectory construct:'stx')construct:'stc')construct:stc) exists ifFalse:[
  1084 "/                    Dialog warn:(self classResources stringWithCRs:'Work directory must contain an stc compiler in the stx/stc subDirectory.').
  1085 "/                    directoryIsOKForMe := false.
  1086 "/                ].
  1087 "/                ((buildDirectory construct:'stx')construct:'include') exists ifFalse:[
  1088 "/                    Dialog warn:(self classResources stringWithCRs:'Work directory must have had a make run before (for include files to exists).').
  1089 "/                    directoryIsOKForMe := false.
  1090 "/                ].
  1091 "/            ]
  1092 "/        ].
  1093 "/        directoryIsOKForMe
  1094 "/    ] whileFalse
  1095 ! !
  1096 
  1097 !ProjectBuilder class methodsFor:'documentation'!
  1098 
  1099 version
  1100     ^ '$Header$'
  1101 !
  1102 
  1103 version_CVS
  1104     ^ '$Header$'
  1105 ! !
  1106