implements #173
This commit is contained in:
parent
2ff8d17369
commit
538b06a123
11 changed files with 114 additions and 39 deletions
|
|
@ -653,7 +653,10 @@ proc genProcHeader(m: BModule, prc: PSym): PRope =
|
||||||
genCLineDir(result, prc.info)
|
genCLineDir(result, prc.info)
|
||||||
# using static is needed for inline procs
|
# using static is needed for inline procs
|
||||||
if gCmd != cmdCompileToLLVM and lfExportLib in prc.loc.flags:
|
if gCmd != cmdCompileToLLVM and lfExportLib in prc.loc.flags:
|
||||||
result.app "N_LIB_EXPORT "
|
if m.isHeaderFile:
|
||||||
|
result.app "N_LIB_IMPORT "
|
||||||
|
else:
|
||||||
|
result.app "N_LIB_EXPORT "
|
||||||
elif prc.typ.callConv == ccInline:
|
elif prc.typ.callConv == ccInline:
|
||||||
result.app "static "
|
result.app "static "
|
||||||
var check = initIntSet()
|
var check = initIntSet()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ when options.hasTinyCBackend:
|
||||||
proc cgenPass*(): TPass
|
proc cgenPass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
|
var
|
||||||
|
generatedHeader: BModule
|
||||||
|
|
||||||
proc ropeff(cformat, llvmformat: string, args: openarray[PRope]): PRope =
|
proc ropeff(cformat, llvmformat: string, args: openarray[PRope]): PRope =
|
||||||
if gCmd == cmdCompileToLLVM: result = ropef(llvmformat, args)
|
if gCmd == cmdCompileToLLVM: result = ropef(llvmformat, args)
|
||||||
else: result = ropef(cformat, args)
|
else: result = ropef(cformat, args)
|
||||||
|
|
@ -754,16 +757,26 @@ proc requestConstImpl(p: BProc, sym: PSym) =
|
||||||
# declare header:
|
# declare header:
|
||||||
if q != m and not ContainsOrIncl(m.declaredThings, sym.id):
|
if q != m and not ContainsOrIncl(m.declaredThings, sym.id):
|
||||||
assert(sym.loc.r != nil)
|
assert(sym.loc.r != nil)
|
||||||
appf(m.s[cfsData], "extern NIM_CONST $1 $2;$n",
|
let headerDecl = ropef("extern NIM_CONST $1 $2;$n",
|
||||||
[getTypeDesc(m, sym.loc.t), sym.loc.r])
|
[getTypeDesc(m, sym.loc.t), sym.loc.r])
|
||||||
|
app(m.s[cfsData], headerDecl)
|
||||||
|
if sfExportc in sym.flags and generatedHeader != nil:
|
||||||
|
app(generatedHeader.s[cfsData], headerDecl)
|
||||||
|
|
||||||
proc genProc(m: BModule, prc: PSym) =
|
proc genProc(m: BModule, prc: PSym) =
|
||||||
if sfBorrow in prc.flags: return
|
if sfBorrow in prc.flags: return
|
||||||
fillProcLoc(prc)
|
fillProcLoc(prc)
|
||||||
if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc)
|
if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc)
|
||||||
else: genProcNoForward(m, prc)
|
else:
|
||||||
|
genProcNoForward(m, prc)
|
||||||
|
if {sfExportc, sfCompilerProc} * prc.flags == {sfExportc} and
|
||||||
|
generatedHeader != nil and lfNoDecl notin prc.loc.Flags:
|
||||||
|
genProcPrototype(generatedHeader, prc)
|
||||||
|
if prc.typ.callConv == ccInline:
|
||||||
|
if not ContainsOrIncl(generatedHeader.declaredThings, prc.id):
|
||||||
|
genProcAux(generatedHeader, prc)
|
||||||
|
|
||||||
proc genVarPrototype(m: BModule, sym: PSym) =
|
proc genVarPrototypeAux(m: BModule, sym: PSym) =
|
||||||
assert(sfGlobal in sym.flags)
|
assert(sfGlobal in sym.flags)
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
|
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
|
||||||
|
|
@ -782,25 +795,12 @@ proc genVarPrototype(m: BModule, sym: PSym) =
|
||||||
if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile")
|
if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile")
|
||||||
appf(m.s[cfsVars], " $1;$n", [sym.loc.r])
|
appf(m.s[cfsVars], " $1;$n", [sym.loc.r])
|
||||||
|
|
||||||
proc getFileHeader(cfilenoext: string): PRope =
|
proc genVarPrototype(m: BModule, sym: PSym) =
|
||||||
if optCompileOnly in gGlobalOptions:
|
genVarPrototypeAux(m, sym)
|
||||||
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
|
if sfExportc in sym.flags and generatedHeader != nil:
|
||||||
"/* (c) 2012 Andreas Rumpf */$n",
|
genVarPrototypeAux(generatedHeader, sym)
|
||||||
"; Generated by Nimrod Compiler v$1$n" &
|
|
||||||
"; (c) 2012 Andreas Rumpf$n", [toRope(versionAsString)])
|
proc addIntTypes(result: var PRope) =
|
||||||
else:
|
|
||||||
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
|
|
||||||
"/* (c) 2012 Andreas Rumpf */$n" &
|
|
||||||
"/* Compiled for: $2, $3, $4 */$n" &
|
|
||||||
"/* Command for C compiler:$n $5 */$n",
|
|
||||||
"; Generated by Nimrod Compiler v$1$n" &
|
|
||||||
"; (c) 2012 Andreas Rumpf$n" &
|
|
||||||
"; Compiled for: $2, $3, $4$n" &
|
|
||||||
"; Command for LLVM compiler:$n $5$n", [toRope(versionAsString),
|
|
||||||
toRope(platform.OS[targetOS].name),
|
|
||||||
toRope(platform.CPU[targetCPU].name),
|
|
||||||
toRope(extccomp.CC[extccomp.ccompiler].name),
|
|
||||||
toRope(getCompileCFileCmd(cfilenoext))])
|
|
||||||
case platform.CPU[targetCPU].intSize
|
case platform.CPU[targetCPU].intSize
|
||||||
of 16:
|
of 16:
|
||||||
appff(result,
|
appff(result,
|
||||||
|
|
@ -813,8 +813,33 @@ proc getFileHeader(cfilenoext: string): PRope =
|
||||||
of 64:
|
of 64:
|
||||||
appff(result, "$ntypedef long long int NI;$n" &
|
appff(result, "$ntypedef long long int NI;$n" &
|
||||||
"typedef unsigned long long int NU;$n", "$n%NI = type i64$n", [])
|
"typedef unsigned long long int NU;$n", "$n%NI = type i64$n", [])
|
||||||
|
else: nil
|
||||||
|
|
||||||
|
proc getCopyright(cfilenoext: string): PRope =
|
||||||
|
if optCompileOnly in gGlobalOptions:
|
||||||
|
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
|
||||||
|
"/* (c) 2012 Andreas Rumpf */$n" &
|
||||||
|
"/* The generated code is subject to the original license. */$n",
|
||||||
|
"; Generated by Nimrod Compiler v$1$n" &
|
||||||
|
"; (c) 2012 Andreas Rumpf$n", [toRope(versionAsString)])
|
||||||
else:
|
else:
|
||||||
nil
|
result = ropeff("/* Generated by Nimrod Compiler v$1 */$n" &
|
||||||
|
"/* (c) 2012 Andreas Rumpf */$n" &
|
||||||
|
"/* The generated code is subject to the original license. */$n" &
|
||||||
|
"/* Compiled for: $2, $3, $4 */$n" &
|
||||||
|
"/* Command for C compiler:$n $5 */$n",
|
||||||
|
"; Generated by Nimrod Compiler v$1$n" &
|
||||||
|
"; (c) 2012 Andreas Rumpf$n" &
|
||||||
|
"; Compiled for: $2, $3, $4$n" &
|
||||||
|
"; Command for LLVM compiler:$n $5$n", [toRope(versionAsString),
|
||||||
|
toRope(platform.OS[targetOS].name),
|
||||||
|
toRope(platform.CPU[targetCPU].name),
|
||||||
|
toRope(extccomp.CC[extccomp.ccompiler].name),
|
||||||
|
toRope(getCompileCFileCmd(cfilenoext))])
|
||||||
|
|
||||||
|
proc getFileHeader(cfilenoext: string): PRope =
|
||||||
|
result = getCopyright(cfilenoext)
|
||||||
|
addIntTypes(result)
|
||||||
|
|
||||||
proc genMainProc(m: BModule) =
|
proc genMainProc(m: BModule) =
|
||||||
const
|
const
|
||||||
|
|
@ -1008,6 +1033,31 @@ proc newModule(module: PSym, filename: string): BModule =
|
||||||
|
|
||||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||||
result = newModule(module, filename)
|
result = newModule(module, filename)
|
||||||
|
if optGenIndex in gGlobalOptions and generatedHeader == nil:
|
||||||
|
let f = if headerFile.len > 0: headerFile else: gProjectFull
|
||||||
|
generatedHeader = rawNewModule(module,
|
||||||
|
changeFileExt(completeCFilePath(f), hExt))
|
||||||
|
generatedHeader.isHeaderFile = true
|
||||||
|
|
||||||
|
proc writeHeader(m: BModule) =
|
||||||
|
var result = getCopyright(m.filename)
|
||||||
|
var guard = ropef("__$1__", m.filename.splitFile.name.toRope)
|
||||||
|
result.appf("#ifndef $1$n#define $1$n", guard)
|
||||||
|
addIntTypes(result)
|
||||||
|
generateHeaders(m)
|
||||||
|
|
||||||
|
generateThreadLocalStorage(m)
|
||||||
|
for i in countup(cfsHeaders, cfsProcs):
|
||||||
|
app(result, genSectionStart(i))
|
||||||
|
app(result, m.s[i])
|
||||||
|
app(result, genSectionEnd(i))
|
||||||
|
app(result, m.s[cfsInitProc])
|
||||||
|
|
||||||
|
if optGenDynLib in gGlobalOptions:
|
||||||
|
result.app("N_LIB_IMPORT ")
|
||||||
|
result.appf("N_CDECL(void, NimMain)(void);$n")
|
||||||
|
result.appf("#endif /* $1 */$n", guard)
|
||||||
|
writeRope(result, m.filename)
|
||||||
|
|
||||||
proc getCFile(m: BModule): string =
|
proc getCFile(m: BModule): string =
|
||||||
result = changeFileExt(completeCFilePath(m.cfilename), cExt)
|
result = changeFileExt(completeCFilePath(m.cfilename), cExt)
|
||||||
|
|
@ -1106,12 +1156,14 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
# we need to process the transitive closure because recursive module
|
# we need to process the transitive closure because recursive module
|
||||||
# deps are allowed (and the system module is processed in the wrong
|
# deps are allowed (and the system module is processed in the wrong
|
||||||
# order anyway)
|
# order anyway)
|
||||||
|
if generatedHeader != nil: finishModule(generatedHeader)
|
||||||
while gForwardedProcsCounter > 0:
|
while gForwardedProcsCounter > 0:
|
||||||
for i in countup(0, high(gModules)):
|
for i in countup(0, high(gModules)):
|
||||||
finishModule(gModules[i])
|
finishModule(gModules[i])
|
||||||
for i in countup(0, high(gModules)):
|
for i in countup(0, high(gModules)):
|
||||||
writeModule(gModules[i], pending=true)
|
writeModule(gModules[i], pending=true)
|
||||||
writeMapping(gMapping)
|
writeMapping(gMapping)
|
||||||
|
if generatedHeader != nil: writeHeader(generatedHeader)
|
||||||
|
|
||||||
proc cgenPass(): TPass =
|
proc cgenPass(): TPass =
|
||||||
initPass(result)
|
initPass(result)
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ type
|
||||||
usesThreadVars*: bool # true if the module uses a thread var
|
usesThreadVars*: bool # true if the module uses a thread var
|
||||||
FrameDeclared*: bool # hack for ROD support so that we don't declare
|
FrameDeclared*: bool # hack for ROD support so that we don't declare
|
||||||
# a frame var twice in an init proc
|
# a frame var twice in an init proc
|
||||||
|
isHeaderFile*: bool # C source file is the header file
|
||||||
cfilename*: string # filename of the module (including path,
|
cfilename*: string # filename of the module (including path,
|
||||||
# without extension)
|
# without extension)
|
||||||
typeCache*: TIdTable # cache the generated types
|
typeCache*: TIdTable # cache the generated types
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of "clib":
|
of "clib":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
if pass in {passCmd2, passPP}: cLinkedLibs.add arg
|
if pass in {passCmd2, passPP}: cLinkedLibs.add arg
|
||||||
|
of "header":
|
||||||
|
headerFile = arg
|
||||||
|
incl(gGlobalOptions, optGenIndex)
|
||||||
of "index":
|
of "index":
|
||||||
ProcessOnOffSwitchG({optGenIndex}, arg, pass, info)
|
ProcessOnOffSwitchG({optGenIndex}, arg, pass, info)
|
||||||
of "import":
|
of "import":
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,9 @@ type
|
||||||
hintSuccess, hintSuccessX,
|
hintSuccess, hintSuccessX,
|
||||||
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
|
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
|
||||||
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
|
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
|
||||||
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser
|
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
|
||||||
|
hintConditionAlwaysTrue,
|
||||||
|
hintUser
|
||||||
|
|
||||||
const
|
const
|
||||||
MsgKindToStr*: array[TMsgKind, string] = [
|
MsgKindToStr*: array[TMsgKind, string] = [
|
||||||
|
|
@ -361,6 +363,7 @@ const
|
||||||
hintCodeEnd: "end of listing [CodeEnd]",
|
hintCodeEnd: "end of listing [CodeEnd]",
|
||||||
hintConf: "used config file \'$1\' [Conf]",
|
hintConf: "used config file \'$1\' [Conf]",
|
||||||
hintPath: "added path: '$1' [Path]",
|
hintPath: "added path: '$1' [Path]",
|
||||||
|
hintConditionAlwaysTrue: "condition is always true: '$1' [CondTrue]",
|
||||||
hintUser: "$1 [User]"]
|
hintUser: "$1 [User]"]
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -373,10 +376,10 @@ const
|
||||||
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
|
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap",
|
||||||
"ImplicitClosure", "EachIdentIsTuple", "User"]
|
"ImplicitClosure", "EachIdentIsTuple", "User"]
|
||||||
|
|
||||||
HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong",
|
HintsToStr*: array[0..14, string] = ["Success", "SuccessX", "LineTooLong",
|
||||||
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||||
"Path",
|
"Path", "CondTrue",
|
||||||
"User"]
|
"User"]
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,8 @@ type # please make sure we have under 32 options
|
||||||
optThreadAnalysis, # thread analysis pass
|
optThreadAnalysis, # thread analysis pass
|
||||||
optTaintMode, # taint mode turned on
|
optTaintMode, # taint mode turned on
|
||||||
optTlsEmulation, # thread var emulation turned on
|
optTlsEmulation, # thread var emulation turned on
|
||||||
optGenIndex # generate index file for documentation
|
optGenIndex # generate index file for documentation;
|
||||||
|
# also: generate header file
|
||||||
|
|
||||||
TGlobalOptions* = set[TGlobalOption]
|
TGlobalOptions* = set[TGlobalOption]
|
||||||
TCommands* = enum # Nimrod's commands
|
TCommands* = enum # Nimrod's commands
|
||||||
|
|
@ -85,6 +86,7 @@ var
|
||||||
gExitcode*: int8
|
gExitcode*: int8
|
||||||
searchPaths*: TLinkedList
|
searchPaths*: TLinkedList
|
||||||
outFile*: string = ""
|
outFile*: string = ""
|
||||||
|
headerFile*: string = ""
|
||||||
gCmd*: TCommands = cmdNone # the command
|
gCmd*: TCommands = cmdNone # the command
|
||||||
gVerbosity*: int # how verbose the compiler is
|
gVerbosity*: int # how verbose the compiler is
|
||||||
gNumberOfProcessors*: int # number of processors
|
gNumberOfProcessors*: int # number of processors
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ proc freezeMutableRope*(r: PRope) {.inline.} =
|
||||||
r.length = r.data.len
|
r.length = r.data.len
|
||||||
|
|
||||||
var
|
var
|
||||||
cache: array[0..2048 -1, PRope]
|
cache: array[0..2048*2 -1, PRope]
|
||||||
|
|
||||||
proc RopeInvariant(r: PRope): bool =
|
proc RopeInvariant(r: PRope): bool =
|
||||||
if r == nil:
|
if r == nil:
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,6 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
n.sons[1] = semExprWithType(c, n.sons[1])
|
n.sons[1] = semExprWithType(c, n.sons[1])
|
||||||
restoreOldStyleType(n.sons[1])
|
restoreOldStyleType(n.sons[1])
|
||||||
|
|
||||||
n.typ = getSysType(tyInt)
|
n.typ = getSysType(tyInt)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
|
|
@ -252,8 +251,19 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||||
var b = skipTypes(n.sons[2].typ, abstractPtrs)
|
var b = skipTypes(n.sons[2].typ, abstractPtrs)
|
||||||
if b.kind != tyObject or a.kind != tyObject:
|
if b.kind != tyObject or a.kind != tyObject:
|
||||||
GlobalError(n.info, errXExpectsObjectTypes, "of")
|
GlobalError(n.info, errXExpectsObjectTypes, "of")
|
||||||
while b != nil and b.id != a.id: b = b.sons[0]
|
let diff = inheritanceDiff(a, b)
|
||||||
if b == nil:
|
# | returns: 0 iff `a` == `b`
|
||||||
|
# | returns: -x iff `a` is the x'th direct superclass of `b`
|
||||||
|
# | returns: +x iff `a` is the x'th direct subclass of `b`
|
||||||
|
# | returns: `maxint` iff `a` and `b` are not compatible at all
|
||||||
|
if diff <= 0:
|
||||||
|
# optimize to true:
|
||||||
|
Message(n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||||
|
result = newIntNode(nkIntLit, 1)
|
||||||
|
result.info = n.info
|
||||||
|
result.typ = getSysType(tyBool)
|
||||||
|
return result
|
||||||
|
elif diff == high(int):
|
||||||
GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
|
||||||
n.typ = getSysType(tyBool)
|
n.typ = getSysType(tyBool)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ type
|
||||||
nestedProcs: int # > 0 if we are in a nested proc
|
nestedProcs: int # > 0 if we are in a nested proc
|
||||||
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
||||||
inLoop: int # > 0 if we are in a loop
|
inLoop: int # > 0 if we are in a loop
|
||||||
transformedInnerProcs: TIntSet
|
|
||||||
PTransf = ref TTransfContext
|
PTransf = ref TTransfContext
|
||||||
|
|
||||||
proc newTransNode(a: PNode): PTransNode {.inline.} =
|
proc newTransNode(a: PNode): PTransNode {.inline.} =
|
||||||
|
|
@ -753,7 +752,6 @@ proc openTransf(module: PSym, filename: string): PPassContext =
|
||||||
n.contSyms = @[]
|
n.contSyms = @[]
|
||||||
n.breakSyms = @[]
|
n.breakSyms = @[]
|
||||||
n.module = module
|
n.module = module
|
||||||
n.transformedInnerProcs = initIntSet()
|
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc openTransfCached(module: PSym, filename: string,
|
proc openTransfCached(module: PSym, filename: string,
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ const
|
||||||
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal}
|
abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal}
|
||||||
|
|
||||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable}
|
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable}
|
||||||
|
typeclassPtrs* = abstractPtrs + {tyTypeClass}
|
||||||
|
|
||||||
proc skipTypes*(t: PType, kinds: TTypeKinds): PType
|
proc skipTypes*(t: PType, kinds: TTypeKinds): PType
|
||||||
proc containsObject*(t: PType): bool
|
proc containsObject*(t: PType): bool
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ Advanced options:
|
||||||
--import:PATH add an automatically imported module
|
--import:PATH add an automatically imported module
|
||||||
--include:PATH add an automatically included module
|
--include:PATH add an automatically included module
|
||||||
--nimcache:PATH set the path used for generated files
|
--nimcache:PATH set the path used for generated files
|
||||||
|
--header:FILE the compiler should produce a .h file (FILE
|
||||||
|
is optional)
|
||||||
-c, --compileOnly compile only; do not assemble or link
|
-c, --compileOnly compile only; do not assemble or link
|
||||||
--noLinking compile but do not link
|
--noLinking compile but do not link
|
||||||
--noMain do not generate a main procedure
|
--noMain do not generate a main procedure
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue