Merge branch 'bigbreak' of https://github.com/Araq/Nimrod into bigbreak

This commit is contained in:
Araq 2014-11-03 12:01:07 +01:00
commit 8853023fd8
7 changed files with 104 additions and 35 deletions

View file

@ -7,8 +7,10 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
# module for calling the different external C compilers # Module providing functions for calling the different external C compilers
# some things are read in from the configuration file # Uses some hard-wired facts about each C/C++ compiler, plus options read
# from a configuration file, to provide generalized procedures to compile
# nim files.
import import
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc
@ -59,6 +61,7 @@ type
template compiler(name: expr, settings: stmt): stmt {.immediate.} = template compiler(name: expr, settings: stmt): stmt {.immediate.} =
proc name: TInfoCC {.compileTime.} = settings proc name: TInfoCC {.compileTime.} = settings
# GNU C and C++ Compiler
compiler gcc: compiler gcc:
result = ( result = (
name: "gcc", name: "gcc",
@ -84,21 +87,24 @@ compiler gcc:
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm, props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasNakedAttribute}) hasNakedAttribute})
# LLVM Frontend for GCC/G++
compiler llvmGcc: compiler llvmGcc:
result = gcc() result = gcc() # Uses settings from GCC
result.name = "llvm_gcc" result.name = "llvm_gcc"
result.compilerExe = "llvm-gcc" result.compilerExe = "llvm-gcc"
result.cppCompiler = "llvm-g++" result.cppCompiler = "llvm-g++"
result.buildLib = "llvm-ar rcs $libfile $objfiles" result.buildLib = "llvm-ar rcs $libfile $objfiles"
# Clang (LLVM) C/C++ Compiler
compiler clang: compiler clang:
result = llvmGcc() result = llvmGcc() # Uses settings from llvmGcc
result.name = "clang" result.name = "clang"
result.compilerExe = "clang" result.compilerExe = "clang"
result.cppCompiler = "clang++" result.cppCompiler = "clang++"
# Microsoft Visual C/C++ Compiler
compiler vcc: compiler vcc:
result = ( result = (
name: "vcc", name: "vcc",
@ -123,6 +129,7 @@ compiler vcc:
packedPragma: "#pragma pack(1)", packedPragma: "#pragma pack(1)",
props: {hasCpp, hasAssume, hasNakedDeclspec}) props: {hasCpp, hasAssume, hasNakedDeclspec})
# Intel C/C++ Compiler
compiler icl: compiler icl:
# Intel compilers try to imitate the native ones (gcc and msvc) # Intel compilers try to imitate the native ones (gcc and msvc)
when defined(windows): when defined(windows):
@ -134,6 +141,7 @@ compiler icl:
result.compilerExe = "icl" result.compilerExe = "icl"
result.linkerExe = "icl" result.linkerExe = "icl"
# Local C Compiler
compiler lcc: compiler lcc:
result = ( result = (
name: "lcc", name: "lcc",
@ -158,6 +166,7 @@ compiler lcc:
packedPragma: "", # XXX: not supported yet packedPragma: "", # XXX: not supported yet
props: {}) props: {})
# Borland C Compiler
compiler bcc: compiler bcc:
result = ( result = (
name: "bcc", name: "bcc",
@ -182,6 +191,7 @@ compiler bcc:
packedPragma: "", # XXX: not supported yet packedPragma: "", # XXX: not supported yet
props: {hasCpp}) props: {hasCpp})
# Digital Mars C Compiler
compiler dmc: compiler dmc:
result = ( result = (
name: "dmc", name: "dmc",
@ -206,6 +216,7 @@ compiler dmc:
packedPragma: "#pragma pack(1)", packedPragma: "#pragma pack(1)",
props: {hasCpp}) props: {hasCpp})
# Watcom C Compiler
compiler wcc: compiler wcc:
result = ( result = (
name: "wcc", name: "wcc",
@ -230,6 +241,7 @@ compiler wcc:
packedPragma: "", # XXX: not supported yet packedPragma: "", # XXX: not supported yet
props: {hasCpp}) props: {hasCpp})
# Tiny C Compiler
compiler tcc: compiler tcc:
result = ( result = (
name: "tcc", name: "tcc",
@ -254,6 +266,7 @@ compiler tcc:
packedPragma: "", # XXX: not supported yet packedPragma: "", # XXX: not supported yet
props: {hasSwitchRange, hasComputedGoto}) props: {hasSwitchRange, hasComputedGoto})
# Pelles C Compiler
compiler pcc: compiler pcc:
# Pelles C # Pelles C
result = ( result = (
@ -279,6 +292,7 @@ compiler pcc:
packedPragma: "", # XXX: not supported yet packedPragma: "", # XXX: not supported yet
props: {}) props: {})
# Your C Compiler
compiler ucc: compiler ucc:
result = ( result = (
name: "ucc", name: "ucc",
@ -339,7 +353,9 @@ var
compileOptions: string = "" compileOptions: string = ""
ccompilerpath: string = "" ccompilerpath: string = ""
proc nameToCC*(name: string): TSystemCC = proc nameToCC*(name: string): TSystemCC =
## Returns the kind of compiler referred to by `name`, or ccNone
## if the name doesn't refer to any known compiler.
for i in countup(succ(ccNone), high(TSystemCC)): for i in countup(succ(ccNone), high(TSystemCC)):
if cmpIgnoreStyle(name, CC[i].name) == 0: if cmpIgnoreStyle(name, CC[i].name) == 0:
return i return i
@ -348,17 +364,18 @@ proc nameToCC*(name: string): TSystemCC =
proc getConfigVar(c: TSystemCC, suffix: string): string = proc getConfigVar(c: TSystemCC, suffix: string): string =
# use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given # use ``cpu.os.cc`` for cross compilation, unless ``--compileOnly`` is given
# for niminst support # for niminst support
let fullSuffix = (if gCmd == cmdCompileToCpp: ".cpp" & suffix else: suffix)
if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and
optCompileOnly notin gGlobalOptions: optCompileOnly notin gGlobalOptions:
let fullCCname = platform.CPU[targetCPU].name & '.' & let fullCCname = platform.CPU[targetCPU].name & '.' &
platform.OS[targetOS].name & '.' & platform.OS[targetOS].name & '.' &
CC[c].name & suffix CC[c].name & fullSuffix
result = getConfigVar(fullCCname) result = getConfigVar(fullCCname)
if result.len == 0: if result.len == 0:
# not overriden for this cross compilation setting? # not overriden for this cross compilation setting?
result = getConfigVar(CC[c].name & suffix) result = getConfigVar(CC[c].name & fullSuffix)
else: else:
result = getConfigVar(CC[c].name & suffix) result = getConfigVar(CC[c].name & fullSuffix)
proc setCC*(ccname: string) = proc setCC*(ccname: string) =
cCompiler = nameToCC(ccname) cCompiler = nameToCC(ccname)
@ -412,8 +429,12 @@ proc addFileToLink*(filename: string) =
prependStr(toLink, filename) prependStr(toLink, filename)
# BUGFIX: was ``appendStr`` # BUGFIX: was ``appendStr``
proc execExternalProgram*(cmd: string) = proc execExternalProgram*(cmd: string, prettyCmd = "") =
if optListCmd in gGlobalOptions or gVerbosity > 0: msgWriteln(cmd) if optListCmd in gGlobalOptions or gVerbosity > 0:
if prettyCmd != "":
msgWriteln(prettyCmd)
else:
msgWriteln(cmd)
if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "") if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "")
proc generateScript(projectFile: string, script: PRope) = proc generateScript(projectFile: string, script: PRope) =
@ -482,7 +503,7 @@ proc getLinkOptions: string =
proc needsExeExt(): bool {.inline.} = proc needsExeExt(): bool {.inline.} =
result = (optGenScript in gGlobalOptions and targetOS == osWindows) or result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
(platform.hostOS == osWindows) (platform.hostOS == osWindows)
proc getCompilerExe(compiler: TSystemCC): string = proc getCompilerExe(compiler: TSystemCC): string =
result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler result = if gCmd == cmdCompileToCpp: CC[compiler].cppCompiler
@ -539,6 +560,7 @@ proc getCompileCFileCmd*(cfilename: string, isExternal = false): string =
"lib", quoteShell(libpath)]) "lib", quoteShell(libpath)])
proc footprint(filename: string): TCrc32 = proc footprint(filename: string): TCrc32 =
# note, '><' further modifies a crc value with a string.
result = crcFromFile(filename) >< result = crcFromFile(filename) ><
platform.OS[targetOS].name >< platform.OS[targetOS].name ><
platform.CPU[targetCPU].name >< platform.CPU[targetCPU].name ><
@ -566,14 +588,16 @@ proc addExternalFileToCompile*(filename: string) =
if optForceFullMake in gGlobalOptions or externalFileChanged(filename): if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
appendStr(externalToCompile, filename) appendStr(externalToCompile, filename)
proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq, proc compileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
isExternal: bool) = prettyCmds: var TStringSeq, isExternal: bool) =
var it = PStrEntry(list.head) var it = PStrEntry(list.head)
while it != nil: while it != nil:
inc(fileCounter) # call the C compiler for the .c file: inc(fileCounter) # call the C compiler for the .c file:
var compileCmd = getCompileCFileCmd(it.data, isExternal) var compileCmd = getCompileCFileCmd(it.data, isExternal)
if optCompileOnly notin gGlobalOptions: if optCompileOnly notin gGlobalOptions:
add(cmds, compileCmd) add(cmds, compileCmd)
let (dir, name, ext) = splitFile(it.data)
add(prettyCmds, "CC: " & name)
if optGenScript in gGlobalOptions: if optGenScript in gGlobalOptions:
app(script, compileCmd) app(script, compileCmd)
app(script, tnl) app(script, tnl)
@ -589,18 +613,24 @@ proc callCCompiler*(projectfile: string) =
var c = cCompiler var c = cCompiler
var script: PRope = nil var script: PRope = nil
var cmds: TStringSeq = @[] var cmds: TStringSeq = @[]
compileCFile(toCompile, script, cmds, false) var prettyCmds: TStringSeq = @[]
compileCFile(externalToCompile, script, cmds, true) let prettyCb = proc (idx: int) =
echo prettyCmds[idx]
compileCFile(toCompile, script, cmds, prettyCmds, false)
compileCFile(externalToCompile, script, cmds, prettyCmds, true)
if optCompileOnly notin gGlobalOptions: if optCompileOnly notin gGlobalOptions:
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors() if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
var res = 0 var res = 0
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res) for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res)
elif optListCmd in gGlobalOptions or gVerbosity > 0: elif optListCmd in gGlobalOptions or gVerbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)
else: elif gVerbosity == 1:
res = execProcesses(cmds, {poUseShell, poParentStreams}, res = execProcesses(cmds, {poUseShell, poParentStreams},
gNumberOfProcessors, prettyCb)
else:
res = execProcesses(cmds, {poUseShell, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)
if res != 0: if res != 0:
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
@ -622,7 +652,6 @@ proc callCCompiler*(projectfile: string) =
if optGenStaticLib in gGlobalOptions: if optGenStaticLib in gGlobalOptions:
linkCmd = CC[c].buildLib % ["libfile", (libNameTmpl() % gProjectName), linkCmd = CC[c].buildLib % ["libfile", (libNameTmpl() % gProjectName),
"objfiles", objfiles] "objfiles", objfiles]
if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
else: else:
var linkerExe = getConfigVar(c, ".linkerexe") var linkerExe = getConfigVar(c, ".linkerexe")
if len(linkerExe) == 0: linkerExe = c.getLinkerExe if len(linkerExe) == 0: linkerExe = c.getLinkerExe
@ -654,7 +683,11 @@ proc callCCompiler*(projectfile: string) =
"objfiles", objfiles, "exefile", exefile, "objfiles", objfiles, "exefile", exefile,
"nimrod", quoteShell(getPrefixDir()), "nimrod", quoteShell(getPrefixDir()),
"lib", quoteShell(libpath)]) "lib", quoteShell(libpath)])
if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd) if optCompileOnly notin gGlobalOptions:
if gVerbosity == 1:
execExternalProgram(linkCmd, "[Linking]")
else:
execExternalProgram(linkCmd)
else: else:
linkCmd = "" linkCmd = ""
if optGenScript in gGlobalOptions: if optGenScript in gGlobalOptions:

