Go: cmd / link: suporte a arquivos de objeto msvc

Criado em 11 jul. 2017  ·  222Comentários  ·  Fonte: golang/go

Eu entendo que o linker go atualmente não pode vincular arquivos de objeto msvc e também reconheço que esse problema provavelmente é de baixa prioridade. No entanto, seria bom dar suporte a isso porque simplificaria um pouco o fluxo de trabalho do Windows. Essa questão é principalmente para entender quanto esforço isso seria e / ou o que seria necessário.

Builders FeatureRequest NeedsInvestigation OS-Windows

Comentários muito úteis

Ei, parece que no final deste tópico você tem seus problemas de MSVC resolvidos. Mas se você tiver problemas, estou na equipe MSVC. Sinta-se à vontade para me enviar um ping no github ou e-mail ([email protected])

Todos 222 comentários

/ cc @alexbrainman

@xoviat qual é o problema que você está tendo? Eu preciso ser capaz de reproduzi-lo aqui. Portanto, forneça todas as etapas que precisarei seguir para reproduzir isso.

Obrigado

Alex

PS: Não terei computador até o final de julho. Vou dar uma olhada nisso então.

qual é o problema que você está tendo?

Ainda não tentei, mas gostaria de chamar especificamente funções c em arquivos de objeto msvc vinculando-os como .syso com o linker go. Tudo o que li indica que isso não é possível, mas vou criar um procedimento para reproduzir o erro específico que ocorre.

chame especificamente funções c em arquivos de objeto msvc vinculando-os como .syso com o linker go

Você já tentou compilá-los em uma DLL e usá-los de dentro da DLL?

Vou criar um procedimento para reproduzir o erro específico que ocorre.

Por favor faça. Obrigada.

Alex

Você já tentou compilá-los em uma DLL e usá-los de dentro da DLL?

Esse era realmente meu plano original. Estou usando o swig, portanto, não é tão conveniente compilar o código c gerado separadamente e, em seguida, reescrever as funções como exportações de DLL. Não é difícil, mas é irritante quando o fluxo de trabalho com gcc é apenas go generate; go build .

Tudo bem, eu tenho um procedimento. Comece com estes arquivos:

ola.go:

package main

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

func main() {
    C.hello()
}

ola.c:

#include <stdio.h>

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

em seguida, execute estes comandos (com msvc no caminho):

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

Ao executar o arquivo produzido:

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

Não tenho o comando cl instalado no meu pc. Como faço para instalar o msvc?

Obrigada.

Alex

Você precisa das "ferramentas de construção 2017" aqui . Na verdade, a Microsoft agora permite que qualquer pessoa use o visual studio gratuitamente, desde que não seja para desenvolvimento comercial. Se for muito problemático, posso apenas fornecer o arquivo objeto, se quiser.

Se c ++ não fosse uma coisa, eu não teria que me preocupar com isso. Mas é, então a dor continua ...

Você precisa das "ferramentas de construção 2017" aqui.

Entendi. Obrigada.

Se for muito problemático, posso apenas fornecer o arquivo objeto, se quiser.

Sim, por favor, poste hello.obj em algum lugar.

Pensando mais um pouco sobre isso. Na verdade, você está usando o gcc para vincular o arquivo objeto compilado com o compilador msvc. Você pode tentar fazer seu exercício, mas substituindo a etapa "go build" por gcc vinculando hello.obj a um programa C? Talvez isso já tenha sido feito antes. Suspeito que, se soubermos como fazer isso, talvez possamos fazer o mesmo com Go.

Alex

AFAIK lld https://github.com/llvm-mirror/lld oferece suporte a arquivos de objeto msvc.

O arquivo de objeto está aqui: https://github.com/xoviat/msvcgo/blob/master/hello.syso

lld https://github.com/llvm-mirror/lld oferece suporte a arquivos de objeto msvc

Go usa o vinculador gcc (não lld) no Windows.

O arquivo de objeto está aqui: https://github.com/xoviat/msvcgo/blob/master/hello.syso

Vou tentar quando chegar em casa em agosto. obrigada.

Alex

Go usa o vinculador gcc (não lld) no Windows.

Eu sei. Mas lld é a melhor documentação de código aberto do formato de objeto msvc.

Na verdade, recebo o mesmo erro do ld, então o erro definitivamente vem do ld.

Na verdade, recebo o mesmo erro do ld, então o erro definitivamente vem do ld.

sim. Precisamos descobrir como construir um programa C compilando parte com msvc e vinculando com gcc.

Alex

Perdoe minha ignorância, mas o que exatamente gcc linking? Ele está vinculando a saída do linker go?

Executando objconv nos arquivos objeto para converter em elf:

objconv -felf hello.obj hello.syso

Agora temos estes erros:

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

Possivelmente stdio está fora dos limites?

Perdoe minha ignorância, mas o que exatamente gcc linking? Ele está vinculando a saída do linker go?

Você usa 2 programas para construir seu programa Go:

  • o compilador converte seus arquivos .go (1 pacote por vez) em um arquivo de objeto armazenado no diretório% GOPATH% / pkg;
  • vinculador que cria o arquivo .exe final a partir de arquivos objeto em% GOPATH% / pkg.

Às vezes (quando um de seus pacotes usa Cgo), o vinculador Go chama o vinculador externo para encontrar todos os bits que são implementados em C. Imagine que você chame printf a partir de seu código C. O código C printf compilado precisa fazer parte do executável Go, mas o linker Go não sabe onde obtê-lo. Então, o vinculador Go chama o vinculador externo para incluir esse código.

O Go atual usa o compilador / vinculador gcc para compilar e vincular o código C (usamos mingw gcc). Se você for compilar seu código C com um compilador diferente (da Microsoft), deverá usar o vinculador correspondente (da Microsoft) para localizar todo o código C externo que o compilador criou.

Então, eu acho que estava errado ao sugerir o uso do gcc linker. Para o cenário geral, você teria que usar o compilador e o vinculador da Microsoft. Teríamos que descobrir o que o Microsoft linker requer como entrada e fazer a correspondência.

Você pode escapar sem o vinculador MC, se o seu código C não tiver nenhum código externo. Por favor, tente algum programa C realmente simples (como aquele que adiciona 2 inteiros ou algo assim). Isso pode funcionar como você descreveu acima.

Alex

Possivelmente stdio está fora dos limites?

Suspeito que você precise ligar para o linker da Microsoft para encontrar esse código.

Alex

Eu não tenho certeza, mas

objconv -felf hello.obj hello.syso

Talvez você deva tentar fazer coff ou omf em vez de elf?

Talvez você deva tentar fazer coff ou omf em vez de elf?

@xoviat sim, você não deve converter arquivos .obj em elf, a versão do Windows do gcc gera arquivos pe / coff como qualquer outro compilador do Windows.

Alex

o vinculador Go chama o vinculador externo para encontrar todos os bits que são implementados em C.

Qual é o comando específico usado? Se eu conheço o comando mingw, talvez possa prosseguir por um caminho de comparação de arquivos para tentar fazer com que o msvc corresponda ao que o mingw está lançando.

Você pode ver o comentário exato executando go build -ldflags=-v .

Ok, então pelo que posso dizer:

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

Go parece criar um diretório temporário com esses arquivos. Existe alguma maneira de preservar o diretório temporário para que eu possa inspecionar seu conteúdo?

Experimente go build -work

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

Os arquivos de objeto permanecem neste diretório.

A opção -work não preserva os arquivos temporários que o vinculador cria. No momento, você só precisa editar as fontes do linker para não remover o diretório. Provavelmente deveríamos adicionar uma opção para isso, de uma forma ou de outra.

No momento, você só precisa editar as fontes do linker para não remover o diretório.

Se você não se importa, vou esperar até que isso seja implementado no HEAD para que eu não tenha que fazer trabalho repetitivo.

Existe alguma maneira de preservar o diretório temporário para que eu possa inspecionar seu conteúdo?

O programa cmd / link tem o sinalizador -tmpdir para isso. Você pode usá-lo assim:

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

Isso é apenas para minha própria referência, mas precisa ser transferido para 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);
}

Eu não subestimaria o tempo que vou levar para completar esta tarefa, pois não estou familiarizado com montagem.

  • [x] Entenda o que a montagem faz
  • [x] Porta para montagem MSVC
  • [x] Entenda _beginthread vs CreateThread
  • [x] Mudar para CreateThread

Além disso, 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

Ok, movendo-se aqui mais rápido do que o esperado!

All: o asm_amd64.s é montado pelo assembler de go (com o assembly ímpar) ou assembler do gcc?

Parece que o gcc não irá montá-lo, o que significa que provavelmente ele será montado. E então a questão se torna: como montá-lo com o montador go em um objeto.

A intenção é que o runtime / cgo / asm_amd64.s seja montado em um objeto Go, em seguida, cmd / link o vincule a todos os outros objetos Go em um único objeto do sistema e, em seguida, o vinculador do sistema vincule esses objetos únicos do sistema mais todos os dependências cgo no programa final.

Existe uma maneira de montar esse objeto por enquanto para fins de teste? Gosta de gcc -c asm_amd64.s exceto com go?

A intenção é que o runtime / cgo / asm_amd64.s seja montado em um objeto Go, em seguida, cmd / link o vincule a todos os outros objetos Go em um único objeto do sistema e, em seguida, o vinculador do sistema vincule esses objetos únicos do sistema mais todos os dependências cgo no programa final.

Até agora encontrei estes objetos:

  • go.o: obviamente, do conjunto de ferramentas go
  • _cgo_.o : gerado pelo gcc, inutilizável
  • 000000.o: gerado pelo gcc, inutilizável
  • 000001.o: Atualização: gerada na verdade pelo linker go, mas contém símbolos gcc. Inutilizável.

go.o é o maior objeto.

@ianlancetaylor

Eu não acho que o que você disse está correto. crosscall_amd64 está localizado em 000001.o, mas esse arquivo não tem "todo o 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 arquivo foi obviamente gerado pelo gcc, que é muito tarde no processo.

Existe uma maneira de montar esse objeto por enquanto para fins de teste? Como gcc -c asm_amd64.s exceto com go?

asm_amd64.s faz parte do pacote de tempo de execução. Você pode ver como o comando "go build" usa o arquivo 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

Obrigado.

O símbolo crosscall_amd64 é definido no arquivo runtime / cgo / gcc_amd64.s. Esse arquivo é compilado pelo GCC (assim como todos os arquivos runtime / cgo / gcc_ *). Portanto, ele não é combinado em um único arquivo go.o que contém todo o código Go. O arquivo do qual estávamos falando antes, runtime / cgo / asm_amd64.s, define o símbolo crosscall2 . Você encontrará esse símbolo em go.o.

