2012-07-07 16 views
5

Mein Projekt verwendet SCons, um den Buildprozess zu verwalten. Ich möchte mehrere Compiler unterstützen, also entschied ich mich, AddOption zu verwenden, so dass der Benutzer angeben kann, welcher Compiler in der Befehlszeile verwendet werden soll (wobei der Standardwert der aktuelle Compiler ist).So ermitteln Sie, welcher Compiler angefordert wurde

AddOption('--compiler', dest = 'compiler', type = 'string', action = 'store', default = DefaultEnvironment()['CXX'], help = 'Name of the compiler to use.') 

Ich möchte eingebauten Compiler-Einstellungen für verschiedene Compiler (einschließlich solcher Dinge wie maximale Warnstufen für diesen speziellen Compiler) haben können. Dies ist, was mein erster Versuch einer Lösung sieht derzeit wie:

if is_compiler('g++'): 
    from build_scripts.gcc.std import cxx_std 
    from build_scripts.gcc.warnings import warnings, warnings_debug, warnings_optimized 
    from build_scripts.gcc.optimizations import optimizations, preprocessor_optimizations, linker_optimizations 
elif is_compiler('clang++'): 
    from build_scripts.clang.std import cxx_std 
    from build_scripts.clang.warnings import warnings, warnings_debug, warnings_optimized 
    from build_scripts.clang.optimizations import optimizations, preprocessor_optimizations, linker_optimizations 

Aber ich bin nicht sicher, was wie die is_compiler() Funktion aussehen zu lassen. Mein erster Gedanke war, den Compiler-Namen (wie "clang ++") direkt mit dem zu vergleichen, was der Benutzer übergibt. Dies ist jedoch sofort fehlgeschlagen, als ich versuchte, scons --compiler=~/data/llvm-3.1-obj/Release+Asserts/bin/clang++ zu verwenden.

Also dachte ich, ich ein wenig schlauer bekommen würde und diese Funktion am Ende des Compilers Zeichenfolge

cxx = GetOption('compiler') 
def is_compiler (compiler): 
    return cxx[-len(compiler):] == compiler 

Das sieht nur verwenden, so dass es Verzeichnisse ignoriert. Unglücklicherweise endet 'clang ++' in 'g ++', daher wurde mein Compiler als g ++ anstelle von clang ++ angesehen.

