summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-11-26 10:49:48 +0100
committerAraq <rumpf_a@web.de>2011-11-26 10:49:48 +0100
commit840979b45caea47c97c3eaac145841464ab5e5b1 (patch)
treee362829bad55797efc0542993a8303b412022560
parentf7f0c90ffe11952472ef6246c90c32d0e65c6b5f (diff)
parentc617479c6848e07f25f92fd33b3397d65683812e (diff)
downloadNim-840979b45caea47c97c3eaac145841464ab5e5b1.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
-rwxr-xr-xcompiler/commands.nim38
-rwxr-xr-xcompiler/docgen.nim23
-rwxr-xr-xcompiler/extccomp.nim550
-rwxr-xr-xcompiler/main.nim157
-rwxr-xr-xcompiler/msgs.nim6
-rwxr-xr-xcompiler/nimconf.nim38
-rwxr-xr-xcompiler/nimrod.nim55
-rwxr-xr-xcompiler/options.nim26
-rwxr-xr-xcompiler/passes.nim14
-rwxr-xr-xcompiler/semfold.nim6
-rwxr-xr-xdoc/advopt.txt10
-rwxr-xr-xdoc/basicopt.txt3
-rwxr-xr-xlib/pure/os.nim32
-rwxr-xr-xweb/news.txt16
14 files changed, 586 insertions, 388 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim
index cf172111a..c6e00265f 100755
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -244,6 +244,10 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "out", "o": 
     expectArg(switch, arg, pass, info)
     options.outFile = arg
+  of "mainmodule", "m":
+    expectArg(switch, arg, pass, info)
+    projectName = arg
+    projectFullPath = projectPath/projectName
   of "define", "d": 
     expectArg(switch, arg, pass, info)
     DefineSymbol(arg)
@@ -333,15 +337,24 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "app": 
     expectArg(switch, arg, pass, info)
     case arg.normalize
-    of "gui": 
+    of "gui":
       incl(gGlobalOptions, optGenGuiApp)
+      defineSymbol("executable")
       defineSymbol("guiapp")
-    of "console": 
+    of "console":
       excl(gGlobalOptions, optGenGuiApp)
-    of "lib": 
+      defineSymbol("executable")
+      defineSymbol("consoleapp")
+    of "lib":
       incl(gGlobalOptions, optGenDynLib)
       excl(gGlobalOptions, optGenGuiApp)
       defineSymbol("library")
+      defineSymbol("dll")
+    of "staticlib":
+      incl(gGlobalOptions, optGenStaticLib)
+      excl(gGlobalOptions, optGenGuiApp)
+      defineSymbol("library")
+      defineSymbol("staticlib")
     else: LocalError(info, errGuiConsoleOrLibExpectedButXFound, arg)
   of "passc", "t": 
     expectArg(switch, arg, pass, info)
@@ -349,12 +362,24 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "passl", "l": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: extccomp.addLinkOption(arg)
+  of "cincludes":
+    expectArg(switch, arg, pass, info)
+    if pass in {passCmd2, passPP}: cIncludes.add arg
+  of "clibdir":
+    expectArg(switch, arg, pass, info)
+    if pass in {passCmd2, passPP}: cLibs.add arg
+  of "clib":
+    expectArg(switch, arg, pass, info)
+    if pass in {passCmd2, passPP}: cLinkedLibs.add arg
   of "index": 
     expectArg(switch, arg, pass, info)
     if pass in {passCmd2, passPP}: gIndexFile = arg
-  of "import": 
+  of "import":
     expectArg(switch, arg, pass, info)
-    options.addImplicitMod(arg)
+    if pass in {passCmd2, passPP}: implicitImports.add arg
+  of "include":
+    expectArg(switch, arg, pass, info)
+    if pass in {passCmd2, passPP}: implicitIncludes.add arg
   of "listcmd": 
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optListCmd)
@@ -405,6 +430,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
   of "skipprojcfg": 
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optSkipProjConfigFile)
+  of "skipusercfg":
+    expectNoArg(switch, arg, pass, info)
+    incl(gGlobalOptions, optSkipUserConfigFile)
   of "genscript": 
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optGenScript)
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 411f93115..e76545c22 100755
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -15,9 +15,9 @@ import
   ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents, 
   wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite
 
-proc CommandDoc*(filename: string)
-proc CommandRst2Html*(filename: string)
-proc CommandRst2TeX*(filename: string)
+proc CommandDoc*()
+proc CommandRst2Html*()
+proc CommandRst2TeX*()
 # implementation
 
 type 
@@ -870,14 +870,14 @@ proc writeOutput(d: PDoc, filename, outExt: string) =
   else:
     writeRope(content, getOutFile(filename, outExt))
 
-proc CommandDoc(filename: string) = 
-  var ast = parseFile(addFileExt(filename, nimExt))
+proc CommandDoc =
+  var ast = parseFile(addFileExt(projectFullPath, nimExt))
   if ast == nil: return 
-  var d = newDocumentor(filename)
+  var d = newDocumentor(projectFullPath)
   initIndexFile(d)
   d.hasToc = true
   generateDoc(d, ast)
-  writeOutput(d, filename, HtmlExt)
+  writeOutput(d, projectFullPath, HtmlExt)
   generateIndex(d)
 
 proc CommandRstAux(filename, outExt: string) = 
@@ -889,9 +889,10 @@ proc CommandRstAux(filename, outExt: string) =
   writeOutput(d, filename, outExt)
   generateIndex(d)
 
-proc CommandRst2Html(filename: string) = 
-  CommandRstAux(filename, HtmlExt)
+proc CommandRst2Html =
+  CommandRstAux(projectFullPath, HtmlExt)
 
-proc CommandRst2TeX(filename: string) = 
+proc CommandRst2TeX =
   splitter = "\\-"
-  CommandRstAux(filename, TexExt)
+  CommandRstAux(projectFullPath, TexExt)
+
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index a6dfe7367..9184b3368 100755
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -32,223 +32,290 @@ type
     compileTmpl: string, # the compile command template
     buildGui: string,    # command to build a GUI application
     buildDll: string,    # command to build a shared library
+    buildLib: string,    # command to build a static library
     linkerExe: string,   # the linker's executable
     linkTmpl: string,    # command to link files to produce an exe
     includeCmd: string,  # command to add an include dir
+    linkDirCmd: string,  # command to add a lib dir
+    linkLibCmd: string,  # command to link an external library
     debug: string,       # flags for debug build
     pic: string,         # command for position independent code
                          # used on some platforms
     asmStmtFrmt: string, # format of ASM statement
     props: TInfoCCProps] # properties of the C compiler
 