Obrigado.

Ok, consegui vincular um executável que falha em uma violação de acesso enquanto em
go.runtime.rt0_go + 5F -> go .___ acrt_stdio_initializer.

É todo o tempo que tenho por agora; Voltarei a isso mais tarde.

@alexbrainman Correto.

@alexbrainman Você precisará do MSVC para continuar. Deixe-me saber se você precisa de ajuda com isso.

Você precisará do MSVC para continuar.

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

O que devo fazer depois de instalado?

Alex

Depois de instalar isso, você precisa construir "libgo", que é a biblioteca go. Copie os seguintes arquivos da pasta cgo :

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

Precisamos ajustar gcc_windows_amd64.c para ser compatível com MSVC. Modifique a função da seguinte maneira:

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);
}

Crie um novo arquivo na pasta com todos esses arquivos chamados "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

Avise-me quando tiver a pasta estruturada conforme solicitado.

A propósito, obrigado por trabalhar nisso e por continuar. Vocês criaram uma linguagem verdadeiramente mágica.

Avise-me quando tiver a pasta estruturada conforme solicitado.

Consegui construir libgo.lib conforme você descreveu aqui https://github.com/golang/go/issues/20982#issuecomment -327365063
O que eu devo fazer a seguir?

Alex

Ok, agora precisamos dos seguintes arquivos:

  • libgo.lib
  • gosma
  • hello.cgo2.o
  • ola.c

hello.c é o seguinte:

#include <stdio.h>

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

Para obter hello.cgo2.o e go.o , você precisa começar com o seguinte arquivo:

package main

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

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

chamado "hello.go"

Configure um script do PowerShell que copia continuamente os arquivos de $ env: TMP :

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

Em seguida, execute go build com hello.c e hello.go na pasta. Você deve conseguir recuperar os arquivos necessários do local para o qual foram copiados.

Depois de ter os arquivos especificados acima, você pode construir com:

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

Deixe-me saber se você tiver alguma dúvida.

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

Isso cria o arquivo executável go.exe, mas ele não é executado. Não vejo nenhum código de asm sensato lá. A primeira instrução salta para lugar nenhum. É apenas uma bagunça.

Talvez você deva começar com algo bem simples. Grave um arquivo asm (arquivo asm Go) com função asm única que executa "INT $ 3" ​​e não tem mais nada. E tente construir um programa executável a partir dele - o programa deve executar sua função logo no início.

Talvez construa usando as ferramentas Go primeiro (e também usando o gcc se necessário) e, em seguida, tente fazer o mesmo usando o MSVC.

Alex

Alex, obrigado por sua ajuda. Eu vou trabalhar nisso.

Vou anexar esses dois artigos aqui para minha própria referência. Caso contrário, não tenho mais nenhuma atualização.

Na verdade, eu tenho um programa go bastante complexo funcionando que usa apenas a biblioteca msvc. Acontece que o linker msvc vanilla e o llvm-lld não manipularam corretamente a seção .bss .

Depois de corrigir o vinculador, o programa pode ser executado.

Infelizmente go build quebra quando gera _cgo_.o / _all.o . É possível lançar algumas luzes sobre os fundamentos por trás da geração desses dois arquivos no cgo?

Você pode executar go tool cgo para executar cgo diretamente. As fontes estão aqui: https://github.com/golang/go/tree/master/src/cmd/cgo

Além disso, se você pudesse fazer isso funcionar, seria incrível. Eu simplesmente não dediquei tempo a isso, então não houve progresso. Desculpe por isso.

Já tenho programas que podem ser executados corretamente por meio de uma série de costuras à mão - o que tento fazer aqui é ver se o processo pode ser integrado de volta ao go para torná-lo menos doloroso. :-)

Se você puder documentar o processo de costura à mão, talvez eu possa ajudar.

Só de olhar, _cgo_.o parece ser produzido assim (simplificado):

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

A partir daqui: https://github.com/golang/go/blob/b4c84a1b010f012668b5e3ccaf63f609cd11c5fe/src/cmd/go/internal/work/exec.go#L1975

Idealmente, escreveríamos um programa go que pré-processe os arquivos de objeto de modo que sejam compatíveis com link.exe para atrito mínimo, mas isso é uma meta exagerada.

Obrigado pela indicação - vou anotar o processo em breve.

Infelizmente, não acho que a vinculação possa ser feita por meio de link.exe menos que alteremos o gcc para emitir dados não inicializados na seção .data vez da seção .bss - mas podemos definitivamente conserte llvm-lld para reconhecer a seção .bss (que é o que eu fiz).

Precisamos lidar com _cgo_.o e _all.o separadamente. Tenho algumas perguntas sobre eles:

(1) Parece que _cgo_.o não é o executável final, pois não contém o tempo de execução go. Parece que o compilador olha seus símbolos DWARF para descobrir a definição da estrutura. O problema é que é difícil gerar um executável se você for vincular a uma série de bibliotecas externamente, especialmente aquelas que são geradas pelo msvc.

É possível evitar essa etapa?

(2) atual vá usar GNU ld para juntar todos os arquivos de objeto em _all.o passando -Wl,-r no GCC. Isso é problemático porque (1) não parece que outro vinculador tenha esse recurso e (2) o comando é afetado pelo CGO_LDFLAGS . Por exemplo, o seguinte comando gera resultados incorretos:

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

Ele gera um executável em vez de um arquivo de objeto empacotado.

É possível evitar essa etapa simplesmente colocando todos os arquivos-objeto diretamente nos .a gerados?

@zooba Quais são as chances de fazer a MSFT atualizar link.exe com este patch?

Infelizmente, não acho que a vinculação possa ser feita via link.exe, a menos que alteremos o gcc para emitir dados não inicializados na seção .data em vez da seção .bss - mas podemos definitivamente corrigir llvm-lld para reconhecer a seção .bss (que é o que eu fiz).

Portanto, supondo que a MSFT não atualize link.exe (o que é provável), seria bom compilar os arquivos-objeto com cl.exe vez de gcc .

Parece que _cgo_.o não é o executável final, pois não contém o tempo de execução go.

Isso está correto, existem basicamente dois conjuntos de arquivos de objeto (eu acho) que são vinculados no final. O arquivo go.o (IIRC) contém todo o código go + tempo de execução e os outros objetos contêm o código C. Existem rotinas de montagem para saltar entre os dois conjuntos de objetos.

Além disso, precisamos de clang para compilar os arquivos assembly do Unix.

Para nossos propósitos, -Wl,-r será o mesmo que executar lib.exe [object files] /OUT:obj . A opção significa "link incremental", que significa "pegar alguns arquivos de entrada, fazer algum trabalho e, em seguida, cuspir outro arquivo-objeto". Se não nos preocuparmos com a parte "fazer algum trabalho" por enquanto, podemos apenas considerar o requisito como "pegar alguns arquivos de entrada e / ou arquivos de objeto e cuspir outro arquivo de objeto", exceto em nosso caso o arquivo de objeto será uma biblioteca.

Você pode dizer ao GCC para evitar colocar variáveis ​​na seção .data em vez da seção .bss usando a opção -fno-zero-initialized-in-bss .

Observe que, como sugestão, não usamos mais -Wl,-r ao construir o código cgo.

Não deve ser necessário que o cmd / link compreenda os arquivos de objeto MSVC para poder usá-los como arquivos .syso . Esses arquivos são apenas passados ​​para o vinculador externo de qualquer maneira. Portanto, acho que o que é necessário aqui é invocar o vinculador MSVC como o vinculador externo, o que você deve ser capaz de fazer usando a opção -extld . Se você já está fazendo isso, minhas desculpas; nesse caso, o que está falhando?

Se você já está fazendo isso, minhas desculpas; nesse caso, o que está falhando?

IIRC, link.exe barfs nos objetos gerados pelo gcc.

É verdade que você também teria que usar o compilador MSVC C, definindo a variável de ambiente CC apropriadamente. Eu não acho que vai funcionar combinar objetos GCC e objetos MSVC em um único link.

Mas então você se depara com o problema em que as bibliotecas C de tempo de execução são pré-compiladas. E se você tentar recompilá-los, terá o problema de que cl não pode compilar o assembly unix. E então você transporta partes das bibliotecas de tempo de execução e tenta vinculá-las, que foi o que fiz e falhei.

Em algum lugar ao longo do caminho, cl compila incorretamente uma parte importante do código. Minha ideia para consertar isso seria fatorar o código MSVC em uma DLL com uma API C simples e, em seguida, apenas compilar mais das bibliotecas de tempo de execução até que pare de funcionar.

A ideia de @haohui para corrigir o problema era diferente. Em vez de corrigir a raiz do problema, ele o contornou corrigindo o vinculador. Obviamente, ele teve mais sucesso do que eu, mas provavelmente porque a abordagem dele, em retrospectiva, tem mais probabilidade de funcionar do que a minha.

O que eu recomendaria neste ponto (IMHO) é compilar incrementalmente mais da biblioteca runtime com cl até que pare de funcionar ou até que você não tenha mais código gcc. Então você sabe exatamente onde está o problema.

E com o patch do vinculador, nenhuma DLL é necessária.

O patch de llvm-lld está disponível em https://bugs.llvm.org/show_bug.cgi?id=35283

Vou dedicar algum tempo para dar um exemplo.

+1 @haohui Muito obrigado por levar isso adiante!

@haohui A qual versão do llvm seu patch se aplica? Alguma instrução sobre como usar seu patch e como vincular a arquivos MSVC?

Em relação a _cgo_.o e _all.o arquivos, tive o mesmo problema, então talvez uma correção para este problema possa ser uma correção para o outro problema também: https://github.com/golang/go / questões / 17014

Obrigado por todo o trabalho nisso. Parece que um bom progresso está sendo feito. Os novos recursos estão congelados até o Go 1.11, alterando assim o marco.

Então entrei nisso ontem à noite. É possível construir tudo via msvc: cl e vincular tudo via msvc: link. Os problemas, no entanto, são numerosos.

Portanto, além dos problemas simples como msvc: cl não suporta totalmente C99 (no momento não podemos lidar com o tipo _Complex). Existem mais problemas sistêmicos com a combinação de libs PE compilados por internals go e aqueles construídos por msvc. Especificamente, msvc: link destrói os segmentos .bss (acho que pode apenas jogar esses dados em .data), o que é um problema, pois parece que o go assembler SB (pseudo reg) resulta em endereçamento incorreto se .bss for movido .

Meu pensamento inicial seria tentar fazer com que o montador coloque as coisas que iriam para .bss e .noptrbss em .data e .noptrdata respectivamente. Eu nem tenho certeza se isso é possível; minha manipulação não teve êxito e o endereçamento foi completamente bloqueado.

