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