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