--- a/STCCompilerInterface.st Tue Oct 11 07:03:24 2016 +0200
+++ b/STCCompilerInterface.st Thu Oct 20 11:08:07 2016 +0100
@@ -53,9 +53,10 @@
"Return C compiler flags that are always passed to the C compiler
when a (ST)C file is compiled."
- ^ OperatingSystem getCPUDefine , ' ', OperatingSystem getOSDefine
+ ^ self getCPUDefine , ' ', self getOSDefine
"Created: / 04-12-2015 / 16:41:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 21-10-2016 / 11:24:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
builtinCIncludeDirectories
@@ -99,6 +100,101 @@
"Created: / 09-12-2015 / 16:59:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+getCCDefine
+ "return a string which was used to identify the C-Compiler used
+ when STX was compiled, and which should be passed down when compiling methods.
+ For example, when compiled with GNUC, this is '__GNUC__';
+ on windows, this is either '__VISUAL__', '__BORLANDC__' or '__MINGW64__'"
+
+%{ /* NOCONTEXT */
+#ifndef CC_DEFINE
+# ifdef __win32__
+# if defined( __BORLANDC__ )
+# define CC_DEFINE "__BORLANDC__"
+# else
+# if defined( __VISUALC__ )
+# define CC_DEFINE "__VISUALC__"
+# else
+# if defined( __MINGW64__ )
+# define CC_DEFINE "__MINGW64__"
+# else
+# if defined( __MINGW32__ )
+# define CC_DEFINE "__MINGW32__"
+# else
+# define CC_DEFINE "__CC__"
+# endif
+# endif
+# endif
+# endif
+# else /* not __win32__ */
+# if defined(__CLANG__) || defined( __clang__ )
+# define CC_DEFINE "__CLANG__"
+# else
+# ifdef __GNUC__
+# define CC_DEFINE "__GNUC__"
+# else
+# define CC_DEFINE "__CC__"
+# endif
+# endif
+# endif
+#endif
+ RETURN ( __MKSTRING(CC_DEFINE));
+%}
+ "
+ STCCompilerInterface getCCDefine
+ "
+!
+
+getCPUDefine
+ "return a string which was used to identify this CPU type when STX was
+ compiled, and which should be passed down when compiling methods.
+ For example, on a 386 (and successors), this may be '-D__x86__';
+ on a vax, this would be '-D__vax__'.
+ This is normally not of interest to 'normal' users; however, it is passed
+ down to the c-compiler when methods are incrementally compiled to machine code.
+ Do not use this for CPU determination; only to pass on to stc for compilation.
+ (see OperatingSystem getCPUType for this)"
+
+%{ /* NOCONTEXT */
+# ifndef CPU_DEFINE
+# define CPU_DEFINE "-DunknownCPU"
+# endif
+
+ RETURN ( __MKSTRING(CPU_DEFINE));
+%}
+ "
+ STCCompilerInterface getCPUDefine
+ "
+!
+
+getOSDefine
+ "return a string which was used to identify this machine when stx was
+ compiled, and which should be passed down when compiling methods.
+ For example, on linux, this is '-D__linux__'; on osx, it is '-D__osx__'.
+ Do not use this for OS determination; only to pass on to stc for compilation.
+ (see OperatingSystem getOSType for this)"
+
+%{ /* NOCONTEXT */
+
+#ifndef OS_DEFINE
+# ifdef __win32__
+# define OS_DEFINE "-D__win32__"
+# endif
+
+# ifndef OS_DEFINE
+# define OS_DEFINE "-DunknownOS"
+# endif
+#endif
+
+ RETURN ( __MKSTRING(OS_DEFINE));
+
+#undef OS_DEFINE
+%}
+ "
+ STCCompilerInterface getOSDefine
+ "
+!
+
stcPathOf:command
"return the path to an stc command, or nil if not found."
@@ -270,20 +366,21 @@
[
self generateSTSource:aString.
self setupCompilationCommandArguments.
- ok := self compileToC.
- ok ifFalse:[
- self reportCompilationErrorFor:stcPath.
- ].
+ ok := self
+ compileToC_onError:[:errorFile |
+ self reportCompilationErrorFor:stcPath fromFile:errorFile
+ ].
- parserFlags stcKeepSIntermediate ifTrue:[ self compileToS ].
+ parserFlags stcKeepSIntermediate ifTrue:[
+ self compileToS_onError:[:errorFile | ]
+ ].
"/ now compile to machine code
- ok := self compileToObj.
- ok ifFalse:[
- self reportCompilationErrorFor:ccPath.
- ].
+ ok := self
+ compileToObj_onError:[:errorFile |
+ self reportCompilationErrorFor:ccPath fromFile:errorFile.
+ ].
originator activityNotification:''.
- OperatingSystem removeFile:'errorOutput'.
"
if required, make a shared or otherwise loadable object file for it
@@ -470,62 +567,71 @@
!STCCompilerInterface methodsFor:'machine code generation-helpers'!
-compileToC
- "compile st to C using stc"
+compileToC_onError:aBlock
+ "compile st to C using stc.
+ If any error happens, call aBlock passing it the fileName containing diagnostics"
- |command errorStream ok|
+ |command ok errorOutputFile|
command := (self possiblyQuotedPath:stcPath) , ' ' , stcFlags
+ , ' -E:',(self possiblyQuotedPath:(Filename tempDirectory / 'lastIncrStcErrorOutput') pathName)
, ' -defdir=', (self possiblyQuotedPath:cFileName asFilename directory pathName).
cFileName asFilename suffix ~= 'c' ifTrue:[
command := command , ' -cSuffix=',cFileName asFilename suffix.
].
- command := command ,
- ' -C ' , (self possiblyQuotedPath:stFileName asFilename pathName).
-
- errorStream := 'errorOutput' asFilename writeStream.
+ command := command , ' -C ' , (self possiblyQuotedPath:stFileName asFilename pathName).
Verbose == true ifTrue:[
Transcript show:'executing: '; showCR:command.
].
originator activityNotification:'compiling (stc)'.
- ok := OperatingSystem
- executeCommand:command
- inputFrom:nil
- outputTo:errorStream
- errorTo:errorStream
- showWindow:false
- onError:[:stat|
- executionStatus := stat.
- false
- ].
- errorStream close.
+ errorOutputFile := Filename tempDirectory / 'stcErrorOutput'.
+ errorOutputFile writingFileDo:[:errorStream |
+ ok := OperatingSystem
+ executeCommand:command
+ inputFrom:nil
+ outputTo:errorStream
+ errorTo:errorStream
+ showWindow:false
+ onError:[:stat|
+ self breakPoint:#cg.
+ executionStatus := stat.
+ false
+ ].
+ ].
cFileName asFilename exists ifTrue:[
ok ifFalse:[
- Transcript showCR:'Compiler [info]: oops - system says stc failed - but c-file is there ...'.
+ 'Compiler [info]: oops - system says stc failed - but c-file is there ...' infoPrintCR.
ok := true
]
] ifFalse:[
ok ifTrue:[
- Transcript showCR:'Compiler [info]: oops - system says stc ok - but no c-file is there ...'.
+ 'Compiler [info]: oops - system says stc ok - but no c-file is there ...' infoPrintCR
].
ok := false
].
+
+ [
+ ok ifFalse:[
+ aBlock value:errorOutputFile
+ ].
+ ] ensure:[
+ errorOutputFile remove.
+ ].
^ ok
"Created: / 07-11-2006 / 12:11:24 / cg"
"Modified: / 08-08-2011 / 22:12:01 / cg"
!
-compileToExe
- "compile C to exe, using cc"
+compileToExe_onError:aBlock
+ "compile C to exe, using cc.
+ If any error happens, call aBlock passing it the fileName containing diagnostics"
- |command errorStream ok|
-
- errorStream := 'errorOutput' asFilename newReadWriteStream.
+ |command errorOutputFile ok|
command := (self possiblyQuotedPath:ccPath) , ' ' , cFlags , ' -D__INCREMENTAL_COMPILE__ ' , (self possiblyQuotedPath:cFileName).
@@ -533,35 +639,38 @@
Transcript show:'executing: ' showCR:command.
].
originator activityNotification:'compiling (' , ccPath , ')'.
- ok := OperatingSystem
- executeCommand:command
- inputFrom:nil
- outputTo:errorStream
- errorTo:errorStream
- showWindow:false
- onError:[:stat|
- executionStatus := stat.
- false
- ].
- ok ifFalse:[
- errorStream reset.
- errorStream copyToEndInto:Transcript.
+ errorOutputFile := Filename tempDirectory / 'stcErrorOutput'.
+ errorOutputFile writingFileDo:[:errorStream |
+ ok := OperatingSystem
+ executeCommand:command
+ inputFrom:nil
+ outputTo:errorStream
+ errorTo:errorStream
+ showWindow:false
+ onError:[:stat|
+ executionStatus := stat.
+ false
+ ].
].
-
- errorStream close.
-
+
+ [
+ ok ifFalse:[
+ aBlock value:errorOutputFile
+ ].
+ ] ensure:[
+ errorOutputFile remove.
+ ].
^ ok
!
-compileToObj
- "compile C to obj, using cc"
+compileToObj_onError:aBlock
+ "compile C to obj, using cc.
+ If any error happens, call aBlock passing it the fileName containing diagnostics"
- |errorStream ok commandTemplate command ccDefine env|
+ |errorOutputFile ok commandTemplate command ccDefine env|
- errorStream := 'errorOutput' asFilename newReadWriteStream.
-
- "/ bcc does not like -D__BORLANDC__ (needs to be set to a version, such as 0x0505
+ "/ bcc does not like -D__BORLANDC__ (needs to be set to a version, such as 0x0505)
"/ others do not need it (is already predefined in the compiler)
"/ ccDefine := ' -D',ParserFlags usedCompilerDefine.
"/ so, never redefine ccDefine
@@ -606,50 +715,52 @@
OperatingSystem setEnvironment: 'PATH' to: path , ';', ccPath asFilename directory pathName
].
].
-
- ok := OperatingSystem
- executeCommand:command
- inputFrom:nil
- outputTo:errorStream
- errorTo:errorStream
- environment:env
- showWindow:false
- onError:
- [:stat|
- executionStatus := stat.
- false
- ].
-
- ok ifFalse:[
- errorStream reset.
- errorStream contents do:[:l | Transcript showCR:(OperatingSystem decodePathOrCommandOutput: l)].
+
+ errorOutputFile := Filename tempDirectory / 'stcErrorOutput'.
+ errorOutputFile writingFileDo:[:errorStream |
+ ok := OperatingSystem
+ executeCommand:command
+ inputFrom:nil
+ outputTo:errorStream
+ errorTo:errorStream
+ environment:env
+ showWindow:false
+ onError:
+ [:stat|
+ executionStatus := stat.
+ false
+ ].
].
-
- errorStream close.
-
+
oFileName asFilename exists ifTrue:[
ok ifFalse:[
- Transcript showCR:'Compiler [info]: system says compile failed - but o-file is there ...'.
+ 'Compiler [info]: system says compile failed - but o-file is there ...' infoPrintCR.
ok := true
]
] ifFalse:[
ok ifTrue:[
- Transcript showCR:'Compiler [info]: system says compile ok - but no o-file is there ...'.
+ 'Compiler [info]: system says compile ok - but no o-file is there ...' infoPrintCR.
].
ok := false
].
+ [
+ ok ifFalse:[
+ aBlock value:errorOutputFile
+ ].
+ ] ensure:[
+ errorOutputFile remove.
+ ].
^ ok
"Created: / 07-11-2006 / 12:14:51 / cg"
"Modified: / 04-01-2016 / 21:12:56 / jv"
!
-compileToS
- "compile C to assembler, using cc"
+compileToS_onError:aBlock
+ "compile C to assembler, using cc.
+ If any error happens, call aBlock passing it the fileName containing diagnostics"
- |command errorStream ok|
-
- errorStream := 'errorOutput' asFilename newReadWriteStream.
+ |command errorOutputFile ok|
command := (self possiblyQuotedPath:ccPath) , ' ' , cFlags , ' -D__INCREMENTAL_COMPILE__ -S ' , (self possiblyQuotedPath:cFileName).
@@ -657,23 +768,27 @@
Transcript show:'executing: '; showCR:command.
].
originator activityNotification:'compiling (' , ccPath , ')'.
- ok := OperatingSystem
- executeCommand:command
- inputFrom:nil
- outputTo:errorStream
- errorTo:errorStream
- showWindow:false
- onError:[:stat|
- executionStatus := stat.
- false
- ].
- ok ifFalse:[
- errorStream reset.
- errorStream copyToEndInto:Transcript.
+ errorOutputFile := Filename tempDirectory / 'stcErrorOutput'.
+ errorOutputFile writingFileDo:[:errorStream |
+ ok := OperatingSystem
+ executeCommand:command
+ inputFrom:nil
+ outputTo:errorStream
+ errorTo:errorStream
+ showWindow:false
+ onError:[:stat|
+ executionStatus := stat.
+ false
+ ].
].
-
- errorStream close.
+ [
+ ok ifFalse:[
+ aBlock value:errorOutputFile
+ ].
+ ] ensure:[
+ errorOutputFile remove.
+ ].
^ ok
!
@@ -946,6 +1061,73 @@
"Modified: / 21-12-2013 / 00:08:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
+reportCompilationErrorFor:aCommand fromFile:anErrorFilename
+ |eMsg errorMessages lNr|
+
+ (executionStatus notNil and:[executionStatus couldNotExecute]) ifTrue:[
+ eMsg := 'oops, no %1 - cannot create machine code' bindWith:aCommand.
+ ] ifFalse:[
+ errorMessages := anErrorFilename contents
+ collect:[:l | OperatingSystem decodePathOrCommandOutput: l ].
+
+ errorMessages notNil ifTrue:[
+ errorMessages := errorMessages reject:[:line | line includesString:'Warning:'].
+
+ errorMessages size > 20 ifTrue:[
+ errorMessages := errorMessages select:[:line | line asLowercase startsWith:'error'].
+ errorMessages size > 20 ifTrue:[
+ errorMessages := (errorMessages copyTo:20) copyWith:'... more messages skipped'
+ ].
+ ].
+"/ errorMessages := errorMessages collect:[:line |
+"/ (line startsWith:(stFileName , ':')) ifTrue:[
+"/ 'Line: ' , (line copyFrom:(stFileName size + 2))
+"/ ] ifFalse:[
+"/ line
+"/ ]
+"/ ].
+ ].
+ errorMessages isNil ifTrue:[
+ errorMessages := #('')
+ ].
+ errorMessages := (Array with:'Failed to execute: "', aCommand,'"') , errorMessages.
+
+ "/ try to extract a line number"
+ (errorMessages contains:[:line | line includesString:'Borland']) ifTrue:[
+ |i i2 s|
+ i := errorMessages findFirst:[:l | l startsWith:(cFileName,':')].
+ i ~~ 0 ifTrue:[
+ ((errorMessages at:i+1) startsWith:'Error') ifTrue:[
+ i2 := (errorMessages at:i+1) indexOfSubCollection:(stFileName).
+ i2 ~~ 0 ifTrue:[
+ s := (errorMessages at:i+1) copyFrom:(i2+stFileName size+1).
+ s := s readStream.
+ lNr := Integer readFrom:s.
+ s skipSeparators.
+ ].
+ ]
+ ].
+ ].
+
+ errorMessages isEmpty ifTrue:[
+ eMsg := 'Error during compilation:\\Unspecified error (no output)' withCRs
+ ] ifFalse:[
+ eMsg := 'Error during compilation:\\' withCRs ,
+ (errorMessages asStringCollection asString).
+ ].
+ ].
+
+ originator activityNotification:''.
+
+ ParseError new
+ lineNumber:lNr;
+ errorMessage:eMsg;
+ raise.
+
+ "Created: / 07-11-2006 / 12:29:04 / cg"
+ "Modified: / 21-12-2013 / 00:08:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
setupCompilationCommandArguments
|stFn libDir incDir incDirArg defs incl opts|
@@ -961,7 +1143,7 @@
cFileName asFilename delete.
"/ stcFlags := '-commonSymbols +sharedLibCode +newIncremental -E:errorOutput -N' , initName .
- stcFlags := '+newIncremental -E:errorOutput'.
+ stcFlags := '+newIncremental'.
initName notEmptyOrNil ifTrue:[
stcFlags := stcFlags,' -N' , initName .
].