|
Buscador
Secciones
Registro
¡Colabora!
Ganamos
Servicios
|
Tabla 15: Valores admitidos por la opción /tde csc Tanto las librerías como los ejecutables son simples colecciones de tipos de datos compilados. La única diferencia entre ellos es que los segundos disponen de un método especial (Main()) que sirve de punto de entrada a partir del que puede ejecutarse código usando los mecanismo ofrecidos por el sistema operativo (escribiendo su nombre en la línea de comandos, seleccionándolo gráficamente, etc.) La diferencia de un módulo con los anteriores tipos de ficheros es que éste no forma parte de ningún ensamblado mientras que los primeros sí. El CLR no puede trabajar con módulos porque estos carecen de manifiesto, pero crearlos permite disponer de código compilado que pueda añadirse a ensamblados que se generen posteriormente y que podrán acceder a sus miembros internal. Como es lógico, lo que nunca puede hacerse es definir más de un punto de entrada en un mismo tipo de dato, pues entonces ni siquiera a través de la opción /main podría resolverse la ambigüedad. El valor que se le dé ha de incluir la extensión del fichero a generar, lo que permite compilar ficheros con extensiones diferentes a las de su tipo. Por ejemplo, para crear un módulo A.exe a partir de un fuente A.cs puede hacerse: csc /out:A.exe /t:module A.cs Obviamente, aunque tenga extensión .exe el fichero generado será un módulo y no un ejecutable, por lo que si se intenta ejecutarlo se producirá un error informando de que no es un ejecutable válido. Como puede deducirse, cambiar la extensión de los ficheros generados no suele ser útil y sólo podría venir bien para dificultar aposta la comprensión del funcionamiento de una aplicación o para identificar ensamblados con algún significado o contenido especial. En mscorlib.dll se encuentran los tipos de uso más frecuentos incluidos en la BCL. En el poco frecuente caso de que haya definido su propia versión de ellos y no desee que se use la de la BCL, puede puede pasar al compilador el flag /nostdlib para indicarle que no desea que busque implícitamente en mscorlib.dll. Puede que termine descubriendo que en realidad tampoco hace falta referenciar a la mayoría de las restantes librerías que forman la BCL. Pues bien, esto no se debe a que también las referencie implícitamente el compilador, sino a que se incluyen en un fichero de respuesta (más adelante se explica lo que son este tipo de ficheros) usado por defecto por el compilador. Si no desea que utilice este fichero puede pasarle el flag /noconfig. Cuando se den valores a /r hay que tener en cuenta que por defecto el compilador interpretará cada ruta así indicada de manera relativa respecto al directorio desde el que se le llame. Si no lo encuentra allí lo hará relativamente respecto al directorio donde esté instalado el CLR, que en los sistemas operativos Windows es el subdirectorio Microsoft.NET\Framework\v1.0.2914 del directorio de instalación de Windows. Y si tampoco lo encuentra allí la interpretará respecto a los directorios indicados por la variable de entorno LIB de su sistema operativo. Esta política de búsqueda puede modificarse incluyendo opciones /lib al llamar al compilador cuyos valores le indiquen en qué directorios ha de buscar antes de pasar a buscar en los indicados por la variable de entorno LIB. Se incluyen opciones /r y /addmodule separadas porque añadir un módulo a una compilación implica decir que se desea que los tipos que incluye formen parte del ensamblado a generar, por lo que los fuentes a compilar podrán acceder a sus miembros internal. Sin embargo, cuando se referencia a otros ensamblados con /r esto no ocurre y los fuentes compilados no podrán acceder a sus miembros internal. Es importante señalar que el CLR espera que todos los módulos que se añadan a un ensamblado se distribuyan dentro del mismo directorio que la librería o ejecutable correspondiente al mismo. Si no se haciese así no los podría localizar y en tiempo de ejecución se produciría una System.TypeLoadException si se intentase acceder a los tipos definidos en ellos. Aunque en principio se ha dicho que no importa cómo se intercalen opciones y nombres de fuentes entre los argumentos pasados a csc, hay una excepción que consiste en que /out y /r siempre han de indicarse antes de algún fuente. Esto permite que en una misma llamada al compilador sea posible solicitar la generación de un ensamblado y múltiples módulos de código, pues se considera que cada aparición de las opciones anteriores hace referencia sólo a los fuentes que le siguen. Por ejemplo, dada: csc /t:library /out:LibA.dll A.cs /t:module /out:ModB.netmodule B.cs Esta llamada provocará la compilación de A.cs como librería de nombre LibA.dll y la de B.cs como módulo llamado ModB.netmodule. Sin embargo, al hacer así compilaciones múltiples hay que tener en cuenta que sólo es válido solicitar que el primer grupo de ficheros indicado se compile como ensamblado. Por tanto, sería incorrecto hacer: csc /t:module /out:ModB.netmodule B.cs /t:library /out:LibA.dll A.cs Esta llamada es incorrecta porque indica que se desea que el segundo grupo de ficheros dé lugar a un ensamblado y ello sólo puede hacerse con el primero. Por otro lado, también hay que tener en cuenta que no es válido que un mismo tipo de dato se defina en varios de los grupos de ficheros indicados. Por ejemplo, si se quisiese compilar A.cs como ejecutable y como módulo podría pensarse en hacer: csc A.cs /t:library A.cs Sin embargo, esta llamada no es válida porque los dos grupos de ficheros indicados contienen el mismo fichero y por tanto definiciones comunes de tipos de datos. La única solución posible sería hacer dos llamadas por separado al compilador como: csc A.cs csc /t:library A.cs
|
| Nivel de aviso | Avisos mostrados |
|---|---|
| 0 | Ninguno |
| 1 | Sólo los más graves |
| 2 | Los más graves y algunos menos graves como por ejemplo los relativos a ocultaciones de miembros |
| 3 | Los de nivel 2 más algunos poco graves como los relativos al uso de expresiones absurdas que siempre produzcan el mismo resultado |
| 4 | Todos |
Tabla 16: Niveles de mensajes de aviso
Si está interesado en conocer en concreto el nivel de algún tipo de aviso puede remitirse a la descripción sobre el mismo incluida en la documentación del SDK antes comentada
Ficheros de
respuestaLa línea de comandos no es la única forma de pasar información al compilador (tanto ficheros a compilar como opciones de compilación), sino que también es posible almacenar información de este tipo en un fichero y pasársele al compilador como argumento solamente dicho fichero y no toda la información en él contenida. De este modo se facilitaría la labor de pasar como parámetros las opciones de uso más frecuente ya que bastaría sólo indicar cuál es el nombre de un fichero que las especifica.
A este ficheros se les llama ficheros de respuesta, ya que al pasárselos al compilador su contenido puede verse como la respuesta a cuáles son los argumentos a usar durante la compilación. La extensión de estos ficheros suele ser .rsp, y aunque nada obliga a dársela es conveniente hacerlo como ocurre con todo convenio.
Al compilar, por defecto el compilador siempre lee un fichero de respuesta llamado csc.rsp ubicado en el directorio del CLR, por lo que para entender cuál es la sintaxis a seguir para escribir estos ficheros nada mejor que ver cuál es su contenido y así de paso saber cuáles son las opciones que por defecto se añadiran a toda compilación:
# This file contains command-line options that the C# # command line compiler (CSC) will process as part # of every compilation, unless the "/noconfig" option # is specified. # Reference the common Framework libraries /r:Accessibility.dll /r:Microsoft.Vsa.dll /r:System.Configuration.Install.dll /r:System.Data.dll /r:System.Design.dll /r:System.DirectoryServices.dll /r:System.dll /r:System.Drawing.Design.dll /r:System.Drawing.dll /r:System.EnterpriseServices.dll /r:System.Management.dll /r:System.Messaging.dll /r:System.Runtime.Remoting.dll /r:System.Runtime.Serialization.Formatters.Soap.dll /r:System.Security.dll /r:System.ServiceProcess.dll /r:System.Web.dll /r:System.Web.RegularExpressions.dll /r:System.Web.Services.dll /r:System.Windows.Forms.Dll /r:System.XML.dll
Del contenido de este fichero es fácil deducir que la estructura de los ficheros de respuesta es sencilla: cada opción se incluye en una línea aparte y pueden intercalarse entre ellas comentarios de una línea que comiencen con #. Además, como puede verse este fichero de respuesta usado por defecto añade referencias a las librerías de la BCL de uso más común, lo que evita tener que incluirlas constantemente al compilar.
Tras tomar las opciones de este fichero, el compilador mira si en el directorio desde el que se le llama hay otro csc.rsp y si es así toma sus opciones. Si por alguna razón no nos interesase que se tomasen las opciones de dichos ficheros (por ejemplo, para usar nuevas versiones de tipos incluidos en las librerías que referencian) bastaría pasar el flag /noconfig al compilar para desactivar esta búsqueda por defecto en ellos, aunque hay que señalar que este flag no admite los sufijos + y - admitidos por el resto de flags.
En realidad, la estructura del fichero de respuesta csc.rsp no es la única posible, pues además de opciones también es válido incluir nombres de fuentes a compilar e incluso puede mezclarse múltiples opciones y nombres de fuentes en cada línea del fichero.
Ahora bien, al escribir ficheros de respuesta hay que tener cuidado con dos cosas: no es posible cortar las opciones o nombres de fichero con retornos de carro que provoquen que ocupen varias líneas; y las opciones son pasadas al compilador en el mismo orden en que aparezcan en el fuente, por lo que hay que tener cuidado con cómo se coloquen las opciones /out y /t por lo ya comentado sobre la importacia de su colocación.
Una vez escrito un fichero de respuesta, para indicar al compilador que ha de usarlo basta pasárselo como un nombre de fuente más pero precediendo su nombre del sufijo @. Por ejemplo, para compilar A.cs usando las opciones almacenadas en opc.rsp habría que llamar al compilador con:
csc @opc.rsp A.rsp
También sería posible indicar múltiples ficheros de respuesta, caso en que se tomarían las opciones de cada uno en el mismo orden en que apareciesen en la llamada a csc. Por ejemplo, para compilar A.rsp tomando las opciones de opc1.rsp y luego las de opc2.rsp podría llamarse al compilador con:
csc @opc1.rsp @opc2.rsp A.rsp
Puede ocurrir que las opciones indicadas en un fichero de respuesta contradigan a opciones indicadas en otro fichero de respuesta indicado a continuación o a opciones dadas al compilador en la línea de comandos. Para resolver estas ambigüedades el compilador siempre va procesando los argumentos que se le pasen de izquierda a derecha y se queda con la última especificación dada a cada opción. Así, en el ejemplo anterior las opciones del csc.rsp del directorio desde el que se le llamó -si existiese- tendría preferencia sobre las del csc.rsp del directorio del CLR, las de opc2.rsp tendrían preferencia sobre las de éste, y las de opc1.rsp sobre las de opc2.rsp.
También pueden incluirse en los ficheros de respuesta opciones @ que incluyan a otros ficheros de respuesta, con lo que se tomaría sus opciones antes de continuar tomando las siguientes del fichero que lo incluyó, aunque obviamente nunca se admitirá que un fichero incluido sea el mismo que el que lo incluye o que alguno que incluya a éste, pues entonces se formarían ciclos y nunca acabaría la búsqueda de opciones.
Opciones de
depuraciónSin duda la opción de depuración más importante es el flag /debug, cuya inclusión indica al compilador que ha de generar un fichero .pdb con información sobre la relación entre el fichero binario generado y las líneas de los fuentes a partir de los que se generó. Esta información es muy útil para depurar aplicaciones, pues permite mostrar la instrucción de código fuente que produjo las excepciones en lugar de mostrar las instrucciones de código nativo en que fue traducida.
Para entender mejor la utilidad de este fichero .pdb puede escribir el programa:
class A
{
public static void Main()
{throw new System.Exception();}
}
Si lo compila con:
csc A.cs
Al ejecutarlo se producirá una excepción y surgirá una ventana de selección de depurador. Si pulsa No en ella verá en la consola un mensaje como el siguiente:
Unhandled Exception: System.Exception: Exception of type System.Exception was thrown. at A.Main()
Sin embargo, si lo compila con:
csc A.cs /debug
Al ejecutarlo se obtendrá un mensaje mucho más detallado en el que se indicará cuál es la línea exácta del código fuente durante cuya ejecución se produjo la excepción:
Unhandled Exception: System.Exception: Exception of type System.Exception was thrown at A.Main() in E:\c#\Ej\A.cs:line 5
Como es fácil deducir, a partir de esta información es fácil crear herramientas de depuración -como el depurador de Visual Studio.NET o el CLR Debugger del SDK- que muestren la línea exácta del código fuente donde se produjo la excepción lanzada; y obviamente estos datos también pueden tener muchos otros usos, como permitir ejecutar paso a paso los programas mostrando en cada momento cuál es la línea del fuente que se ejecutará a continuación y cosas similares.
También puede usarse /debug como opción con argumentos en vez de cómo flag, lo que permite generar una versión recortada de la información de depuración. Si de esta forma se le da el valor full funcionará exáctamente igual que al activarla como flag, pero si se le da el valor pdbonly entonces la información de depuración generada sólo estará disponible para los depuradores desde los que se haya lanzado la aplicación pero no para los que se le hayan adjuntado dinámicamente una vez lanzada.
Por último, respecto a la depuración de aplicaciones conviene señalar que por defecto el compilador siempre intenta generar el código más compacto y eficiente posible, lo que provoca que compile más lentamente. Sin embargo, como cuando se está depurando suelen realizarse mmuchas recompilaciones de los fuentes puede que en esos casos interese desactivar dichas optimizaciones y así así conseguir recompilar más rápido. Ello puede conseguirse llamando al compilador con /optimize- (/o-)
Compilación
incrementalLa compilación incremental consiste en sólo recompilar en cada compilación que se haga de un proyecto aquellos métodos cuya definición haya cambiado respecto a la última compilación realizada, con lo que el proyecto podría compilarse más rápido que haciendo una compilación completa normal.
Para que esto sea posible hacerlo hay que llamar al compilador con el flag /incremental (/incr), lo que provocará la generación de un fichero adicional con el mismo nombre que el binario generado más una extensión .incr. Por ejemplo, dado:
csc /out:fuente.exe /incremental Fuente.cs
Se generará un ejecutable fuente.exe y un fichero adicional fuente.exe.incr. Aunque pueda parecer redundante incluir en el ejemplo la opción /out al llamar al compilador, es necesaria porque al menos en la versión del compilador incluida en la beta 2 del es obligatorio especificarla siempre que se utilice /incr.
El fichero .incr generado incluye información sobre la compilación que permitirá que posteriores compilaciones que se realicen con /incr activado puedan hacerse de manera incremental. Obviamente, si este fichero se elimina será reconstruido en la siguiente compilación que se haga con /incr, pero dicha compilación no se realizará de manera completa por no disponerse del fichero .incr durante ella.
Sin embargo, el hecho de que esté disponible un fichero .incr al compilar un proyecto no implica que se use, pues el compilador puede ignorarlo y realizar una compilación completa si detecta que han cambiado las opciones de compilación especificadas o si detecta que los fuentes han cambiado tanto que es al menos igual de eficiente hacerla así que de manera incremental.
En realidad no es bueno hacer siempre las compilaciones incrementalmente sino que sólo es útil hacerlo en proyectos formados por mútilples fuentes de pequeño tamaño, minetras que en proyectos con pocos y grandes ficheros se gana poco o nada en tiempo de compilación. Además, los ejecutables generados incrementalmente pueden ocupar más que los generados por compilación completa, por lo sólo es recomendable compilar incrementalmente las versiones de prueba de los proyectos pero no las definitivas.
Opciones relativas al
lenguajeA lo largo de los anteriores temas se ha ido diseminando diversas opciones de compilación relacionadas de manera más o menos directa con el lenguaje C#. En este punto haremos recapitulación de todas ellas mismas y las resumiremos:
Por ejemplo, si se desea compilar los fuentes A.cs y B.cs como si al principio de ellos se hubiese incluido las directivas de preprocesado #define PRUEBA y #define VERSION1 podría llamarse al compilador con:
csc /d:PRUEBA;VERSION1 A.cs B.cs
Obviamente el código compilado con /checked se ejecutará más lento que el que lo haga sin ella ya que incluirá comprobaciones de desbordamiento adicionales. Sin embago, a cambio con ello se consigue detectar con facilidad errores derivados de desbordamientos que de otra manera podrían pasar inadvertidos.
Al usar esta opción hay que tener en cuenta una cosa, y es que para optimizar el tiempo que se tarda en realizar compilaciones incrementales, durante ellas esta opción es ignorada. Por tanto, no tiene mucho sentido combinar /doc y /incr.
Otras opcionesAparte de las opciones comentadas, csc admite unas cuantas más aún no descritas ya sea porque su uso es muy poco frecuente o porque no encajan correctamente en ninguno de los subepígrafes tratados. Todas estas opciones se recogen finalmente aquí:
Por defecto el valor que se le dé puede variar dependiendo de la implementación que se haga del CLR, aunque darle un valor a medida puede ser útil en el diseño de aplicaciones para dispositivos empotrados con escasa capacidad de almacenamiento ya que puede reducir el tamaño de los ficheros generados.
El valor que se dé a esta opción es el nombre de con el que se desea que se genere el fichero con la información relativa al error descubierto durante la compilación. En dicho fichero csc insertará automáticamente la siguiente información:
Aparte de toda esta información insertada automáticamente por el compilador, durante la generación del fichero de error también se pedirá al usuario que indique una pequeña descripción sobre el error detectado y cómo cree que podría solucionarse. Dicha información también será añadida de manera automática al fichero de error que se cree.
Un ejemplo cómo generar información relativa a un error verídico que se produce al compilar un programa error.cs con la Beta 1 del .NET SDK Framework es:
csc error.cs /bugreport:ErrorUsing.cs
Tras contestar a las preguntas que el compilador hará al usuario sobre el error encontrado, el contenido del fichero generado es el siguiente:
### C# Compiler Defect Report, created 07/12/00 20:14:36
### Compiler version: 7.00.9030
### Common Language Runtime version: 1.00.2914.16
### Operating System: Windows NT 5.0.2195 Service Pack 2
### User Name: Administrador
### Compiler command line
csc.exe error.cs /bugreport:ErrorUsing.cs
### Source file: 'e:\c#\ej\error.cs'
using System;
public class R1:IDisposable
{
public static void Main()
{
using (R1 r1 = new R1())
{
}
}
public void Dispose()
{}
}
### Compiler output
error.cs(7,3): error CS1513: } expected
error.cs(7,26): error CS1002: ; expected
error.cs(12,9): error CS1518: Expected class, delegate, enum,
interface, or struct
error.cs(14,1): error CS1022: Type or namespace definition, or
end-of-file expected
### User description
No detecta la instruccion using
### User suggested correct behavior
Posiblemente no haya sido implementada en esta version del compilador
Nótese que aunque el error detectado en el ejemplo es verídico, en versiones del compilador posteriores a la Beta 1 no se produce porque ya fue corregido.
El valor que se dé a esta opción puede indicarse tanto en hexadecimal como en octal o decimal siguiendo las reglas usadas en C# para la escritura de literales enteros. Sin embargo, hay que tener en cuenta que los bits menos significativos de esta dirección pueden ser redondeados. Por ejemplo, si escribimos:
csc fichero.cs /baseaddress:0x11110001
El compilador tratará esta llamada tal y como si se le hubiese pasado:
csc fichero.cs /baseaddress:0x11110000
Si no se da valor a esta opción, las librerías se instalarán en el área de memoria que se estime conveniente en cada implementación del CLR.
Un uso típico de esta opción es permitir compilar fuentes escritos en español con un editor de textos de MS-DOS (como edit.com), caso en que hay que darle el valor 437 para que acepte los caracteres especiales tales como acentos o eñes.
/utf8output: Su inclusión indica que el compilador ha de mostrar los mensajes usando el juego de caracteres UTF-8, lo que es útil cuando se utilizan ciertos sistemas operativos internacionales en los que por defecto no se muestren correctamente dichos mensajes por la ventana de consola.
Para poder leerla en esos casos se recomienda usar este flag al compilar y redirigir la salida a un fichero como muestra el siguiente ejemplo donde se compila A.cs redirigiendo los mensajes de compilación a salida.txt y mostrándolos en UTF-8:
csc A.cs /utf8output > salida.txt
Suele usarse cuando la compilación se solicita desde una aplicación o fichero de procesamiento por lotes, pues oculta la ejecución del compilador al usuario y ello puede venir bien para evitar que éste conozca cómo funciona la aplicación o para conseguir un funcionamiento más elegante y transparente de la misma.
Acceso al compilador
desde Visual Studio.NETComo se explicó en su momento en el Tema 2: Introducción a C#, a las opciones de compilación de un proyecto se accede desde VS.NET a través de las páginas de propiedades del mismo, las cuales tiene el aspecto mostrado en la Ilustración 9 y se obtienen seleccionando el proyecto en el Solution Explorer y pulsando sobre View -> Property Pages en el menú principial de Visual Studio.