Mein nächster Gedanke war, eine Rückwärtssuche durchzuführen und nach dem ersten Vorkommen eines Pfadtrennzeichens ('\' oder '/') zu suchen, aber dann erkannte ich, dass dies nicht für Leute mit mehreren Compilerversionen funktioniert . Jemand, der mit 'g ++ - 4.7' kompiliert, wird nicht als g ++ registriert.

Gibt es also eine einfache Möglichkeit zu bestimmen, welcher Compiler angefordert wurde?

Momentan werden nur g ++ und clang ++ (und nur ihre zuletzt veröffentlichten Versionen) aufgrund ihrer C++ 11 Unterstützung unterstützt, daher wäre eine Lösung, die nur für diese beiden funktioniert, gut genug für jetzt. Mein oberstes Ziel ist es jedoch, mindestens g ++, clang ++, icc und msvC++ zu unterstützen (sobald sie die erforderlichen C++ 11-Funktionen unterstützen), sodass allgemeinere Lösungen bevorzugt werden.

+2

Ich würde die beiden Ausgaben hier trennen. Problem # 1) * welcher * Compiler angefordert wird und # 2) * wobei * der angeforderte Compiler gefunden wird (dafür können Sie die meisten Zeit sinnvolle Standardwerte verwenden und sie nur angeben lassen, wenn sie den Standardcall nicht wollen/gcc/was auch immer). Die zwei Dinge haben nicht viel gemeinsam, schließlich kann ich leicht einen Softlink zum Klängen erstellen, der 'msvc' genannt wird, wenn ich wollte (tatsächlich nie ausprobiert, aber warum nicht?) – Voo

+0

Ich stimme dem Vorschlag zu, den @Voo dir gegeben hat . Bearbeiten Sie dies, um auf eine Frage einzugrenzen, und erstellen Sie anschließend eine neue Frage. Sie haben zwei gute Fragen, weshalb ich den von Ihnen erstellten (bis jetzt) ​​upvoted habe. – octopusgrabbus

+0

@Voo Wenn du das als Antwort aufschreibst, werde ich es akzeptieren, denn das war die Schlüsseleinsicht, mit der ich das Problem gelöst habe. –

Antwort

1

Diese Frage führte zur Entwicklung eines SCons Projekt, das damit umgehen kann:

https://bitbucket.org/davidstone/scons-template/

Der entsprechende Code ist in build_scripts/compiler_settings.py. Die SCons Optionen werden in der SConstruct Datei mit den folgenden Zeilen ein:

AddOption('--compiler', dest = 'compiler', type = 'string', action = 'store', help = 'Name of the compiler to use.') 
AddOption('--compiler-command', dest = 'compiler_command', type = 'string', action = 'store', help = 'Command to launch the compiler.') 

Der Benutzer kann angeben, 0, 1, 2 oder Befehlszeilenoptionen.

Wenn Sie nichts angeben (scons), wird es mit dem Compiler von der DefaultEnvironment erstellt.

Sie können optional den Namen des Compilers angeben (scons --compiler=g++). Mein Skript geht dann davon aus, dass der zum Kompilieren verwendete Befehl mit dem Namen identisch ist.

Sie können optional auch den zu kompilierenden Befehl angeben (scons --compiler-command=~/llvm-3.1-obj/Release+Asserts/bin/clang++). Mein Skript nimmt dann an, dass der Name des Compilers, den Sie verwenden, der Name der ausführbaren Datei ist (alles nach dem letzten Verzeichnistrennzeichen, wie von os.path.basename bestimmt).

Sie können beide angeben. So können Sie mit seltsamen Situationen umgehen: scons --compiler-command=/path/to/executable/that/is/not/clang++ --compiler=g++

Es verwendet den Namen, um zu bestimmen, welche Warnungen/Optimierungen einzuschalten sind. Ich habe dem Namen sogar ein wenig Normalisierung hinzugefügt, so dass g ++, gcc und GcC alle gleich behandelt werden, was den Namen des Compilers betrifft.

Es hat immer noch eine Menge Arbeit übrig, wie Unterstützung für mehr Compiler, bessere Unterstützung für Mingw Compiler und Erkennung von Compiler-Versionen, um eine bessere Handhabung von Flags zu ermöglichen, die nur in der Version x.y.z + verfügbar sind. Es wäre auch schön, wenn ich etwas wie scons --compiler-command=/path/to/gcc-4.7.1 machen könnte und feststellen würde, dass der Compiler gcc ist, ohne dass ich es explizit sagen muss.

Allerdings hat es das ursprüngliche Problem gelöst, das ich beheben wollte. Ein großer Teil des Verdienstes muss in den Kommentaren zu Voo gehen, um mich auf den richtigen Weg zu bringen.

1

Sie könnten einfach die Python os.path.basename() oder os.path.split() Funktionen verwenden, wie angegeben here.

Sie könnten tun, was die Leute in den Kommentaren vorgeschlagen haben, indem Sie diese Frage in zwei verschiedene Probleme aufteilen, aber ich denke, es könnte eine gute Idee sein, den Pfad mit dem Compiler anzugeben, da Sie 2 Versionen von g ++ haben könnten installiert, und wenn der Benutzer nur g ++ angibt, erhalten sie möglicherweise nicht die erwartete Version.

2

Compiler sind nur Teil des Build-Prozesses. Auch benötigen Sie Linker-Tool und möglicherweise andere zusätzliche Programme. In Scons heißt es - Tool. Liste der unterstützten Werkzeuge from box können Sie in man page sehen, nach Aussage suchen: SCons supports the following tool specifications out of the box: ... Werkzeugset notwendig SCON-Umgebungsvariablen, es ist dokumentiert here.

Scons erkennt automatisch Compiler in OS und haben eine Priorität, um eine von ihnen zu wählen, natürlich funktioniert Autodetect ordnungsgemäß, wenn PATH-Variable auf die erforderlichen Dirs eingestellt. Zum Beispiel von Ihnen haben msvc und mingw auf Windows, wählen Sie msvc Werkzeug. Zum Erzwingen der Verwendung des Werkzeugs Werkzeug ('Name') (env) verwenden. Zum Beispiel:

env = Environment() 
Tool('mingw')(env) 

Jetzt env Kraft mit mingw.

Also ist clang eines der Werkzeuge, die derzeit nicht unterstützt from box von SCONS. Sie müssen es implementieren, oder legen Sie env vars wie CC, CXX, die Verwendung von SCONS zum Generieren von Build-Befehlen.

Verwandte Themen