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