Não acho que seja possível usar o link.exe por enquanto. Acho que devemos começar com lld-link.exe

Se o pensamento por trás disso é que podemos corrigir o link lld para não mover os dados .bss, entendo o apelo. Realisticamente, se o objetivo é oferecer suporte à cadeia de ferramentas msvc real, vá para a compilação interna, colocando os dados em .bss / .noptrbss para que precisem ser resolvidos.

Não podemos simplesmente redistribuir lld-link.exe com go? Esse parece ser o caminho de menor risco para oferecer suporte a arquivos de objeto MSVC, desde que LTCG não esteja habilitado. Eu entendo que não é ideal, mas enfrentamos uma restrição de recursos.

Também permite um progresso incremental, que é a melhor estratégia.

Ok, boas notícias de acompanhamento. Consegui passar uma hora trabalhando nisso durante o almoço.

No momento, tenho o exemplo do início do 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

O binário é construído completamente com o conjunto de ferramentas MSVC e Go (sem GCC ou outro LLVM instalado).

Resultados:

  • Fazer com que as ferramentas Go / link.exe gerassem dados .bss de assemblies internos para .data era, em última análise, bastante trivial
  • Várias peças ASM tiveram que ser ajustadas para msvc
  • Alguns #defs do GCC foram reduzidos
  • Vários pequenos ajustes tiveram que ser feitos em alguns dos arquivos .c gerados por cgo
  • Números complexos precisarão ser reduzidos, no momento em que não forem suportados
  • É provável que sinalizadores adicionais precisem ser adicionados diretamente para construir ou link para suporte a msvc, ldflags etc não serão suficientes

Próximos passos:
Se eu tiver tempo neste fim de semana, irei trabalhar em colocar minhas alterações em um fork e na funcionalidade por trás dos sinalizadores em build / link. Depois disso, vou fazer uma revisão de um RP para que possamos resolver os tipos. Não estou 100% confiante de que mover os dados .bss não terá algum tipo de impacto em algum lugar.

A única desvantagem em que posso pensar é que isso aumentará o tamanho do binário, mas deve ficar bem.

OK!

Desculpe, demorei alguns dias a mais para fazer isso. Portanto, o primeiro rascunho de um patch pode ser encontrado aqui: https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 :: https://github.com/cchamplin/go/tree/msvc_toolchain_support

Isso ainda é difícil, mas tenho sucesso ao construir código com msvc.

Seria incrível se as pessoas pudessem começar a testar isso agora e relatar os bugs de volta para mim, para que eu possa colocar isso em um local melhor para o upstream. Além disso, se alguém quiser escrever testes, seria incrível!

Uso:

go build -compiler msvc [path]
  • Números complexos não são suportados atualmente até eu descobrir se podemos fazê-los funcionar.
  • Não tenho ideia do que acontece se você tentar construir o runtime go com o compilador msvc.
  • gcc ainda está sendo necessário e usado por gco para definir e digitar dados ao compilá- lo (não é usado para construir nada ). Não sei se podemos contornar isso, msvc não tem nada que possa fazer o mesmo anão e # definir dumps de código ... se alguém tiver idéias sobre isso, seria ótimo

O patch vinculado cria um problema de inicialização.

@alexbrainman Como e onde é determinado quais arquivos serão copiados em pkg/boostrap/src/bootstrap durante a fase de boostrapping de toolchain1 ?

cc @alexbrainman

O patch vinculado cria um problema de inicialização.

Não sei como funciona o bootstrap hoje em dia. Mas tenho certeza de que outros ( @rsc e @ianlancetaylor) podem ajudar.

Eu me pergunto como @cchamplin executa make.bat se a inicialização não funciona.

Alex

@xoviat Não sei qual é o problema, mas a lista de diretórios de bootstrap está em cmd / dist / buildtool.go.

Hey @alexbrainman, @ianlancetaylor, @xoviat muito por isso eu acho que eu deveria ter verificado mais profundamente.

Atualizei o branch aqui https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 com uma correção para o problema de inicialização, acho que deve inicializar corretamente agora.

Tive que copiar alguns diretórios / src / internal / syscall para cmd / internal / msvc. Isso vai ser um grande problema? Não tenho certeza de como obter acesso ao registro sem usar src / internal.

Tive que copiar alguns diretórios / src / internal / syscall para cmd / internal / msvc. Isso vai ser um grande problema? Não tenho certeza de como obter acesso ao registro sem usar src / internal.

Não sei como isso é feito hoje em dia, mas suspeito que cmd / dist pode fazer isso sem você copiar manualmente os arquivos de origem. Tenho certeza de que Russ ou Ian o ajudarão quando você estiver pronto para enviar o código.

Acho que é hora de @bradfitz e @ianlancetaylor decidirem como proceder aqui. Queremos que Go ofereça suporte a ferramentas de compilação da Microsoft e também ao gcc? Teríamos que instalar ferramentas correspondentes da Microsoft em nossos construtores (teríamos que fazer isso antes de começarmos a aceitar CLs). Provavelmente, teríamos que introduzir novas variáveis ​​de ambiente. Nova documentação.

Se a resposta for sim, @cchamplin teria que enviar suas alterações de código de acordo com https://golang.org/doc/contribute.html Você estaria disposto a fazer isso? A mudança é muito grande, por isso precisa ser dividida em CLs menores, para que possam ser revisados ​​e enviados separadamente. Cada alteração deve ter all.bat PASS antes de ser enviada. Seria bom se pudéssemos ver todos os CLs antes de começarmos a enviar o primeiro CL.

Obrigada.

Alex

Queremos que Go ofereça suporte a ferramentas de compilação da Microsoft e também ao gcc?

Apenas uma observação: este patch também facilita o # 17014, para o qual já tenho um patch em andamento.

Se a resposta for sim, @cchamplin teria que enviar suas alterações de código de acordo com https://golang.org/doc/contribute.html Você estaria disposto a fazer isso? A mudança é muito grande, por isso precisa ser dividida em CLs menores, para que possam ser revisados ​​e enviados separadamente.

Sim, e separar não deve ser um grande negócio. Eu só preciso saber se isso é algo que provavelmente acontecerá antes de me esforçar para limpar todo o código, escrever documentação, criar testes etc.

Queremos que Go ofereça suporte a ferramentas de compilação da Microsoft e também ao gcc?

Em minha opinião, a resposta é sim. Os próprios compiladores são gratuitos com o VS Community, e não ter suporte completo do Windows é realmente frustrante. Eu não deveria ter que criar uma máquina Linux para compilar github.com/Microsoft/hcsshim (por exemplo), porque um conjunto de ferramentas do Windows não é suportado.

Qual seria a razão para não oferecer suporte a um conjunto de ferramentas do Windows?

Acho que, em princípio, não há problema em oferecer suporte a arquivos de objeto MSVC. Precisamos de um construtor.

Minha principal preocupação é o quanto o formato pode mudar entre as versões do Windows ou do MSVC. O formato ELF usado na maioria das outras plataformas é muito estável; raramente precisamos ajustar o suporte ELF de outra forma que não seja adicionando suporte para novos processadores. O formato de arquivo MSVC é similarmente estável?

Os formatos associados ao conjunto de ferramentas MSVC são bastante estáveis. O maior problema será o suporte das próprias ferramentas. A Microsoft tende a mover as coisas (arquivos e entradas do registro) entre os lançamentos do Visual Studio. A maior parte disso é configurável (pelo menos no patch que escrevi), mas ainda existe a possibilidade de que, quando uma nova versão principal do Visual Studio for lançada, ela não seja compatível como uma cadeia de ferramentas de construção sem alterações em Go. Todas as versões anteriores com suporte do Visual Studio continuariam a funcionar, no entanto.

Pelo que eu sei, o formato COFF tem estabilidade razoável se você se expõe apenas ao C ABI (não C ++). Também é amplamente documentado e o LLVM fornece uma implementação de referência.

@cchamplin Eu recomendaria exigir que os usuários invocassem o vcvarsall.bat antes de vincular ao MSVC. Isso reduzirá significativamente a manutenção para quase zero.

Precisamos de um construtor.

@ianlancetaylor uma vez que os objetos MSVC provaram que funcionam como pretendido, você acredita que seria necessário um construtor msys / cygwin e um construtor MSVC, ou haveria apenas um construtor MSVC?

Tenho certeza de que algumas pessoas preferirão usar as ferramentas cygwin, e elas já funcionam e queremos que continuem a funcionar, então acho que precisamos de dois construtores.

Ei, parece que no final deste tópico você tem seus problemas de MSVC resolvidos. Mas se você tiver problemas, estou na equipe MSVC. Sinta-se à vontade para me enviar um ping no github ou e-mail ([email protected])

Precisamos de um construtor.

sim. E provavelmente devemos começar mudando nossos construtores existentes para ter as ferramentas de construção MS instaladas. Portanto, podemos usá-los já que aceitamos CLs para esse problema.

Podemos instalar ferramentas gcc e ferramentas microsoft em todos os nossos construtores. Podemos executar all.bat que testa as ferramentas gcc e microsoft de uma só vez? Do contrário, precisaríamos ter construtores diferentes configurados para ferramentas diferentes. Quais são os parâmetros que controlam quais compiladores e vinculadores externos são usados?

Minha principal preocupação é o quanto o formato pode mudar entre as versões do Windows ou do MSVC.

Você não tem um compilador instalado com o Windows. Você tem que instalá-lo sozinho. Assim como fazemos com o gcc. Instalamos qualquer versão que quisermos. Poderíamos até rodar diferentes versões do gcc em diferentes construtores.

O formato de arquivo MSVC é similarmente estável?

Eu não sei nada sobre isso. Suspeito que você apenas use as ferramentas fornecidas.

Alex

Minha principal preocupação é o quanto o formato pode mudar entre as versões do Windows ou do MSVC. O formato ELF usado na maioria das outras plataformas é muito estável; raramente precisamos ajustar o suporte ELF de outra forma que não seja adicionando suporte para novos processadores. O formato de arquivo MSVC é similarmente estável?

Sim, o COFF é muito estável.

@bradfitz e @ianlancetaylor o que precisamos para obter um Windows Builder disponível para testar as alterações para esse problema? Veja minhas perguntas em https://github.com/golang/go/issues/20982#issuecomment -370719472

Obrigado

Alex

agora é go support msvc object?

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

@alexbrainman @bradfitz @ianlancetaylor :

Acredito que realizei a maior parte do trabalho necessário para limpar e quebrar o remendo em pedaços mais digeríveis. Acredito que estou quase pronto para uma apresentação efetiva ao projeto. Acho que preciso saber se devo esperar por notícias sobre a situação do construtor antes de enviar o código ou apenas fazê-lo o mais rápido possível.