+
+# Configuration settings for various compilers. 
+# When adding new compilers, the cmake sources could be a good reference:
+# http://cmake.org/gitweb?p=cmake.git;a=tree;f=Modules/Platform;
+
+template compiler(name: expr, settings: stmt):stmt =
+  proc name: TInfoCC {.compileTime.} = settings
+
+compiler gcc:
+  result = (
+    name: "gcc",
+    objExt: "o",
+    optSpeed: " -O3 -ffast-math ",
+    optSize: " -Os -ffast-math ",
+    compilerExe: "gcc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: " -mwindows",
+    buildDll: " -shared",
+    buildLib: "ar rcs $libfile $objfiles",
+    linkerExe: "gcc",
+    linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options",
+    includeCmd: " -I",
+    linkDirCmd: " -L",
+    linkLibCmd: " -l$1",
+    debug: "",
+    pic: "-fPIC",
+    asmStmtFrmt: "asm($1);$n",
+    props: {hasSwitchRange, hasComputedGoto, hasCpp})
+    
+compiler gpp:
+  result = gcc()
+  
+  result.name = "gpp"
+  result.compilerExe = "g++"
+  result.linkerExe = "g++"  
+  
+  result.debug.add " -g " # XXX: Why is this default for g++, but not for gcc?
+
+  result.buildDll = " -mdll" # XXX: Hmm, I'm keeping this from the previos version, 
+                             # but my gcc doesn't even have such an option (is this mingw?)
+
+compiler llvmGcc:
+  result = gcc()
+  
+  result.name = "llvm_gcc"
+  result.compilerExe = "llvm-gcc"
+  result.buildLib = "llvm-ar rcs $libfile $objfiles"
+  result.linkerExe = "llvm-gcc"
+
+compiler clang:
+  result = llvmGcc()
+
+  result.name = "clang"
+  result.compilerExe = "clang"
+  result.linkerExe = "clang"
+
+compiler vcc:
+  result = (
+    name: "vcc",
+    objExt: "obj",
+    optSpeed: " /Ogityb2 /G7 /arch:SSE2 ",
+    optSize: " /O1 /G7 ",
+    compilerExe: "cl",
+    compileTmpl: "/c $options $include /Fo$objfile $file",
+    buildGui: " /link /SUBSYSTEM:WINDOWS ",
+    buildDll: " /LD",
+    buildLib: "lib /OUT:$libfile $objfiles",
+    linkerExe: "cl",
+    linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui",
+    includeCmd: " /I",
+    linkDirCmd: " /LIBPATH:",
+    linkLibCmd: " $1.lib",
+    debug: " /GZ /Zi ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp, hasAssume})
+
+compiler icc:
+  # Intel compilers try to imitate the native ones (gcc and msvc)
+  when defined(windows):
+    result = vcc()
+  else:
+    result = gcc()
+
+  result.name = "icc"
+  result.compilerExe = "icc"
+  result.linkerExe = "icc"
+
+compiler lcc:
+  result = (
+    name: "lcc",
+    objExt: "obj",
+    optSpeed: " -O -p6 ",
+    optSize: " -O -p6 ",
+    compilerExe: "lcc",
+    compileTmpl: "$options $include -Fo$objfile $file",
+    buildGui: " -subsystem windows",
+    buildDll: " -dll",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "lcclnk",
+    linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g5 ",
+    pic: "",
+    asmStmtFrmt: "_asm{$n$1$n}$n",
+    props: {})
+
+compiler bcc:
+  result = (
+    name: "bcc",
+    objExt: "obj",
+    optSpeed: " -O2 -6 ",
+    optSize: " -O1 -6 ",
+    compilerExe: "bcc32",
+    compileTmpl: "-c $options $include -o$objfile $file",
+    buildGui: " -tW",
+    buildDll: " -tWD",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "bcc32",
+    linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: "",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler dmc:
+  result = (
+    name: "dmc",
+    objExt: "obj",
+    optSpeed: " -ff -o -6 ",
+    optSize: " -ff -o -6 ",
+    compilerExe: "dmc",
+    compileTmpl: "-c $options $include -o$objfile $file",
+    buildGui: " -L/exet:nt/su:windows",
+    buildDll: " -WD",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "dmc",
+    linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler wcc:
+  result = (
+    name: "wcc",
+    objExt: "obj",
+    optSpeed: " -ox -on -6 -d0 -fp6 -zW ",
+    optSize: "",
+    compilerExe: "wcl386",
+    compileTmpl: "-c $options $include -fo=$objfile $file",
+    buildGui: " -bw",
+    buildDll: " -bd",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "wcl386",
+    linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ",
+    includeCmd: " -i=",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -d2 ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasCpp})
+
+compiler tcc:
+  result = (
+    name: "tcc",
+    objExt: "o",
+    optSpeed: "",
+    optSize: "",
+    compilerExe: "tcc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: "UNAVAILABLE!",
+    buildDll: " -shared",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "tcc",
+    linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -g ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {hasSwitchRange, hasComputedGoto})
+
+compiler pcc:
+  # Pelles C
+  result = (
+    name: "pcc",
+    objExt: "obj",
+    optSpeed: " -Ox ",
+    optSize: " -Os ",
+    compilerExe: "cc",
+    compileTmpl: "-c $options $include -Fo$objfile $file",
+    buildGui: " -SUBSYSTEM:WINDOWS",
+    buildDll: " -DLL",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "cc",
+    linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: " -Zi ",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {})
+
+compiler ucc:
+  result = (
+    name: "ucc",
+    objExt: "o",
+    optSpeed: " -O3 ",
+    optSize: " -O1 ",
+    compilerExe: "cc",
+    compileTmpl: "-c $options $include -o $objfile $file",
+    buildGui: "",
+    buildDll: " -shared ",
+    buildLib: "", # XXX: not supported yet
+    linkerExe: "cc",
+    linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options",
+    includeCmd: " -I",
+    linkDirCmd: "", # XXX: not supported yet
+    linkLibCmd: "", # XXX: not supported yet
+    debug: "",
+    pic: "",
+    asmStmtFrmt: "__asm{$n$1$n}$n",
+    props: {})
+
 const 
   CC*: array[succ(low(TSystemCC))..high(TSystemCC), TInfoCC] = [
-    (name: "gcc", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "gcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "gcc", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "llvm_gcc", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "llvm-gcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "llvm-gcc", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "clang", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "clang", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -shared", 
-     linkerExe: "clang", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "lcc", 
-     objExt: "obj", 
-     optSpeed: " -O -p6 ", 
-     optSize: " -O -p6 ", 
-     compilerExe: "lcc", 
-     compileTmpl: "$options $include -Fo$objfile $file", 
-     buildGui: " -subsystem windows", 
-     buildDll: " -dll", 
-     linkerExe: "lcclnk", 
-     linkTmpl: "$options $buildgui $builddll -O $exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g5 ", 
-     pic: "", 
-     asmStmtFrmt: "_asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "bcc", 
-     objExt: "obj", 
-     optSpeed: " -O2 -6 ", 
-     optSize: " -O1 -6 ", 
-     compilerExe: "bcc32", 
-     compileTmpl: "-c $options $include -o$objfile $file", 
-     buildGui: " -tW", 
-     buildDll: " -tWD", 
-     linkerExe: "bcc32", 
-     linkTmpl: "$options $buildgui $builddll -e$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "dmc", 
-     objExt: "obj", 
-     optSpeed: " -ff -o -6 ", 
-     optSize: " -ff -o -6 ", 
-     compilerExe: "dmc", 
-     compileTmpl: "-c $options $include -o$objfile $file", 
-     buildGui: " -L/exet:nt/su:windows", 
-     buildDll: " -WD", 
-     linkerExe: "dmc", 
-     linkTmpl: "$options $buildgui $builddll -o$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "wcc", 
-     objExt: "obj", 
-     optSpeed: " -ox -on -6 -d0 -fp6 -zW ", 
-     optSize: "", 
-     compilerExe: "wcl386", 
-     compileTmpl: "-c $options $include -fo=$objfile $file", 
-     buildGui: " -bw", 
-     buildDll: " -bd", 
-     linkerExe: "wcl386", 
-     linkTmpl: "$options $buildgui $builddll -fe=$exefile $objfiles ", 
-     includeCmd: " -i=", 
-     debug: " -d2 ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp}), 
-    (name: "vcc", 
-     objExt: "obj", 
-     optSpeed: " /Ogityb2 /G7 /arch:SSE2 ", 
-     optSize: " /O1 /G7 ", 
-     compilerExe: "cl", 
-     compileTmpl: "/c $options $include /Fo$objfile $file", 
-     buildGui: " /link /SUBSYSTEM:WINDOWS ", 
-     buildDll: " /LD", 
-     linkerExe: "cl", 
-     linkTmpl: "$options $builddll /Fe$exefile $objfiles $buildgui", 
-     includeCmd: " /I", 
-     debug: " /GZ /Zi ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasCpp, hasAssume}), 
-    (name: "tcc", 
-     objExt: "o", 
-     optSpeed: "", 
-     optSize: "", 
-     compilerExe: "tcc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: "UNAVAILABLE!", 
-     buildDll: " -shared", 
-     linkerExe: "tcc", 
-     linkTmpl: "-o $exefile $options $buildgui $builddll $objfiles", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {hasSwitchRange, hasComputedGoto}), 
-    (name: "pcc", # Pelles C
-     objExt: "obj", 
-     optSpeed: " -Ox ", 
-     optSize: " -Os ", 
-     compilerExe: "cc", 
-     compileTmpl: "-c $options $include -Fo$objfile $file", 
-     buildGui: " -SUBSYSTEM:WINDOWS", 
-     buildDll: " -DLL", 
-     linkerExe: "cc", 
-     linkTmpl: "$options $buildgui $builddll -OUT:$exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: " -Zi ", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "ucc", 
-     objExt: "o", 
-     optSpeed: " -O3 ", 
-     optSize: " -O1 ", 
-     compilerExe: "cc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: "", 
-     buildDll: " -shared ", 
-     linkerExe: "cc", 
-     linkTmpl: "-o $exefile $buildgui $builddll $objfiles $options", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "", 
-     asmStmtFrmt: "__asm{$n$1$n}$n", 
-     props: {}), 
-    (name: "icc", 
-     objExt: "o", 
-     optSpeed: " -O3 ", 
-     optSize: " -Os ", 
-     compilerExe: "icc", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -mdll", 
-     linkerExe: "icc", 
-     linkTmpl: "$options $buildgui $builddll -o $exefile $objfiles", 
-     includeCmd: " -I", 
-     debug: "", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp}), 
-    (name: "gpp", 
-     objExt: "o", 
-     optSpeed: " -O3 -ffast-math ", 
-     optSize: " -Os -ffast-math ", 
-     compilerExe: "g++", 
-     compileTmpl: "-c $options $include -o $objfile $file", 
-     buildGui: " -mwindows", 
-     buildDll: " -mdll", 
-     linkerExe: "g++", 
-     linkTmpl: "$buildgui $builddll -o $exefile $objfiles $options", 
-     includeCmd: " -I", 
-     debug: " -g ", 
-     pic: "-fPIC", 
-     asmStmtFrmt: "asm($1);$n", 
-     props: {hasSwitchRange, hasComputedGoto, hasCpp})]
-
-var ccompiler*: TSystemCC = ccGcc # the used compiler
+    gcc(),
+    llvmGcc(),
+    clang(),
+    lcc(),
+    bcc(),
+    dmc(),
+    wcc(),
+    vcc(),
+    tcc(),
+    pcc(),
+    ucc(),
+    icc(),
+    gpp() ]
 
 const               
   hExt* = "h"
 
-var cExt*: string = "c" # extension of generated C/C++ files
-                        # (can be changed to .cpp later)
+var
+  cCompiler* = ccGcc # the used compiler
+
+  cExt* = "c" # extension of generated C/C++ files
+              # (can be changed to .cpp later)
+  
+  cIncludes*: seq[string] = @[] # list of directories to search for included files
+  cLibs*: seq[string] = @[] # list of directories to search for lib files
+  cLinkedLibs*: seq[string] = @[] # list of libraries to link
 
 # implementation
 
+when defined(windows):
+  var libNameTmpl = "$1.lib"
+else:
+  var libNameTmpl = "lib$1.a"
+
 var 
   toLink, toCompile, externalToCompile: TLinkedList
   linkOptions: string = ""
@@ -363,6 +430,11 @@ const
 
 var fileCounter: int
 
+proc add(s: var string, many: openarray[string]) =
+  # XXX: is there something like C++'s reserve?
+  # We can use it here to avoid multiple reallocations
+  for x in items(many): s.add x
+
 proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string = 
   var 
     cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string
@@ -396,6 +468,10 @@ proc getCompileCFileCmd*(cfilename: string, isExternal: bool = false): string =
     includeCmd = cc[c].includeCmd # this is more complex than needed, but
                                   # a workaround of a FPC bug...
     add(includeCmd, quoteIfContainsWhite(libpath))
+
+    for includeDir in items(cIncludes):
+      includeCmd.add cc[c].includeCmd, includeDir.quoteIfContainsWhite
+
     compilePattern = JoinPath(ccompilerpath, exe)
   else: 
     includeCmd = ""
@@ -453,47 +529,57 @@ proc CallCCompiler*(projectfile: string) =
       res = execProcesses(cmds, {poUseShell, poParentStreams}, 
                           gNumberOfProcessors)
     if res != 0: rawMessage(errExecutionOfProgramFailed, [])
-  if optNoLinking notin gGlobalOptions: 
+  if optNoLinking notin gGlobalOptions:
     # call the linker:
-    var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
-    if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
-    if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
-    if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe)
-    else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe))
-    if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui
-    else: buildGui = ""
-    var exefile: string
-    if optGenDynLib in gGlobalOptions: 
-      exefile = `%`(platform.os[targetOS].dllFrmt, [splitFile(projectFile).name])
-      buildDll = cc[c].buildDll
-    else: 
-      exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt
-      buildDll = ""
-    if targetOS == platform.hostOS: 
-      exefile = joinPath(splitFile(projectFile).dir, exefile)
-    exefile = quoteIfContainsWhite(exefile)
     var it = PStrEntry(toLink.head)
     var objfiles = ""
