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