Você pode enviar os CLs a qualquer momento, mas alguém precisa configurar um construtor. Caso contrário, não temos como testá-los.

@johnsonj , você poderia adicionar as ferramentas do compilador MSVC às nossas imagens do Windows?

Eu gostaria de não adicionar um novo tipo de host e apenas fazer com que 1-3 de nossos tipos de host do Windows existentes tivessem as ferramentas MSVC além do Cygwin. E então podemos adicionar mais configurações do construtor sobre os tipos de host modificados.

/ cc @andybons @bcmills como FYI (para saber como as coisas do Windows acontecem ... imploramos a ajuda de Jeff :))

@johnsonj , você poderia adicionar as ferramentas do compilador MSVC às nossas imagens do Windows?

@cchamplin Eu sugiro que você tente adicionar as ferramentas necessárias para o construtor você mesmo. Ninguém mais, mas você sabe o que é necessário. Você pode procurar no diretório golang.org/x/build/env/windows para obter instruções completas. Em particular, você provavelmente deseja adicionar mais linhas em startup.ps1. Assim que você souber o que precisa ser mudado nesse diretor, faça as mudanças e envie sua mudança para revisão via https://golang.org/doc/contribute.html Uma vez aceito, poderíamos atualizar os construtores usando estas instruções.

Eu gostaria de não adicionar um novo tipo de host e apenas fazer com que 1-3 de nossos tipos de host do Windows existentes tivessem as ferramentas MSVC além do Cygwin. E então podemos adicionar mais configurações do construtor sobre os tipos de host modificados.

Sempre tivemos o compilador Mingw (gcc) C e o vinculador no windows. Nunca temos um conjunto diferente de ferramentas de construção C. Assim que adicionarmos suporte para o compilador Microsoft C, seria possível ter as funções Mingw e Microsoft C testadas com uma única execução de all.bat? Ou o Mingw ou o Microsoft C se excluem? Teríamos que definir alguma variável de ambiente para apontar para Mingw ou Microsoft, mas nunca ambos? Suponho que estou tentando entender como o código precisa ser estruturado e testado. Além disso, isso determinará quantos construtores diferentes precisamos.

Alex

Vou tentar preparar os binários da imagem

Mudança https://golang.org/cl/112036 menciona este problema: env/windows: add visual studio tools to image

@johnsonj @bradfitz : Obrigado por colocar isso no construtor.

@alexbrainman @bradfitz @ianlancetaylor : Então, quanto à estratégia de teste para isso, não tenho certeza do que fazer. Podemos seguir o caminho de execução do teste dist para ambos os conjuntos de ferramentas na janela e realizar cada teste duas vezes, ou devemos apenas testar os testes cgo duas vezes (uma para gcc, uma vez para msvc)?

Então, no que diz respeito à estratégia de teste para isso, não tenho certeza exatamente do que fazer. Podemos seguir o caminho de execução do teste dist para ambos os conjuntos de ferramentas na janela e realizar cada teste duas vezes, ou devemos apenas testar os testes cgo duas vezes (uma para gcc, uma vez para msvc)?

@cchamplin Não tenho resposta para sua pergunta. Suspeito que Ian saiba a resposta.

Alex

Qual é o custo de executar todos os testes duas vezes em vez de apenas cgo?

@mxplusb , podemos apenas executar uma nova configuração de build para Windows e ela será executada em paralelo com o nosso 3. Uma nova configuração de builder é adequada. Nós os adicionamos regularmente.

Apenas me diga como torná-lo diferente: defina uma variável de ambiente diferente / nova e então algo acontecerá, eu presumo?

Provavelmente, são necessárias algumas coisas para fazer isso funcionar.

Precisamos executar dentro de um shell / ambiente onde o teste go que o teste dist executa será executado dentro de após o vsvars.bat apropriado ter sido executado / chamado

Ou podemos fazer com que dist execute os vsvars apropriados e extraia as variáveis ​​de ambiente de que precisa e, em seguida, defina / passe-as para o teste.

Provavelmente também iremos querer alguma variável de ambiente para dizer ao dist ou make.bat que queremos executar os testes com -compiler msvc set.

Precisamos executar dentro de um shell / ambiente onde o teste go que o teste dist executa será executado dentro de após o vsvars.bat apropriado ter sido executado / chamado

Ou podemos fazer com que dist execute os vsvars apropriados e extraia as variáveis ​​de ambiente de que precisa e, em seguida, defina / passe-as para o teste.

Eu preferiria que não executássemos arquivos em lote de dist.exe ou go.exe. É problemático lidar com arquivos em lote.

Provavelmente também iremos querer alguma variável de ambiente para dizer ao dist ou make.bat que queremos executar os testes com -compiler msvc set.

Eu esperava que Ian soubesse qual é a melhor abordagem aqui. Pelo que eu sei, também oferecemos suporte a diferentes compiladores C no Unix (gcc ou clang). Certamente, nosso processo de construção nos permite testar diferentes compiladores C.

Alex

Não percebi antes que você planeja usar go build -compiler msvc . Isso não faz sentido. A opção go build -compiler leva o nome de um compilador Go (atualmente gc ou gccgo). Não leva o nome de um compilador C. O compilador C é passado na variável de ambiente CC . O compilador C padrão é definido definindo a variável de ambiente CC_FOR_TARGET ao executar make.bat, conforme documentado nos comentários em make.bat.

Eu esperaria ter um construtor para o qual planejamos definir a variável de ambiente CC_FOR_TARGET msvc antes de executar all.bat. Não vejo por que teríamos que fazer outra coisa.

O compilador C é passado na variável de ambiente CC. O compilador C padrão é definido pela configuração da variável de ambiente CC_FOR_TARGET ao executar make.bat, conforme documentado nos comentários em make.bat.

Obrigado Ian por explicar.

@cchamplin Espero que você possa ajustar suas alterações para caber no modelo existente. Deixe-nos saber, se você tiver qualquer problema. Obrigada.

Eu esperaria ter um construtor para o qual planejamos definir a variável de ambiente CC_FOR_TARGET para msvc antes de executar all.bat.

Temos 3 construtores de janelas amd64 em https://build.golang.org. Devemos substituir um por um MSVC? Queremos o construtor 386 MSVC?

Alex

@ianlancetaylor @alexbrainman Compreendido sobre o sinalizador -compiler. Não acho que haja uma maneira fácil de fazer apenas definir CC="msvc" (ou realmente CC="cl.exe" ) para funcionar. O CC ainda precisa apontar para um local GCC para que as compilações MSVC funcionem. O conjunto de ferramentas do compilador msvc não tem as ferramentas disponíveis para permitir que o CGO execute a introspecção necessária (pesquisa de definição, resolução de tipo), então o GCC ainda é necessário em compilações MSVC, o GCC apenas não é usado na fase real de compilação / vinculação.

Adicionar um novo sinalizador para construir et all seria aceitável (conjunto de ferramentas ou algo assim)? Eu já tive que adicionar um sinalizador de conjunto de ferramentas ao cgo, eu acredito.

Além disso, definir CC_FOR_TARGET antes de all.bat parece que pode ter consequências negativas porque afetaria o compilador usado na inicialização. Não acredito que o MSVC possa ser usado durante o processo de bootstrap (não estou 100% nisso, na verdade não tentei, mas duvido que funcione)

Entendo, para MSVC precisamos ter GCC e MSVC? Onde o GCC é usado apenas pela ferramenta cgo? Isso parece um tanto infeliz, pois significa que estaríamos absolutamente contando com o GCC e o MSVC implementando exatamente a mesma ABI, mas acho que é bastante provável.

Acho que podemos adicionar outra variável de ambiente CC_FOR_CGO , que pode ser definida como GCC.

O CC_FOR_TARGET usado por make.bat será usado para construir o runtime / cgo. Não está claro para mim como o cgo poderia funcionar se o runtime / cgo não for construído pelo compilador C que você está usando.

Talvez devêssemos começar fazendo as coisas funcionarem quando make.bat é invocado definindo CC_FOR_TARGET para cl e CGO_ENABLED para 0 .

Obrigado @ianlancetaylor :

Entendo, para MSVC precisamos ter GCC e MSVC? Onde o GCC é usado apenas pela ferramenta cgo? Isso parece um tanto infeliz, pois significa que estaríamos absolutamente contando com o GCC e o MSVC implementando exatamente a mesma ABI, mas acho que é bastante provável.

Concordo que é lamentável e ficaria feliz em saber de alguma alternativa, ainda não encontrei uma. Certamente há risco de construir desta forma (por exemplo, o código cgo que está sendo construído tem diferentes tipos de defs ou define, dependendo de qual compilador ele pensa que está sendo construído). Portanto, as compilações podem nem sempre ser bem-sucedidas ou funcionar corretamente sem alguns ajustes (há um mecanismo para lidar com isso na minha implementação, mas é um processo um pouco manual). Infelizmente, acho que esse é um risco que as pessoas terão de correr se quiserem usar o conjunto de ferramentas MSVC e tudo o que podemos fazer é documentá-lo por enquanto.

Em uma nota semelhante, ainda não há um caminho real a seguir para fornecer suporte a complex64 e complex128 em programas cgo desenvolvidos por MSVC simplesmente porque o compilador MSVC não é compatível com c99.

Acho que podemos adicionar outra variável de ambiente CC_FOR_CGO , que pode ser definida como GCC.

Portanto, a implementação que tenho atualmente é se go build for instruído a construir com MSVC, ele irá, por padrão, procurar cl.exe no caminho, mas isso pode ser substituído pela variável de ambiente MSCC. CGO continuará a usar a variável de ambiente CC voltando para gcc / tudo o que está sentado no zdefaultcc.go gerado

O CC_FOR_TARGET usado por make.bat será usado para construir o runtime / cgo. Não está claro para mim como o cgo poderia funcionar se o runtime / cgo não for construído pelo compilador C que você está usando.

Na implementação atual, o cgo funcionará alegremente com binários msvc, mesmo que todo o conjunto de ferramentas go tenha sido compilado pelo gcc. por exemplo, o código MSVC é adicionado a go / src. all.bat é executado construindo o ambiente go usando gcc. Depois disso, go / bin / go.exe pode ser usado para compilar com o conjunto de ferramentas msvc (supondo que os sinalizadores sejam fornecidos). Posso estar entendendo mal o que você está dizendo aqui.