-    while it != nil: 
+    while it != nil:
       add(objfiles, ' ')
-      if targetOS == platform.hostOS: 
+      if targetOS == platform.hostOS:
         add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
-      else: 
+      else:
         add(objfiles, quoteIfContainsWhite(addFileExt(it.data, cc[ccompiler].objExt)))
       it = PStrEntry(it.next)
-    linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll, 
-        "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles, 
-        "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
-    add(linkCmd, ' ')
-    addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll, 
-        "buildgui", buildgui, "options", linkOptions, 
-        "objfiles", objfiles, "exefile", exefile, 
-        "nimrod", quoteIfContainsWhite(getPrefixDir()), 
-        "lib", quoteIfContainsWhite(libpath)])
-    if not (optCompileOnly in gGlobalOptions): execExternalProgram(linkCmd)
-  else: 
+
+    if optGenStaticLib in gGlobalOptions:
+      linkcmd = cc[c].buildLib % ["libfile", (libNameTmpl % projectName), "objfiles", objfiles]
+      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
+    else:
+      var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
+      if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
+      if targetOS == osWindows: linkerExe = addFileExt(linkerExe, "exe")
+      if (platform.hostOS != targetOS): linkCmd = quoteIfContainsWhite(linkerExe)
+      else: linkCmd = quoteIfContainsWhite(JoinPath(ccompilerpath, linkerExe))
+      if optGenGuiApp in gGlobalOptions: buildGui = cc[c].buildGui
+      else: buildGui = ""
+      var exefile: string
+      if optGenDynLib in gGlobalOptions:
+        exefile = `%`(platform.os[targetOS].dllFrmt, [splitFile(projectFile).name])
+        buildDll = cc[c].buildDll
+      else:
+        exefile = splitFile(projectFile).name & platform.os[targetOS].exeExt
+        buildDll = ""
+      if targetOS == platform.hostOS:
+        exefile = joinPath(splitFile(projectFile).dir, exefile)
+      exefile = quoteIfContainsWhite(exefile)
+      for linkedLib in items(cLinkedLibs):
+        linkOptions.add(cc[c].linkLibCmd % linkedLib.quoteIfContainsWhite)
+      for libDir in items(cLibs):
+        linkOptions.add cc[c].linkDirCmd, libDir.quoteIfContainsWhite
+
+      linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll,
+          "buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
+          "exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
+      linkCmd.add ' '
+      addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll,
+          "buildgui", buildgui, "options", linkOptions,
+          "objfiles", objfiles, "exefile", exefile,
+          "nimrod", quoteIfContainsWhite(getPrefixDir()),
+          "lib", quoteIfContainsWhite(libpath)])
+      if optCompileOnly notin gGlobalOptions: execExternalProgram(linkCmd)
+  else:
     linkCmd = ""
