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