A complexidade em torno disso, porque dizer que queremos construir com msvc é mais complicado do que apenas trocar o compilador para cl. O conjunto de ferramentas MSVC é muito diferente do conjunto de ferramentas gcc. No MSVC, um ambiente precisa ser configurado executando dentro de um vcvars.bat (ou fazendo o que v8 faz, por exemplo, que é executar vcvars.bat e extrair todas as informações de que precisa das variáveis ​​de ambiente que ele configura e, em seguida, usar isso em sua construção processo). Depois que estamos em um ambiente MSVC, a principal diferença são as próprias ferramentas cl.exe é usado para compilar arquivos C e C ++, ml.exe e ml64.exe são usados ​​para montar arquivos e, finalmente, link.exe (ms) é usado para ligue tudo junto. Portanto, é mais do que apenas definir CC=cl.exe e passar os sinalizadores certos. Isso faz sentido / ajuda a esclarecer as coisas?

Para esclarecer mais sobre

O CC_FOR_TARGET usado por make.bat será usado para construir runtime / cgo. Não está claro para mim como o cgo poderia funcionar se o runtime / cgo não for construído pelo compilador C que você está usando.

go build está selecionando os arquivos apropriados do runtime / cgo durante o processo de construção (por exemplo, go build / go test / go run - não o processo de construção) quando o O conjunto de ferramentas msvc foi selecionado.

Estou aberto a sugestões de como isso deve funcionar, mas não deve exigir uma nova opção de linha de comando para a ferramenta go. Podemos escrever um programa Go puro que atue como o GCC no que diz respeito à ferramenta go, mas na verdade execute o MSVC?

Podemos escrever um programa Go puro que atue como o GCC no que diz respeito à ferramenta go, mas na verdade execute o MSVC?

Eu acredito que isso pode ser viável, deixe-me ver se consigo algo acontecendo nesse caminho.

Além disso, acho que preciso esclarecer se adicionar sinalizadores de linha de comando a outras ferramentas também será um problema. No momento, o patch abrangente para isso está criando vários novos sinalizadores de linha de comando em várias ferramentas

  • cmd / cgo

    • -toolchain [gcc, msvc] (o padrão é gcc) Conjunto de ferramentas para usar ao construir arquivos de saída cgo

  • cmd / link

    • -rlocbss (o padrão é falso) Realocar .bss para .data

    • -toolchain [gcc, msvc] (o padrão é gcc) Conjunto de ferramentas a ser usado para links externos

também criamos as seguintes opções de construção / variáveis ​​de ambiente cgo:

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

Depois de alguns minutos de reflexão, existem alguns obstáculos que podem ser difíceis de superar se apenas usarmos como proxy os comandos do compilador em um programa diferente todos juntos

  1. go build precisa saber o que é o conjunto de ferramentas externo para determinar quais arquivos runtime / cgo construir, caso contrário, ele acabaria apenas passando as versões gcc incompatíveis para nosso comando proxy. Podemos conseguir contornar isso dentro do próprio proxy, mas seria frágil e provavelmente quebraria se arquivos adicionais fossem adicionados ao runtime / cgo.
  2. cmd / cgo precisa saber que tipo de conjunto de ferramentas externo está sendo usado para escolher qual versão do código C de saída usar
  3. O programa de proxy precisaria de algum mecanismo para saber se deveria ou não executar gcc (como quando chamado por cmd / cgo) ou para executar cl.exe que poderia ser passado, mas isso significa que o chamador precisaria saber qual conjunto de ferramentas é ou teríamos cmd / cgo passando sinalizadores inexistentes para gcc.
  4. go build chama cmd / link que também precisa saber qual é o conjunto de ferramentas para que possa realizar a realocação de .bss para .data e para que possa passar sinalizadores específicos para o vinculador (podemos ser capazes de lidar com este último parte do próprio proxy)

A especificação de uma variável de ambiente para ter go build usada para determinar as compilações do msvc funcionaria? Embora eu ache que aumenta o nível para alguém que deseja apenas construir um programa com msvc, já que agora eles precisam definir várias variáveis ​​de ambiente, além de executar dentro de vsvars.bat (no mínimo CC e UNDECIDED_TURN_ON_MSVC_BUILD_VAR )

Outra alternativa seria fazer go build executar um comando falso noop no CC especificado e, em seguida, analisar o logotipo / cabeçalho para detectar se é msvc ou gcc e prosseguir com os ajustes apropriados do conjunto de ferramentas naquele ponto ... não tenho certeza de como isso é frágil ou de como funcionaria com conjuntos de ferramentas compatíveis com msvc, como o clang.

Descobri esse problema do Github recentemente, e esse trabalho é muito empolgante para mim. Estou esperando que isso chegue em algum lugar no futuro próximo.

Minha intenção é usar CGo no Windows como wrappers para algum código de terceiros que foi construído usando MSVC, que não posso simplesmente reconstruir de fontes usando mingw-w64 . Eu tenho alguns casos de teste relativamente sérios para executá-lo, então posso validá-lo muito bem.

De qualquer forma, obrigado a @cchamplin e a quem mais está trabalhando nisso, e por favor me avise assim mesmo que posso ajudar.

@cchamplin Eu sei o suficiente para ser perigoso sobre os conjuntos de ferramentas do compilador no Windows e cgo que talvez eu possa ajudar. Você seria capaz de me atualizar sobre um pouco do que está trabalhando? Vou ver o que posso fazer para ajudar. Eu conheço o caso de uso @deadprogram , então tenho uma boa base de teste avançada quando estivermos prontos para testar.

Ei @mxplusb , o patch está mais ou menos pronto para funcionar. Se eu conseguir encontrar um tempo, enviarei as alterações para gerrit hoje à noite ou amanhã, o que nos ajudará a obter tudo revisado, atualizado e aprovado.

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

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

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

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

Parece que eu digitei o problema em alguns dos commits. Vou deixar o processo de revisão começar e determinar a melhor maneira de corrigir.

Mudança https://golang.org/cl/133943 menciona este problema: cmd/cgo: Add support for CC_FOR_CGO environment variable

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

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

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

Mudança https://golang.org/cl/133945 menciona este problema: cmd/link: Add external toolchain support for MSVC

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

@cchamplin você pode descrever qual foi a decisão final? Como é o suporte MSVC? Quais sinalizadores de linha de comando serão adicionados? O que um usuário terá que fazer em seu ambiente além de baixar o MSVC? Obrigado

Além disso, como podemos tentar este patch? Não consegui encontrar seus commits no repo.

@rasky Ainda está

@blizzardplus Semelhante ao anterior, as coisas estão em um grande fluxo agora com a análise, então pode ser um pouco cedo para começar a experimentá-lo (no entanto, você decide). Todas as alterações relacionadas foram postadas de volta a este problema pelo gopherbot, você pode encontrá-las lá.

@cchamplin há suporte para compilação cruzada usando gcc ou clang ? Em caso afirmativo, eles são testados?

@cchamplin Não vejo nenhuma atividade nos CLs desde 11 de setembro. Há algum progresso nisso ou precisa de recursos adicionais?

