Go: cmd / link: admite archivos de objeto msvc

Creado en 11 jul. 2017  ·  222Comentarios  ·  Fuente: golang/go

Entiendo que el enlazador go no puede actualmente vincular archivos de objeto msvc y también reconozco que es probable que este problema sea de baja prioridad. Sin embargo, sería bueno admitir esto porque simplificaría un poco el flujo de trabajo de Windows. Este problema es principalmente para comprender cuánto esfuerzo sería y / o qué se requeriría.

Builders FeatureRequest NeedsInvestigation OS-Windows

Comentario más útil

Oye, desde la parte inferior de este hilo parece que tienes resueltos tus problemas de MSVC. Pero si tiene algún problema, estoy en el equipo de MSVC. No dude en enviarme un ping en github o por correo electrónico ([email protected])

Todos 222 comentarios

/ cc @alexbrainman

@xoviat ¿cuál es el problema que estás teniendo? Necesito poder reproducirlo aquí. Por lo tanto, proporcione todos los pasos que tendré que seguir para reproducir esto.

Gracias

Alex

PD: No tendré computadora hasta finales de julio. Entonces echaré un vistazo a esto.

cual es el problema que estas teniendo?

No lo he probado todavía, pero me gustaría llamar específicamente a funciones c en archivos de objeto msvc vinculándolos como .syso con el enlazador go. Todo lo que he leído indica que esto no es posible pero crearé un procedimiento para reproducir el error específico que se produzca.

llamar específicamente a funciones c en archivos de objeto msvc vinculándolos como .syso con el enlazador go

¿Ha intentado construirlos en una DLL y usarlos desde dentro de la DLL?

Crearé un procedimiento para reproducir el error específico que ocurra.

Por favor, hazlo. Gracias.

Alex

¿Ha intentado construirlos en una DLL y usarlos desde dentro de la DLL?

Ese era en realidad mi plan original. Estoy usando swig, por lo que no es tan conveniente compilar el código c generado por separado y luego reescribir las funciones como exportaciones de DLL. No es difícil, pero es molesto cuando el flujo de trabajo con gcc es solo go generate; go build .

Muy bien, tengo un procedimiento. Comience con estos archivos:

hola.go:

package main

/*
    extern void hello();
*/
import "C"

func main() {
    C.hello()
}

Hola C:

#include <stdio.h>

extern void hello()
{
    printf("Hello World from C");
}

luego ejecute estos comandos (con msvc en la ruta):

cl /c hello.c
mv hello.obj hello.syso
mv hello.c hello.c.bak
go build

Resultado:
Warning: corrupt .drectve at end of def file

Al ejecutar el archivo producido:

Exception 0xc0000005 0x8 0x13 0x13
PC=0x13
signal arrived during external code execution

main._Cfunc_hello()
        _//_obj/_cgo_gotypes.go:41 +
main.main()
        C://hello.go:9 +0x27

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        C:/Program Files/Go/src/runtime/asm_amd64.s:2197 +0x1
rax     0x4a5960
rbx     0xc042045f78
rcx     0x4a9a20
rdi     0xc042045f78
rsi     0x4adc60
rbp     0xc042045f38
rsp     0x6dfd68
r8      0xc042016340
r9      0x0
r10     0xc04204faa0
r11     0x4783c2
r12     0x0
r13     0x6
r14     0x0
r15     0xf1
rip     0x13
rflags  0x10216
cs      0x33
fs      0x53
gs      0x2b

No tengo el comando cl instalado en mi PC. ¿Cómo instalo msvc?

Gracias.

Alex

Necesita las "herramientas de construcción 2017" aquí . En realidad, Microsoft ahora permite que cualquier persona use Visual Studio de forma gratuita siempre que no sea para desarrollo comercial. Si es demasiado problema, puedo darle el archivo de objeto si lo desea.

Si solo C ++ no fuera una cosa, no tendría que preocuparme por esto. Pero lo es, así que el dolor continúa ...

Necesita las "herramientas de construcción 2017" aquí.

Entiendo. Gracias.

Si es demasiado problema, puedo darle el archivo de objeto si lo desea.

Sí, por favor, publique hello.obj en algún lugar.

Pensando en esto un poco más. En realidad, está utilizando gcc para vincular el archivo de objeto compilado con el compilador msvc. ¿Puedes intentar hacer tu ejercicio, pero reemplazando el paso "go build" con gcc vinculando hello.obj a un programa en C? Quizás ya se haya hecho antes. Sospecho que, si sabemos cómo hacer eso, podríamos hacer algo similar con Go.

Alex

AFAIK lld https://github.com/llvm-mirror/lld admite archivos de objeto msvc.

El archivo de objeto está aquí: https://github.com/xoviat/msvcgo/blob/master/hello.syso

lld https://github.com/llvm-mirror/lld admite archivos de objeto msvc

Go usa el enlazador gcc (no lld) en Windows.

El archivo de objeto está aquí: https://github.com/xoviat/msvcgo/blob/master/hello.syso

Lo intentaré cuando llegue a casa en agosto. gracias.

Alex

Go usa el enlazador gcc (no lld) en Windows.

Sé. Pero lld es la mejor documentación de código abierto del formato de objeto msvc.

De hecho, obtengo el mismo error de ld, por lo que el error definitivamente proviene de ld.

De hecho, obtengo el mismo error de ld, por lo que el error definitivamente proviene de ld.

Si. Necesitamos averiguar cómo construir un programa en C compilando parte con msvc y vinculándolo con gcc.

Alex

Perdona mi ignorancia, pero ¿qué es exactamente la vinculación gcc? ¿Está vinculando la salida del enlazador go?

Ejecutando objconv en los archivos de objeto para convertir a elf:

objconv -felf hello.obj hello.syso

Ahora tenemos estos errores:

hello.syso: In function `__local_stdio_printf_options':
(.text$mn+0x3): undefined reference to `?_OptionsStorage@?1??__local_stdio_printf_options@@9<strong i="9">@9</strong>'
hello.syso: In function `_vfprintf_l':
(.text$mn+0x3a): undefined reference to `__stdio_common_vfprintf'
hello.syso: In function `printf':
(.text$mn+0x28): undefined reference to `__acrt_iob_func'
collect2.exe: error: ld returned 1 exit status

¿Posiblemente stdio está fuera de los límites?

Perdona mi ignorancia, pero ¿qué es exactamente la vinculación gcc? ¿Está vinculando la salida del enlazador go?

Utiliza 2 programas para crear su programa Go:

  • El compilador convierte sus archivos .go (1 paquete a la vez) en un archivo objeto almacenado en el directorio% GOPATH% / pkg;
  • enlazador que crea el archivo .exe final a partir de archivos de objeto de debajo de% GOPATH% / pkg.

A veces (cuando uno de sus paquetes usa Cgo), el enlazador Go llama al enlazador externo para encontrar todos los bits que están implementados en C. Imagine que llama a printf desde su código C. El código compilado de C printf debe ser parte del ejecutable de Go, pero el enlazador de Go no sabe dónde conseguirlo. Entonces, el vinculador de Go llama al vinculador externo para incluir ese código.

Current Go usa el compilador / enlazador gcc para compilar y vincular el código C (usamos mingw gcc). Si va a compilar su código C con un compilador diferente (de Microsoft), tendrá que usar el enlazador correspondiente (de Microsoft) para encontrar todo el código C externo que creó el compilador.

Entonces, supongo que me equivoqué al sugerir el uso del enlazador gcc. Para un escenario general, tendría que usar tanto el compilador como el vinculador de Microsoft. Tendríamos que averiguar qué requiere el enlazador de Microsoft como entrada y combinarlo.

Es posible que se salga con la suya sin el vinculador MC, si su código C no tiene ningún código externo. Pruebe algún programa en C realmente simple (como el que agrega 2 enteros o algo así). Eso podría funcionar como lo describió anteriormente.

Alex

¿Posiblemente stdio está fuera de los límites?

Sospecho que necesita llamar al vinculador de Microsoft para encontrar ese código.

Alex

No estoy seguro pero

objconv -felf hello.obj hello.syso

Tal vez, ¿deberías intentar hacer coff u omf en lugar de elf?

Tal vez, ¿deberías intentar hacer coff u omf en lugar de elf?

@xoviat sí, no debe convertir archivos .obj a elf, la versión de Windows de gcc genera archivos pe / coff como cualquier otro compilador de Windows.

Alex

el enlazador Go llama al enlazador externo para encontrar todos los bits que están implementados en C.

¿Cuál es el comando específico que se usa? Si conozco el comando mingw, entonces tal vez pueda seguir una ruta de comparación de archivos para intentar que msvc coincida con lo que mingw está emitiendo.

Puede ver el comentario exacto ejecutando go build -ldflags=-v .

Bien, por lo que puedo decir:

ld (link -> go.obj) + (gcc -> obj files) ==> a.out.exe

Ir aparece para crear un directorio temporal con estos archivos. ¿Hay alguna forma de preservar el directorio temporal para que pueda inspeccionar su contenido?

Prueba go build -work

WORK=C:\Users\mattn\AppData\Local\Temp\go-build566171254

Los archivos de objeto permanecen en este directorio.

La opción -work realidad no conservará los archivos temporales que crea el enlazador. Por el momento, solo tiene que editar las fuentes del enlazador para no eliminar el directorio. Probablemente deberíamos agregar una opción para eso, de una forma u otra.

Por el momento, solo tiene que editar las fuentes del enlazador para no eliminar el directorio.

Si no le importa, esperaré hasta que esto se implemente en HEAD para no tener que hacer un trabajo repetitivo.

¿Hay alguna forma de preservar el directorio temporal para que pueda inspeccionar su contenido?

El programa cmd / link tiene el indicador -tmpdir para eso. Puedes usarlo así:

c:\Users\Alex\dev\src\a>dir
 Volume in drive C has no label.
 Volume Serial Number is 9012-A870

 Directory of c:\Users\Alex\dev\src\a

06/08/2017  02:02 PM    <DIR>          .
06/08/2017  02:02 PM    <DIR>          ..
06/08/2017  02:02 PM                77 main.go
               1 File(s)             77 bytes
               2 Dir(s)  430,809,088,000 bytes free

c:\Users\Alex\dev\src\a>type main.go
package main

import "fmt"
import "C"

func main() {
        fmt.Println("Hello")
}

c:\Users\Alex\dev\src\a>go build -o a.exe -ldflags="-tmpdir=c:\Users\Alex\dev\src\a" main.go

c:\Users\Alex\dev\src\a>dir
 Volume in drive C has no label.
 Volume Serial Number is 9012-A870

 Directory of c:\Users\Alex\dev\src\a

06/08/2017  02:02 PM    <DIR>          .
06/08/2017  02:02 PM    <DIR>          ..
06/08/2017  02:02 PM             2,055 000000.o
06/08/2017  02:02 PM            22,376 000001.o
06/08/2017  02:02 PM         2,017,382 a.exe
06/08/2017  02:02 PM               135 fix_debug_gdb_scripts.ld
06/08/2017  02:02 PM         2,402,226 go.o
06/08/2017  02:02 PM                77 main.go
06/08/2017  02:02 PM                24 trivial.c
               7 File(s)      4,444,275 bytes
               2 Dir(s)  430,804,631,552 bytes free

c:\Users\Alex\dev\src\a>

Alex

Esto es solo para mi propia referencia, pero esto debe trasladarse a msvc:

_cgo_sys_thread_start(ThreadStart *ts)
{
    uintptr_t thandle;

    thandle = _beginthread(threadentry, 0, ts);
    if(thandle == -1) {
        fprintf(stderr, "runtime: failed to create new OS thread (%d)\n", errno);
        abort();
    }
}

static void
threadentry(void *v)
{
    ThreadStart ts;

    ts = *(ThreadStart*)v;
    free(v);

    ts.g->stackhi = (uintptr)&ts;
    ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;

    /*
     * Set specific keys in thread local storage.
     */
    __asm {
          "movq %0, %%gs:0x28\n"    // MOVL tls0, 0x28(GS)
          "movq %%gs:0x28, %%rax\n" // MOVQ 0x28(GS), tmp
          "movq %1, 0(%%rax)\n" // MOVQ g, 0(GS)
          :: "r"(ts.tls), "r"(ts.g) : "%rax"
    }

    crosscall_amd64(ts.fn);
}

No subestimaría el tiempo que me llevará completar esta tarea, ya que no estoy familiarizado en absoluto con el montaje.

  • [x] Entender lo que hace la asamblea
  • [x] Puerto al ensamblaje de MSVC
  • [x] Comprender _beginthread frente a CreateThread
  • [x] Cambiar a CreateThread

Además, símbolos indefinidos:

  • [x] timeBeginPeriod -> winmm.lib
  • [x] timeBeginPeriod
  • [x] WSAGetOverlappedResult -> Ws2_32.lib
  • [x] WSAGetOverlappedResult
  • [x] _cgo_18b6f6fc815b_Cfunc_hello
  • [x] x_cgo_init -> msvc_windows_amd64.c
  • [x] x_cgo_thread_start -> msvc_windows_amd64.c
  • [x] x_cgo_sys_thread_create -> msvc_windows_amd64.c
  • [x] x_cgo_notify_runtime_init_done -> gcc_libinit_windows.c
  • [x] x_cgo_set_context_function -> gcc_libinit_windows.c

Bien, ¡avanzando por aquí más rápido de lo esperado!

Todo: ¿ asm_amd64.s está ensamblado por el ensamblador de go (con el ensamblaje impar) o el ensamblador de gcc?

Parece que gcc no lo ensamblará, lo que significa que probablemente esté listo para ensamblar. Y luego la pregunta es: cómo ensamblarlo con el ensamblador go en un objeto.

La intención es que runtime / cgo / asm_amd64.s se ensamble en un objeto Go, luego cmd / link lo vincule con todos los demás objetos Go en un solo objeto del sistema, y ​​luego el vinculador del sistema vincula esos objetos del sistema individuales más todos los cgo dependencias en el programa final.

¿Hay alguna forma de ensamblar ese objeto por ahora con fines de prueba? Como gcc -c asm_amd64.s excepto con ir?

La intención es que runtime / cgo / asm_amd64.s se ensamble en un objeto Go, luego cmd / link lo vincule con todos los demás objetos Go en un solo objeto del sistema, y ​​luego el vinculador del sistema vincula esos objetos del sistema individuales más todos los cgo dependencias en el programa final.

