2012-07-07 9 views
5

Mi proyecto utiliza SCons para gestionar el proceso de construcción. Quiero admitir múltiples compiladores, así que decidí usar AddOption para que el usuario pueda especificar qué compilador usar en la línea de comandos (siendo el valor predeterminado el compilador actual).Cómo determinar qué compilador se solicitó

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

Quiero ser capaz de tener configuración del compilador incorporados para varios compiladores (incluyendo cosas tales como niveles máximos de advertencia para que el compilador particular). Esto es lo que mi primer intento de solución se ve actualmente como:

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 

Sin embargo, no estoy seguro de qué hacer con el aspecto is_compiler() función similar. Lo primero que pensé fue comparar directamente el nombre del compilador (como 'clang ++') con lo que pasa el usuario. Sin embargo, esto falló inmediatamente cuando traté de usar scons --compiler=~/data/llvm-3.1-obj/Release+Asserts/bin/clang++.

Así que pensé que tendría un poco más inteligente y el uso de esta función

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

Esto sólo se ve al final de la cadena del compilador, por lo que ignora los directorios. Desafortunadamente, 'clang ++' termina en 'g ++', por lo que se vio que mi compilador era g ++ en lugar de clang ++.

Mi siguiente pensamiento fue hacer una búsqueda hacia atrás y buscar la primera aparición de un separador de ruta ('\' o '/'), pero luego me di cuenta de que esto no funcionaría para las personas que tienen múltiples versiones de compilación . Alguien que compila con 'g ++ - 4.7' no se registrará como g ++.

Entonces, ¿hay alguna forma sencilla de determinar qué compilador fue solicitado?

Actualmente, solo se admiten g ++ y clang ++ (y solo sus versiones más recientes) debido a su compatibilidad con C++ 11, por lo que una solución que solo funcione para esos dos sería lo suficientemente buena por ahora. Sin embargo, mi objetivo final es soportar al menos g ++, clang ++, icc y msvC++ (una vez que admiten las características requeridas de C++ 11), por lo que se prefieren soluciones más generales.

+2

Yo separaría los dos problemas aquí. problema # 1) * qué * compilador se solicita y # 2) * donde * está localizado el compilador solicitado (para eso puede usar valores predeterminados razonables la mayor parte del tiempo y solo dejar que lo especifiquen si no quieren el clang predeterminado gcc/lo que sea). Las dos cosas no tienen mucho en común, después de todo, puedo crear fácilmente un enlace suave para clang que se llama 'msvc' si quisiera (en realidad nunca lo intenté, pero ¿por qué no?) – Voo

+0

Estoy de acuerdo con la sugerencia que @Voo te dio . Edítalo para limitar a una pregunta y luego crea una nueva pregunta. Tienes dos buenas preguntas, por lo que subí la que creaste (hasta ahora). – octopusgrabbus

+0

@Voo si lo escribe como una respuesta, lo aceptaré, ya que esa fue la idea clave que utilicé para resolver el problema. –

Respuesta

1

Esta pregunta llevó al desarrollo de un proyecto SCons que puede manejar esto:

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

El código en cuestión está en build_scripts/compiler_settings.py. Las opciones SCons se configuran en el archivo SConstruct con las siguientes líneas:

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

El usuario puede especificar 0, 1 o 2 opciones de línea de comandos.

Si no especifica nada (scons), se compila con el compilador del DefaultEnvironment.

Opcionalmente, puede especificar el nombre del compilador (scons --compiler=g++). Mi secuencia de comandos asume que el comando utilizado para compilar es el mismo que el nombre.

También puede especificar opcionalmente el comando para compilar (scons --compiler-command=~/llvm-3.1-obj/Release+Asserts/bin/clang++). Mi secuencia de comandos asume que el nombre del compilador que está utilizando es el nombre del ejecutable (todo después del separador de directorio final, según lo determinado por os.path.basename).

Puede especificar ambos. Esto le permite manejar situaciones extrañas: scons --compiler-command=/path/to/executable/that/is/not/clang++ --compiler=g++

Utiliza el nombre para determinar qué advertencias/optimizaciones se deben activar. Incluso he agregado un poco de normalización al nombre, por lo que g ++, gcc y GcC se tratan como la misma cosa, en lo que respecta al nombre del compilador.

Aún le queda mucho trabajo por hacer, como soporte para más compiladores, mejor compatibilidad con los compiladores mingw y detección de versiones de compilación para permitir un mejor manejo de las banderas que están disponibles solo en la versión x.y.z +. También sería bueno si pudiera hacer algo como scons --compiler-command=/path/to/gcc-4.7.1 y hacer que detecte que el compilador es gcc sin que tenga que decirlo explícitamente.

Sin embargo, se ha solucionado el problema inicial que me propuse solucionar. Gran parte del mérito de esto tiene que ir a Voo en los comentarios por ponerme en el camino correcto.

1

Puede simplemente usar las funciones de Python os.path.basename() o os.path.split(), como se especifica here.

Podría hacer lo que la gente sugirió en los comentarios al dividir esta pregunta en 2 problemas diferentes, pero creo que podría ser una buena idea poder especificar la ruta con el compilador, ya que podría tener 2 versiones de g ++ instalado, y si el usuario solo especifica g ++, es posible que no obtenga la versión esperada.

2

compilador simplemente forman parte del proceso de construcción. También necesita una herramienta enlazadora y puede haber otros programas adicionales. En Scons se llama - Herramienta. Lista de herramientas compatibles from box que se puede ver en man page, búsqueda por estado: SCons supports the following tool specifications out of the box: ... Conjunto de herramientas necesarias variables de entorno scons, está documentado here.

Scons detecta automáticamente el compilador en la SG y tienen cierta prioridad para elegir uno de ellos, por supuesto detección automática funcionará correctamente si la variable PATH establece en directorios necesarios. Por ejemplo, si tienes msvc y mingw en windows, scons elige msvc tool. Para usar la herramienta con fuerza, use la herramienta ('nombre') (env). Por ejemplo:

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

Ahora env fuerza utilizando MinGW.

Por lo tanto, clang es una herramienta que actualmente no es compatible con from box por scons. Necesita implementarlo, o establecer variables como CC, CXX que usan scons para generar comandos de compilación.

Cuestiones relacionadas