@cchamplin para que isso funcione para c-archive, a seção ctors deve ser alterada para .CRT $ XCU (https://msdn.microsoft.com/en-us/library/bb918180.aspx) - Se isso não for feito, então o o tempo de execução do golang não será inicializado. Além disso, se você definir assim, também funcionará bem para o gcc - o gcc ainda pega essas funções, move-as para uma seção de texto e modifica main para chamá-las antes do principal real. O Visual Studio pode compreender arquivos .a archive e, como a interface dos arquivos pré-compilados / montados é C, não deve haver nenhum problema em apenas ter isso no archive. Há um aviso sobre 2 seções de texto, mas casos simples parecem funcionar bem (precisa de mais testes para confirmação, não há problemas).

Além disso, para que isso funcione em c-shared, as funções a serem exportadas devem ser decoradas com __declspec (dllexport), mas não consigo encontrar onde ocorre essa expansão de // exportação.

@blizzardplus Existe um patch de acompanhamento para oferecer suporte ao clang-MSVC. Não tenho certeza do que você quer dizer com compilação cruzada neste caso? Você não poderá usar o conjunto de ferramentas MSVC em sistemas que não sejam Windows. Outras funcionalidades de compilação cruzada não devem ser alteradas.

@kshelton Infelizmente esta é uma época do ano muito ocupada para mim, pois tenho outros projetos em andamento e conferências em que estou apresentando. Posso não conseguir voltar a obter a refatoração necessária no patch até dezembro.

@kshelton Obrigado. Não verifiquei duas vezes o patch, presumo que o desenvolvi supondo que c-archive não funcionaria no MSVC ou o desativei especificamente. Eu segui o caminho de tentar decorar corretamente as exportações quando estava tentando fazer com que o plugin / compartilhado funcionasse no Windows. Acredito que haja outras questões, mas posso estar confundindo duas questões. Existem problemas reais com a forma como vai colocar seu código compartilhado no PLT / GOT para ELF vs Windows .edata, idata e EAT. Acredito que a maioria dos problemas que enfrentei foi em torno de realocações e de não conseguir fazê-los trabalhar. Se alguém tiver uma ideia disso, seria maravilhoso. Veja # 19282

@cchamplin tentei ver se consigo construir Go em cima do seu CL

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

Eu usei este arquivo em lote para definir meu ambiente

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

e recebo este erro quando executo 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>

O que estou perdendo aqui?

Obrigada.

Alex

@alexbrainman

O que estou perdendo aqui?

Você provavelmente precisa, no mínimo, definir CC_FOR_CGO = gcc. Eu também nunca tentei pessoalmente construir Go com MSVC. Não tenho certeza se isso funcionaria / deveria ser apoiado.

-C

Você provavelmente precisa, no mínimo, definir CC_FOR_CGO = gcc.

Seu https://go-review.googlesource.com/c/go/+/133940 contém alguns testes. Como verifico se os testes foram aprovados? Quais são as etapas exatas?

Além disso, os construtores Go https://build.golang.org executam% GOROOT% \ src \ all.bat para verificar todos os testes (incluindo aqueles listados em https://go-review.googlesource.com/c/go/+/ 133940) passar. Como você propõe que modifiquemos o código Go para fazer% GOROOT% \ src \ all.bat executar seus testes ajustados em https://go-review.googlesource.com/c/go/+/133940. Talvez all.bat possa testar as versões gcc e msvc dos testes. Talvez possamos usar alguma variável de ambiente que diga a all.bat qual versão dos testes executar - e então poderíamos ter dois construtores diferentes executando versões diferentes dos testes. Você pensou sobre tudo isso?

Eu também nunca tentei pessoalmente construir Go com MSVC. Não tenho certeza se isso funcionaria / deveria ser apoiado.

Você pode executar all.bat até a conclusão bem-sucedida sem o gcc instalado. A versão atual do Go precisa apenas de outra versão do Go (pelo menos go1.4) para ser compilada. Apenas o Cgo precisa do compilador C, fiquei com a impressão de que suas alterações implementam a versão do Cgo que é construída pela MSVC. Mas, talvez, eu esteja enganado. Por favor corrija-me se eu estiver errado.

Obrigada.

Alex

@alexbrainman

Seu https://go-review.googlesource.com/c/go/+/133940 contém alguns testes. Como verifico se os testes foram aprovados? Quais são as etapas exatas?

Talvez all.bat possa testar as versões gcc e msvc dos testes. Talvez possamos usar alguma variável de ambiente que diga a all.bat qual versão dos testes executar - e então poderíamos ter dois construtores diferentes executando versões diferentes dos testes. Você pensou sobre tudo isso?

Sim, esse mecanismo exato é usado em https://go-review.googlesource.com/c/go/+/133946/. Como todas as chamadas para run.bat no Windows, o mecanismo para chamar os testes cgo foi colocado lá. Portanto, você ou o construtor deve começar com uma configuração normal CC = gcc. Em seguida, você configuraria GOTESTMSVC = 1 e GOVSVARSPATH = algum caminho vsvars.bat. Depois disso, a compilação com all.bat deve executar os testes gcc e msvc cgo.

Você pode executar all.bat até a conclusão bem-sucedida sem o gcc instalado. A versão atual do Go precisa apenas de outra versão do Go (pelo menos go1.4) para ser compilada. Apenas o Cgo precisa do compilador C, fiquei com a impressão de que suas alterações implementam a versão do Cgo que é construída pela MSVC. Mas, talvez, eu esteja enganado. Por favor corrija-me se eu estiver errado.

Você está certo. O próprio Go deve construir bem. Pode haver problemas ao chegar ao teste, uma vez que run.bat foi modificado para definir algumas variáveis ​​de ambiente quando GOTESTMSVC = 1. Provavelmente poderíamos tentar detectar se go está apenas sendo construído com msvc e, em seguida, definir as variáveis ​​de ambiente dist apropriadas para que os testes não falhem.

Em seguida, você configuraria GOTESTMSVC = 1 e GOVSVARSPATH = algum caminho vsvars.bat. Depois disso, a compilação com all.bat deve executar os testes gcc e msvc cgo.

Eu tentei isso.

eu usei

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

Eu executo este arquivo em lote primeiro:

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

e, em seguida, execute all.bat . all.bat falha com

--- 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

Além disso, definir GOTESTMSVC e GOVSVARSPATH pode funcionar para pessoas executando all.bat. Mas o que outros usuários de sua mudança farão quando precisarem usar o MSVC para Cgo? Qual é o seu plano para isso?

Alex

@alexbrainman
Não tenho certeza do que está acontecendo. Esse teste está falhando para mim no mestre

> 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

Em help.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/internal/help/help.go#L37
ele itera por meio de base.Go.Commands. Que é inicializado em main.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/main.go#L43
mas não tenho certeza de como essa função init seria chamada em um executável de teste, então não tenho ideia de como o master está passando nos testes agora, pois acho que isso deveria estar falhando em todos os níveis.


Além disso, definir GOTESTMSVC e GOVSVARSPATH pode funcionar para pessoas executando all.bat. Mas o que outros usuários de sua mudança farão quando precisarem usar o MSVC para Cgo? Qual é o seu plano para isso?

Então, em uma situação onde você deseja apenas construir algum código Cgo com MSVC

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

deve ser tudo que você precisa, eu acho

Não tenho certeza de como essa função init seria chamada em um executável de teste, então não tenho ideia de como o master está passando nos testes agora, pois acho que isso deveria estar falhando em todos os níveis.

Ao usar go test com um arquivo em cmd / go, a ferramenta go construirá o pacote cmd / go e então construirá os testes, gerará o driver de teste, construirá e vinculará tudo em um novo pacote principal. Isso acontece mesmo que cmd / go seja um pacote principal. Ou seja, o pacote principal em cmd / go / *. Go será tratado como um pacote não principal para fins de teste. Isso permite que os testes chamem funções definidas no pacote principal, se apropriado.

Desculpe, estou lento para responder. Mas não tive tempo livre para examinar isso novamente.

Não tenho certeza do que está acontecendo. Esse teste está falhando para mim no mestre

Eu não usei master. Usei seu commit e56d52f66b95b87001867a2487a11bd961f40d4d. Você não executou all.bat naquele commit antes de enviá-lo para revisão? All.bat teve sucesso? Você pode tentar rodar all.bat naquele commit novamente para ver se tem algo a ver com a configuração do meu sistema. Obrigada.

Então, em uma situação onde você deseja apenas construir algum código Cgo com MSVC

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

deve ser tudo que você precisa, eu acho

2 variáveis ​​de ambiente são, provavelmente, muito complicadas para o usuário médio. E CC_FOR_CGO=gcc parece estranho para mim - por que usamos gcc para construir código com MSVC?

Alex

@alexbrainman

Eu não usei master. Usei seu commit e56d52f66b95b87001867a2487a11bd961f40d4d. Você não executou all.bat naquele commit antes de enviá-lo para revisão? All.bat teve sucesso? Você pode tentar rodar all.bat naquele commit novamente para ver se tem algo a ver com a configuração do meu sistema. Obrigada.

Acho que era algo relacionado à configuração do meu sistema que estava me dando resultados estranhos ao executar os testes. Acho que resolvi o problema e enviei algumas atualizações para o conjunto de alterações.

2 variáveis ​​de ambiente são, provavelmente, muito complicadas para o usuário médio. E CC_FOR_CGO = gcc parece estranho para mim - por que usamos gcc para construir código com MSVC?

Na verdade, provavelmente deve ser CC_FOR_CGO = gcc.exe, erro meu. Mas para responder sua pergunta; de gerrit:

PS1, Linha 1324:
cgo ainda precisa do gcc disponível para análise de tipo. Se CC for definido como um compilador MSVC, cgo precisa de um meio para chamar o GCC, que é fornecido por CC_FOR_CGO. Infelizmente, o conjunto de ferramentas MSVC não tem mecanismo para fornecer o mesmo tipo de informação que está sendo coletado do gcc. Teoricamente, uma ferramenta específica de go poderia ser criada para coletar as informações de tipo que são usadas pelo cgo, mas isso pode estar fora do escopo e possivelmente um esforço considerável (eu pessoalmente nunca escrevi nada para realizar análise de tipo estático de código C / C ++).

Também pareço ter quebrado algo com a limpeza do cache entre as execuções para GCC vs MSVC, não tenho certeza por que alguns testes ainda estão agindo como se estivessem em cache.

Acho que resolvi o problema e enviei algumas atualizações para o conjunto de alterações.

Esta configuração https://github.com/golang/go/issues/20982#issuecomment -447618566 em

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 leva mais longe, mas ainda falha com

##### 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>

Na verdade, provavelmente deve ser CC_FOR_CGO = gcc.exe, erro meu.

Não estou preocupado com o .exe no gcc.exe. Meus problemas são

  • você precisa das ferramentas gcc e MSVC para usar o MSVC (seria difícil explicar para nossos usuários), mas eu entendo que nada pode ser feito a respeito;

  • Eu precisava de ambas as variáveis ​​de ambiente CC_FOR_CGO = gcc e CC = cl.exe definidas - talvez possamos simplesmente assumir que CC_FOR_CGO está sempre definido como gcc?

Mas para responder sua pergunta; de gerrit:

Obrigado por explicar.

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

Não tenho certeza de como esse aviso estaria ocorrendo, a menos que de alguma forma você tenha uma cópia diferente / antiga de msvc_libinit_windows.c. Você pode confirmar que tem esta linha nele:

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

C4710 deve ser suprimido para o stdio include. Vejo que sua versão do MSVC é um pouco diferente da minha, o que também pode ser o culpado. Não sei por que eles ignorariam ativamente essa supressão em uma versão diferente.

Você também pode tentar fazer uma mudança para incluir a supressão globalmente, não importa o que

// 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") 

Eu precisava de ambas as variáveis ​​de ambiente CC_FOR_CGO = gcc e CC = cl.exe definidas - talvez possamos simplesmente assumir que CC_FOR_CGO está sempre definido como gcc?

Acho que verificar gco se gcc existe se CC_FOR_CGO não está definido seria bom. CC_FOR_CGO é mais para pessoas como eu, que não têm o gcc em seu caminho. Meu CC_FOR_CGO tem esta aparência CC_FOR_CGO = I: \ Development \ tmd-gcc \ bingcc.exe. Se não quisermos oferecer suporte ao caso de uso do GCC por não estar no caminho para as compilações do MSVC, me avise e eu poderei me livrar da variável de ambiente todos juntos.

Eu tentei novamente esta versão

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

e recebo o mesmo erro

##### 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>

Você pode confirmar que tem esta linha nele:

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

Este é o começo do meu arquivo 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>
...

Você também pode tentar fazer uma mudança para incluir a supressão globalmente, não importa o que

// 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") 

Eu fiz esta mudança:

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>

mas eu vejo o mesmo erro

##### 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

Eu estava tentando reproduzir isso ontem à noite e não consegui. Gostaria de saber se você está passando por isso: https://developercommunity.visualstudio.com/content/problem/35734/c-cannot-disable-specific-warnings-with-pragmas-wh.html

É possível atualizar para o SDK e as ferramentas de construção mais recentes? Estou no SDK 10.0.17763.0. e a versão 15.9.28307.222 das ferramentas de compilação / devenv

Estou tentando construir uma DLL do Windows com MSVC, mas parece que Go tenta desativar algum aviso com número maior que 65535 (ou não um número), o que faz com que o MSVC pare.

image

Não. Werror é uma opção do GCC, para tratar cada aviso como um erro.

Para MSVC, você deve usar WX .

@pravic bom ponto, como eu faria isso? Não estou configurando, tudo que estou fazendo é:

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

@galich Infelizmente, não posso ajudar porque não sigo a integração do MSVC.

Por exemplo, onde estão os patches relacionados a este tópico? No mestre ou em outro lugar?

@pravic você pode encontrar as mudanças aqui: https://go-review.googlesource.com/c/go/+/133946/5

@mxplusb obrigado pelo link, parece que meu problema específico com / Werror foi resolvido lá.
Você sabe quando isso chegará ao beta / noturno / estável?

É possível atualizar para o SDK e as ferramentas de construção mais recentes? Estou no SDK 10.0.17763.0. e a versão 15.9.28307.222 das ferramentas de compilação / devenv

@cchamplin finalmente consegui atualizar meu MSVC. eu tenho agora

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>

Eu tentei novamente esta versão

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

e all.bat é concluído com sucesso. Mas eu recebo esses avisos.

##### ../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>

E também notei que você executa todos os testes duas vezes.

...
##### 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
...

Porque?

Alex

@alexbrainman Os avisos podem provavelmente ser suprimidos para esses testes, especialmente neste caso os avisos espectrais.

Para os testes executados duas vezes, acredito que foi feito dessa forma para o construtor, execute os testes uma vez com a compilação gcc e depois execute-os novamente com MSVC (quando habilitado) para garantir que a compilação com os dois conjuntos de ferramentas funcione. Não tenho certeza do que é desejado aqui, então posso alterá-lo para que quando all.bat for chamado com o MSVC habilitado, nós apenas executemos os testes com o MSVC, me avise. Nesse caso, presumo que construtores adicionais precisem ser incluídos apenas para MSVC, ao contrário de alguns construtores que também constroem com MSVC?

Concordou que no Windows será necessário executar um construtor usando a cadeia de ferramentas MinGW-W64 e outro com a cadeia de ferramentas MSVC para testar os dois cenários.

Acredito que tenha sido feito dessa forma para o construtor, execute os testes uma vez com a compilação gcc e, em seguida, execute-os novamente com MSVC (quando habilitado) para garantir que a compilação com os dois conjuntos de ferramentas funcione.

Concordo que esse deve ser o comportamento preferido, portanto, há uma garantia de que ele não interromperá as cargas de trabalho existentes se os dois conjuntos de ferramentas estiverem presentes.

Os avisos provavelmente podem ser suprimidos para esses testes, especialmente neste caso os avisos de espectro.

O comando Go não exibe avisos, portanto, os avisos não devem ser exibidos.

Também notei que o comando go env não exibe a variável CC_FOR_CGO. Se CC_FOR_CGO afeta o funcionamento do go build, CC_FOR_CGO deve ser exibido junto com outros. Nós realmente precisamos da variável CC_FOR_CGO? O que mais, mas CC_FOR_CGO = gcc pode ser?

Para os testes executados duas vezes, acredito que foi feito dessa forma para o construtor, execute os testes uma vez com a compilação gcc e depois execute-os novamente com MSVC (quando habilitado) para garantir que a compilação com os dois conjuntos de ferramentas funcione.

Muitos testes não usam gcc. É uma perda de tempo das pessoas / computador quando os testes de pacote são executados duas vezes sem motivo. Como você pode ver em https://github.com/golang/go/issues/20982#issuecomment -480569880 archive/zip testes do pacote foram executados duas vezes - não vejo necessidade de uma segunda execução.

Não tenho certeza de como fazer isso, mas talvez você deva substituir sua chamada de go tool dist test em run.bat para fazer apenas uma seleção de testes que são necessários para testar a compilação do MSVC. Veja, por exemplo, go tool dist test -h sobre como você pode selecionar apenas alguns testes específicos. @bradfitz talvez possamos criar algum sinalizador ou variável de ambiente que diga ao comando dist para executar testes específicos do MSVC.

Mas, em geral, seu https://go-review.googlesource.com/c/go/+/133946/5 está criando um executável para mim. Por exemplo, posso construir executáveis ​​com 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>

e então posso construir um executável com 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>

Portanto, a construção com MSVC exigirá que os usuários executem o arquivo em lote MS para definir todas as variáveis ​​de ambiente (consulte GOVSVARSPATH em minha saída) - e isso, presumo, é padrão e não tem nada a ver com Go. E set CC=cl . Simples o suficiente.

O único problema que vejo com essa abordagem é que os usuários do MSVC ainda precisarão ter o gcc instalado. gcc é usado por cmd / cgo para descobrir todas as interfaces C - esta parte não é implementada usando MSVC. Parece incomum para pessoas que não sabem como o cmd / cgo funciona, mas é o que é.

@ianlancetaylor e @bradfitz tudo isso parece razoável para levar isso adiante? Devemos tentar disponibilizá-lo em go1.13?

Os construtores que já possuem o MSVC instalado podem testar todos os novos códigos. Outros construtores simplesmente pularão os testes.

Alex

gcc é usado por cmd / cgo para descobrir todas as interfaces C - esta parte não é implementada usando MSVC.

Como isso pode ser superado? Idealmente, seria ótimo se não houvesse nenhum requisito para o gcc, apenas MSVC.

Como isso pode ser superado?

Partes de cmd / cgo que usam gcc precisam ser reescritas para usar MSVC. Se for possível.

Alex

Eu queria saber se esse recurso está mais perto de entrar em produção? Vejo que foi marcado para 1.13 e acabou de sair. Estou tentando construir extensões Python usando uma compilação Go c-archive que está vinculada ao código de extensão, mas Python requer MSVC.

Não sei qual é a situação desse problema. Foi chutado de lançamento para lançamento, então vou movê-lo para não planejado. Se entrar em 1.14, ótimo.

Mesmo com o requisito de duplo compilador, adoraria ver a implementação atual chegar à próxima versão. Ele pelo menos torna possível compilar executáveis ​​/ bibliotecas usando MSVC, que é melhor do que nada.

Mesmo com o requisito de duplo compilador, adoraria ver a implementação atual chegar à próxima versão.

Acho que essa seria uma boa implementação "beta". Isso permitiria que os bugs fossem eliminados e a implementação começasse a amadurecer. O que mais resta a ser feito antes de passar por uma revisão séria?

Portanto, da minha perspectiva e do que me lembro da última vez que olhei para isso (cerca de 6 meses atrás), havia cerca de uma dúzia de itens de limpeza que precisavam ser concluídos para o processo de revisão de código. Também pode ser necessário trabalho adicional para desduplicar alguns testes que foram basicamente copiados com pequenas modificações para funcionar com um conjunto de ferramentas diferente. Também é necessário revisar e desligar alguns avisos do msvc.

As principais questões pendentes incluem:

Não podemos fazer análise de tipo sem gcc, não existe uma solução simples ou imediata para isso.

Finalizando a configuração e como tudo funcionará para os construtores.

Acredito que tenha havido algumas mudanças bastante significativas no compilador e vinculador nos últimos 6 meses que podem impactar severamente o trabalho atual feito para isso, mas não fui capaz de confirmar isso. Devido à complexidade e à alta curva de aprendizado em torno da navegação do compilador / vinculador / cadeia de ferramentas do Go, pode levar um tempo considerável para que eu me acelere o suficiente para descobrir o impacto, se houver, das alterações neste corpo de trabalho.

Não há suporte para os tipos numéricos complexos. MSCVs C lib é simplesmente incompatível. Acredito que haja uma maneira de corrigir isso com C ++, mas não tenho certeza, talvez alguém da MS familiarizado com as cadeias de ferramentas do MSVC possa intervir.

Infelizmente, a vida e outros projetos têm ficado muito no caminho de eu dedicar mais tempo a isso, mas vou tentar gastar algum tempo nisso nas próximas semanas.

@manbearian, este problema é sobre como adicionar suporte MSVC ao golang. Quem na equipe do MSVC deveria ser consultado em caso de dúvidas sobre o MSVC?

@ kesmit13 e @mxplusb

Esse

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

é o código mais recente do @cchamplin que funciona.

Minha preocupação atual com o código é que não está claro como usá-lo. Que comando você executa? Como meu ambiente precisa ser configurado?

Acho que a próxima etapa é alguém tentar usar esse código e ver se pode realmente usá-lo. Se funcionar, as etapas precisam ser documentadas para que outras pessoas também possam usar o código. Talvez seja muito complicado ou não funcione. Então, precisamos ajustar o código de acordo.

Quando estivermos satisfeitos com o estado atual do código, devemos rebaseá-lo no master. A alteração ajustou muitos arquivos diferentes, então não será fácil realocar. Talvez pudéssemos ajustar a alteração para fazer menos alterações, por isso é mais fácil de rebase.

Alex

@mxplusb @ kesmit13 A implementação atual foi refeita em relação ao mestre e pode ser encontrada aqui: https://go-review.googlesource.com/c/go/+/133946/6

@alexbrainman

Minha preocupação atual com o código é que não está claro como usá-lo. Que comando você executa? Como meu ambiente precisa ser configurado?

Eu concordo que a documentação precisa ser adicionada sobre como usar isso. Não tenho certeza de onde colocá-lo, no entanto, deixe-me saber se você tem alguma ideia. Idk se ele deve ir na documentação cmd / go para compilar / executar via MSVC, ou se ele deve estar na documentação CGO, ou talvez em algum outro lugar inteiramente?

Muitos testes não usam gcc. É uma perda de tempo das pessoas / computador quando os testes de pacote são executados duas vezes sem motivo. Como você pode ver em # 20982 (comentário), os testes do pacote archive / zip foram executados duas vezes - não vejo necessidade de uma segunda execução.

Não tenho certeza de como fazer isso, mas talvez você deva substituir sua chamada de go tool dist test em run.bat para fazer apenas uma seleção de testes que são necessários para testar a compilação do MSVC. Veja, por exemplo, go tool dist test -h para saber como você pode selecionar apenas alguns testes específicos. @bradfitz talvez possamos criar algum sinalizador ou variável de ambiente que diga ao comando dist para executar testes específicos do MSVC.

A mudança já inclui uma variável de ambiente adicionada a dist para informá-lo que estamos fazendo coisas MSVC "GO_TEST_TESTINGMSVC", eu acredito. O que não tenho certeza é como vamos filtrar os testes a serem executados para coisas que apenas o MSVC poderia afetar se não executarmos todos os testes duas vezes. Potencialmente limitando aos testes relacionados ao CGO, mas acredito que haja testes CGO por todo o lugar e não sei se o dist tem um mecanismo para filtrá-los?

Não tenho certeza de onde colocá-lo, no entanto, deixe-me saber se você tem alguma ideia.

Acho que antes de atualizar qualquer documentação, você deve apenas descrever como construir o código Cgo com MSVC aqui. Para @mxplusb e @ kesmit13 para que eles possam tentar suas alterações.

Por exemplo, para usar o gcc para construir o código Cgo, eu

  1. ajuste meu% PATH% para incluir gcc.exe
  2. build Vá primeiro executando make.bat do diretório %GOROOT%\src
  3. use os comandos go build e go install padrão

Como faço o mesmo com o MSVC?

O que não tenho certeza é como vamos filtrar os testes a serem executados para coisas que apenas o MSVC poderia afetar se não executarmos todos os testes duas vezes. Potencialmente limitando aos testes relacionados ao CGO, mas acredito que haja testes CGO por todo o lugar e não sei se o dist tem um mecanismo para filtrá-los?

Eu começaria com o diretório% GOROOT% \ misc \ cgo. Qualquer fonte que você possa construir lá, você deve construir. Qualquer coisa acima disso depende de você.

Alex

@cchamplin desculpe pelos atrasos nisto, farei o meu melhor para testá-lo esta semana e informá-lo sobre como está indo.

Olá, pessoal, desculpem pelo atraso na festa ... posso tentar responder a perguntas sobre a funcionalidade do MSVC ou encaminhá-los para quem puder. Li a conversa, mas, infelizmente, não estou familiarizado o suficiente com go para entender a funcionalidade do GCC necessária que pode ou não estar ausente do MSVC.

Oi pessoal,
Este recurso foi lançado no Go 1.14?
Se liberado, compartilhe todos os documentos disponíveis para fazer uso dele.
Se ainda não foi lançado, há alguma ideia de quando será lançado?
Esperando ansiosamente pelo suporte MSVC.
Desde já, obrigado :)