Hasta ahora encontré estos objetos:

  • go.o: obviamente de la cadena de herramientas Go
  • _cgo_.o : generado por gcc, inutilizable
  • 000000.o: generado por gcc, inutilizable
  • 000001.o: Actualización: realmente generado por el enlazador go, pero contiene símbolos gcc. Inutilizable.

go.o es el objeto más grande.

@ianlancetaylor

No creo que lo que dijiste sea correcto. crosscall_amd64 se encuentra en 000001.o, pero ese archivo no tiene "todo el código go":

000001.o:     file format pe-x86-64

SYMBOL TABLE:
[201](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000440 crosscall_amd64
[206](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000000 free

Este archivo obviamente ha sido generado por gcc, que es demasiado tarde en el proceso.

¿Hay alguna forma de ensamblar ese objeto por ahora con fines de prueba? Como gcc -c asm_amd64.s excepto con go?

asm_amd64.s es parte del paquete de tiempo de ejecución. Puede ver cómo el comando "go build" usa el archivo asm_amd64.s, como:

$ touch asm_amd64.s
$ GOOS=windows go build -x runtime 2>&1 | grep asm_amd64.s
/home/a/go/pkg/tool/linux_amd64/asm -trimpath $WORK -I $WORK/runtime/_obj/ -I /home/a/go/pkg/include -D GOOS_windows -D GOARCH_amd64 -o $WORK/runtime/_obj/asm_amd64.o ./asm_amd64.s
$

Alex

Gracias.

El símbolo crosscall_amd64 se define en el archivo runtime / cgo / gcc_amd64.s. Ese archivo es compilado por GCC (al igual que todos los archivos runtime / cgo / gcc_ *). Por lo tanto, no se combina en un solo archivo go.o que contiene todo el código Go. El archivo del que hablábamos antes, runtime / cgo / asm_amd64.s, define el símbolo crosscall2 . Encontrará ese símbolo en go.o.

Gracias.

De acuerdo, me las arreglé para vincular un ejecutable que falla en una infracción de acceso mientras está en
go.runtime.rt0_go + 5F -> go .___ acrt_stdio_initializer.

Ese es todo el tiempo que tengo por ahora; Volveré a esto más tarde.

@alexbrainman Eso es correcto.

@alexbrainman Necesitará MSVC para continuar. Déjame saber si necesitas ayuda con esto.

Necesitará MSVC para continuar.

Estoy instalando este https://www.visualstudio.com/downloads/#build -tools-for-visual-studio-2017

¿Qué debo hacer una vez instalado?

Alex

Una vez que lo haya instalado, debe compilar "libgo", que es la biblioteca go. Copie los siguientes archivos de la carpeta cgo :

  • gcc_amd64.S
  • gcc_fatalf.c
  • gcc_libinit_windows.c
  • gcc_util.c
  • gcc_windows_amd64.c
  • libcgo.h

Necesitamos ajustar gcc_windows_amd64.c para que sea compatible con MSVC. Modifique la función de la siguiente manera:

static void
threadentry(void *v)
{
    fprintf(stderr, "threadentry: started");
    abort();

    ThreadStart ts;

    ts = *(ThreadStart*)v;
    free(v);

    ts.g->stackhi = (uintptr)&ts;
    ts.g->stacklo = (uintptr)&ts - STACKSIZE + 8*1024;

    /*
     * Set specific keys in thread local storage.
     */
    __writegsqword(0x28, (unsigned long long) ts.tls);
    *(void **)ts.tls = (void *) ts.g;

    crosscall_amd64(ts.fn);
}

Cree un nuevo archivo en la carpeta con todos estos archivos llamado "build.bat":

REM TMP use gcc for assmebly file, in future port to ml64
gcc -c gcc_amd64.S
cl -c gcc_fatalf.c
cl -c gcc_libinit_windows.c
cl -c gcc_windows_amd64.c
cl -c gcc_util.c

ren gcc_amd64.o gcc_amd64.obj

lib gcc_amd64.obj gcc_fatalf.obj gcc_libinit_windows.obj ^
    gcc_windows_amd64.obj gcc_util.obj ^
    /OUT:libgo.lib

Avísame cuando tengas la carpeta estructurada según lo solicitado.

Por cierto, gracias por trabajar en esto y por ir. Ustedes han creado un lenguaje verdaderamente mágico.

Avísame cuando tengas la carpeta estructurada según lo solicitado.

Logré compilar libgo.lib como ha descrito aquí https://github.com/golang/go/issues/20982#issuecomment -327365063
¿Qué debería hacer después?

Alex

Bien, ahora necesitamos los siguientes archivos:

  • libgo.lib
  • cosa muy pegajosa
  • hola.cgo2.o
  • Hola C

hello.c es el siguiente:

#include <stdio.h>

extern void hello()
{
    printf("Hello World from C");
}

Para obtener hello.cgo2.o y go.o , debe comenzar con el siguiente archivo:

package main

/*
    extern void hello();
*/
import "C"
import "fmt"

func main() {
    fmt.Println("Hello from Go!")
    C.hello()
}

llamado "hola.go"

Configure un script de PowerShell que copie continuamente archivos de $ env: TMP :

while ($true) {  cp -r $env:TMP\go-* C:\Users\User\Downloads }

Luego ejecute go build con hello.c y hello.go en la carpeta. Debería poder recuperar los archivos necesarios desde la ubicación en la que se copiaron.

Una vez que tenga los archivos especificados anteriormente, puede compilar con:

cl libgo.lib go.o hello.cgo2.o hello.c Ws2_32.lib Winmm.lib -link /DEBUG:FULL

Hazme saber si tienes alguna pregunta.

cl libgo.lib go.o hello.cgo2.o hello.c Ws2_32.lib Winmm.lib -link / DEBUG: FULL

Eso crea el archivo ejecutable go.exe, pero no se ejecuta. No veo ningún código ASM sensible allí. La primera instrucción simplemente salta a la nada. Es solo un desastre.

Quizás deberías comenzar con algo realmente simple. Escriba un archivo asm (archivo Go asm) con una única función asm que ejecute "INT $ 3" ​​y no tenga nada más. E intente construir un programa ejecutable a partir de él: el programa debería ejecutar su función desde el principio.

Tal vez compile primero usando las herramientas de Go (y también usando gcc si es necesario), y luego intente hacer lo mismo usando MSVC.

Alex

Alex, gracias por tu ayuda. Trabajaré en eso.

Adjuntaré estos dos artículos aquí para mi propia referencia. De lo contrario, no tengo más actualizaciones.

De hecho, obtuve un programa go bastante complejo que solo usa la biblioteca msvc. Resulta que tanto el enlazador vanilla msvc como llvm-lld no manejaron correctamente la sección .bss .

Una vez que parcheé el enlazador, el programa se puede ejecutar.

Desafortunadamente, go build rompe cuando genera _cgo_.o / _all.o . ¿Es posible arrojar algunas luces sobre las razones detrás de la generación de estos dos archivos en cgo?

Puede ejecutar go tool cgo para ejecutar cgo directamente. Las fuentes están aquí: https://github.com/golang/go/tree/master/src/cmd/cgo

Además, si pudieras hacer que esto se ejecutara, sería genial. Simplemente no he dedicado tiempo a esto, así que no ha habido ningún progreso. Lo siento por eso.

Ya tengo programas que pueden ejecutarse correctamente a través de una serie de costuras a mano; lo que intento hacer aquí es ver si el proceso se puede integrar nuevamente en Go para que sea menos doloroso. :-)

Si puede documentar el proceso de costura a mano, es posible que pueda ayudarlo.

Con solo mirar, _cgo_.o parece producirse así (simplificado):

gcc [*.c] [*.cxx] -o _cgo_.o

Desde aquí: https://github.com/golang/go/blob/b4c84a1b010f012668b5e3ccaf63f609cd11c5fe/src/cmd/go/internal/work/exec.go#L1975

Idealmente, escribiríamos un programa go que preprocesa los archivos de objeto para que sean compatibles con link.exe para una fricción mínima, pero esa es una especie de objetivo exagerado.

Gracias por el puntero, voy a escribir el proceso en breve.

Desafortunadamente, no creo que el enlace se pueda realizar a través de link.exe menos que cambiemos gcc para emitir datos no inicializados en la sección .data lugar de la sección .bss , pero podemos definitivamente arregla llvm-lld para reconocer la sección .bss (que es lo que he hecho).

Necesitamos abordar _cgo_.o y _all.o separado. Tengo algunas preguntas sobre ellos:

(1) Parece que _cgo_.o no es el ejecutable final ya que no contiene el tiempo de ejecución de go. Parece que el compilador mira sus símbolos DWARF para averiguar la definición de la estructura. El problema es que es difícil generar un ejecutable si vas a enlazar con varias bibliotecas externamente, especialmente las que son generadas por msvc.

¿Es posible evitar este paso?

(2) use GNU ld para unir todos los archivos de objeto en _all.o pasando -Wl,-r en GCC. Esto es problemático ya que (1) no parece que otro enlazador tenga esta característica, y (2) el comando se ve afectado por CGO_LDFLAGS . Por ejemplo, el siguiente comando genera resultados incorrectos:

CGO_LDFLAGS="-Wl,-T,my-linker-script"
gcc .... $CGO_LDFLAGS -Wl,-r,...

Genera un ejecutable en lugar de un archivo de objeto empaquetado.

¿Es posible evitar este paso simplemente colocando todos los archivos de objeto en el .a generado directamente?

@zooba ¿Cuáles son las posibilidades de que MSFT actualice link.exe con este parche?

Desafortunadamente, no creo que el enlace se pueda realizar a través de link.exe a menos que cambiemos gcc para emitir datos no inicializados en la sección .data en lugar de la sección .bss, pero definitivamente podemos arreglar llvm-lld para reconocer la sección .bss (que es lo que he hecho).

Entonces, asumiendo que MSFT no actualiza link.exe (lo cual es probable), sería bueno compilar los archivos de objeto con cl.exe lugar de gcc .

Parece que _cgo_.o no es el ejecutable final ya que no contiene el tiempo de ejecución de go.

Eso es correcto, básicamente hay dos conjuntos de archivos de objetos (creo) que se vinculan al final. El archivo go.o (IIRC) contiene todo el código go + tiempo de ejecución, y los otros objetos contienen el código C. Hay rutinas de ensamblaje para saltar entre los dos conjuntos de objetos.

Además, necesitamos clang para compilar los archivos de ensamblaje de Unix.

Para nuestros propósitos, -Wl,-r será lo mismo que ejecutar lib.exe [object files] /OUT:obj . La opción significa "vincular incrementalmente", lo que significa "tomar algunos archivos de entrada, hacer un trabajo y luego escupir otro archivo de objeto". Si no nos preocupamos por la parte "hacer algo de trabajo" por ahora, podemos simplemente tomar el requisito como "tomar algunos archivos de entrada y / o archivos de objeto y escupir otro archivo de objeto" excepto en nuestro caso, el archivo de objeto será una biblioteca.

Puede decirle a GCC que evite poner variables en la sección .data en lugar de en la sección .bss usando la opción -fno-zero-initialized-in-bss .

Tenga en cuenta que en la sugerencia ya no usamos -Wl,-r al crear el código cgo.

No debería ser necesario que cmd / link comprenda los archivos de objeto MSVC para usarlos como archivos .syso . Esos archivos simplemente se pasan al vinculador externo de todos modos. Así que creo que lo que se necesita aquí es invocar el enlazador MSVC como enlazador externo, lo que debería poder hacer usando la opción -extld . Si ya está haciendo eso, mis disculpas; en ese caso, ¿qué está fallando?

Si ya está haciendo eso, mis disculpas; en ese caso, ¿qué está fallando?

IIRC, link.exe barfs en los objetos generados por gcc.

Es cierto que también tendría que usar el compilador de MSVC C, configurando la variable de entorno CC adecuada. No creo que funcione combinar objetos GCC y objetos MSVC en un solo enlace.

Pero luego se encuentra con el problema de que las bibliotecas C en tiempo de ejecución están precompiladas. Y si intenta volver a compilarlos, se encontrará con el problema de que cl no puede compilar el ensamblaje de Unix. Y entonces transfieres partes de las bibliotecas en tiempo de ejecución e intentas vincularlas, que es lo que hice y fallé.

En algún momento del camino, cl compila mal una parte clave del código. Mi idea para solucionarlo sería factorizar el código MSVC en una DLL con una API C plana, y luego simplemente compilar gradualmente más bibliotecas en tiempo de ejecución hasta que deje de funcionar.

La idea de @haohui para solucionar el problema fue diferente. En lugar de arreglar la raíz del problema, lo solucionó parcheando el enlazador. Obviamente, tuvo más éxito que yo, pero probablemente se deba a que su enfoque, en retrospectiva, es más probable que funcione que el mío.

Lo que recomendaría en este punto (en mi humilde opinión) es compilar gradualmente más de la biblioteca en tiempo de ejecución con cl hasta que deje de funcionar o hasta que no le quede código gcc. Entonces sabrá exactamente dónde está el problema.

Y con el parche del enlazador, no se necesita DLL.

El parche de llvm-lld está disponible en https://bugs.llvm.org/show_bug.cgi?id=35283

Dedicaré un tiempo a dar un ejemplo.

+1 @haohui ¡ Muchas gracias por llevar esto adelante!

@haohui ¿

Con respecto a los archivos _cgo_.o y _all.o , tuve el mismo problema, por lo que tal vez una solución para este problema también pueda ser una solución para el otro problema: https://github.com/golang/go / issues / 17014

Gracias por todo el trabajo en esto. Parece que se están haciendo buenos progresos. Las nuevas funciones están congeladas hasta Go 1.11, por lo que se cambia el hito.

Así que salté a esto anoche. Es posible compilar todo a través de msvc: cl y luego vincular todo a través de msvc: link. Sin embargo, los problemas son innumerables.

Entonces, más allá de los problemas simples como msvc: cl no es completamente compatible con C99 (en este momento no podemos manejar el tipo _Complex). Hay problemas más sistémicos al combinar las bibliotecas de PE compiladas por go internos y las compiladas por msvc. Específicamente msvc: link elimina los segmentos .bss (creo que puede arrojar estos datos a .data), lo cual es un problema ya que parece que el ensamblador go SB (pseudo reg) da como resultado un direccionamiento incorrecto si se mueve .bss .

Mi pensamiento inicial sería intentar que el ensamblador coloque las cosas que irían en .bss y .noptrbss en .data y .noptrdata respectivamente. Ni siquiera estoy seguro de si esto es posible; mi manipulación no ha tenido éxito y el direccionamiento se borra por completo.

No creo que sea posible usar link.exe por ahora. Creo que deberíamos comenzar con lld-link.exe

Si la idea detrás de eso es que podemos parchear lld-link para no movernos por los datos .bss, entiendo el atractivo. Siendo realistas, si el objetivo es admitir la cadena de herramientas msvc real, entonces será necesario abordar la compilación interna colocando los datos en .bss / .noptrbss.

¿No podemos simplemente redistribuir lld-link.exe con go? Esa parece ser la ruta de menor riesgo para admitir archivos de objetos MSVC siempre que LTCG no esté habilitado. Entiendo que no es ideal, pero enfrentamos una limitación de recursos.

También permite un progreso incremental que es la mejor estrategia.

Bien, buenas noticias de seguimiento, pude pasar una hora trabajando en esto durante el almuerzo.

Por el momento, tengo el ejemplo de antes en el problema funcionando:

- hello.go:
package main

/*
    extern void hello();
*/
import "C"

func main() {
    C.hello()
}

- extern.c
#include <stdio.h>

extern void hello()
{
    printf("Hello World from C");
}
>ac.out.exe
Hello World from C

El binario se construye completamente con la cadena de herramientas MSVC y Go (sin GCC u otro LLVM instalado).

Recomendaciones:

  • Tener los datos de salida .bss de Go tools / link.exe para ensamblajes internos en .data fue, en última instancia, bastante trivial
  • Varias piezas de ASM tuvieron que ajustarse para msvc
  • Se cambiaron algunas definiciones de GCC
  • Se tuvieron que hacer varios pequeños ajustes en algunos de los archivos .c generados por cgo
  • Los números complejos deberán ajustarse, en el momento en que no son compatibles.
  • Es probable que sea necesario agregar indicadores adicionales directamente para construir o vincular para soporte de msvc, ldflags, etc.no serán suficientes

Próximos pasos:
Si tengo tiempo este fin de semana, trabajaré para llevar mis cambios a una bifurcación y la funcionalidad detrás de las banderas en build / link. Después haré una revisión de un PR para que podamos resolver los tipos. No estoy 100% seguro de que mover los datos .bss no tenga algún tipo de impacto en alguna parte.

El único inconveniente que se me ocurre es que aumentará el tamaño del binario, pero debería estar bien.

¡Okey!

Lo siento, me tomó un par de días más armar esto. Entonces, el primer borrador de un parche se puede encontrar aquí: https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 :: https://github.com/cchamplin/go/tree/msvc_toolchain_support

Esto todavía es difícil, pero lo he creado con éxito el código con msvc.

Sería increíble si la gente pudiera comenzar a probar esto ahora e informarme los errores para que pueda colocar esto en un lugar mejor para el upstream. Además, si alguien quiere aportar pruebas de escritura, ¡sería increíble!

Uso:

go build -compiler msvc [path]
  • Los números complejos no se admiten actualmente hasta que averigüe si podemos hacer que funcionen.
  • No tengo idea de lo que sucede si intentas construir el tiempo de ejecución de go con el compilador msvc.
  • gcc todavía es necesario y utilizado por gco para obtener define y escribe datos cuando la compilación no se usa para construir nada ). No sé si podemos evitar esto, msvc no tiene nada que pueda hacer el mismo enano y #definir volcados de código ... si alguien tiene ideas sobre esto, sería genial