Para la mayoría de opciones admitidas por csc.exe se incluye en estas páginas controles tales como cajas de texto y listas desplegables que permiten configurarlas de una manera visual, cómoda e intuitiva. En la Tabla 17 se resume en orden alfabético cuál es el control que en concreto se asocia en estas páginas a cada opción:
| Opción | Control visual |
|---|---|
| /baseaddress | Configuration Properties -> Advanced -> Base Address |
| /checked | Configuration Properties -> Build -> Check for Arithmetic Overflow/Underflow |
| /debug | Configuration Properties -> Build -> Generate Debugging Information |
| /define | Configuration Properties -> Build -> Conditional Compilation Constants |
| /doc | Configuration Properties -> Build -> XML Documentation File |
| /filealign | Configuration Properties -> Build -> File Alignment |
| /incremental | Configuration Properties -> Advanced -> Incremental Build |
| /main | Common Properties -> General -> Startup Object |
| /optimize | Configuration Properties -> Build -> Optimize code |
| /out | Common Properties -> General -> Assembly Name |
| /target | Common Properties -> General -> Output Type |
| /unsafe | Configuration Properties -> Build -> Allow unsafe code blocks |
| /warn | Configuration Properties -> Build -> Warning Level blocks |
| /warnaserror | Configuration Properties -> Build -> Treat Warnings As Errors |
| /win32icon | Common Properties -> General -> Application Icon |
Tabla 17: Controles asociados a opciones de compilación
Como puede observar, desde VS.NET no es posible acceder a muchas de las opciones del compilador en línea de comandos. En los casos de /codepage, /fullpaths, /lib, /help, /nologo, /recurse y /utf8output esto es lógico ya que son opciones que pierden su sentido desde dentro en una interfaz gráfica. Hay otros casos en que ello se debe a que se ofrecen desde el menú principal de VS.NET otros mecanismos alternativos para especificarlas, como son los indicados en la Tabla 18:
| Opción | Mecanismo de acceso |
|---|---|
| /bugreport | Help -> Customer Feedback |
| /resource | Seleccionar el recurso en Project -> Add Existing Item |
| /reference | Seleccionar la referencia en Project -> Add Reference |
Tabla 18: Acceso a opciones fuera de las páginas de propiedades
Finalmente, queda un grupo de opciones que no disponibles simplemente porque la implementación de VS.NET (al menos en la Beta 2) no las contempla, y son @, /linkresource, /nostdlib, /noconfig, /nowarn y /win32res. En este sentido, mención aparte merece el valor module de /t, que tampoco puede usarse en tanto que VS.NET no soporta el trabajo con módulos.
| Leer comentarios (150) | |
| Escribir comentario | |
| Puntuación: |
|
| Votar | |
| Recomendar este tutorial | |
| Estadísticas |
Copyright © 1999-2006
Programación en castellano.
Todos los derechos reservados.
Formulario de Contacto -
Datos legales -
Publicidad
Hospedaje web y servidores dedicados linux por
Ferca Network