Olá, ninguém respondeu ao meu pedido de mais informações, por isso não tenho a certeza do que é necessário. Alguém pode me preencher por favor?

Infelizmente, não sei se alguém está trabalhando ativamente nessa questão.

Olá, nunca ninguém respondeu ao meu pedido de mais informações, ...

Ola @manbearian

Que pedido é esse? Que informações você precisa?

Alex

Fui marcado anteriormente neste tópico para obter informações, mas não sei o que as pessoas estão procurando e não consegui ajudar. Se nenhuma ajuda for necessária, isso é ótimo. Apenas por favor me avise.

Apenas por favor me avise.

@manbearian

Obrigado pela sua oferta. Não sei quem te marcou. Se eles ainda precisarem de ajuda, eles marcarão você novamente.

Alex

Se ainda não foi lançado, há alguma ideia de quando será lançado?
Esperando ansiosamente pelo suporte MSVC.

@ dhinesherode91

O código está lá e completo; Acredito que a única coisa que realmente impede isso são as pessoas testando as alterações e fornecendo feedback para que possam ser devidamente revisadas e aprovadas. No entanto, estou hesitante em realocar as alterações sobre o mestre atual. Eu fiz isso de 5 a 6 vezes e é extremamente demorado, então não recebo nenhum teste / feedback. A menos que outras partes estejam dispostas a participar do teste, o problema pode estar morto.