El parche vinculado crea un problema de arranque.

@alexbrainman ¿Cómo y dónde se determina qué archivos se copiarán en pkg/boostrap/src/bootstrap durante la fase de toolchain1 boostrapping?

cc @alexbrainman

El parche vinculado crea un problema de arranque.

No sé cómo funciona el bootstrapping hoy en día. Pero estoy seguro de que otros ( @rsc y @ianlancetaylor) pueden ayudar.

Me pregunto cómo @cchamplin ejecuta make.bat si el arranque no funciona.

Alex

@xoviat No sé cuál es el problema, pero la lista de directorios de arranque está en cmd / dist / buildtool.go.

Hola @alexbrainman , @ianlancetaylor , @xoviat lo siento, supongo que debería haber verificado más a fondo.

Actualicé la rama aquí https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 con una solución para el problema de arranque, creo que debería arrancar correctamente ahora.

Tuve que copiar algunos directorios / src / internal / syscall en cmd / internal / msvc. ¿Va a ser un gran problema? No estoy seguro de cómo obtener acceso al registro sin usar src / internal.

Tuve que copiar algunos directorios / src / internal / syscall en cmd / internal / msvc. ¿Va a ser un gran problema? No estoy seguro de cómo obtener acceso al registro sin usar src / internal.

No sé cómo se hace hoy en día, pero sospecho que cmd / dist puede hacerlo sin que usted copie manualmente los archivos fuente. Estoy seguro de que Russ o Ian te ayudarán cuando estés listo para enviar el código.

Creo que es hora de que @bradfitz y @ianlancetaylor decidan cómo proceder aquí. ¿Queremos que Go sea compatible con las herramientas de compilación de Microsoft y con gcc? Tendríamos que instalar las herramientas correspondientes de Microsoft en nuestros constructores (tendríamos que hacerlo antes de comenzar a aceptar CL). Probablemente, tendríamos que introducir nuevas variables de entorno. Nueva documentación.

Si la respuesta es sí, entonces @cchamplin tendría que enviar sus cambios de código según https://golang.org/doc/contribute.html ¿ Estaría dispuesto a hacer eso? El cambio es bastante grande, por lo que debe dividirse en CL más pequeños para que puedan revisarse y enviarse por separado. Cada cambio debe tener all.bat PASS antes de que pueda enviarse. Sería bueno si pudiéramos ver todos los CL antes de comenzar a enviar el primer CL.

Gracias.

Alex

¿Queremos que Go sea compatible con las herramientas de compilación de Microsoft y con gcc?

Solo una nota que este parche también facilita el # 17014 para el cual ya tengo un parche en proceso.

Si la respuesta es sí, entonces @cchamplin tendría que enviar sus cambios de código según https://golang.org/doc/contribute.html ¿ Estaría dispuesto a hacer eso? El cambio es bastante grande, por lo que debe dividirse en CL más pequeños para que puedan revisarse y enviarse por separado.

Sí, y romperlo no debería ser un gran problema. Solo necesito saber si esto es algo que es probable que ocurra antes de hacer el esfuerzo de limpiar todo el código, escribir la documentación, crear las pruebas, etc.

¿Queremos que Go sea compatible con las herramientas de compilación de Microsoft y con gcc?

En mi opinión, la respuesta es sí. Los compiladores en sí son gratuitos con VS Community, y no tener soporte completo para Windows es realmente frustrante. No debería tener que levantar una caja de Linux para compilar github.com/Microsoft/hcsshim (por ejemplo), porque una cadena de herramientas de Windows no es compatible.

¿Cuál sería la razón para no admitir una cadena de herramientas de Windows?

Creo que está bien, en principio, admitir archivos de objetos MSVC. Necesitaríamos tener un constructor.

Mi principal preocupación es cuánto puede cambiar el formato entre las versiones de Windows o MSVC. El formato ELF utilizado en la mayoría de las otras plataformas es muy estable; Rara vez tenemos que modificar la compatibilidad con ELF de otra forma que no sea la de agregar compatibilidad para nuevos procesadores. ¿Es el formato de archivo MSVC igualmente estable?

Los formatos asociados con la cadena de herramientas de MSVC son bastante estables. El mayor problema será el soporte de las herramientas en sí. Microsoft tiene una tendencia a mover cosas (archivos y entradas de registro) entre versiones de Visual Studio. La mayor parte de esto es configurable (al menos en el parche que escribí), pero aún existe la posibilidad de que cuando se lance una nueva versión principal de Visual Studio, puede que no sea compatible como una cadena de herramientas de compilación sin cambios en Go. Sin embargo, todas las versiones anteriores compatibles de Visual Studio seguirían funcionando.

Hasta donde yo sé, el formato COFF tiene una estabilidad razonable si te expones solo a C ABI (no a C ++). También está ampliamente documentado y LLVM proporciona una implementación de referencia.

@cchamplin Recomendaría exigir a los usuarios que invoquen vcvarsall.bat antes de vincular con MSVC. Esto reducirá significativamente el mantenimiento a casi cero.

Necesitaríamos tener un constructor.

@ianlancetaylor una vez que se haya demostrado que los objetos

Estoy seguro de que algunas personas preferirán usar las herramientas cygwin, y ya funcionan y queremos que sigan funcionando, así que creo que necesitamos dos constructores.

Oye, desde la parte inferior de este hilo parece que tienes resueltos tus problemas de MSVC. Pero si tiene algún problema, estoy en el equipo de MSVC. No dude en enviarme un ping en github o por correo electrónico ([email protected])

Necesitaríamos tener un constructor.

Si. Y probablemente deberíamos comenzar cambiando nuestros constructores existentes para tener instaladas las herramientas de compilación de MS. Entonces podemos usarlos ya que aceptamos CL para este problema.

Podemos instalar tanto herramientas gcc como herramientas microsoft en todos nuestros constructores. ¿Podemos ejecutar all.bat que prueba las herramientas gcc y microsoft de una sola vez? De lo contrario, necesitaríamos tener diferentes constructores configurados para diferentes herramientas. ¿Cuáles son los parámetros que controlan qué compiladores y enlazadores externos se utilizan?

Mi principal preocupación es cuánto puede cambiar el formato entre las versiones de Windows o MSVC.

No se instala un compilador con Windows. Tienes que instalarlo tú mismo. Al igual que hacemos con gcc. Instalamos la versión que queramos. Incluso podríamos ejecutar diferentes versiones de gcc en diferentes constructores.

¿Es el formato de archivo MSVC igualmente estable?

No sé nada de eso. Sospecho que solo usa las herramientas proporcionadas.

Alex

Mi principal preocupación es cuánto puede cambiar el formato entre las versiones de Windows o MSVC. El formato ELF utilizado en la mayoría de las otras plataformas es muy estable; Rara vez tenemos que modificar la compatibilidad con ELF de otra forma que no sea la de agregar compatibilidad para nuevos procesadores. ¿Es el formato de archivo MSVC igualmente estable?

Sí, COFF es muy estable.

@bradfitz y @ianlancetaylor ¿qué necesitamos para tener un constructor de Windows disponible para probar los cambios para este problema? Vea mis preguntas en https://github.com/golang/go/issues/20982#issuecomment -370719472

Gracias

Alex

¿Ir ahora soporta el objeto msvc?

El cambio https://golang.org/cl/110555 menciona este problema: debug/pe: parse the import directory correctly

@alexbrainman @bradfitz @ianlancetaylor :

Creo que hice la mayor parte del trabajo necesario para limpiar el parche y romperlo en trozos más digeribles. Creo que estoy casi listo para la presentación real del proyecto. Supongo que necesito saber si debo esperar noticias sobre la situación del constructor antes de enviar el código o simplemente hacerlo lo antes posible.

Puede enviar las CL en cualquier momento, pero alguien necesita configurar un constructor. De lo contrario, no tenemos forma de probarlos.

@johnsonj , ¿podría agregar las herramientas del compilador MSVC a nuestras imágenes de Windows?

Idealmente, me gustaría no agregar un nuevo tipo de host y hacer que 1-3 de nuestros tipos de host de Windows existentes tengan las herramientas MSVC además de Cygwin. Y luego podemos agregar más configuraciones de constructor además de esos tipos de host modificados.

