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