View file

@ -11,7 +11,7 @@
# This is needed for proper handling of forward declarations. # This is needed for proper handling of forward declarations.
import import
ast, astalgo, msgs, semdata, types, trees ast, astalgo, msgs, semdata, types, trees, strutils
proc equalGenericParams(procA, procB: PNode): bool = proc equalGenericParams(procA, procB: PNode): bool =
if sonsLen(procA) != sonsLen(procB): return if sonsLen(procA) != sonsLen(procB): return
@ -68,11 +68,17 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
ExactConstraints, IgnoreCC} ExactConstraints, IgnoreCC}
var it: TIdentIter var it: TIdentIter
result = initIdentIter(it, scope.symbols, fn.name) result = initIdentIter(it, scope.symbols, fn.name)
while result != nil: while result != nil:
if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags): if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
case equalParams(result.typ.n, fn.typ.n) case equalParams(result.typ.n, fn.typ.n)
of paramsEqual: of paramsEqual:
if (sfExported notin result.flags) and (sfExported in fn.flags):
let message = ("public implementation '$1' has non-public " &
"forward declaration in $2") %
[getProcHeader(result), $result.info]
localError(fn.info, errGenerated, message)
return return
of paramsIncompatible: of paramsIncompatible:
localError(fn.info, errNotOverloadable, fn.name.s) localError(fn.info, errNotOverloadable, fn.name.s)

View file

@ -71,7 +71,7 @@ hint[LineTooLong]=off
@if not bsd: @if not bsd:
# -fopenmp # -fopenmp
gcc.options.linker = "-ldl" gcc.options.linker = "-ldl"
gpp.options.linker = "-ldl" gcc.cpp.options.linker = "-ldl"
clang.options.linker = "-ldl" clang.options.linker = "-ldl"
tcc.options.linker = "-ldl" tcc.options.linker = "-ldl"
@end @end
@ -101,19 +101,19 @@ hint[LineTooLong]=off
cc = clang cc = clang
tlsEmulation:on tlsEmulation:on
gcc.options.always = "-w -fasm-blocks" gcc.options.always = "-w -fasm-blocks"
gpp.options.always = "-w -fasm-blocks -fpermissive" gcc.cpp.options.always = "-w -fasm-blocks -fpermissive"
@else: @else:
gcc.options.always = "-w" gcc.options.always = "-w"
gpp.options.always = "-w -fpermissive" gcc.cpp.options.always = "-w -fpermissive"
@end @end
gcc.options.speed = "-O3 -fno-strict-aliasing" gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os" gcc.options.size = "-Os"
gcc.options.debug = "-g3 -O0" gcc.options.debug = "-g3 -O0"
gpp.options.speed = "-O3 -fno-strict-aliasing" gcc.cpp.options.speed = "-O3 -fno-strict-aliasing"
gpp.options.size = "-Os" gcc.cpp.options.size = "-Os"
gpp.options.debug = "-g3 -O0" gcc.cpp.options.debug = "-g3 -O0"
#passl = "-pg" #passl = "-pg"
# Configuration for the LLVM GCC compiler: # Configuration for the LLVM GCC compiler:

View file

@ -55,7 +55,7 @@ proc oidToString*(oid: Oid, str: cstring) =
str[24] = '\0' str[24] = '\0'
proc `$`*(oid: Oid): string = proc `$`*(oid: Oid): string =
result = newString(25) result = newString(24)
oidToString(oid, result) oidToString(oid, result)
var var

View file

@ -235,11 +235,13 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
proc execProcesses*(cmds: openArray[string], proc execProcesses*(cmds: openArray[string],
options = {poStdErrToStdOut, poParentStreams}, options = {poStdErrToStdOut, poParentStreams},
n = countProcessors()): int {.rtl, extern: "nosp$1", n = countProcessors(),
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect]} = beforeRunEvent: proc(idx: int) = nil): int
{.rtl, extern: "nosp$1",
tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect]} =
## executes the commands `cmds` in parallel. Creates `n` processes ## executes the commands `cmds` in parallel. Creates `n` processes
## that execute in parallel. The highest return value of all processes ## that execute in parallel. The highest return value of all processes
## is returned. ## is returned. Runs `beforeRunEvent` before running each command.
when defined(posix): when defined(posix):
# poParentStreams causes problems on Posix, so we simply disable it: # poParentStreams causes problems on Posix, so we simply disable it:
var options = options - {poParentStreams} var options = options - {poParentStreams}
@ -250,6 +252,8 @@ proc execProcesses*(cmds: openArray[string],
newSeq(q, n) newSeq(q, n)
var m = min(n, cmds.len) var m = min(n, cmds.len)
for i in 0..m-1: for i in 0..m-1:
if beforeRunEvent != nil:
beforeRunEvent(i)
q[i] = startCmd(cmds[i], options=options) q[i] = startCmd(cmds[i], options=options)
when defined(noBusyWaiting): when defined(noBusyWaiting):
var r = 0 var r = 0
@ -263,6 +267,8 @@ proc execProcesses*(cmds: openArray[string],
echo(err) echo(err)
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil:
beforeRunEvent(i)
q[r] = startCmd(cmds[i], options=options) q[r] = startCmd(cmds[i], options=options)
r = (r + 1) mod n r = (r + 1) mod n
else: else:
@ -274,6 +280,8 @@ proc execProcesses*(cmds: openArray[string],
#echo(outputStream(q[r]).readLine()) #echo(outputStream(q[r]).readLine())
result = max(waitForExit(q[r]), result) result = max(waitForExit(q[r]), result)
if q[r] != nil: close(q[r]) if q[r] != nil: close(q[r])
if beforeRunEvent != nil:
beforeRunEvent(i)
q[r] = startCmd(cmds[i], options=options) q[r] = startCmd(cmds[i], options=options)
inc(i) inc(i)
if i > high(cmds): break if i > high(cmds): break
@ -282,6 +290,8 @@ proc execProcesses*(cmds: openArray[string],
if q[j] != nil: close(q[j]) if q[j] != nil: close(q[j])
else: else:
for i in 0..high(cmds): for i in 0..high(cmds):
if beforeRunEvent != nil:
beforeRunEvent(i)
var p = startCmd(cmds[i], options=options) var p = startCmd(cmds[i], options=options)
result = max(waitForExit(p), result) result = max(waitForExit(p), result)
close(p) close(p)

View file

@ -0,0 +1,9 @@
discard """
line: 8
errormsg: "public implementation 'tmismatchedvisibility.foo(a: int): int' has non-public forward declaration in tmismatchedvisibility.nim(6,5)"
"""
proc foo(a: int): int
proc foo*(a: int): int =
result = a + a

View file

@ -20,6 +20,7 @@ REM call the compiler:
ECHO %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")} ECHO %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
%CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")} %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
# linkCmd.add(" " & changeFileExt(f, "o")) # linkCmd.add(" " & changeFileExt(f, "o"))
IF ERRORLEVEL 1 (GOTO:END)
# end for # end for
ECHO %LINKER% -o ?{"%BIN_DIR%"\toLower(c.name)}.exe ?linkCmd %LINK_FLAGS% ECHO %LINKER% -o ?{"%BIN_DIR%"\toLower(c.name)}.exe ?linkCmd %LINK_FLAGS%
@ -27,4 +28,14 @@ ECHO %LINKER% -o ?{"%BIN_DIR%"\toLower(c.name)}.exe ?linkCmd %LINK_FLAGS%
# end block # end block
ECHO SUCCESS :END
IF ERRORLEVEL 1 (
ECHO FAILURE
ECHO.
ECHO CSource compilation failed. Please check that the gcc compiler is in
ECHO the PATH environment variable, and that you are calling the batch script
ECHO that matches the target architecture of the compiler.
) ELSE (
ECHO SUCCESS
)
exit /b %ERRORLEVEL%