(Enlaces de referencia: https://zhuanlan.zhihu.com/p/69393545 )
Linux
Tratamos de preparar programa de metal desnudo bajo Linux, se pueden producir este tipo de errores de enlace:
Error: la vinculación con `cc` falló: código de salida: 1 | = Nota: "cc" [...] = Nota: /usr/lib/gcc/../x86_64-linux-gnu/Scrt1.o: En función `_start ': (.Text + 0x12): referencia indefinida a `__libc_csu_fini' /usr/lib/gcc/../x86_64-linux-gnu/Scrt1.o: En función `_start ': (.Text + 0x19): referencia indefinida a `__libc_csu_init' /usr/lib/gcc/../x86_64-linux-gnu/Scrt1.o: En función `_start ': (.Text + 0x25): referencia indefinida a `__libc_start_main' collect2: Error: ld devolvió el código de salida 1
El problema aquí es que el enlazador será por defecto para iniciar el proceso de referencia de tiempo de ejecución de lenguaje C, o también descrito como _start
función. Vamos a utilizar no_std
una biblioteca que implementa excluidos en virtud de la biblioteca estándar del lenguaje C libc
, por lo que el enlazador no puede resolver las referencias pertinentes, obtener "indefinido de referencia" problema. Para resolver este problema, tenemos que decirle al enlazador que debe comenzar el proceso no se refiere a la utilización del lenguaje C - podemos añadir -nostartfiles
etiquetas de hacer esto.
Para añadir un parámetro al enlazador por la carga, se utiliza el cargo rustc
comando. El papel de la orden y cargo build
el mismo, pero permite al desarrollador el compilador Rust bajos rustc
parámetros de paso. Además, rustc
una -C link-arg
etiqueta, es posible pasar los parámetros necesarios para el enlazador. En resumen, podemos escribir el siguiente comando:
rustc de carga - -C enlace-arg = -nostartfiles
Después de esto, debemos ser capaces de compilar correctamente el paquete, como un programa ejecutable independiente bajo el sistema Linux. Aquí no se especifica explícitamente el nombre de la función de punto de entrada, porque el vinculador usará el nombre de la función por defecto _start
.
ventanas
En el sistema Windows, puede tener un error de vinculador diferente:
Error: la vinculación con `link.exe` falló: código de salida: 1561 | = Nota: "C: \\ Archivos de programa (x86) \\ \\ ... link.exe" [...] = Nota: LINK: LNK1561 error fatal: punto de entrada debe definirse
El error de vinculador "se debe definir los puntos de entrada", lo que significa que no encuentra un punto de entrada. En el sistema Windows, el punto de entrada por defecto determinada por el nombre de la función del subsistema [1] . Del CONSOLE
subsistema, el enlazador buscará llamada mainCRTStartup
función; mientras que el WINDOWS
subsistema, que se verá WinMainCRTStartup
. Nuestras _start
funciones no son dos nombres - con el fin de usarlo, podemos pasar al enlazador /ENTRY
parámetros:
rustc de carga - -C enlace-arg = / ENTRADA: _start
Desde aquí también vemos el formato de los parámetros, el siguiente eslabón en el sistema Windows en el uso de, y bajo Linux son bastante diferentes.
Ejecutar el comando, tenemos otros errores de enlace:
Error: la vinculación con `link.exe` falló: código de salida: 1221 | = Nota: "C: \\ Archivos de programa (x86) \\ \\ ... link.exe" [...] = Nota: LINK: LNK1221 error fatal: un subsistema no puede deducirse y debe estar definido
Este error se debe al programa ejecutable de Windows pueden utilizar diferentes subsistemas ( el subsistema ). programas generales de Windows, nombre de sub-función utilizada por el punto de entrada infiere de: Si el punto de entrada es la main
función que va a utilizar CONSOLE
el subsistema; si se trata de WinMain
una función, utilice el WINDOWS
subsistema. Dado que nuestro _start
nombre de la función y la diferencia entre los dos, tenemos que especificar explícitamente el uso del subsistema:
rustc de carga - -C enlace-args = "/ ENTRADA: _start / SUBSISTEMA: consola"
Aquí se utiliza el CONSOLE
subsistema, pero WINDOWS
el subsistema es factible. Aquí, utilizamos un argumento complejo link-args
en lugar de múltiples -C link-arg
, ya que este último requiere que todos los parámetros se enumeran en secuencia, más espacio.
Después de utilizar este comando, el programa ejecutable que debe ser capaz de funcionar bajo Windows.
Mac OS
Si utiliza el desarrollo del sistema MacOS, podemos encontrar errores de enlace:
Error: la vinculación con `cc` falló: código de salida: 1 | = Nota: "cc" [...] = Nota: LD: punto de entrada (_main) sin definir. para la arquitectura x86_64 tañido: error: comando enlazador falló con el código de salida 1 [...]
El mensaje de error nos dice que el enlazador no puede encontrar la función de punto de entrada por defecto, se llama main
- por alguna razón, todos los nombres de las funciones son macOS ser subrayada _
prefijo. Para establecer el punto de entrada a la función _start
, enviamos a los parámetros de enlace -e
:
rustc de carga - -C enlace-args = "- e __start"
-e
Parámetro especifica el nombre del punto de entrada. Dado que la función en cada macOS tiene un guión _
prefijo, que debe ser nombrado como la función de punto de entrada __start
en su lugar _start
.
Ejecutar este comando, la aparición de dicho error un enlace ahora:
Error: la vinculación con `cc` falló: código de salida: 1 | = Nota: "cc" [...] = Nota: LD: ejecutables principales dinámicas deben enlazar con libSystem.dylib para la arquitectura x86_64 tañido: error: comando enlazador falló con el código de salida 1 [...]
La razón es conseguir este error, MacOS no con apoyo oficial enlazado estáticamente biblioteca binaria [2] , y el programa predeterminado requiere un enlace a libSystem
la biblioteca. Para enlazar a la biblioteca estática binaria, ponemos -static
etiquetas a enlazadores:
rustc de carga - -C enlace-args = "- e __start -static"
Ejecute el comando modificado. Enlazador parecen satisfechos, nos dio tiramos un nuevo error:
Error: la vinculación con `cc` falló: código de salida: 1 | = Nota: "cc" [...] = Nota: LD: biblioteca no se encontró para -lcrt0.o tañido: error: comando enlazador falló con el código de salida 1 [...]
La razón de este error es que el programa está vinculado a los valores predeterminados en MacOS crt0
(C tiempo de ejecución cero) de la biblioteca. Este problema encontrado en Linux y sistemas similares, se puede añadir una -nostartfiles
parámetros de enlace:
rustc de carga - -C enlace-args = "- e __start -static -nostartfiles"
Ahora, nuestro programa debe ser capaz de compilado correctamente en MacOS.