-  if optGenScript in gGlobalOptions: 
+  if optGenScript in gGlobalOptions:
     app(script, linkCmd)
     app(script, tnl)
     generateScript(projectFile, script)
diff --git a/compiler/main.nim b/compiler/main.nim
index 7a0d016ce..94c115912 100755
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -23,7 +23,7 @@ const
 when has_LLVM_Backend:
   import llvmgen
 
-proc MainCommand*(cmd, filename: string)
+proc MainCommand*()
 
 # ------------------ module handling -----------------------------------------
 
@@ -68,7 +68,7 @@ proc importModule(filename: string): PSym =
   elif sfSystemModule in result.flags: 
     LocalError(result.info, errAttemptToRedefine, result.Name.s)
   
-proc CompileModule(filename: string, flags: TSymFlags): PSym = 
+proc CompileModule(filename: string, flags: TSymFlags): PSym =
   var rd: PRodReader = nil
   var f = addFileExt(filename, nimExt)
   result = newModule(filename)
@@ -81,57 +81,56 @@ proc CompileModule(filename: string, flags: TSymFlags): PSym =
     result.id = getID()
   processModule(result, f, nil, rd)
 
-proc CompileProject(filename: string) = 
-  discard CompileModule(options.libpath / addFileExt("system", nimExt),
-                        {sfSystemModule})
-  discard CompileModule(addFileExt(filename, nimExt), {sfMainModule})
+proc CompileProject(projectFile = projectFullPath) =
+  discard CompileModule(options.libpath / "system", {sfSystemModule})
+  discard CompileModule(projectFile, {sfMainModule})
 
-proc semanticPasses() = 
+proc semanticPasses =
   registerPass(verbosePass())
   registerPass(sem.semPass())
   registerPass(transf.transfPass())
 
-proc CommandGenDepend(filename: string) = 
+proc CommandGenDepend =
   semanticPasses()
   registerPass(genDependPass())
   registerPass(cleanupPass())
-  compileProject(filename)
-  generateDot(filename)
-  execExternalProgram("dot -Tpng -o" & changeFileExt(filename, "png") & ' ' &
-      changeFileExt(filename, "dot"))
+  compileProject()
+  generateDot(projectFullPath)
+  execExternalProgram("dot -Tpng -o" & changeFileExt(projectFullPath, "png") & ' ' &
+      changeFileExt(projectFullPath, "dot"))
 
-proc CommandCheck(filename: string) = 
+proc CommandCheck =
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()            # use an empty backend for semantic checking only
   registerPass(rodwrite.rodwritePass())
-  compileProject(filename)
+  compileProject(mainCommandArg())
 
-proc CommandCompileToC(filename: string) = 
+proc CommandCompileToC =
   semanticPasses()
   registerPass(cgen.cgenPass())
   registerPass(rodwrite.rodwritePass())
   #registerPass(cleanupPass())
-  compileProject(filename)
+  compileProject()
   if gCmd != cmdRun:
-    extccomp.CallCCompiler(changeFileExt(filename, ""))
+    extccomp.CallCCompiler(changeFileExt(projectFullPath, ""))
 
 when has_LLVM_Backend:
-  proc CommandCompileToLLVM(filename: string) = 
+  proc CommandCompileToLLVM =
     semanticPasses()
     registerPass(llvmgen.llvmgenPass())
     registerPass(rodwrite.rodwritePass())
     #registerPass(cleanupPass())
-    compileProject(filename)
+    compileProject()
 
-proc CommandCompileToEcmaScript(filename: string) = 
+proc CommandCompileToEcmaScript =
   incl(gGlobalOptions, optSafeCode)
   setTarget(osEcmaScript, cpuEcmaScript)
   initDefines()
   semanticPasses()
   registerPass(ecmasgenPass())
-  compileProject(filename)
+  compileProject()
 
-proc CommandInteractive() = 
+proc CommandInteractive =
   msgs.gErrorMax = high(int)  # do not stop after first error
   incl(gGlobalOptions, optSafeCode)
   #setTarget(osNimrodVM, cpuNimrodVM)
@@ -140,20 +139,22 @@ proc CommandInteractive() =
   registerPass(verbosePass())
   registerPass(sem.semPass())
   registerPass(evals.evalPass()) # load system module:
-  discard CompileModule(options.libpath / addFileExt("system", nimExt),
-                        {sfSystemModule})
-  var m = newModule("stdin")
-  m.id = getID()
-  incl(m.flags, sfMainModule)
-  processModule(m, "stdin", LLStreamOpenStdIn(), nil)
+  discard CompileModule(options.libpath /"system", {sfSystemModule})
+  if commandArgs.len > 0:
+    discard CompileModule(mainCommandArg(), {})
+  else:
+    var m = newModule("stdin")
+    m.id = getID()
+    incl(m.flags, sfMainModule)
+    processModule(m, "stdin", LLStreamOpenStdIn(), nil)
 
-proc CommandPretty(filename: string) = 
-  var module = parseFile(addFileExt(filename, NimExt))
+proc CommandPretty =
+  var module = parseFile(addFileExt(mainCommandArg(), NimExt))
   if module != nil: 
-    renderModule(module, getOutFile(filename, "pretty." & NimExt))
+    renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
   
-proc CommandScan(filename: string) = 
-  var f = addFileExt(filename, nimExt)
+proc CommandScan =
+  var f = addFileExt(mainCommandArg(), nimExt)
   var stream = LLStreamOpen(f, fmRead)
   if stream != nil: 
     var 
@@ -169,107 +170,107 @@ proc CommandScan(filename: string) =
   else: 
     rawMessage(errCannotOpenFile, f)
   
-proc CommandSuggest(filename: string) = 
+proc CommandSuggest =
   msgs.gErrorMax = high(int)  # do not stop after first error
   semanticPasses()
   registerPass(rodwrite.rodwritePass())
-  compileProject(filename)
+  compileProject()
 
-proc WantFile(filename: string) = 
-  if filename.len == 0: 
+proc wantMainModule =
+  if projectFullPath.len == 0:
     Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename)
   
-proc MainCommand(cmd, filename: string) = 
+proc MainCommand =
   appendStr(searchPaths, options.libpath)
-  if filename.len != 0:
-    # current path is always looked first for modules
-    prependStr(searchPaths, splitFile(filename).dir)
+  if projectFullPath.len != 0:
+    # current path is dalways looked first for modules
+    prependStr(searchPaths, projectPath)
   setID(100)
   passes.gIncludeFile = syntaxes.parseFile
   passes.gImportModule = importModule
-  case cmd.normalize
+  case command.normalize
   of "c", "cc", "compile", "compiletoc": 
     # compile means compileToC currently
     gCmd = cmdCompileToC
-    wantFile(filename)
-    CommandCompileToC(filename)
+    wantMainModule()
+    CommandCompileToC()
   of "cpp", "compiletocpp": 
     extccomp.cExt = ".cpp"
     gCmd = cmdCompileToCpp
-    wantFile(filename)
+    wantMainModule()
     DefineSymbol("cpp")
-    CommandCompileToC(filename)
+    CommandCompileToC()
   of "objc", "compiletooc":
     extccomp.cExt = ".m"
     gCmd = cmdCompileToOC
-    wantFile(filename)
+    wantMainModule()
     DefineSymbol("objc")
-    CommandCompileToC(filename)
+    CommandCompileToC()
   of "run":
     gCmd = cmdRun
-    wantFile(filename)
+    wantMainModule()
     when hasTinyCBackend:
       extccomp.setCC("tcc")
-      CommandCompileToC(filename)
+      CommandCompileToC()
     else: 
-      rawMessage(errInvalidCommandX, cmd)
+      rawMessage(errInvalidCommandX, command)
   of "js", "compiletoecmascript": 
     gCmd = cmdCompileToEcmaScript
-    wantFile(filename)
-    CommandCompileToEcmaScript(filename)
+    wantMainModule()
+    CommandCompileToEcmaScript()
   of "compiletollvm": 
     gCmd = cmdCompileToLLVM
-    wantFile(filename)
+    wantMainModule()
     when has_LLVM_Backend:
-      CommandCompileToLLVM(filename)
+      CommandCompileToLLVM()
     else:
-      rawMessage(errInvalidCommandX, cmd)
+      rawMessage(errInvalidCommandX, command)
   of "pretty":
     gCmd = cmdPretty
-    wantFile(filename)
-    CommandPretty(filename)
+    wantMainModule()
+    CommandPretty()
   of "doc": 
     gCmd = cmdDoc
-    LoadSpecialConfig(DocConfig)
-    wantFile(filename)
-    CommandDoc(filename)
+    LoadConfigs(DocConfig)
+    wantMainModule()
+    CommandDoc()
   of "rst2html": 
     gCmd = cmdRst2html
-    LoadSpecialConfig(DocConfig)
-    wantFile(filename)
-    CommandRst2Html(filename)
+    LoadConfigs(DocConfig)
+    wantMainModule()
+    CommandRst2Html()
   of "rst2tex": 
     gCmd = cmdRst2tex
-    LoadSpecialConfig(DocTexConfig)
-    wantFile(filename)
-    CommandRst2TeX(filename)
+    LoadConfigs(DocTexConfig)
+    wantMainModule()
+    CommandRst2TeX()
   of "gendepend": 
     gCmd = cmdGenDepend
-    wantFile(filename)
-    CommandGenDepend(filename)
+    wantMainModule()
+    CommandGenDepend()
   of "dump": 
     gCmd = cmdDump
     condsyms.ListSymbols()
     for it in iterSearchPath(): MsgWriteln(it)
   of "check": 
     gCmd = cmdCheck
