2012-07-07 11 views
5

Mój projekt używa SCons do zarządzania procesem kompilacji. Chcę obsługiwać wiele kompilatorów, dlatego postanowiłem użyć AddOption, aby użytkownik mógł określić, który kompilator ma być używany w wierszu poleceń (domyślnie jest to, co jest ich aktualnym kompilatorem).Jak ustalić, który kompilator był wymagany?

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

Chcę móc mieć wbudowane ustawienia kompilatora dla różnych kompilatorów (w tym takie rzeczy jak najwyższych dopuszczalnych poziomów ostrzegawczych dla tego konkretnego kompilatora). To właśnie moja pierwsza próba rozwiązania obecnie wygląda następująco:

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 

Jednak nie jestem pewien, co do wyglądu is_compiler() działają jak. Moja pierwsza myśl polegała na bezpośrednim porównywaniu nazwy kompilatora (na przykład "clang ++") z tym, co podaje użytkownik. Jednak natychmiast to się nie powiodło, gdy próbowałem użyć scons --compiler=~/data/llvm-3.1-obj/Release+Asserts/bin/clang++.

Więc pomyślałem, że trochę mądrzejszy i używać tej funkcji

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

To tylko wygląda na końcu łańcucha kompilatora, tak że ignoruje katalogów. Niestety "clang ++" kończy się na 'g ++', więc mój kompilator był postrzegany jako g ++ zamiast clang ++.

Moja następna myśl polegała na wyszukiwaniu wstecznym i wyszukaniu pierwszego wystąpienia separatora ścieżek ("\" lub "/"), ale wtedy zdałem sobie sprawę, że to nie zadziała dla osób, które mają wiele wersji kompilatora . Ktoś kompilujący się z "g ++ - 4.7" nie zarejestruje się jako g ++.

Czy istnieje prosty sposób ustalenia, który kompilator został zamówiony?

Obecnie tylko g ++ i clang ++ są obsługiwane (i tylko ich ostatnio wydane wersje) ze względu na obsługę C++ 11, więc rozwiązanie, które działa tylko dla tych dwóch, byłoby na razie wystarczająco dobre. Jednak moim ostatecznym celem jest wspieranie co najmniej g ++, clang ++, icc i msvC++ (gdy obsługują wymagane funkcje C++ 11), dlatego preferowane są bardziej ogólne rozwiązania.

+2

Oddzielę te dwa problemy tutaj. problem # 1) * który * kompilator jest żądany i # 2) * gdzie * znajduje się żądany kompilator (domyślnie możesz używać rozsądnych wartości domyślnych i pozwolić im je określić, jeśli nie chcą domyślnego języka/gcc/cokolwiek). Te dwie rzeczy nie mają ze sobą wiele wspólnego, w końcu mogę z łatwością utworzyć miękki link do dzwonka, który nazywa się 'msvc', jeśli chcę (właściwie nigdy nie próbował, ale dlaczego nie?) – Voo

+0

Zgadzam się z sugestią @Voo . Edytuj, aby zawęzić do jednego pytania, a następnie utwórz nowe pytanie. Masz dwa dobre pytania, dlatego też przegłosowałem ten, który stworzyłeś (do tej pory). – octopusgrabbus

+0

@Voo, jeśli napiszesz to jako odpowiedź, przyjmuję to, ponieważ to był kluczowy wgląd, którego użyłem do rozwiązania problemu. –

Odpowiedz

1

To pytanie doprowadziły do ​​opracowania projektu SCons który może obsłużyć to:

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

Odpowiedni kod jest w build_scripts/compiler_settings.py. Opcje SCons są ustawione w pliku SConstruct z następujących linii:

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.') 

Użytkownik może określić, 0, 1 lub 2 opcje wiersza polecenia.

Jeśli nic nie podasz (scons), to kompiluje się z kompilatorem z DefaultEnvironment.

Opcjonalnie można podać nazwę kompilatora (scons --compiler=g++). Mój skrypt zakłada następnie, że polecenie użyte do kompilacji jest takie samo jak nazwa.

Opcjonalnie można również określić komendę do kompilacji (scons --compiler-command=~/llvm-3.1-obj/Release+Asserts/bin/clang++). Mój skrypt zakłada, że ​​nazwa używanego kompilatora to nazwa pliku wykonywalnego (wszystko po ostatecznym separatorze katalogu, określonym przez os.path.basename).

Można określić oba. Umożliwia to obsługę dziwnych sytuacji: scons --compiler-command=/path/to/executable/that/is/not/clang++ --compiler=g++

Używa tej nazwy do określenia, które ostrzeżenia/optymalizacje mają zostać włączone. Dodałem nawet trochę normalizacji do nazwy, więc g ++, gcc i GcC są traktowane tak samo, jak nazwa kompilatora.

Pozostało w nim jeszcze wiele pracy, na przykład obsługa większej liczby kompilatorów, lepsza obsługa kompilatorów mingw i wykrywanie wersji kompilatora, aby umożliwić lepszą obsługę flag, które są dostępne tylko w wersji x.y.z +. Byłoby również miło, gdybym mógł zrobić coś takiego, jak scons --compiler-command=/path/to/gcc-4.7.1 i wykryć, że kompilator jest gcc, bez konieczności wyraźnego informowania go.

Jednakże rozwiązał początkowy problem, który postanowiłem rozwiązać. Duża zasługa na to musi trafić do Voo w komentarzach do postawienia mnie na właściwej drodze.

1

Można po prostu użyć funkcji Python os.path.basename() lub os.path.split(), jak określono here.

Możesz zrobić to, co ludzie zasugerowali w komentarzach, dzieląc to pytanie na 2 różne kwestie, ale myślę, że dobrym pomysłem byłoby wskazanie ścieżki z kompilatorem, ponieważ możesz mieć 2 wersje g ++ zainstalowane, a jeśli użytkownik określi tylko g ++, mogą nie uzyskać oczekiwanej wersji.

2

Kompilator właśnie wchodzi w skład procesu kompilacji. Potrzebujesz również narzędzia do linkowania i mogą to być inne dodatkowe programy. W Scons nosi nazwę - Tool. Lista narzędzi obsługiwanych from box można zobaczyć w man page, wyszukaj według instrukcji: SCons supports the following tool specifications out of the box: ... Zestaw narzędzi niezbędnych zmiennych środowiskowych scons, jest to udokumentowane here.

Scons automatycznie wykrywa kompilator w systemie operacyjnym i ma pewien priorytet, aby wybrać jedno z nich, oczywiście automatyczne wykrywanie będzie działać poprawnie, jeśli zmienna PATH jest ustawiona na potrzebne dirs. Na przykład masz msvc i mingw na windows, scons wybierz narzędzie msvc. Aby użyć narzędzia przy użyciu narzędzia, użyj narzędzia ("nazwa") (env). Na przykład:

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

Teraz env życie przy użyciu mingw.

Tak więc, clang jest jednym z narzędzi, które obecnie nie są wspierane przez from box przez scons. Musisz go zaimplementować lub ustawić env vars takie CC, CXX, które używają scons do generowania poleceń build.

Powiązane problemy