A menos que outras partes estejam dispostas a participar do teste, o problema pode estar morto.

@cchamplin conte comigo para testar / depurar suas alterações. Não tenho experiência com o conjunto de ferramentas to go, mas revisei seus commits e eles parecem estar muito bem estruturados e documentados.

@cchamplin Ótimo saber que a parte de implementação foi concluída.
Estou interessado em envolver-me na parte de teste, mas sou um iniciante em GoLang e também um bom aprendiz em Windows Apis (comecei algumas semanas antes). Eu estava planejando trabalhar com a API do Windows no MS C ++, pois parece que muitos recursos oficiais estão disponíveis para isso. Mas então comecei a procurar uma linguagem (para a programação do meu sistema) onde pudesse usá-la para a programação do meu sistema multi-plataforma e estou impressionado com GoLang. Sempre pronto para a contribuição do meu final e com muita necessidade de orientação.

@cchamplin se você rebase, tentarei construir em cima dele. Eu adoraria descartar o requisito mingw64 de alguns dos meus projetos no trabalho. Minhas ferramentas de construção estão todas configuradas para MSVC, então eu não teria que fazer nada além de usar seu patch.

@cchamplin também, olhei seus CLs e não vi nenhum para a ferramenta cgo, então comecei no meu próprio patch. Existe algum trabalho anterior?

@ericlagergren

@cchamplin também, olhei seus CLs e não vi nenhum para a ferramenta cgo, então comecei no meu próprio patch. Existe algum trabalho anterior?

Não tenho certeza se entendi, em https://go-review.googlesource.com/c/go/+/133946/6 muitos dos commits relacionados tocam diretamente a parte cgo do Go de alguma forma.

@ccahoon ok, devo ter sentido falta deles. Se a ferramenta cgo não tivesse sido atualizada, eu me ofereceria para fazer isso.

@ericlagergren

Adoraria eliminar o requisito do mingw64 de alguns dos meus projetos no trabalho

Apenas para sua informação. o

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

a mudança ainda precisa do Mingw para funcionar. Você precisará das ferramentas Mingw e MSVC instaladas para usar a alteração @cchamplin .

Alex

@cchamplin , por que o Mingw ainda é necessário? O que seria necessário para remover essa dependência?

@alexbrainman eu isso seria fantástico. Mas também como @cglong disse, não sei por que isso também exigiria o mingw64.

@ericlagergren @cglong CGO precisa reunir e ter informações de tipo disponíveis sobre o código C com o qual está sendo compilado. O GCC tem um sinalizador que produzirá dados de tipo em um formato convenientemente analisável. O MSVC, tanto quanto eu sei, não tem a funcionalidade para fornecer as mesmas informações. Construir o conjunto de ferramentas em go não só exigiria código para lexar / analisar código C e C ++, mas também para entender e avaliar as diretivas do pré-processador. Seria um empreendimento bastante grande construir tal coisa em Go. Talvez já haja uma biblioteca disponível em algum lugar que possamos descobrir como adotar?

@cchamplin te peguei , foi o que imaginei. Eu conheço bibliotecas de terceiros, como libclang e cznic / cc. Mas, infelizmente, o libclang é gigantesco e o cznic / cc não foi testado no Windows ou no macOS. O PDB não fornece informações suficientes?

O CGO precisa reunir e ter informações de tipo disponíveis sobre o código C com o qual está sendo compilado. O GCC tem um sinalizador que produzirá dados de tipo em um formato convenientemente analisável. O MSVC, tanto quanto eu sei, não tem a funcionalidade para fornecer as mesmas informações.

Talvez @manbearian possa fornecer algumas dicas aqui?

Eu não diria que o GCC emite dados de tipo de saída em um formato especial. Ele emite dados de depuração DWARF destinados a depuradores e cgo lê esses dados usando o pacote debug / anão. O MSVC provavelmente também possui um formato de depuração. Se esse formato estiver documentado em qualquer lugar, poderíamos lê-lo usando cgo da mesma forma que fazemos com os dados DWARF.

@ianlancetaylor MSVC pode emitir arquivos PDB. Consulte https://github.com/Microsoft/microsoft-pdb

FWIW, ler a saída de depuração do MSVC é o que eu estava falando quando mencionei a ferramenta cgo em https://github.com/golang/go/issues/20982#issuecomment -648462003

Eu não diria que o GCC emite dados de tipo de saída em um formato especial. Ele emite dados de depuração DWARF destinados a depuradores e cgo lê esses dados usando o pacote debug / anão. O MSVC provavelmente também possui um formato de depuração. Se esse formato estiver documentado em qualquer lugar, poderíamos lê-lo usando cgo da mesma forma que fazemos com os dados DWARF.

@ericlagergren @ianlancetaylor
Portanto, precisamos dos dados DWARF, que são uma grande parte deles. No entanto, poderíamos teoricamente obter as mesmas informações dos dados do PDB.

No entanto, eu estava me referindo especificamente não apenas aos dados DWARF que o GCC produz, mas à saída de gcc -E -dM que gera todos os # define após o pré-processamento ter ocorrido. É possível que o PDB por si só forneça as mesmas informações ... o que duvido em saber se seríamos ou não capazes de coagir o MSVC a despejar informações de depuração / tipo de informações em qualquer capacidade, sem a necessidade de compilar de fato o código. No momento, o CGO está fazendo exatamente isso com o GCC.

Da memória, / EP / d1PP deve emitir algo semelhante a -E -dM.

Da memória, / EP / d1PP deve emitir algo semelhante a -E -dM.

Se sim, isso seria excelente, presumo que / d1PP é um sinalizador não documentado. Eu nunca vi isso antes. Isso apenas deixaria a obtenção de informações de tipo equivalente fora do tempo.

@cchamplin sim, não é documentado. Aparentemente, muitos sinalizadores / dXXX são. Usar sinalizadores não documentados é lamentável, mas (IMO) não parece ser um pecado tão ruim no Windows, pelo menos. Eu vi desenvolvedores de STL MSVC falando sobre isso em um tópico do reddit, mas também está em toda a Internet.

Alguém pode me dar um breve resumo do estado atual do suporte MSVC? Eu não entendo muito de toda essa coisa de compilador de baixo nível. É que eu tenho uma biblioteca go que quero usar do C # / UWP - e que já está funcionando com o go build e o buildmode c-shared. MAS: esse aplicativo nunca será aceito pela Windows Store, já que a DLL gerada de go perde alguns sinalizadores de compilador / vinculador que (presumo) só podem ser definidos pelo conjunto de ferramentas MSVC.

Então: como eu poderia testar isso aqui? Qualquer conselho é apreciado! Obrigado!

esse aplicativo nunca será aceito pela Windows Store, já que a DLL gerada de go perde alguns sinalizadores de compilador / vinculador que (presumo) só podem ser definidos pelo conjunto de ferramentas MSVC.

@TopperDEL a Windows Store informa quais sinalizadores de compilador estão faltando? Se o mingw-64 suportá-los, você sempre pode usar -extldflags com os sinalizadores corretos ao construir a dll.

@qmuntal Sim, eles fazem:
"Aplique as opções de vinculador necessárias - SAFESEH, DYNAMICBASE, NXCOMPAT e APPCONTAINER - ao vincular o aplicativo."

Eu ja tentei
go build -ldflags="-s -w '-extldflags=-Wl,--dynamicbase,--high-entropy-va'" -o storj_uplink.dll -buildmode c-shared

Mas isso não mudou nada em relação ao envio à loja. E pelo meu entendimento, pelo menos o SAFESEH é uma coisa específica do MSVC, certo?

"Aplique as opções de vinculador necessárias - SAFESEH, DYNAMICBASE, NXCOMPAT e APPCONTAINER - ao vincular o aplicativo."

Não conheço nenhuma maneira fácil de habilitar os sinalizadores SAFESEH ou APPCONTAINER no Mingw-w64, talvez este projeto https://github.com/status-im/mingw-windows10-uwp possa lhe dar algumas orientações.

Por outro lado, DYNAMICBASE e NXCOMPAT serão habilitados por padrão no go 1.16 (consulte # 41421), mas já podem ser usados ​​com -extldflags conforme mencionado, na verdade estou fazendo isso para alguns projetos.

Obrigado @qmuntal ! Portanto, pelo menos meus extldflags acima devem estar corretos?
Vou dar uma olhada no mingw para windows 10-uwp.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

stub42 picture stub42  ·  3Comentários

longzhizhi picture longzhizhi  ·  3Comentários

enoodle picture enoodle  ·  3Comentários

myitcv picture myitcv  ·  3Comentários

Miserlou picture Miserlou  ·  3Comentários