-    wantFile(filename)
-    CommandCheck(filename)
+    wantMainModule()
+    CommandCheck()
   of "parse": 
     gCmd = cmdParse
-    wantFile(filename)
-    discard parseFile(addFileExt(filename, nimExt))
+    wantMainModule()
+    discard parseFile(addFileExt(projectFullPath, nimExt))
   of "scan": 
     gCmd = cmdScan
-    wantFile(filename)
-    CommandScan(filename)
+    wantMainModule()
+    CommandScan()
     MsgWriteln("Beware: Indentation tokens depend on the parser\'s state!")
   of "i": 
     gCmd = cmdInteractive
     CommandInteractive()
   of "idetools":
     gCmd = cmdIdeTools
-    wantFile(filename)
-    CommandSuggest(filename)
-  else: rawMessage(errInvalidCommandX, cmd)
+    wantMainModule()
+    CommandSuggest()
+  else: rawMessage(errInvalidCommandX, command)
 
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 63204459a..a1fd73c88 100755
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -377,7 +377,7 @@ const
   warnMax* = pred(hintSuccess)
   hintMin* = hintSuccess
   hintMax* = high(TMsgKind)
-
+ 
 type 
   TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
   TNoteKinds* = set[TNoteKind]
@@ -392,6 +392,7 @@ type
     
   ERecoverableError* = object of EInvalidValue
 
+proc newLineInfo*(filename: string, line, col: int): TLineInfo
 proc raiseRecoverableError*() {.noinline, noreturn.} =
   raise newException(ERecoverableError, "")
 
@@ -401,7 +402,7 @@ var
   gHintCounter*: int = 0
   gWarnCounter*: int = 0
   gErrorMax*: int = 1         # stop after gErrorMax errors
-
+  
 # this format is understood by many text editors: it is the same that
 # Borland and Freepascal use
 const
@@ -420,6 +421,7 @@ proc UnknownLineInfo*(): TLineInfo =
 var 
   filenames: seq[tuple[filename: string, fullpath: string]] = @[]
   msgContext: seq[TLineInfo] = @[]
+  gCmdLineInfo* = newLineInfo("command line", -1, -1)
 
 proc pushInfoContext*(info: TLineInfo) = 
   msgContext.add(info)
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index baffe350c..18bbe6cb4 100755
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -204,21 +204,17 @@ proc readConfigFile(filename: string) =
     if len(condStack) > 0: lexMessage(L, errTokenExpected, "@end")
     closeLexer(L)
     if gVerbosity >= 1: rawMessage(hintConf, filename)
-  
-proc getConfigPath(filename: string): string = 
-  # try local configuration file:
+
+proc getUserConfigPath(filename: string): string =
   result = joinPath(getConfigDir(), filename)
-  if not ExistsFile(result): 
-    # try standard configuration file (installation did not distribute files
-    # the UNIX way)
-    result = joinPath([getPrefixDir(), "config", filename])
-    if not ExistsFile(result): result = "/etc/" & filename
 
-proc LoadSpecialConfig*(configfilename: string) = 
-  if optSkipConfigFile notin gGlobalOptions:
-    readConfigFile(getConfigPath(configfilename))
-  
-proc LoadConfig*(project: string) = 
+proc getSystemConfigPath(filename: string): string =
+  # try standard configuration file (installation did not distribute files
+  # the UNIX way)
+  result = joinPath([getPrefixDir(), "config", filename])
+  if not ExistsFile(result): result = "/etc/" & filename
+
+proc LoadConfigs*(cfg = "nimrod.cfg") =
   # set default value (can be overwritten):
   if libpath == "": 
     # choose default libpath:
@@ -226,8 +222,14 @@ proc LoadConfig*(project: string) =
     if (prefix == "/usr"): libpath = "/usr/lib/nimrod"
     elif (prefix == "/usr/local"): libpath = "/usr/local/lib/nimrod"
     else: libpath = joinPath(prefix, "lib")
-  LoadSpecialConfig("nimrod.cfg") # read project config file:
-  if optSkipProjConfigFile notin gGlobalOptions and project != "": 
-    var conffile = changeFileExt(project, "cfg")
-    if existsFile(conffile): readConfigFile(conffile)
-  
+
+  if optSkipConfigFile notin gGlobalOptions:
+    readConfigFile getSystemConfigPath(cfg)
+
+  if optSkipUserConfigFile notin gGlobalOptions:
+    readConfigFile getUserConfigPath(cfg)
+
+  if optSkipProjConfigFile notin gGlobalOptions and projectPath != "":
+    for dir in parentDirs(projectPath, fromRoot = true):
+      readConfigFile(dir/cfg)
+    
diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim
index a8a273cc4..87a9b1a75 100755
--- a/compiler/nimrod.nim
+++ b/compiler/nimrod.nim
@@ -20,9 +20,8 @@ when hasTinyCBackend:
 var 
   arguments: string = ""      # the arguments to be passed to the program that
                               # should be run
-  cmdLineInfo: TLineInfo
 
-proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = 
+proc ProcessCmdLine(pass: TCmdLinePass) = 
   var p = parseopt.initOptParser()
   while true: 
     parseopt.next(p)
@@ -35,15 +34,19 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
       if bracketLe >= 0: 
         var key = substr(p.key, 0, bracketLe - 1)
         var val = substr(p.key, bracketLe + 1) & ':' & p.val
-        ProcessSwitch(key, val, pass, cmdLineInfo)
+        ProcessSwitch(key, val, pass, gCmdLineInfo)
       else: 
-        ProcessSwitch(p.key, p.val, pass, cmdLineInfo)
+        ProcessSwitch(p.key, p.val, pass, gCmdLineInfo)
     of cmdArgument: 
-      if command == "": 
-        command = p.key
-      elif filename == "": 
-        filename = unixToNativePath(p.key) # BUGFIX for portable build scripts
-        break 
+      if pass == passCmd1:
+        if options.command == "":
+          options.command = p.key
+        else:
+          options.commandArgs.add p.key
+
+          if options.projectName == "":
+            options.projectName = unixToNativePath(p.key) # BUGFIX for portable build scripts
+          
   if pass == passCmd2: 
     arguments = cmdLineRest(p)
     if optRun notin gGlobalOptions and arguments != "": 
@@ -55,33 +58,30 @@ proc prependCurDir(f: string): string =
     else: result = "./" & f
   else:
     result = f
-  
+
 proc HandleCmdLine() = 
   var start = epochTime()
   if paramCount() == 0: 
     writeCommandLineUsage()
   else: 
     # Process command line arguments:
-    var command = ""
-    var filename = ""
-    ProcessCmdLine(passCmd1, command, filename)
-    if filename != "": 
-      var fullpath: string
+    ProcessCmdLine(passCmd1)
+    if projectName != "":
       try:
-        fullPath = expandFilename(filename)
-      except EOS: 
-        fullpath = filename
-      var p = splitFile(fullPath)
-      options.projectPath = p.dir
-      options.projectName = p.name
-    nimconf.LoadConfig(filename) # load the right config file
+        projectFullPath = expandFilename(projectName)
+      except EOS:
+        projectFullPath = projectName
+      var p = splitFile(projectFullPath)
+      projectPath = p.dir
+      projectName = p.name
+    else:
+      projectPath = getCurrentDir()
+    LoadConfigs() # load all config files
     # now process command line arguments again, because some options in the
     # command line can overwite the config file's settings
     extccomp.initVars()
-    command = ""
-    filename = ""
-    ProcessCmdLine(passCmd2, command, filename)
-    MainCommand(command, filename)
+    ProcessCmdLine(passCmd2)
+    MainCommand()
     if gVerbosity >= 2: echo(GC_getStatistics())
     if msgs.gErrorCounter == 0:
       when hasTinyCBackend:
@@ -91,11 +91,10 @@ proc HandleCmdLine() =
         rawMessage(hintSuccessX, [$gLinesCompiled, 
                    formatFloat(epochTime() - start, ffDecimal, 3)])
       if optRun in gGlobalOptions: 
-        var ex = quoteIfContainsWhite(changeFileExt(filename, "").prependCurDir)
+        var ex = quoteIfContainsWhite(changeFileExt(projectName, "").prependCurDir)
         execExternalProgram(ex & ' ' & arguments)
 
 #GC_disableMarkAndSweep()
-cmdLineInfo = newLineInfo("command line", -1, -1)
 condsyms.InitDefines()
 HandleCmdLine()
 quit(options.gExitcode)
diff --git a/compiler/options.nim b/compiler/options.nim
index 640daf808..8820b1803 100755
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -33,6 +33,7 @@ type                          # please make sure we have under 32 options
     optSafeCode,              # only allow safe code
     optCDebug,                # turn on debugging information
     optGenDynLib,             # generate a dynamic library
+    optGenStaticLib,          # generate a static library
     optGenGuiApp,             # generate a GUI application
     optGenScript,             # generate a script file to compile the *.c files
     optGenMapping,            # generate a mapping file
@@ -40,6 +41,7 @@ type                          # please make sure we have under 32 options
     optSymbolFiles,           # use symbol files for speeding up compilation
     optSkipConfigFile,        # skip the general config file
     optSkipProjConfigFile,    # skip the project's config file
+    optSkipUserConfigFile,    # skip the users's config file
     optNoMain,                # do not generate a "main" proc
     optThreads,               # support for multi-threading
     optStdout,                # output to stdout
@@ -98,11 +100,24 @@ const
 var
   gConfigVars* = newStringTable(modeStyleInsensitive)
   libpath* = ""
-  projectPath* = ""
-  projectName* = ""
+  projectName* = "" # holds a name like `nimrod'
+  projectPath* = "" # holds a path like /home/alice/projects/nimrod/compiler/
+  projectFullPath* = "" # projectPath/projectName
   nimcacheDir* = ""
+  command* = "" # the main command (e.g. cc, check, scan, etc)
+  commandArgs*: seq[string] = @[] # any arguments after the main command
   gKeepComments*: bool = true # whether the parser needs to keep comments
-  gImplicitMods*: TStringSeq = @[] # modules that are to be implicitly imported
+  implicitImports*: seq[string] = @[] # modules that are to be implicitly imported
+  implicitIncludes*: seq[string] = @[] # modules that are to be implicitly included
+  
+proc mainCommandArg*: string =
+  ## This is intended for commands like check or parse
+  ## which will work on the main project file unless
+  ## explicitly given a specific file argument
+  if commandArgs.len > 0:
+    result = commandArgs[0]
+  else:
+    result = projectName
 
 proc existsConfigVar*(key: string): bool = 
   result = hasKey(gConfigVars, key)
@@ -117,11 +132,6 @@ proc getOutFile*(filename, ext: string): string =
   if options.outFile != "": result = options.outFile
   else: result = changeFileExt(filename, ext)
   