/ cc @andybons @bcmills como para su información (para

@johnsonj , ¿podría agregar las herramientas del compilador MSVC a nuestras imágenes de Windows?

@cchamplin Le sugiero que intente agregar las herramientas necesarias al constructor usted mismo. Nadie más, pero usted sabe lo que se requiere. Puede buscar en el directorio golang.org/x/build/env/windows las instrucciones completas. En particular, probablemente desee agregar más líneas en startup.ps1. Una vez que sepa qué debe cambiar en ese director, realice los cambios y envíe su cambio para su revisión a través de https://golang.org/doc/contribute.html Una vez aceptado, podríamos actualizar los constructores usando estas instrucciones.

Idealmente, me gustaría no agregar un nuevo tipo de host y hacer que 1-3 de nuestros tipos de host de Windows existentes tengan las herramientas MSVC además de Cygwin. Y luego podemos agregar más configuraciones de constructor además de esos tipos de host modificados.

Siempre tuvimos el compilador y enlazador de Mingw (gcc) C en Windows. Nunca tenemos un conjunto diferente de herramientas de construcción de C. Una vez que agreguemos soporte para el compilador de Microsoft C, ¿sería posible probar las funciones de Mingw y Microsoft C con una sola ejecución de all.bat? ¿O se excluyen Mingw o Microsoft C? ¿Tendríamos que establecer alguna variable de entorno para apuntar a Mingw o Microsoft, pero nunca a ambos? Supongo que estoy tratando de entender cómo se debe estructurar y probar el código. Además, esto determinará cuántos constructores diferentes necesitamos.

Alex

Buscaré cómo hornear los binarios en la imagen.

El cambio https://golang.org/cl/112036 menciona este problema: env/windows: add visual studio tools to image

@johnsonj @bradfitz : Gracias por

@alexbrainman @bradfitz @ianlancetaylor : En cuanto a la estrategia de prueba para esto, no estoy seguro de qué hacer. ¿Podemos tomar el camino de ejecutar la prueba dist para ambas cadenas de herramientas en la ventana y realizar cada prueba dos veces, o solo deberíamos probar las pruebas cgo dos veces (una para gcc, una vez para msvc)?

En cuanto a la estrategia de prueba para esto, no estoy seguro de qué hacer. ¿Podemos tomar el camino de ejecutar la prueba dist para ambas cadenas de herramientas en la ventana y realizar cada prueba dos veces, o solo deberíamos probar las pruebas cgo dos veces (una para gcc, una vez para msvc)?

@cchamplin No tengo respuesta a tu pregunta. Sospecho que Ian conoce la respuesta.

Alex

¿Cuál es el costo de ejecutar todas las pruebas dos veces en lugar de solo cgo?

@mxplusb , podemos ejecutar una nueva configuración de compilación para Windows y se ejecutará en paralelo con nuestra 3. Una nueva configuración de compilación está bien. Los agregamos regularmente.

Solo dígame cómo hacerlo diferente: establezca una variable de entorno diferente / nueva y luego algo se dará cuenta de eso, supongo.

Probablemente se necesiten algunas cosas para que esto funcione.

O tenemos que ejecutar dentro de un shell / entorno donde la prueba go que ejecuta dist test se ejecutará dentro de después de que se haya ejecutado / llamado el vsvars.bat apropiado

O podemos hacer que dist ejecute los vsvars apropiados y extraiga las variables de entorno que necesita y luego establecer / pasarlas para probar.

Probablemente también querremos alguna variable de entorno para decirle a dist o make.bat que queremos ejecutar las pruebas con -compiler msvc set.

O tenemos que ejecutar dentro de un shell / entorno donde la prueba go que ejecuta dist test se ejecutará dentro de después de que se haya ejecutado / llamado el vsvars.bat apropiado

O podemos hacer que dist ejecute los vsvars apropiados y extraiga las variables de entorno que necesita y luego establecer / pasarlas para probar.

Preferiría que no ejecutamos archivos por lotes desde dist.exe o go.exe. Es problemático trabajar con archivos por lotes.

Probablemente también querremos alguna variable de entorno para decirle a dist o make.bat que queremos ejecutar las pruebas con -compiler msvc set.

Esperaba que Ian supiera cuál es el mejor enfoque aquí. Por lo que sé, también admitimos diferentes compiladores de C en Unix (gcc o clang). Seguramente nuestro proceso de construcción nos permite probar diferentes compiladores de C.

Alex

No me di cuenta antes de que planea usar go build -compiler msvc . Eso no tiene sentido. La opción go build -compiler toma el nombre de un compilador de Go (actualmente gc o gccgo). No toma el nombre de un compilador de C. El compilador de C se pasa en la variable de entorno CC . El compilador de C predeterminado se establece configurando la variable de entorno CC_FOR_TARGET cuando se ejecuta make.bat, como se documenta en los comentarios de make.bat.

Esperaría que tuviéramos un constructor para el cual arreglamos establecer la variable de entorno CC_FOR_TARGET en msvc antes de ejecutar all.bat. No veo por qué tendríamos que hacer otra cosa.

El compilador de C se pasa en la variable de entorno CC. El compilador de C predeterminado se establece configurando la variable de entorno CC_FOR_TARGET cuando se ejecuta make.bat, como se documenta en los comentarios de make.bat.

Gracias Ian por explicarme.

@cchamplin Espero que pueda ajustar sus cambios para que se ajusten al modelo existente. Háganos saber si tiene algún problema. Gracias.

Esperaría que tuviéramos un constructor para el cual arreglamos establecer la variable de entorno CC_FOR_TARGET en msvc antes de ejecutar all.bat.

Tenemos 3 constructores de Windows amd64 en https://build.golang.org. ¿Deberíamos reemplazar uno por uno de MSVC? ¿Queremos el constructor 386 MSVC?

Alex

@ianlancetaylor @alexbrainman Entendido sobre la marca -compiler. No creo que haya una manera fácil de hacer que simplemente configurar CC="msvc" (o realmente CC="cl.exe" ) funcione. CC todavía necesita apuntar a una ubicación de GCC para que funcionen las compilaciones de MSVC. El conjunto de herramientas del compilador de msvc no tiene las herramientas disponibles para permitir que CGO realice la introspección que necesita (búsqueda de definiciones, resolución de tipos), por lo que GCC aún es necesario en las compilaciones de MSVC, pero GCC simplemente no se usa en la fase real de compilación / enlace.

¿Sería aceptable agregar una nueva bandera para ir a construir y todos (cadena de herramientas o algo así)? Creo que ya tuve que agregar una bandera de cadena de herramientas a cgo.

Además, establecer CC_FOR_TARGET antes de all.bat parece que puede tener consecuencias negativas porque afectaría al compilador utilizado en el arranque. No creo que MSVC se pueda usar durante el proceso de arranque (no estoy al 100% en esto, en realidad no lo he intentado, pero dudo mucho que funcione)

Ya veo, para MSVC necesitamos tener GCC y MSVC. ¿Dónde GCC es utilizado solo por la herramienta cgo? Eso parece algo desafortunado, ya que significa que dependeríamos absolutamente de que GCC y MSVC implementaran exactamente el mismo ABI, pero supongo que es bastante probable.

Supongo que podríamos agregar otra variable de entorno CC_FOR_CGO , que podría establecerse en GCC.

El CC_FOR_TARGET usado por make.bat se usará para construir runtime / cgo. No me queda claro cómo podría funcionar cgo si el compilador de C que está utilizando no crea runtime / cgo.

Quizás deberíamos comenzar por hacer que las cosas funcionen cuando se invoca make.bat configurando CC_FOR_TARGET en cl y CGO_ENABLED en 0 .

Gracias @ianlancetaylor :

Ya veo, para MSVC necesitamos tener GCC y MSVC. ¿Dónde GCC es utilizado solo por la herramienta cgo? Eso parece algo desafortunado, ya que significa que dependeríamos absolutamente de que GCC y MSVC implementaran exactamente el mismo ABI, pero supongo que es bastante probable.

Estoy de acuerdo en que es lamentable, y estaría feliz de conocer alguna alternativa, todavía no he encontrado una. Ciertamente existe el riesgo de construir de esta manera (por ejemplo, el código cgo que se está construyendo tiene diferentes tipos de defs o define dependiendo del compilador que crea que lo está construyendo). Por lo tanto, es posible que las compilaciones no siempre tengan éxito o funcionen correctamente sin algunos ajustes (hay un mecanismo para manejar esto en mi implementación, pero es un proceso un poco manual). Lamentablemente, creo que este es un riesgo que las personas tendrán que tomar si quieren usar la cadena de herramientas de MSVC y todo lo que podemos hacer es documentarlo por ahora.

En una nota similar, todavía no hay un camino real a seguir para proporcionar soporte complex64 y complex128 en programas cgo construidos por MSVC simplemente porque el compilador de MSVC no es compatible con c99.

Supongo que podríamos agregar otra variable de entorno CC_FOR_CGO , que podría establecerse en GCC.

Entonces, la implementación actual que tengo es que si go build tiene instrucciones de compilar con MSVC, de forma predeterminada buscará cl.exe en la ruta, pero esto se puede anular con la variable de entorno MSCC. CGO continuará usando la variable de entorno CC recurriendo a gcc / lo que sea que se encuentre en el zdefaultcc.go generado

El CC_FOR_TARGET usado por make.bat se usará para construir runtime / cgo. No me queda claro cómo podría funcionar cgo si el compilador de C que está utilizando no crea runtime / cgo.

En la implementación actual, cgo funcionará felizmente para los binarios de msvc incluso si gcc ha creado toda la cadena de herramientas de go. por ejemplo, se agrega código MSVC a go / src. all.bat se ejecuta construyendo el entorno go usando gcc. Después de eso, se puede usar go / bin / go.exe para compilar con la cadena de herramientas msvc (suponiendo que se proporcionen indicadores). Sin embargo, podría estar malinterpretando lo que estás diciendo aquí.

La complejidad en torno a esto porque decir que queremos compilar con msvc es más complicado que simplemente cambiar el compilador a cl. La cadena de herramientas de MSVC es muy diferente de la cadena de herramientas de gcc. En MSVC, un entorno debe configurarse ejecutándose dentro de un vcvars.bat (o haciendo lo que hace v8, por ejemplo, ejecutar vcvars.bat y extraer toda la información que necesita de las variables de entorno que configura y luego usar eso en su compilación proceso). Después de estar en un entorno MSVC, la principal diferencia son las herramientas mismas. Cl.exe se usa para compilar archivos C y C ++, ml.exe y ml64.exe se usan para ensamblar archivos, y finalmente se usa link.exe (ms) para compilar archivos. vincular todo junto. Entonces, es más que simplemente configurar CC=cl.exe y pasarle las banderas correctas. ¿Eso tiene sentido / ayuda a aclarar las cosas?

Para aclarar más sobre

El CC_FOR_TARGET usado por make.bat se usará para construir runtime / cgo. No me queda claro cómo podría funcionar cgo si el compilador de C que está utilizando no crea runtime / cgo.

go build selecciona los archivos apropiados del tiempo de ejecución / cgo durante el proceso de compilación (por ejemplo, go build / go test / go run - no el proceso de compilación) cuando el Se ha seleccionado la cadena de herramientas msvc.

Estoy abierto a sugerencias sobre cómo debería funcionar esto, pero no debería requerir una nueva opción de línea de comando para la herramienta Go. ¿Podemos escribir un programa Go puro que actúe como GCC en lo que respecta a la herramienta Go pero que en realidad ejecute MSVC?

¿Podemos escribir un programa Go puro que actúe como GCC en lo que respecta a la herramienta Go pero que en realidad ejecute MSVC?

Creo que eso podría funcionar, déjame ver si puedo hacer algo en ese camino.

Además, supongo que debo aclarar si agregar indicadores de línea de comando a otras herramientas también será un problema. Por el momento, el parche completo para esto está creando varios nuevos indicadores de línea de comando en varias herramientas

  • cmd / cgo

    • -toolchain [gcc, msvc] (predeterminado en gcc) Cadena de herramientas para usar al crear archivos de salida cgo

  • cmd / enlace

    • -rlocbss (el valor predeterminado es falso) Reubicar .bss a .data

    • -toolchain [gcc, msvc] (predeterminado en gcc) Cadena de herramientas que se utilizará para enlaces externos

también creamos las siguientes opciones de compilación / variables de entorno cgo:

  • MSCXX
  • MSCC
  • MSCFLAGS
  • MSCPPFLAGS
  • MSCXXFLAGS
  • MSLDFLAGS

Después de unos minutos de reflexión, hay algunos obstáculos que podrían ser difíciles de superar si solo usamos el proxy de los comandos del compilador en un programa diferente todos juntos.

  1. go build necesita saber cuál es la cadena de herramientas externa para determinar qué archivos de tiempo de ejecución / cgo construir, de lo contrario, terminaría simplemente pasando las versiones incompatibles de gcc a nuestro comando proxy. Es posible que podamos piratear esto dentro del propio proxy, pero sería frágil y es probable que se rompa si alguna vez se agregan archivos adicionales al tiempo de ejecución / cgo.
  2. cmd / cgo necesita saber qué tipo de cadena de herramientas externa se está utilizando para elegir qué versión del código C de salida usar
  3. El programa proxy necesitaría algún mecanismo para saber si debería o no estar ejecutando gcc (como cuando lo llama cmd / cgo) o ejecutar cl.exe que podría pasarse, pero eso significa que la persona que llama necesitaría saber cuál es la cadena de herramientas es o tendríamos cmd / cgo pasando banderas no existentes a gcc.
  4. go build llama a cmd / link, que también necesita saber cuál es la cadena de herramientas para que pueda realizar la reubicación de .bss a .data y para que pueda pasar indicadores específicos al vinculador (es posible que podamos manejar este último parte en el proxy en sí mismo)

¿Especificar una variable de entorno para que se use go build para determinar que las compilaciones de msvc funcionan? Aunque creo que pone el listón más alto para alguien que solo quiere construir un programa con msvc, ya que ahora tiene que establecer múltiples variables de entorno además de ejecutarse dentro de vsvars.bat (como mínimo CC y UNDECIDED_TURN_ON_MSVC_BUILD_VAR )

Otra alternativa sería hacer que go build ejecute un comando noop falso en el CC especificado y luego analizar el logotipo / encabezado para detectar si es msvc o gcc y proceder con los ajustes apropiados de la cadena de herramientas en ese punto. ... no estoy seguro de cuán frágil es esto o cómo funcionaría con cadenas de herramientas compatibles con msvc como clang.

Descubrí este problema de Github recientemente, y este trabajo es muy emocionante para mí. Espero que esto aterrice en algún lugar en el futuro cercano.

Mi intención es usar CGo en Windows como envoltorios para algún código de terceros que se haya creado con MSVC, que no puedo simplemente reconstruir a partir de fuentes usando mingw-w64 . Tengo algunos casos de prueba relativamente serios para ejecutarlo, por lo que puedo validarlo bastante bien.

De todos modos, gracias a @cchamplin y a cualquier otra persona que esté trabajando en ello, y hágamelo saber de todos modos que puedo ayudar.

@cchamplin Sé lo suficiente como para ser peligroso acerca de las cadenas de herramientas del compilador en Windows y cgo, por lo que podría ayudar. ¿Podrías ponerme al día con algo de lo que has estado trabajando? Veré qué puedo hacer para ayudar. Sé el caso de uso que tiene @deadprogram, así que tengo un buen banco de pruebas avanzado cuando estemos listos para probar.

Hola @mxplusb , el parche está más o menos listo para funcionar. Si puedo encontrar el tiempo, enviaré los cambios a gerrit esta noche o mañana, lo que nos permitirá revisar, actualizar y aprobar todo.

El cambio https://golang.org/cl/133937 menciona este problema: cmd/link: Add flag rlocbss to relocate .bss data to .data

El cambio https://golang.org/cl/133938 menciona este problema: runtime/cgo: MSVC toolchain support in cgo native code

El cambio https://golang.org/cl/133939 menciona este problema: cmd/cgo: Add toolchain flag to cgo command for MSVC support

El cambio https://golang.org/cl/133946 menciona este problema: cmd/compile: Add support for MSVC toolchain to go build

Parece que escribí el problema en algunas de las confirmaciones. Dejaré que el proceso de revisión se ponga en marcha y determinaré la mejor manera de solucionarlo.

El cambio https://golang.org/cl/133943 menciona este problema: cmd/cgo: Add support for CC_FOR_CGO environment variable

El cambio https://golang.org/cl/133942 menciona este problema: tests: Update various tests to prepare for MSVC compiler toolchain

El cambio https://golang.org/cl/133940 menciona este problema: misc/cgo: Adjust tests to be compatible with MSVC toolchain support

El cambio https://golang.org/cl/133941 menciona este problema: runtime: Add runtime.CompilerType to denote between host compiler type

El cambio https://golang.org/cl/133945 menciona este problema: cmd/link: Add external toolchain support for MSVC

El cambio https://golang.org/cl/133944 menciona este problema: cmd/compile, cgo: Add support for MSVC flags

@cchamplin, ¿puedes describir cuál fue la decisión final? ¿Cómo es el soporte de MSVC? ¿Qué indicadores de línea de comando se agregarán? ¿Qué tendrá que hacer un usuario con su entorno además de descargar MSVC? Gracias

Además, ¿cómo podemos probar este parche? No pude encontrar tus confirmaciones en el repositorio.

@rasky Todavía está

@blizzardplus Similar a lo anterior, las cosas están

@cchamplin, ¿hay soporte para la compilación cruzada usando gcc o clang ? Si es así, ¿se prueban?

@cchamplin No veo ninguna actividad en los CL desde el 11 de septiembre, ¿hay avances en esto o se necesitan recursos adicionales?

@cchamplin para que esto funcione para c-archive, la sección ctors debe cambiarse a .CRT $ XCU (https://msdn.microsoft.com/en-us/library/bb918180.aspx) - Si esto no se hace, entonces el El tiempo de ejecución de golang no se inicializará. Además, resulta que si lo configuras así, también funciona bien para gcc; gcc todavía toma esas funciones, las mueve a una sección de texto y modifica main para llamarlas antes que la main real. Visual Studio puede comprender los archivos .a y, como la interfaz de los archivos precompilados / ensamblados es C, no debería haber ningún problema con solo tener esto en el archivo. Hay una advertencia sobre 2 secciones de texto, pero los casos simples parecen funcionar bien (se necesitan más pruebas para confirmar que no hay problemas).

Además, para que esto funcione para c-shared, las funciones que se exportarán deben estar decoradas con __declspec (dllexport), pero parece que no puedo encontrar dónde ocurre esta expansión de // exportación.

@blizzardplus Hay un parche de seguimiento para apoyar clang-MSVC. No estoy seguro de lo que quiere decir con compilación cruzada en este caso. No podrá utilizar la cadena de herramientas de MSVC en sistemas que no sean Windows. Otras funciones de compilación cruzada no deberían cambiar.

@kshelton Desafortunadamente, esta es una época del año muy ocupada para mí, ya que tengo otros proyectos en los trabajos y conferencias en las que estoy presentando. Es posible que no pueda volver a obtener la refactorización requerida en el parche hasta diciembre.

@kshelton Gracias. No he verificado el parche dos veces, supongo que lo desarrollé con la suposición de que c-archive no funcionaría en MSVC, o lo desactivé específicamente. Seguí el camino de intentar decorar correctamente las exportaciones cuando intentaba que el complemento / compartido funcionara en Windows. Creo que hay otras cuestiones, pero podría estar combinando dos cuestiones. Hay problemas reales con la forma en que coloca el código compartido en PLT / GOT para ELF frente a Windows .edata, idata y EAT. Creo que la mayoría de los problemas que enfrenté fueron relacionados con las reubicaciones y la imposibilidad de hacer que funcionen. Si alguien tiene una idea de esto, sería maravilloso. Ver # 19282

@cchamplin Traté de ver si puedo construir Go sobre tu CL

https://go-review.googlesource.com/c/go/+/133946/3

Usé este archivo por lotes para configurar mi entorno

set TERM=msys
set MYHOME=c:\users\alex\dev
set GOROOT=%MYHOME%\go
set GOROOT_BOOTSTRAP=%MYHOME%\go1.4.3
set GOPATH=%MYHOME%
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
set CC=cl
set PATH=%PATH%;%MYHOME%\my\bin\;%GOROOT%\bin
cd %GOROOT%\src
CMD

y me sale este error cuando ejecuto make.bat

C:\Users\Alex\Desktop>set TERM=msys

C:\Users\Alex\Desktop>set MYHOME=c:\users\alex\dev

C:\Users\Alex\Desktop>set GOROOT=c:\users\alex\dev\go

C:\Users\Alex\Desktop>set GOROOT_BOOTSTRAP=c:\users\alex\dev\go1.4.3

C:\Users\Alex\Desktop>set GOPATH=c:\users\alex\dev

C:\Users\Alex\Desktop>call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
Microsoft Windows [Version 10.0.17134.407]
(c) 2018 Microsoft Corporation. All rights reserved.

c:\Users\Alex\dev\go\src>make
Building Go cmd/dist using c:\users\alex\dev\go1.4.3
go tool dist: cannot invoke C compiler "cl": exit status 2

Go needs a system C compiler for use with cgo.
To set a C compiler, set CC=the-compiler.
To disable cgo, set CGO_ENABLED=0.

Command output:

Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25507.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

cl : Command line warning D9002 : ignoring unknown option '--help'
cl : Command line error D8003 : missing source filename

The system cannot find the batch label specified - fail

c:\Users\Alex\dev\go\src>

¿Que me estoy perdiendo aqui?

Gracias.

Alex

@alexbrainman

¿Que me estoy perdiendo aqui?

Es probable que, como mínimo, necesite configurar CC_FOR_CGO = gcc. Tampoco he intentado personalmente construir Go con MSVC. No estoy seguro de si esto funcionaría / debería ser compatible.

-C

Es probable que, como mínimo, necesite configurar CC_FOR_CGO = gcc.

Su https://go-review.googlesource.com/c/go/+/133940 contiene algunas pruebas. ¿Cómo verifico que pasen las pruebas? ¿Cuáles son los pasos exactos?

También los constructores de Go https://build.golang.org ejecutan% GOROOT% \ src \ all.bat para verificar todas las pruebas (incluidas las enumeradas en https://go-review.googlesource.com/c/go/+/ 133940) pasar. ¿Cómo propone que modifiquemos el código Go para que% GOROOT% \ src \ all.bat ejecute sus pruebas ajustadas desde https://go-review.googlesource.com/c/go/+/133940? Quizás all.bat pueda probar las versiones gcc y msvc de las pruebas. Quizás podamos usar alguna variable de entorno que le diga a all.bat qué versión de las pruebas ejecutar, y entonces podríamos tener dos constructores diferentes que ejecuten diferentes versiones de las pruebas. ¿Pensaste en todo eso?

Tampoco he intentado personalmente construir Go con MSVC. No estoy seguro de si esto funcionaría / debería ser compatible.

Puede ejecutar all.bat hasta completarlo correctamente sin gcc instalado. La versión actual de Go solo necesita otra versión de Go (al menos go1.4) para compilarse. Solo Cgo necesita el compilador de C, tenía la impresión de que sus cambios implementan la versión de Cgo compilada por MSVC. Pero, tal vez, me equivoque. Por favor, corríjame si estoy equivocado.

Gracias.

Alex

@alexbrainman

Su https://go-review.googlesource.com/c/go/+/133940 contiene algunas pruebas. ¿Cómo verifico que pasen las pruebas? ¿Cuáles son los pasos exactos?

Quizás all.bat pueda probar las versiones gcc y msvc de las pruebas. Quizás podamos usar alguna variable de entorno que le diga a all.bat qué versión de las pruebas ejecutar, y entonces podríamos tener dos constructores diferentes que ejecuten diferentes versiones de las pruebas. ¿Pensaste en todo eso?

Sí, este mecanismo exacto se utiliza en https://go-review.googlesource.com/c/go/+/133946/. Dado que todas las llamadas a run.bat en Windows, el mecanismo para llamar a las pruebas de cgo se colocó allí. Entonces usted o el constructor comenzarían con una configuración normal CC = gcc. Luego, establecería GOTESTMSVC = 1 y GOVSVARSPATH = alguna ruta vsvars.bat. Después de eso, la compilación con all.bat debería ejecutar las pruebas gcc y msvc cgo.

Puede ejecutar all.bat hasta completarlo correctamente sin gcc instalado. La versión actual de Go solo necesita otra versión de Go (al menos go1.4) para compilarse. Solo Cgo necesita el compilador de C, tenía la impresión de que sus cambios implementan la versión de Cgo compilada por MSVC. Pero, tal vez, me equivoque. Por favor, corríjame si estoy equivocado.

Estás en lo correcto. Go en sí debería construir bien. Puede haber problemas cuando llegue a la prueba, ya que run.bat se modificó para establecer algunas variables de entorno cuando GOTESTMSVC = 1. Probablemente podríamos intentar detectar si go se está construyendo con msvc, y luego establecer las variables de entorno dist apropiadas para que las pruebas no fallen.

Luego, establecería GOTESTMSVC = 1 y GOVSVARSPATH = alguna ruta vsvars.bat. Después de eso, la compilación con all.bat debería ejecutar las pruebas gcc y msvc cgo.

Intenté eso.

solía

commit e56d52f66b95b87001867a2487a11bd961f40d4d (HEAD)
Author: Caleb Champlin <[email protected]>
Date:   Sat Sep 8 00:26:32 2018 -0600

    cmd/compile: add support for MSVC toolchain to go build

    Allows building with MSVC as an external compiler/linker.

    Setting CC=cl.exe inside an MSVC environment will automatically
    build cgo executables using MSVC as the external compiler and
    linker.

    For the builders setting the environment variable GOVSVARSPATH
    to the location of a msvsvars.bat file and setting the
    environment variable GOTESTMSVC=1 will automatically cause
    all.bat to run tests and compiler with both gcc and MSVC.

    Updates #20982

    Change-Id: I44be1f43aa0d53a688c595bc8336e0364b809ced

Ejecuto este archivo por lotes primero:

set TERM=msys
set MYHOME=c:\users\alex\dev
set GOROOT=%MYHOME%\go
set GOROOT_BOOTSTRAP=%MYHOME%\go1.4.3
set GOPATH=%MYHOME%
set MINGW=%MYHOME%\mingw64_4.9.1

set GOTESTMSVC=1
set GOVSVARSPATH="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"

set PATH=%PATH%;%MINGW%\bin;%MYHOME%\my\bin\;%GOROOT%\bin
cd %GOROOT%\src
CMD

y luego ejecute all.bat . all.bat falla con

--- FAIL: TestDocsUpToDate (0.00s)
    help_test.go:26: alldocs.go is not up to date; run mkalldocs.sh to regenerate it
go test proxy starting
go test proxy running at GOPROXY=http://127.0.0.1:52023/mod
go proxy: no archive w.1 v1.2.0
go proxy: no archive x.1 v1.0.0
go proxy: no archive z.1 v1.2.0
go proxy: no archive rsc.io v1.5.0
go proxy: no archive example.com/unused v0.0.0
go proxy: no archive example.com/unused v0.0.0
go proxy: no archive sub.1 v1.0.0
go proxy: no archive badsub.1 v1.0.0
go proxy: no archive versioned.1 v1.0.0
go proxy: no archive versioned.1 v1.1.0
go proxy: no archive golang.org/x/text/language 14c0d48
go proxy: no archive golang.org/x/text/language 14c0d48
go proxy: no archive golang.org/x/text/language 14c0d48
go proxy: no archive golang.org/x/text/foo 14c0d48
go proxy: no archive golang.org/x 14c0d48
go proxy: no archive golang.org 14c0d48
go proxy: no archive example.com/split/subpkg v1.0.0
FAIL
FAIL    cmd/go  147.247s
ok      cmd/go/internal/cache   13.115s
ok      cmd/go/internal/dirhash 0.518s
ok      cmd/go/internal/generate        0.180s
ok      cmd/go/internal/get     0.761s
ok      cmd/go/internal/imports 0.212s
ok      cmd/go/internal/load    1.050s
ok      cmd/go/internal/modconv 1.596s
ok      cmd/go/internal/modfetch        0.881s
ok      cmd/go/internal/modfetch/codehost       0.179s
ok      cmd/go/internal/modfile 0.193s
ok      cmd/go/internal/modload 2.820s
ok      cmd/go/internal/module  0.860s
ok      cmd/go/internal/mvs     0.255s
ok      cmd/go/internal/par     0.107s
ok      cmd/go/internal/search  0.087s
ok      cmd/go/internal/semver  0.140s
ok      cmd/go/internal/txtar   0.249s
ok      cmd/go/internal/web2    0.136s
ok      cmd/go/internal/work    0.200s
ok      cmd/gofmt       0.216s
ok      cmd/internal/buildid    0.522s
ok      cmd/internal/dwarf      0.077s
ok      cmd/internal/edit       0.160s
ok      cmd/internal/goobj      2.430s
ok      cmd/internal/obj        0.103s
ok      cmd/internal/obj/arm64  0.190s
ok      cmd/internal/obj/x86    0.845s
ok      cmd/internal/objabi     0.063s
ok      cmd/internal/src        0.093s
ok      cmd/internal/test2json  0.253s
ok      cmd/link        6.285s
ok      cmd/link/internal/ld    24.147s
ok      cmd/link/internal/sym   0.887s
ok      cmd/nm  7.678s
ok      cmd/objdump     2.772s
ok      cmd/pack        3.256s
ok      cmd/trace       0.449s
ok      cmd/vendor/github.com/google/pprof/internal/binutils    0.479s
ok      cmd/vendor/github.com/google/pprof/internal/driver      6.103s
ok      cmd/vendor/github.com/google/pprof/internal/elfexec     0.079s
ok      cmd/vendor/github.com/google/pprof/internal/graph       0.455s
ok      cmd/vendor/github.com/google/pprof/internal/measurement 0.066s
ok      cmd/vendor/github.com/google/pprof/internal/report      0.154s
ok      cmd/vendor/github.com/google/pprof/internal/symbolizer  0.096s
ok      cmd/vendor/github.com/google/pprof/internal/symbolz     0.078s
ok      cmd/vendor/github.com/google/pprof/profile      0.527s
ok      cmd/vendor/github.com/ianlancetaylor/demangle   0.109s
ok      cmd/vendor/golang.org/x/arch/arm/armasm 0.424s
ok      cmd/vendor/golang.org/x/arch/arm64/arm64asm     0.537s
ok      cmd/vendor/golang.org/x/arch/ppc64/ppc64asm     0.155s
ok      cmd/vendor/golang.org/x/arch/x86/x86asm 0.239s
ok      cmd/vendor/golang.org/x/crypto/ssh/terminal     0.174s
ok      cmd/vendor/golang.org/x/sys/windows     0.334s
ok      cmd/vendor/golang.org/x/sys/windows/registry    0.199s
ok      cmd/vendor/golang.org/x/sys/windows/svc 0.316s
ok      cmd/vendor/golang.org/x/sys/windows/svc/eventlog        0.089s
ok      cmd/vendor/golang.org/x/sys/windows/svc/mgr     0.432s
ok      cmd/vet 6.392s
ok      cmd/vet/internal/cfg    0.102s
2018/12/16 15:55:18 Failed: exit status 1

Además, la configuración de GOTESTMSVC y GOVSVARSPATH podría funcionar para las personas que ejecutan all.bat. Pero, ¿qué harán otros usuarios de su cambio cuando necesiten usar MSVC para Cgo? ¿Cuál es tu plan para eso?

Alex

@alexbrainman
No estoy seguro de lo que está pasando. Esa prueba me está fallando en el maestro

> git status
On branch master
Your branch is up to date with 'origin/master'

> cd src\cmd\go
> go test .\help_test.go
--- FAIL: TestDocsUpToDate (0.00s)
    help_test.go:26: alldocs.go is not up to date; run mkalldocs.sh to regenerate it

En help.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/internal/help/help.go#L37
itera a través de base.Go.Commands. Que se inicializa en main.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/main.go#L43
pero no estoy seguro de cómo se llamaría a esa función de inicio en un ejecutable de prueba, por lo que no tengo idea de cómo el maestro está pasando las pruebas en este momento, ya que creo que esto debería estar fallando en todos los ámbitos.


Además, la configuración de GOTESTMSVC y GOVSVARSPATH podría funcionar para las personas que ejecutan all.bat. Pero, ¿qué harán otros usuarios de su cambio cuando necesiten usar MSVC para Cgo? ¿Cuál es tu plan para eso?

Entonces, en una situación en la que solo desea crear un código Cgo con MSVC

call vsvars64.bat
set CC_FOR_CGO=gcc
set CC=cl.exe
go build

debería ser todo lo que necesitas, creo

No estoy seguro de cómo se llamaría a esa función de inicio en un ejecutable de prueba, por lo que no tengo idea de cómo el maestro está pasando las pruebas en este momento, ya que creo que esto debería estar fallando en todos los ámbitos.

Al usar go test con un archivo en cmd / go, la herramienta go creará el paquete cmd / go y luego creará las pruebas, generará el controlador de prueba, lo creará y vinculará todo en un nuevo paquete principal. Esto sucede a pesar de que cmd / go es en sí mismo un paquete principal. Es decir, el paquete principal en cmd / go / *. Go se tratará como un paquete no principal para fines de prueba. Esto permite que las pruebas llamen a funciones definidas en el paquete principal si es apropiado.

Lo siento, tardo en responder. Pero no tuve tiempo libre para investigar esto nuevamente.

No estoy seguro de lo que está pasando. Esa prueba me está fallando en el maestro

No usé maestro. Usé su confirmación e56d52f66b95b87001867a2487a11bd961f40d4d. ¿No ejecutó all.bat en ese compromiso antes de enviarlo para su revisión? ¿All.bat tuvo éxito? ¿Puedes intentar ejecutar all.bat en ese compromiso de nuevo para ver si tiene algo que ver con la configuración de mi sistema? Gracias.

Entonces, en una situación en la que solo desea crear un código Cgo con MSVC

call vsvars64.bat
set CC_FOR_CGO=gcc
set CC=cl.exe
go build

debería ser todo lo que necesitas, creo

2 variables de entorno es, probablemente, demasiado complicado para el usuario medio. Y CC_FOR_CGO=gcc parece extraño, ¿por qué usamos gcc para compilar código con MSVC?

Alex

@alexbrainman

No usé maestro. Usé su confirmación e56d52f66b95b87001867a2487a11bd961f40d4d. ¿No ejecutó all.bat en ese compromiso antes de enviarlo para su revisión? ¿All.bat tuvo éxito? ¿Puedes intentar ejecutar all.bat en ese compromiso de nuevo para ver si tiene algo que ver con la configuración de mi sistema? Gracias.

Creo que fue algo relacionado con la configuración de mi sistema lo que me dio resultados extraños al ejecutar las pruebas. Creo que solucioné el problema y envié algunas actualizaciones al conjunto de cambios.

2 variables de entorno es, probablemente, demasiado complicado para el usuario medio. Y CC_FOR_CGO = gcc me parece extraño, ¿por qué usamos gcc para compilar código con MSVC?

Probablemente debería ser CC_FOR_CGO = gcc.exe, mi error. Pero para responder a tu pregunta; de gerrit:

PS1, línea 1324:
cgo todavía necesita gcc disponible para el análisis de tipos. Si CC se establece en un compilador MSVC, cgo necesita un medio para llamar a GCC que es proporcionado por CC_FOR_CGO. Desafortunadamente, la cadena de herramientas de MSVC no tiene ningún mecanismo para proporcionar el mismo tipo de información que se recopila de gcc. Teóricamente, se podría crear una herramienta específica de go para recopilar el tipo de información que utiliza cgo, pero que podría estar fuera de alcance y posiblemente un esfuerzo considerable (personalmente nunca he escrito nada para realizar un análisis de tipo estático de código C / C ++).

También parece que he roto algo con el caché limpio entre ejecuciones para GCC vs MSVC, no estoy seguro de por qué algunas pruebas siguen actuando como si estuvieran en caché.

Creo que solucioné el problema y envié algunas actualizaciones al conjunto de cambios.

Esta configuración https://github.com/golang/go/issues/20982#issuecomment -447618566 en

commit 5479fc9fe61fb998082fea5cb423314cc1afa649 (HEAD)
Author: Caleb Champlin <[email protected]>
Date:   Sat Sep 8 00:26:32 2018 -0600

    cmd/compile: add support for MSVC toolchain to go build

    Allows building with MSVC as an external compiler/linker.

    Setting CC=cl.exe inside an MSVC environment will automatically
    build cgo executables using MSVC as the external compiler and
    linker.

    For the builders setting the environment variable GOVSVARSPATH
    to the location of a msvsvars.bat file and setting the
    environment variable GOTESTMSVC=1 will automatically cause
    all.bat to run tests and compiler with both gcc and MSVC.

    Updates #20982

    Change-Id: I44be1f43aa0d53a688c595bc8336e0364b809ced

me lleva más lejos, pero aún falla con

##### API check
+pkg go/build, type Context struct, CompilerType string
+pkg go/build, type Package struct, CgoMSCFLAGS []string
+pkg go/build, type Package struct, CgoMSCPPFLAGS []string
+pkg go/build, type Package struct, CgoMSCXXFLAGS []string
+pkg go/build, type Package struct, CgoMSLDFLAGS []string
+pkg os, method (*File) SyscallConn() (syscall.RawConn, error)

ALL TESTS PASSED

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

# runtime/cgo
msvc_libinit_windows.c
msvc_libinit_windows.c(133): error C2220: warning treated as error - no 'object' file generated
msvc_libinit_windows.c(133): warning C4710: 'int fprintf(FILE *const ,const char *const ,...)': function not inlined
C:\Program Files (x86)\Windows Kits\10\include\10.0.15063.0\ucrt\stdio.h(826): note: see declaration of 'fprintf'
go tool dist: FAILED: go install -gcflags=all= -ldflags=all= std cmd: exit status 2

c:\Users\Alex\dev\go\src>

Probablemente debería ser CC_FOR_CGO = gcc.exe, mi error.

No me preocupa .exe en gcc.exe. Mis problemas son

  • necesita herramientas gcc y MSVC para usar MSVC (sería difícil explicárselo a nuestros usuarios), pero entiendo que no se puede hacer nada al respecto;

  • Necesitaba ambas variables de entorno CC_FOR_CGO = gcc y CC = cl.exe configuradas; ¿tal vez podamos asumir que CC_FOR_CGO siempre está configurado en gcc?

Pero para responder a tu pregunta; de gerrit:

Gracias por explicarlo.

Alex

@alexbrainman

# runtime/cgo
msvc_libinit_windows.c
msvc_libinit_windows.c(133): error C2220: warning treated as error - no 'object' file generated
msvc_libinit_windows.c(133): warning C4710: 'int fprintf(FILE *const ,const char *const ,...)': function not inlined
C:\Program Files (x86)\Windows Kits\10\include\10.0.15063.0\ucrt\stdio.h(826): note: see declaration of 'fprintf'
go tool dist: FAILED: go install -gcflags=all= -ldflags=all= std cmd: exit status 2

No estoy seguro de cómo ocurriría esa advertencia a menos que de alguna manera tenga una copia diferente / antigua de msvc_libinit_windows.c. ¿Puedes confirmar que tiene esta línea?

// src/runtime/cgo/msvc_libinit_windows.c
#pragma warning(disable:4668 4255 4710)

C4710 debe suprimirse para stdio include. Veo que su versión de MSVC es ligeramente diferente a la mía, lo que también podría ser el culpable. Sin embargo, no estoy seguro de por qué ignorarían activamente esa supresión en una versión diferente.

También puede intentar hacer un cambio para incluir la supresión globalmente sin importar qué

// src/cmd/go/internal/work/exec.go
// Line 2719
cgoMSCPPFLAGS = append(cgoMSCFLAGS, "/wd4668") // this should be cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4668") I'll fix the change set to correct
+cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4710") 

Necesitaba ambas variables de entorno CC_FOR_CGO = gcc y CC = cl.exe configuradas; ¿tal vez podamos asumir que CC_FOR_CGO siempre está configurado en gcc?

Creo que gco comprobar si existe gcc si CC_FOR_CGO no está configurado estaría bien. CC_FOR_CGO es más para personas como yo que no tienen gcc en su camino. Mi CC_FOR_CGO se ve así CC_FOR_CGO = I: \ Development \ tmd-gcc \ bingcc.exe. Si no queremos admitir el caso de uso de que GCC no esté en el camino para las compilaciones de MSVC, avíseme y puedo deshacerme de la variable de entorno por completo.

Intenté de nuevo esta versión

commit 6741b7009d1894b5bf535d82ad46f4a379651670 (HEAD)
Author: Caleb Champlin <[email protected]>
Date:   Sat Sep 8 00:26:32 2018 -0600

    cmd/compile: add support for MSVC toolchain to go build

    Allows building with MSVC as an external compiler/linker.

    Setting CC=cl.exe inside an MSVC environment will automatically
    build cgo executables using MSVC as the external compiler and
    linker.

    For the builders setting the environment variable GOVSVARSPATH
    to the location of a msvsvars.bat file and setting the
    environment variable GOTESTMSVC=1 will automatically cause
    all.bat to run tests and compiler with both gcc and MSVC.

    Updates #20982

    Change-Id: I44be1f43aa0d53a688c595bc8336e0364b809ced

y me sale el mismo error

##### API check
+pkg go/build, type Context struct, CompilerType string
+pkg go/build, type Package struct, CgoMSCFLAGS []string
+pkg go/build, type Package struct, CgoMSCPPFLAGS []string
+pkg go/build, type Package struct, CgoMSCXXFLAGS []string
+pkg go/build, type Package struct, CgoMSLDFLAGS []string
+pkg os, method (*File) SyscallConn() (syscall.RawConn, error)

ALL TESTS PASSED

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

# runtime/cgo
msvc_libinit_windows.c
msvc_libinit_windows.c(133): error C2220: warning treated as error - no 'object' file generated
msvc_libinit_windows.c(133): warning C4710: 'int fprintf(FILE *const ,const char *const ,...)': function not inlined
C:\Program Files (x86)\Windows Kits\10\include\10.0.15063.0\ucrt\stdio.h(826): note: see declaration of 'fprintf'
go tool dist: FAILED: go install -gcflags=all= -ldflags=all= std cmd: exit status 2

c:\Users\Alex\dev\go\src>

¿Puedes confirmar que tiene esta línea?

// src/runtime/cgo/msvc_libinit_windows.c
#pragma warning(disable:4668 4255 4710)

Este es el comienzo de mi archivo src / runtime / cgo / msvc_libinit_windows.c

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build cgo

#define WIN64_LEAN_AND_MEAN
// Suppress MSVC specific warnings.
// C4668: symbol' is not defined as a preprocessor macro, 
// replacing with '0' for 'directives'.
// C4255: function' : no function prototype given: converting '()' 
// to '(void)'.
// C4710: function' : function not inlined
#pragma warning(disable:4668 4255 4710)
#include <windows.h>
#include <process.h>
...

También puede intentar hacer un cambio para incluir la supresión globalmente sin importar qué

// src/cmd/go/internal/work/exec.go
// Line 2719
cgoMSCPPFLAGS = append(cgoMSCFLAGS, "/wd4668") // this should be cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4668") I'll fix the change set to correct
+cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4710") 

Hice este cambio:

c:\Users\Alex\dev\go\src>git diff
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 49d1d849f5..9fb442ab95 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -2717,6 +2717,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcMSCFLAGS, pc
        cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
        if cfg.BuildContext.CompilerType == "msvc" {
                cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4668")
+               cgoMSCFLAGS = append(cgoMSCFLAGS, "/wd4710")

                cgoMSCPPFLAGS = append(cgoMSCPPFLAGS, pcMSCFLAGS...)
                cgoMSCPPFLAGS = append(cgoMSCPPFLAGS, "/c")

c:\Users\Alex\dev\go\src>

pero veo el mismo error

##### API check
+pkg go/build, type Context struct, CompilerType string
+pkg go/build, type Package struct, CgoMSCFLAGS []string
+pkg go/build, type Package struct, CgoMSCPPFLAGS []string
+pkg go/build, type Package struct, CgoMSCXXFLAGS []string
+pkg go/build, type Package struct, CgoMSLDFLAGS []string
+pkg os, method (*File) SyscallConn() (syscall.RawConn, error)

ALL TESTS PASSED

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

# runtime/cgo
msvc_libinit_windows.c
msvc_libinit_windows.c(133): error C2220: warning treated as error - no 'object' file generated
msvc_libinit_windows.c(133): warning C4710: 'int fprintf(FILE *const ,const char *const ,...)': function not inlined
C:\Program Files (x86)\Windows Kits\10\include\10.0.15063.0\ucrt\stdio.h(826): note: see declaration of 'fprintf'
go tool dist: FAILED: go install -gcflags=all= -ldflags=all= std cmd: exit status 2

c:\Users\Alex\dev\go\src>

Alex

Estaba tratando de reproducir esto anoche y no pude. Me pregunto si está experimentando esto: https://developercommunity.visualstudio.com/content/problem/35734/c-cannot-disable-specific-warnings-with-pragmas-wh.html

¿Es posible que actualice al SDK y las herramientas de compilación más recientes? Estoy en SDK 10.0.17763.0. y la versión 15.9.28307.222 de las herramientas de compilación / devenv

Estoy intentando crear una DLL de Windows con MSVC, pero parece que Go intenta desactivar alguna advertencia con un número superior a 65535 (o no un número), lo que hace que MSVC se detenga.

image

No. Werror es una opción de GCC, para tratar cada advertencia como un error.

Para MSVC, debe usar WX .

@pravic buen punto, ¿cómo haría eso? No lo estoy configurando, todo lo que hago es:

set CC=cl.exe
go build -o next.dll .\main.go

@galich Desafortunadamente, no puedo ayudar porque no sigo la integración de MSVC.

Por ejemplo, ¿dónde están los parches relacionados con este hilo? ¿En master o en otro lugar?

@pravic puede encontrar los cambios aquí: https://go-review.googlesource.com/c/go/+/133946/5

@mxplusb gracias por el enlace, parece que mi problema particular con / Werror se resuelve allí.
¿Sabes cuándo llegará a beta / nightly / stable?

¿Es posible que actualice al SDK y las herramientas de compilación más recientes? Estoy en SDK 10.0.17763.0. y la versión 15.9.28307.222 de las herramientas de compilación / devenv

@cchamplin finalmente logré actualizar mi MSVC. ahora tengo

c:\Users\Alex\dev\go\src>%GOVSVARSPATH%
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

c:\Users\Alex\dev\go\src>cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27030.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

c:\Users\Alex\dev\go\src>

Intenté de nuevo esta versión

commit 6741b7009d1894b5bf535d82ad46f4a379651670 (HEAD)
Author: Caleb Champlin <[email protected]>
Date:   Sat Sep 8 00:26:32 2018 -0600

    cmd/compile: add support for MSVC toolchain to go build

    Allows building with MSVC as an external compiler/linker.

    Setting CC=cl.exe inside an MSVC environment will automatically
    build cgo executables using MSVC as the external compiler and
    linker.

    For the builders setting the environment variable GOVSVARSPATH
    to the location of a msvsvars.bat file and setting the
    environment variable GOTESTMSVC=1 will automatically cause
    all.bat to run tests and compiler with both gcc and MSVC.

    Updates #20982

    Change-Id: I44be1f43aa0d53a688c595bc8336e0364b809ced

y all.bat se completa con éxito. Pero recibo estas advertencias.

##### ../misc/cgo/stdio

##### ../misc/cgo/life

##### ../misc/cgo/test
# _/c_/Users/Alex/dev/go/misc/cgo/test
issue28896.cgo2.c
.\issue28896.go(30): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'g1'
.\issue28896.go(36): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'f2'
# _/c_/Users/Alex/dev/go/misc/cgo/test
cthread_windows.c
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(37) : note: index 'i' range checked by comparison on this line
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : note: feeds call on this line
PASS
scatter = 00007FF670706000
hello from C
sqrt is: 0
ok      _/c_/Users/Alex/dev/go/misc/cgo/test    3.534s
# _/c_/Users/Alex/dev/go/misc/cgo/test
issue28896.cgo2.c
.\issue28896.go(30): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'g1'
.\issue28896.go(36): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'f2'
# _/c_/Users/Alex/dev/go/misc/cgo/test
cthread_windows.c
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(37) : note: index 'i' range checked by comparison on this line
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : note: feeds call on this line
PASS
scatter = 00007FF7DD026000
hello from C
sqrt is: 0
ok      _/c_/Users/Alex/dev/go/misc/cgo/test    3.229s
# _/c_/Users/Alex/dev/go/misc/cgo/test
issue28896.cgo2.c
.\issue28896.go(30): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'g1'
.\issue28896.go(36): warning C4820: '<anonymous-tag>': '4' bytes padding added after data member 'f2'
# _/c_/Users/Alex/dev/go/misc/cgo/test
cthread_windows.c
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(37) : note: index 'i' range checked by comparison on this line
c:\users\alex\dev\go\misc\cgo\test\cthread_windows.c(39) : note: feeds call on this line
PASS
scatter = 00007FF655CF6000
hello from C
sqrt is: 0
ok      _/c_/Users/Alex/dev/go/misc/cgo/test    3.172s

##### ../test/bench/go1
testing: warning: no tests to run
PASS
ok      _/c_/Users/Alex/dev/go/test/bench/go1   3.178s

##### ../test

##### API check
+pkg go/build, type Context struct, CompilerType string
+pkg go/build, type Package struct, CgoMSCFLAGS []string
+pkg go/build, type Package struct, CgoMSCPPFLAGS []string
+pkg go/build, type Package struct, CgoMSCXXFLAGS []string
+pkg go/build, type Package struct, CgoMSLDFLAGS []string
+pkg os, method (*File) SyscallConn() (syscall.RawConn, error)

ALL TESTS PASSED

---
Installed Go for windows/amd64 in c:\Users\Alex\dev\go
Installed commands in c:\Users\Alex\dev\go\bin
*** You need to add c:\Users\Alex\dev\go\bin to your PATH.

c:\Users\Alex\dev\go\src>

Y también noté que ejecutas todas las pruebas dos veces.

...
##### API check
+pkg go/build, type Context struct, CompilerType string
+pkg go/build, type Package struct, CgoMSCFLAGS []string
+pkg go/build, type Package struct, CgoMSCPPFLAGS []string
+pkg go/build, type Package struct, CgoMSCXXFLAGS []string
+pkg go/build, type Package struct, CgoMSLDFLAGS []string
+pkg os, method (*File) SyscallConn() (syscall.RawConn, error)

ALL TESTS PASSED

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'


##### Testing packages.
ok      archive/tar     0.256s
ok      archive/zip     2.070s
ok      bufio   (cached)
ok      bytes   1.624s
ok      compress/bzip2  (cached)
ok      compress/flate  1.067s
...

¿Por qué?

Alex

@alexbrainman Las advertencias probablemente se pueden suprimir para estas pruebas, especialmente en este caso las advertencias del espectro.

Para las pruebas que se ejecutan dos veces, creo que se hizo de esa manera para el constructor, ejecute las pruebas una vez con la compilación gcc y luego vuelva a ejecutarlas con MSVC (cuando esté habilitado) para garantizar que la compilación con ambas cadenas de herramientas funcione. No estoy seguro de lo que se desea aquí, así que puedo cambiarlo para que cuando se llame a all.bat con MSVC habilitado, solo ejecutemos las pruebas con MSVC, avíseme. En ese caso, supongo que sería necesario agregar constructores adicionales solo para MSVC, a diferencia de algunos constructores que también construyen con MSVC.

Acordó que en Windows será necesario ejecutar un constructor usando la cadena de herramientas MinGW-W64 y otro con la cadena de herramientas MSVC para probar ambos escenarios.

Creo que se hizo de esa manera para el constructor, ejecute las pruebas una vez con la compilación gcc y luego vuelva a ejecutarlas con MSVC (cuando esté habilitado) para garantizar que la compilación con ambas cadenas de herramientas funcione.

Estoy de acuerdo en que este debería ser el comportamiento preferido, por lo que hay una garantía de que no interrumpe las cargas de trabajo existentes si ambas cadenas de herramientas están presentes.

Es probable que las advertencias se puedan suprimir para estas pruebas, especialmente en este caso las advertencias del espectro.

El comando Go no muestra advertencias, por lo que no deben mostrarse advertencias.

También noté que el comando go env no muestra la variable CC_FOR_CGO. Si CC_FOR_CGO afecta el funcionamiento de Go build, entonces CC_FOR_CGO debería mostrarse junto con otros. ¿Realmente necesitamos la variable CC_FOR_CGO? ¿Qué más, pero CC_FOR_CGO = gcc puede ser?

Para las pruebas que se ejecutan dos veces, creo que se hizo de esa manera para el constructor, ejecute las pruebas una vez con la compilación gcc y luego vuelva a ejecutarlas con MSVC (cuando esté habilitado) para garantizar que la compilación con ambas cadenas de herramientas funcione.

Muchas pruebas no usan gcc. Es una pérdida de tiempo para las personas / computadoras cuando las pruebas de paquetes se ejecutan dos veces sin ningún motivo. Como puede ver en https://github.com/golang/go/issues/20982#issuecomment -480569880 Las pruebas del paquete archive/zip se ejecutaron dos veces; no veo la necesidad de una segunda ejecución.

No estoy seguro de cómo arreglar eso, pero tal vez debería reemplazar su llamada de go tool dist test en run.bat para hacer solo una selección de las pruebas necesarias para probar la compilación de MSVC. Vea, por ejemplo, go tool dist test -h sobre cómo puede seleccionar solo algunas pruebas específicas. @bradfitz tal vez podríamos crear alguna bandera o variable de entorno que le diga al comando dist que ejecute pruebas específicas de MSVC.

Pero, en general, su https://go-review.googlesource.com/c/go/+/133946/5 está compilando un ejecutable para mí. Por ejemplo, puedo compilar ejecutables con gcc:

c:\Users\Alex\dev\src\issue\go\20982\hello>type *

hello.c


#include <stdio.h>

extern void hello()
{
    printf("Hello World from C");
}

hello.go


package main

/*
        extern void hello();
*/
import "C"
import "fmt"

func main() {
    fmt.Println("Hello from Go!")
        C.hello()
}

c:\Users\Alex\dev\src\issue\go\20982\hello>go build

c:\Users\Alex\dev\src\issue\go\20982\hello>hello
Hello from Go!
Hello World from C
c:\Users\Alex\dev\src\issue\go\20982\hello>

y luego puedo construir ejecutables con MSVC

c:\Users\Alex\dev\src\issue\go\20982\hello>%GOVSVARSPATH%
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

c:\Users\Alex\dev\src\issue\go\20982\hello>set CC=cl

c:\Users\Alex\dev\src\issue\go\20982\hello>go build
# issue/go/20982/hello
hello.c
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h(948): warning C4710: 'int printf(const char *const ,...)': function not inlined
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt\stdio.h(948): note: see declaration of 'printf'

c:\Users\Alex\dev\src\issue\go\20982\hello>hello
Hello from Go!
Hello World from C
c:\Users\Alex\dev\src\issue\go\20982\hello>

Entonces, construir con MSVC requerirá que los usuarios ejecuten un archivo por lotes de MS para configurar todas las variables de entorno (consulte GOVSVARSPATH en mi salida), y eso, supongo, es estándar y no tiene nada que ver con Go. Y set CC=cl . Suficientemente simple.

El único problema que veo con este enfoque es que los usuarios de MSVC aún necesitarán tener instalado gcc. cmd / cgo usa gcc para descubrir todas las interfaces C; esta parte no se implementa mediante MSVC. Suena inusual para las personas que no saben cómo funciona cmd / cgo, pero es lo que es.

@ianlancetaylor y @bradfitz, ¿suena todo esto razonable para impulsar esto? ¿Deberíamos intentar que esto esté disponible en go1.13?

Los constructores que ya tienen MSVC instalado pueden probar todo el código nuevo. Otros constructores simplemente se saltearán las pruebas.

Alex

cmd / cgo usa gcc para descubrir todas las interfaces C; esta parte no se implementa mediante MSVC.

¿Cómo se puede superar eso? Idealmente, sería genial si no hubiera ningún requisito para gcc, solo MSVC.

¿Cómo se puede superar eso?

Las partes de cmd / cgo que usan gcc deben reescribirse para usar MSVC. Si es posible.

Alex

Me preguntaba si esta función está más cerca de entrar en producción. Veo que fue etiquetado para 1.13, y eso acaba de salir. Estoy tratando de crear extensiones de Python usando una compilación de c-archive de Go que está vinculada al código de extensión, pero Python requiere MSVC.

No sé cuál es el estado de este problema. Ha sido impulsado de un lanzamiento a otro, así que lo moveré a no planeado. Si llega a 1,14, genial.

Incluso con el requisito del doble compilador, me encantaría ver la implementación actual en la próxima versión. Al menos hace posible compilar ejecutables / bibliotecas usando MSVC, que es mejor que nada.

Incluso con el requisito del doble compilador, me encantaría ver la implementación actual en la próxima versión.

Creo que esta sería una buena implementación "beta". Permitiría eliminar los errores y comenzar a madurar la implementación. ¿Qué más queda por hacer antes de que pueda pasar por una revisión seria?

Entonces, desde mi perspectiva y lo que puedo recordar de la última vez que miré esto (hace unos 6 meses), había una docena de elementos de limpieza que debían completarse para el proceso de revisión del código. También es posible que se necesite trabajo adicional para deduplicar algunas pruebas que básicamente se copiaron con modificaciones muy pequeñas para que funcionen con una cadena de herramientas diferente. También es necesario revisar y desactivar ciertas advertencias de msvc.

Los principales problemas pendientes incluyen:

No podemos hacer análisis de tipos sin gcc, no existe una solución simple o inmediata para esto.

Finalizando la configuración y cómo va a funcionar todo para los constructores.

Creo que ha habido algunos cambios bastante significativos en el compilador y enlazador en los últimos 6 meses que pueden afectar gravemente el trabajo actual realizado para esto, pero no he podido confirmarlo. Debido a la complejidad y la alta curva de aprendizaje en torno a la navegación por el compilador / enlazador / cadena de herramientas de Go, me puede llevar un tiempo considerable ponerme al día con la velocidad suficiente para calcular el impacto, si es que alguno de los cambios, tiene en este cuerpo de trabajo.

No hay soporte para los tipos numéricos complejos. MSCVs C lib es simplemente incompatible. Creo que es probable que haya una manera de ajustar esto con C ++, pero no estoy seguro, tal vez alguien de MS familiarizado con las cadenas de herramientas de MSVC pueda intervenir.

Desafortunadamente, la vida y otros proyectos se han interpuesto bastante en mi camino para dedicar más tiempo a esto, pero intentaré dedicar algo de tiempo a esto en las próximas semanas.

@manbearian, este problema se trata de agregar compatibilidad con MSVC a golang. ¿A quién del equipo de MSVC sería bueno consultar si tiene preguntas sobre MSVC?

@ kesmit13 y @mxplusb

Esta

https://go-review.googlesource.com/c/go/+/133946/5

es el último código de @cchamplin que funciona.

Mi preocupación actual con el código es que no está claro cómo usarlo. ¿Qué comando ejecutas? ¿Cómo se debe configurar mi entorno?

Creo que el siguiente paso es que alguien intente usar ese código y vea si realmente puede usarlo. Si funciona, entonces los pasos deben documentarse para que otros también puedan usar el código. Quizás sea demasiado complicado o no funcione. Entonces necesitamos ajustar el código en consecuencia.

Una vez que estemos satisfechos con el estado actual del código, deberíamos volver a basarlo en master. El cambio ha ajustado demasiados archivos diferentes, por lo que no será fácil volver a establecer la base. Tal vez podríamos ajustar el cambio para hacer menos cambios, por lo que es más fácil reajustar.

Alex

@mxplusb @ kesmit13 La implementación actual se ha modificado con respecto a la maestra y se puede encontrar aquí: https://go-review.googlesource.com/c/go/+/133946/6

@alexbrainman

Mi preocupación actual con el código es que no está claro cómo usarlo. ¿Qué comando ejecutas? ¿Cómo se debe configurar mi entorno?

Estoy de acuerdo en que se debe agregar documentación sobre cómo usar esto. Sin embargo, no estoy del todo seguro de dónde ponerlo, avíseme si tiene alguna idea. ¿Idk si debería ir debajo de la documentación de cmd / go para compilar / ejecutar a través de MSVC, o si debería vivir bajo la documentación de CGO, o tal vez en otro lugar completamente?

Muchas pruebas no usan gcc. Es una pérdida de tiempo para las personas / computadoras cuando las pruebas de paquetes se ejecutan dos veces sin ningún motivo. Como puede ver en # 20982 (comentario), las pruebas del paquete de archivo / zip se ejecutaron dos veces; no veo la necesidad de una segunda ejecución.

No estoy seguro de cómo arreglar eso, pero tal vez debería reemplazar su prueba de dist de la herramienta de llamada de go en run.bat para hacer solo una selección de las pruebas necesarias para probar la compilación de MSVC. Vea, por ejemplo, go tool dist test -h sobre cómo puede seleccionar solo algunas pruebas específicas. @bradfitz tal vez podríamos crear alguna bandera o variable de entorno que le diga al comando dist que ejecute pruebas específicas de MSVC.

El cambio ya incluye una variable de entorno agregada a dist para hacerle saber que estamos haciendo cosas de MSVC "GO_TEST_TESTINGMSVC", creo. De lo que no estoy seguro es de cómo filtraremos las pruebas para que se ejecuten en cosas que solo MSVC podría afectar si no ejecutamos todas las pruebas dos veces. Potencialmente, solo se limita a las pruebas relacionadas con CGO, pero creo que hay pruebas de CGO por todas partes y no sé si dist tiene un mecanismo para filtrarlas.

Sin embargo, no estoy del todo seguro de dónde ponerlo, avíseme si tiene alguna idea.

Creo que antes de actualizar cualquier documentación, debería describir cómo crear código Cgo con MSVC aquí. Para @mxplusb y @ kesmit13 para que puedan probar sus cambios.

Por ejemplo, para usar gcc para compilar código Cgo,

  1. ajustar mi% PATH% para incluir gcc.exe
  2. build Go primero ejecutando make.bat desde el directorio %GOROOT%\src
  3. use los comandos estándar go build y go install

¿Cómo hago lo mismo con MSVC?

De lo que no estoy seguro es de cómo filtraremos las pruebas para que se ejecuten en cosas que solo MSVC podría afectar si no ejecutamos todas las pruebas dos veces. Potencialmente, solo se limita a las pruebas relacionadas con CGO, pero creo que hay pruebas de CGO por todas partes y no sé si dist tiene un mecanismo para filtrarlas.

Comenzaría con el directorio% GOROOT% \ misc \ cgo. Cualquiera que sea la fuente que pueda construir allí, debe construirla. Todo lo que esté por encima de eso depende de usted.

Alex

@cchamplin perdón por los retrasos en esto, haré todo lo posible para probarlo esta semana y les haré saber cómo va.

Hola, lamento llegar tarde a la fiesta ... Puedo intentar responder preguntas sobre la funcionalidad de MSVC o dirigirlos a las personas que puedan. Leí la conversación, pero desafortunadamente, no estoy lo suficientemente familiarizado con go para comprender la funcionalidad de GCC requerida que puede o no faltar en MSVC.

Hola amigos,
¿Se lanzó esta función en Go 1.14?
Si se publica, comparta los documentos disponibles para utilizarlo.
Si aún no se ha lanzado, ¿hay alguna idea de cuándo se lanzará?
Esperando ansiosamente el soporte de MSVC.
Gracias por adelantado :)

Hola, nadie respondió a mi solicitud de más información, así que no estoy seguro de lo que se necesita. ¿Alguien puede informarme por favor?

Desafortunadamente, no sé si alguien está trabajando activamente en este tema.

Hola, nadie respondió a mi solicitud de más información, ...

Hola @manbearian

¿Qué solicitud es esa? ¿Qué información necesitas?

Alex

Me etiquetaron anteriormente en este hilo para obtener información, pero no sé qué está buscando la gente y no he podido ayudar. Si no se necesita ayuda, es genial. Házmelo saber.

Házmelo saber.

@manbearian

Gracias por tu oferta. No sé quién te etiquetó. Si aún necesitan ayuda, lo etiquetarán nuevamente.

Alex

Si aún no se ha lanzado, ¿hay alguna idea de cuándo se lanzará?
Esperando ansiosamente el soporte de MSVC.

@ dhinesherode91

El código está ahí y completo; Creo que lo único que realmente frena esto es que las personas prueben los cambios y brinden comentarios para que luego puedan ser revisados ​​y aprobados adecuadamente. Sin embargo, dudo en volver a basar los cambios sobre el maestro actual. Lo he hecho de 5 a 6 veces y lleva mucho tiempo, y luego no recibo pruebas / comentarios. A menos que otras partes estén dispuestas a participar en la prueba de esto, el problema podría estar muerto en el agua.

A menos que otras partes estén dispuestas a participar en la prueba de esto, el problema podría estar muerto en el agua.

@cchamplin cuente conmigo para probar / depurar sus cambios. No tengo experiencia con to go toolchain, pero he revisado sus confirmaciones y parecen estar bastante bien estructuradas y documentadas.

@cchamplin Es genial saber que la parte de implementación está completa.
Estoy interesado en participar en la parte de prueba, pero soy un principiante en GoLang y también un buen aprendiz en Windows Apis (comencé unas semanas antes). Estaba planeando trabajar con la API de Windows en MS C ++, ya que parece que hay muchos recursos oficiales disponibles para ello. Pero luego comencé a buscar un lenguaje (para la programación de mi sistema) donde pudiera usarlo para la programación de mi sistema multiplataforma y estoy impresionado con GoLang. Siempre listo para la contribución de mi parte y necesita mucha orientación.

@cchamplin, si rebasas, intentaré construir sobre él. Me encantaría eliminar el requisito mingw64 de algunos de mis proyectos en el trabajo. Mis herramientas de compilación están configuradas para MSVC, por lo que no tendría que hacer nada más que usar su parche.

@cchamplin también, miré a través de sus CL y no vi ninguno para la herramienta cgo, así que comencé con mi propio parche. ¿Hay algún trabajo previo?

@ericlagergren

@cchamplin también, miré a través de sus CL y no vi ninguno para la herramienta cgo, así que comencé con mi propio parche. ¿Hay algún trabajo previo?

No estoy seguro de haberlo entendido, en https://go-review.googlesource.com/c/go/+/133946/6 muchas de las confirmaciones relacionadas tocan directamente la parte cgo de Go de alguna manera.

@ccahoon está bien, debo haberlos extrañado. Si la herramienta cgo no se hubiera actualizado, me ofrecería hacerlo.

@ericlagergren

Me encantaría eliminar el requisito de mingw64 de algunos de mis proyectos en el trabajo.

Solo para tu información. los

https://go-review.googlesource.com/c/go/+/133946/6

El cambio aún necesita que Mingw funcione. Necesitará las herramientas Mingw y MSVC instaladas para usar el cambio @cchamplin .

Alex

@cchamplin , ¿por qué todavía se necesita a Mingw? ¿Qué se necesitaría para eliminar esta dependencia?

@alexbrainman Me eso sería fantástico. Pero también como dijo @cglong , no estoy seguro de por qué esto también requeriría mingw64.

@ericlagergren @cglong CGO necesita recopilar y tener información de tipo disponible sobre el código C con el que se está compilando. GCC tiene una bandera que generará datos de tipo en un formato convenientemente analizable. Hasta donde yo sé, MSVC no tiene la funcionalidad para proporcionar la misma información. La construcción de las herramientas en marcha no solo requeriría código para lex / analizar el código C y C ++, sino también para comprender y evaluar las directivas del preprocesador. Sería una empresa bastante grande construir algo así en Go. ¿Quizás ya hay una biblioteca disponible en algún lugar que podríamos descubrir cómo adoptar?

@cchamplin gotcha, eso es lo que pensé. Conozco bibliotecas de terceros como libclang y cznic / cc. Pero desafortunadamente libclang es gigantesco y cznic / cc no se ha probado en Windows o macOS. ¿PDB no proporciona suficiente información?

CGO necesita recopilar y tener información de tipo disponible sobre el código C con el que se está compilando. GCC tiene una bandera que generará datos de tipo en un formato convenientemente analizable. Hasta donde yo sé, MSVC no tiene la funcionalidad para proporcionar la misma información.

¿Quizás @manbearian podría proporcionar algunos consejos aquí?

No diría que GCC emite datos de tipo de salida en un formato especial. Emite datos de depuración DWARF destinados a depuradores, y cgo lee esos datos utilizando el paquete debug / dwarf. MSVC presumiblemente también tiene un formato de depuración. Si ese formato está documentado en algún lugar, podríamos leerlo usando cgo tal como lo hacemos con los datos DWARF.

@ianlancetaylor MSVC puede emitir archivos PDB. Ver https://github.com/Microsoft/microsoft-pdb

FWIW, leer la salida de depuración de MSVC es de lo que estaba hablando cuando mencioné la herramienta cgo en https://github.com/golang/go/issues/20982#issuecomment -648462003

No diría que GCC emite datos de tipo de salida en un formato especial. Emite datos de depuración DWARF destinados a depuradores, y cgo lee esos datos utilizando el paquete debug / dwarf. MSVC presumiblemente también tiene un formato de depuración. Si ese formato está documentado en algún lugar, podríamos leerlo usando cgo tal como lo hacemos con los datos DWARF.

@ericlagergren @ianlancetaylor
Entonces, necesitamos los datos DWARF, que son una gran parte de ellos. Sin embargo, teóricamente podríamos obtener la misma información de los datos de PDB.

Sin embargo, a lo que me refería específicamente no era solo a los datos DWARF que produce GCC, sino a la salida de gcc -E -dM que genera todos los # define después de que se haya realizado el preprocesamiento. Es posible que PDB por sí solo pueda proporcionar la misma información ... de lo que soy escéptico es de si podríamos o no coaccionar a MSVC para que descargue información de depuración / tipo de información en cualquier capacidad sin necesidad de compilar realmente el código. En este momento, CGO está haciendo exactamente eso con GCC.

Desde la memoria, / EP / d1PP debería emitir algo similar a -E -dM.

Desde la memoria, / EP / d1PP debería emitir algo similar a -E -dM.

Si es así, sería excelente, supongo que / d1PP es una bandera indocumentada. Nunca lo había visto antes. Eso dejaría obtener información de tipo equivalente con anticipación.

@cchamplin sí, no está documentado. Muchas de las banderas / dXXX lo son, aparentemente. El uso de banderas indocumentadas es desafortunado, pero (en mi opinión) no parece ser un pecado tan grave en Windows, al menos. Vi a los desarrolladores de MSVC STL hablando de ello en un hilo de Reddit, pero también está en Internet.

¿Alguien puede darme un breve resumen del estado actual del soporte de MSVC? No entiendo mucho de todo esto del compilador de bajo nivel. Es solo que tengo una biblioteca go que quiero usar desde C # / UWP, y eso ya está funcionando con go build y buildmode c-shared. PERO: esa aplicación nunca será aceptada por la Tienda Windows, ya que la DLL generada desde go pierde algunos indicadores de compilador / enlazador que (supongo) solo pueden ser configurados por la cadena de herramientas MSVC.

Entonces, ¿cómo podría probar esto aquí? ¡Se agradece cualquier consejo! ¡Gracias!

esa aplicación nunca será aceptada por la Tienda Windows, ya que la DLL generada desde go pierde algunos indicadores de compilador / enlazador que (supongo) solo pueden ser configurados por MSVC-toolchain.

@TopperDEL, ¿Windows Store te dice qué indicadores del compilador faltan? Si mingw-64 los admite, siempre puede usar -extldflags con las banderas correctas cuando compile la dll.

@qmuntal Sí, lo hacen:
"Aplique las opciones de vinculador requeridas (SAFESEH, DYNAMICBASE, NXCOMPAT y APPCONTAINER) cuando vincule la aplicación".

Ya lo intenté
go build -ldflags="-s -w '-extldflags=-Wl,--dynamicbase,--high-entropy-va'" -o storj_uplink.dll -buildmode c-shared

Pero eso no cambió nada con respecto a la presentación de la tienda. Y a mi entender, al menos SAFESEH es algo específico de MSVC, ¿verdad?

"Aplique las opciones de vinculador requeridas (SAFESEH, DYNAMICBASE, NXCOMPAT y APPCONTAINER) cuando vincule la aplicación".

No conozco una manera fácil de habilitar las banderas SAFESEH ni APPCONTAINER en Mingw-w64, tal vez este proyecto https://github.com/status-im/mingw-windows10-uwp pueda brindarle alguna orientación.

Por otro lado, DYNAMICBASE y NXCOMPAT estarán habilitados por defecto en go 1.16 (ver # 41421) pero ya se pueden usar con -extldflags tal como se mencionó, de hecho lo estoy haciendo para algunos proyectos.

@qmuntal ¡Gracias! Entonces, ¿al menos mis extldflags anteriores deberían ser correctas?
Echaré un vistazo a mingw para windows 10-uwp.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

enoodle picture enoodle  ·  3Comentarios

bradfitz picture bradfitz  ·  3Comentarios

rsc picture rsc  ·  3Comentarios

OneOfOne picture OneOfOne  ·  3Comentarios

natefinch picture natefinch  ·  3Comentarios