-proc addImplicitMod*(filename: string) = 
-  var length = len(gImplicitMods)
-  setlen(gImplicitMods, length + 1)
-  gImplicitMods[length] = filename
-
 proc getPrefixDir*(): string = 
   ## gets the application directory
   result = SplitPath(getAppDir()).head
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 1ce5ad2d3..e24f82927 100755
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -151,10 +151,24 @@ proc processModule(module: PSym, filename: string, stream: PLLStream,
       s = stream
     while true: 
       openParsers(p, filename, s)
+
+      if sfSystemModule notin module.flags:
+        template processImplicits(implicits, nodeKind: expr): stmt =
+          for module in items(implicits):
+            var importStmt = newNodeI(nodeKind, gCmdLineInfo)
+            var str = newStrNode(nkStrLit, module)
+            str.info = gCmdLineInfo
+            importStmt.addSon str
+            processTopLevelStmt importStmt, a
+        
+        processImplicits implicitImports, nkImportStmt
+        processImplicits implicitIncludes, nkIncludeStmt
+
       while true: 
         var n = parseTopLevelStmt(p)
         if n.kind == nkEmpty: break 
         processTopLevelStmt(n, a)
+
       closeParsers(p)
       if s.kind != llsStdIn: break 
     closePasses(a)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index f1c92cdc3..bda3e3891 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -285,14 +285,16 @@ proc magicCall(m: PSym, n: PNode): PNode =
     b = nil
   result = evalOp(s.magic, n, a, b, c)
   
-proc getAppType(n: PNode): PNode = 
+proc getAppType(n: PNode): PNode =
   if gGlobalOptions.contains(optGenDynLib):
     result = newStrNodeT("lib", n)
+  elif gGlobalOptions.contains(optGenStaticLib):
+    result = newStrNodeT("staticlib", n)
   elif gGlobalOptions.contains(optGenGuiApp):
     result = newStrNodeT("gui", n)
   else:
     result = newStrNodeT("console", n)
-  
+
 proc foldConv*(n, a: PNode): PNode = 
   case skipTypes(n.typ, abstractRange).kind
   of tyInt..tyInt64: 
diff --git a/doc/advopt.txt b/doc/advopt.txt
index 1022a9136..c7dee653f 100755
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -14,9 +14,10 @@ Advanced commands:
     --track:FILE,LINE,COL   track a file/cursor position
     --suggest               suggest all possible symbols at position
     --def                   list all possible symbols at position
-    --context               list possible invokation context  
+    --context               list possible invokation context
 
 Advanced options:
+  -m, --mainmodule:FILE     set the project main module
   -o, --out:FILE            set the output filename
   --stdout                  output to stdout
   -w, --warnings:on|off     turn all warnings on|off
@@ -25,6 +26,8 @@ Advanced options:
   --hint[X]:on|off          turn specific hint X on|off
   --recursivePath:PATH      add a path and all of its subdirectories
   --lib:PATH                set the system library path
+  --import:PATH             add an automatically imported module
+  --include:PATH            add an automatically included module
   --nimcache:PATH           set the path used for generated files
   -c, --compileOnly         compile only; do not assemble or link
   --noLinking               compile but do not link
@@ -37,6 +40,10 @@ Advanced options:
   --debugger:on|off         turn Embedded Nimrod Debugger on|off
   -t, --passc:OPTION        pass an option to the C compiler
   -l, --passl:OPTION        pass an option to the linker
+  --cincludes:DIR           modify the C compiler header search path
+  --clibdir:DIR             modify the linker library search path
+  --clib:LIBNAME            link an additional C library
+                            (you should omit platform-specific extensions)
   --genMapping              generate a mapping file containing
                             (Nimrod, mangled) identifier pairs
   --lineDir:on|off          generation of #line directive on|off
@@ -46,6 +53,7 @@ Advanced options:
   --symbolFiles:on|off      turn symbol files on|off (experimental)
   --skipCfg                 do not read the general configuration file
   --skipProjCfg             do not read the project's configuration file
+  --skipUserCfg             do not read the user's configuration file
   --gc:refc|boehm|none      use Nimrod's native GC|Boehm GC|no GC
   --index:FILE              use FILE to generate a documentation index file
   --putenv:key=value        set an environment variable
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index dd9e50ec2..b7bb77f75 100755
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -28,7 +28,8 @@ Options:
   --infChecks:on|off        turn Inf checks on|off
   --deadCodeElim:on|off     whole program dead code elimination on|off
   --opt:none|speed|size     optimize not at all or for speed|size
-  --app:console|gui|lib     generate a console|GUI application|dynamic library
+  --app:console|gui|lib|staticlib
+                            generate a console app|GUI app|DLL|static library
   -r, --run                 run the compiled program with given arguments
   --advanced                show advanced command line switches
   -h, --help                show this help
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index c7e3dccb4..626fbc7eb 100755
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -408,6 +408,36 @@ proc parentDir*(path: string): string {.
   else:
     result = path
 
+proc isRootDir*(path: string): bool {.
+  noSideEffect, rtl, extern: "nos$1".} =
+  ## Checks whether a given `path` is a root directory 
+  var p = parentDir(path)
+  result = p == path or p.len == 0
+
+iterator parentDirs*(path: string, fromRoot = false, inclusive = true): string =
+  ## Walks over all parent directories of a given `path`
+  ##
+  ## If `fromRoot` is set, the traversal will start from the file system root
+  ## diretory. If `inclusive` is set, the original argument will be included
+  ## in the traversal.
+  ##
+  ## Relative paths won't be expanded by this proc. Instead, it will traverse
+  ## only the directories appearing in the relative path.
+  if not fromRoot:
+    var current = path
+    if inclusive: yield path
+    while true:
+      if current.isRootDir: break
+      current = current.parentDir
+      yield current
+  else:
+    for i in countup(0, path.len - 2): # ignore the last /
+      # deal with non-normalized paths such as /foo//bar//baz
+      if path[i] in {dirsep, altsep} and (i == 0 or path[i-1] notin {dirsep, altsep}):
+        yield path.substr(0, i)
+
+    if inclusive: yield path
+
 proc `/../` * (head, tail: string): string {.noSideEffect.} =
   ## The same as ``parentDir(head) / tail``
   return parentDir(head) / tail
@@ -522,7 +552,7 @@ proc cmpPaths*(pathA, pathB: string): int {.
     result = cmpIgnoreCase(pathA, pathB)
 
 proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
-  ## Checks whether a given path is absolute.
+  ## Checks whether a given `path` is absolute.
   ##
   ## on Windows, network paths are considered absolute too.
   when doslike:
diff --git a/web/news.txt b/web/news.txt
index 1affafc1e..511591592 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -46,6 +46,7 @@ Changes affecting backwards compatibility
   raise hooks.
 - Changed exception handling/error reporting for ``os.removeFile`` and
   ``os.removeDir``.
+- The algorithm for searching and loading configuration files have been changed
 - Operators now have diffent precedence rules: Assignment-like operators 
   (like ``*=``) are now special-cased. 
 - The fields in ``TStream`` have been renamed to have an ``Impl`` suffix 
@@ -89,6 +90,15 @@ Compiler Additions
   and Objective C somewhat easier.
 - Added a ``--nimcache:PATH`` configuration option for control over the output
   directory for generated code.
+- Added ``--cincludes:dir``, ``--clibdir:lib`` configuration options for 
+  modifying the C compiler's header/library search path in cross-platform way.
+- Added ``--clib:lib`` configuration options for specifying additional
+  C libraries to be linked.
+- Added ``--mainmodule:file`` configuration options for specifying the main
+  project file. This is intended to be used in project configuration files to
+  allow commands like ``nimrod c`` or ``nimrod check`` to be executed anywhere
+  within the project's directory structure
+- Added a ``--app:staticlib`` option for creating static libraries
 - Added a ``--tlsEmulation:on|off`` switch for control over thread local
   storage emulation.
 - The compiler and standard library now support a *taint mode*. Input strings
@@ -98,6 +108,9 @@ Compiler Additions
 - The compiler now supports the compilation cache via ``--symbolFiles:on``. 
   This potentially speeds up compilations by an order of magnitude, but is
   still highly experimental!
+- Added ``--import:file`` and ``--include:file`` configuration options
+  for specifying modules that will be automatically imported/incluced.
+- ``nimrod i`` can now optionally be given a module to execute.
 
 
 Library Additions
@@ -114,7 +127,8 @@ Library Additions
 - Added ``system.running`` for threads.
 - Added ``system.program_result``.
 - Added ``xmltree.innerText``.
-- Added ``os.isAbsolute``, ``os.dynLibFormat``.
+- Added ``os.isAbsolute``, ``os.dynLibFormat``, ``os.isRootDir``,
+   ``os.parentDirs``.
 - Added ``parseutils.interpolatedFragments``.
 - Added ``macros.treeRepr``, ``macros.lispRepr``, ``macros.dumpTree``, 
   ``macros.dumpLisp``, ``macros.parseExpr``, ``macros.parseStmt``,