Go: cmd / link: поддержка объектных файлов msvc

Созданный на 11 июл. 2017  ·  222Комментарии  ·  Источник: golang/go

Я понимаю, что компоновщик go в настоящее время не может связывать объектные файлы msvc, а также понимаю, что эта проблема, вероятно, имеет низкий приоритет. Однако было бы неплохо поддержать это, потому что это несколько упростило бы рабочий процесс Windows. Этот вопрос в основном состоит в том, чтобы понять, сколько усилий это потребует и / или что потребуется.

Builders FeatureRequest NeedsInvestigation OS-Windows

Самый полезный комментарий

Привет, из нижней части этой ветки видно, что у вас разобрались с проблемами MSVC. Но если у вас возникнут какие-либо проблемы, я в команде MSVC. Не стесняйтесь пинговать меня на github или по электронной почте ([email protected])

Все 222 Комментарий

/ cc @alexbrainman

@xoviat, в чем проблема? Мне нужно воспроизвести это здесь. Итак, пожалуйста, предоставьте все шаги, которые мне нужно будет выполнить, чтобы воспроизвести это.

Спасибо

Алекс

PS: У меня не будет компьютера до конца июля. Тогда я посмотрю на это.

в чем проблема, которая у вас возникла?

Я еще не пробовал, но я хотел бы специально вызывать функции c в объектных файлах msvc, связывая их как .syso с компоновщиком go. Все, что я прочитал, указывает на то, что это невозможно, но я создам процедуру для воспроизведения конкретной возникающей ошибки.

в частности, вызывать функции c в объектных файлах msvc, связывая их как .syso с компоновщиком go

Вы пробовали встроить их в DLL и использовать их изнутри DLL?

Я создам процедуру для воспроизведения конкретной возникающей ошибки.

Пожалуйста, сделай. Спасибо.

Алекс

Вы пробовали встроить их в DLL и использовать их изнутри DLL?

На самом деле это был мой первоначальный план. Я использую swig, поэтому не очень удобно компилировать сгенерированный код c отдельно, а затем переписывать функции как экспорт DLL. Это несложно, но раздражает, когда рабочий процесс с gcc занимает всего лишь go generate; go build .

Хорошо, у меня процедура. Начните с этих файлов:

hello.go:

package main

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

func main() {
    C.hello()
}

Привет:

#include <stdio.h>

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

затем запустите эти команды (с msvc на пути):

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

Результат:
Warning: corrupt .drectve at end of def file

При запуске созданного файла:

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

На моем компьютере не установлена ​​команда cl. Как мне установить MSVC?

Спасибо.

Алекс

Вам нужны «утилиты сборки 2017 года» здесь . На самом деле Microsoft теперь позволяет любому использовать Visual Studio бесплатно, если это не для коммерческой разработки. Если это слишком сложно, я могу просто дать вам объектный файл, если хотите.

Если бы только С ++ не существовало, мне бы не пришлось об этом беспокоиться. Но это так, поэтому боль продолжается ...

Здесь вам понадобятся «инструменты сборки 2017».

Понятно. Спасибо.

Если это слишком сложно, я могу просто дать вам объектный файл, если хотите.

Да, пожалуйста, напишите где-нибудь hello.obj.

Подумал об этом еще немного. Фактически вы используете gcc для связывания объектного файла, скомпилированного с помощью компилятора msvc. Можете ли вы попробовать выполнить свое упражнение, но заменив шаг «go build» на gcc, связывающий hello.obj с программой на языке C? Возможно, это было сделано раньше. Я подозреваю, что если мы узнаем, как это сделать, мы могли бы сделать то же самое с Go.

Алекс

AFAIK lld https://github.com/llvm-mirror/lld поддерживает объектные файлы msvc.

Объектный файл находится здесь: https://github.com/xoviat/msvcgo/blob/master/hello.syso

lld https://github.com/llvm-mirror/lld поддерживает объектные файлы msvc

Go использует компоновщик gcc (не lld) в Windows.

Объектный файл находится здесь: https://github.com/xoviat/msvcgo/blob/master/hello.syso

Я попробую, когда вернусь домой в августе. Спасибо.

Алекс

Go использует компоновщик gcc (не lld) в Windows.

Я знаю. Но lld - лучшая документация с открытым исходным кодом для объектного формата msvc.

На самом деле я получаю ту же ошибку от ld, поэтому ошибка определенно исходит от ld.

На самом деле я получаю ту же ошибку от ld, поэтому ошибка определенно исходит от ld.

да. Нам нужно решить, как собрать программу на C, скомпилировав часть с помощью msvc и связав ее с gcc.

Алекс

Простите мое незнание, но что именно связывает gcc? Это связывает вывод компоновщика go?

Запуск objconv для объектных файлов для преобразования в elf:

objconv -felf hello.obj hello.syso

Теперь у нас есть эти ошибки:

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

Возможно, stdio не работает?

Простите мое незнание, но что именно связывает gcc? Это связывает вывод компоновщика go?

Для создания программы Go вы используете 2 программы:

  • компилятор преобразует ваши файлы .go (1 пакет за раз) в объектный файл, хранящийся в каталоге% GOPATH% / pkg;
  • компоновщик, который создает окончательный файл .exe из объектных файлов из каталога% GOPATH% / pkg.

Иногда (когда один из ваших пакетов использует Cgo) компоновщик Go вызывает внешний компоновщик, чтобы найти все биты, реализованные в C. Представьте, что вы вызываете printf из своего кода C. Скомпилированный код C printf должен быть частью исполняемого файла Go, но компоновщик Go не знает, где его взять. Поэтому компоновщик Go вызывает внешний компоновщик, чтобы включить этот код.

Current Go использует компилятор / компоновщик gcc для компиляции и компоновки кода C (мы используем mingw gcc). Если вы собираетесь компилировать свой код C с помощью другого компилятора (от Microsoft), вам придется использовать соответствующий компоновщик (от Microsoft), чтобы найти весь внешний код C, созданный компилятором.

Итак, я думаю, я ошибался, предлагая использовать компоновщик gcc. Для общего сценария вам придется использовать как компилятор Microsoft, так и компоновщик. Нам нужно будет выяснить, что требуется компоновщику Microsoft в качестве входных данных, и сопоставить это.

Вы можете обойтись без компоновщика MC, если ваш код C не имеет внешнего кода. Пожалуйста, попробуйте какую-нибудь действительно простую программу на C (например, ту, которая добавляет 2 целых числа или что-то в этом роде). Это может работать так, как вы описали выше.

Алекс

Возможно, stdio не работает?

Я подозреваю, что вам нужно позвонить в компоновщик Microsoft, чтобы найти этот код.

Алекс

Я не уверен но

objconv -felf hello.obj hello.syso

Может, стоит попробовать сделать coff или omf вместо elf?

Может, стоит попробовать сделать coff или omf вместо elf?

@xoviat да, вам не следует конвертировать файлы .obj в elf, версия gcc для Windows генерирует файлы pe / coff, как и любой другой компилятор Windows.

Алекс

компоновщик Go вызывает внешний компоновщик, чтобы найти все биты, реализованные в C.

Какая конкретная команда используется? Если я знаю команду mingw, то, возможно, я смогу перейти по пути сравнения файлов, чтобы попытаться заставить msvc соответствовать тому, что выдает mingw.

Вы можете увидеть точный комментарий, запустив go build -ldflags=-v .

Итак, из того, что я могу сказать:

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

Go создает временный каталог с этими файлами. Есть ли способ сохранить временный каталог, чтобы я мог проверить его содержимое?

Попробуйте go build -work

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

В этом каталоге остались объектные файлы.

Параметр -work самом деле не сохраняет временные файлы, создаваемые компоновщиком. На данный момент вам просто нужно отредактировать источники компоновщика, чтобы не удалять каталог. Вероятно, мы должны, так или иначе, добавить возможность для этого.

На данный момент вам просто нужно отредактировать источники компоновщика, чтобы не удалять каталог.

Если вы не возражаете, я подожду, пока это не будет реализовано в HEAD, чтобы мне не приходилось выполнять повторяющуюся работу.

Есть ли способ сохранить временный каталог, чтобы я мог проверить его содержимое?

Программа cmd / link имеет для этого флаг -tmpdir. Вы можете использовать это так:

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>

Алекс

Это просто для моей справки, но для этого нужно перенести на 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);
}

Я бы не стал недооценивать время, которое у меня уйдет на выполнение этой задачи, поскольку я совершенно не знаком со сборкой.

  • [x] Понять, что делает сборка
  • [x] Порт на сборку MSVC
  • [x] Сравнение _beginthread и CreateThread
  • [x] Перейти на CreateThread

Также неопределенные символы:

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

Хорошо, так что продвигайтесь сюда быстрее, чем ожидалось!

Все: asm_amd64.s собирается ассемблером go (с нечетной сборкой) или ассемблером gcc?

Похоже, что gcc его не соберет, а значит, вероятно, идет сборка. И тогда возникает вопрос: как собрать его с помощью go-ассемблера в объект.

Цель состоит в том, чтобы среда выполнения / cgo / asm_amd64.s была собрана в объект Go, затем cmd / link связывает его вместе со всеми другими объектами Go в один системный объект, а затем системный компоновщик связывает эти отдельные системные объекты плюс все cgo в окончательную программу.

Есть ли сейчас способ собрать этот объект для тестирования? Нравится gcc -c asm_amd64.s кроме go?

Цель состоит в том, чтобы среда выполнения / cgo / asm_amd64.s была собрана в объект Go, затем cmd / link связывает его вместе со всеми другими объектами Go в один системный объект, а затем системный компоновщик связывает эти отдельные системные объекты плюс все cgo в окончательную программу.

Пока что нашел эти объекты:

  • go.o: очевидно, из набора инструментов go
  • _cgo_.o : сгенерировано gcc, непригодно для использования
  • 000000.o: сгенерировано gcc, непригодно для использования
  • 000001.o: Обновление: фактически создается компоновщиком go, но содержит символы gcc. Непригоден для использования.

go.o - самый большой объект.

@ianlancetaylor

Я не думаю, что ты сказал правильно. crosscall_amd64 находится в 000001.o, но в этом файле нет "всего кода перехода":

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

Этот файл, очевидно, был создан gcc, который слишком поздно в процессе.

Есть ли сейчас способ собрать этот объект для тестирования? Как gcc -c asm_amd64.s, кроме go?

asm_amd64.s является частью пакета времени выполнения. Вы можете увидеть, как команда go build использует файл asm_amd64.s, например:

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

Алекс

Спасибо.

Символ crosscall_amd64 определен в среде выполнения файла / cgo / gcc_amd64.s. Этот файл компилируется GCC (как и все файлы runtime / cgo / gcc_ *). Таким образом, он не объединен в один файл go.o, содержащий весь код Go. Файл, о котором мы говорили раньше, runtime / cgo / asm_amd64.s, определяет символ crosscall2 . Вы найдете этот символ в go.o.

Спасибо.

Хорошо, мне удалось связать исполняемый файл, который вылетает из-за нарушения прав доступа в
go.runtime.rt0_go + 5F -> go .___ acrt_stdio_initializer.

Это все, что у меня есть на данный момент; Я вернусь к этому позже.

@alexbrainman Верно.

@alexbrainman Для продолжения вам понадобится MSVC. Сообщите мне, нужна ли вам в этом помощь.

Для продолжения вам понадобится MSVC.

Я устанавливаю этот https://www.visualstudio.com/downloads/#build -tools-for-visual-studio-2017

Что мне делать после установки?

Алекс

После того, как вы его установили, вам нужно создать «libgo», которая является библиотекой go. Скопируйте из папки cgo следующие файлы:

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

Нам нужно настроить gcc_windows_amd64.c для совместимости с MSVC. Измените функцию следующим образом:

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

Создайте в папке со всеми этими файлами новый файл с именем "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

Дайте мне знать, когда ваша папка будет структурирована согласно запросу.

Кстати, спасибо за работу и за то, что пошли. Вы, ребята, создали поистине волшебный язык.

Дайте мне знать, когда ваша папка будет структурирована согласно запросу.

Мне удалось создать libgo.lib, как вы описали здесь https://github.com/golang/go/issues/20982#issuecomment -327365063
Что я должен делать дальше?

Алекс

Итак, теперь нам понадобятся следующие файлы:

  • libgo.lib
  • идти
  • hello.cgo2.o
  • Привет

hello.c выглядит следующим образом:

#include <stdio.h>

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

Чтобы получить hello.cgo2.o и go.o , вам нужно начать со следующего файла:

package main

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

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

называется "hello.go"

Настройте сценарий PowerShell, который непрерывно копирует файлы из $ env: TMP :

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

Затем запустите go build с hello.c и hello.go в папке. У вас должна быть возможность восстановить необходимые файлы из того места, куда они были скопированы.

Когда у вас есть файлы, указанные выше, вы можете строить с помощью:

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

Дайте знать, если у вас появятся вопросы.

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

При этом создается исполняемый файл go.exe, но он не запускается. Я не вижу там разумного asm-кода. Первая инструкция просто прыгнула в никуда. Это просто беспорядок.

Может, тебе стоит начать с чего-нибудь очень простого. Напишите файл asm (файл Go asm) с единственной функцией asm, которая выполняет "INT $ 3" ​​и не имеет ничего другого. И попробуйте собрать из него исполняемую программу - программа должна запускать вашу функцию с самого начала.

Возможно, сначала создайте его с помощью инструментов Go (а также, если необходимо, с помощью gcc), а затем попробуйте сделать то же самое с помощью MSVC.

Алекс

Алекс, спасибо за помощь. Я буду работать над этим.

Я собираюсь приложить эти две статьи для справки. В противном случае у меня больше не будет обновлений.

На самом деле у меня работает довольно сложная программа go, которая использует только библиотеку msvc. Оказывается, и ванильный компоновщик msvc, и llvm-lld некорректно обрабатывали раздел .bss .

Как только я исправлю компоновщик, программа сможет работать.

К сожалению, go build ломается, когда генерирует _cgo_.o / _all.o . Можно ли пролить свет на причины создания этих двух файлов в cgo?

Вы можете запустить go tool cgo чтобы запустить cgo напрямую. Исходники здесь: https://github.com/golang/go/tree/master/src/cmd/cgo

Кроме того, если бы вы могли запустить это, это было бы здорово. Просто я не уделял этому времени, так что прогресса нет. Прости за это.

У меня уже есть программы, которые могут правильно работать через серию ручных вышивок - я пытаюсь здесь посмотреть, можно ли интегрировать этот процесс обратно в go, чтобы сделать его менее болезненным. :-)

Если вы сможете задокументировать процесс вышивания вручную, возможно, я смогу помочь.

На первый взгляд кажется, что _cgo_.o создается следующим образом (упрощенно):

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

Отсюда: https://github.com/golang/go/blob/b4c84a1b010f012668b5e3ccaf63f609cd11c5fe/src/cmd/go/internal/work/exec.go#L1975

В идеале мы должны были бы написать программу go, которая предварительно обрабатывает объектные файлы, чтобы они были совместимы с link.exe для минимального трения, но это своего рода непростая цель.

Спасибо за указатель - в ближайшее время я запишу процесс.

К сожалению, я не думаю, что связывание может быть выполнено через link.exe если мы не изменим gcc для выдачи неинициализированных данных в разделе .data вместо раздела .bss - но мы можем определенно исправьте llvm-lld чтобы распознать раздел .bss (что я и сделал).

Нам нужно решать _cgo_.o и _all.o отдельности. У меня по ним несколько вопросов:

(1) Кажется, что _cgo_.o не является последним исполняемым файлом, поскольку он не содержит среду выполнения go. Похоже, что компилятор смотрит на свои символы DWARF, чтобы выяснить определение структуры. Проблема в том, что сложно сгенерировать исполняемый файл, если вы собираетесь связать с рядом библиотек извне, особенно с теми, которые генерируются msvc.

Можно ли избежать этого шага?

(2) в настоящее время используется GNU ld для сшивания всех объектных файлов в _all.o путем передачи -Wl,-r в GCC. Это проблематично, поскольку (1) похоже, что другой компоновщик не имеет этой функции, и (2) на команду влияет CGO_LDFLAGS . Например, следующая команда дает неверные результаты:

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

Он генерирует исполняемый файл вместо связанного объектного файла.

Можно ли вообще избежать этого шага, просто поместив все объектные файлы в сгенерированный .a напрямую?

@zooba Каковы шансы заставить MSFT обновить link.exe этим патчем?

К сожалению, я не думаю, что связывание может быть выполнено через link.exe, если мы не изменим gcc для выдачи неинициализированных данных в разделе .data вместо раздела .bss, но мы определенно можем исправить llvm-lld для распознавания раздела .bss (что я и сделал).

Итак, предполагая, что MSFT не обновляет link.exe (что вполне вероятно), было бы хорошо скомпилировать объектные файлы с помощью cl.exe а не gcc .

Похоже, что _cgo_.o не является последним исполняемым файлом, поскольку он не содержит среду выполнения go.

Это правильно, в основном есть два набора объектных файлов (я думаю), которые в конечном итоге связываются вместе. Файл go.o (IIRC) содержит весь код go + время выполнения, а другие объекты содержат код C. Существуют сборочные процедуры, позволяющие переключаться между двумя наборами объектов.

Также нам понадобится clang для компиляции файлов сборки Unix.

Для наших целей -Wl,-r будет тем же самым, что и lib.exe [object files] /OUT:obj . Параметр означает «постепенно связывать», что означает «взять несколько входных файлов, выполнить некоторую работу, а затем выплюнуть другой объектный файл». Если нас не беспокоит часть «поработать», мы можем просто принять требование как «взять некоторые входные файлы и / или объектные файлы и выплюнуть другой объектный файл», за исключением того, что в нашем случае объектный файл будет библиотека.

Вы можете указать GCC избегать размещения переменных в разделе .data, а не в разделе .bss, используя параметр -fno-zero-initialized-in-bss .

Обратите внимание, что мы больше не используем -Wl,-r при создании программного кода.

Команда cmd / link не обязательно должна понимать объектные файлы MSVC, чтобы использовать их как файлы .syso . В любом случае эти файлы просто передаются внешнему компоновщику. Итак, я думаю, что здесь необходимо вызвать компоновщик MSVC в качестве внешнего компоновщика, что вы должны иметь возможность сделать, используя параметр -extld . Если вы уже делаете это, мои извинения; в таком случае, что не получается?

Если вы уже делаете это, мои извинения; в таком случае, что не получается?

IIRC, link.exe barfs для объектов, созданных gcc.

Правда, вам также придется использовать компилятор MSVC C, правильно установив переменную среды CC . Я не думаю, что сработает объединение объектов GCC и объектов MSVC в одной ссылке.

Но затем вы сталкиваетесь с проблемой, когда библиотеки времени выполнения C предварительно скомпилированы. И если вы попытаетесь их перекомпилировать, вы столкнетесь с проблемой, что cl не может скомпилировать сборку unix. Итак, вы переносите части библиотек времени выполнения и пытаетесь связать их, что я и сделал, но потерпел неудачу.

Где-то по пути cl неправильно компилирует ключевую часть кода. Моя идея для исправления этого состояла бы в том, чтобы вынести код MSVC в DLL с плоским C API, а затем просто постепенно компилировать больше библиотек времени выполнения, пока он не перестанет работать.

Идея @haohui по устранению проблемы была другой. Вместо того, чтобы устранять корень проблемы, он решил ее исправить, исправив компоновщик. Очевидно, он добился большего успеха, чем я, но это, вероятно, потому, что его подход, оглядываясь назад, с большей вероятностью сработает, чем мой.

Что я бы порекомендовал на этом этапе (IMHO), так это постепенно компилировать больше библиотеки времени выполнения с cl пока она не перестанет работать или пока у вас не останется кода gcc. Тогда вы точно знаете, в чем проблема.

А с патчем компоновщика DLL не требуется.

Патч для llvm-lld доступен по адресу https://bugs.llvm.org/show_bug.cgi?id=35283

Я потрачу некоторое время, чтобы привести пример.

+1 @haohui Спасибо, что продвинулись вперед!

@haohui К какой версии llvm подходит ваш патч? Любые инструкции о том, как использовать ваш патч и как ссылаться на файлы MSVC?

Что касается файлов _cgo_.o и _all.o , у меня была такая же проблема, поэтому, возможно, исправление этой проблемы может быть исправлением и для другой проблемы: https://github.com/golang/go / issues / 17014

Спасибо за всю работу над этим. Похоже, есть хороший прогресс. Новые функции заморожены до версии 1.11, поэтому вехи меняются.

Итак, я вскочил в это прошлой ночью. Можно собрать все через msvc: cl, а затем связать все через msvc: link. Однако проблем масса.

Итак, помимо простых проблем, таких как msvc: cl не полностью поддерживает C99 (сейчас мы не можем обрабатывать тип _Complex). Есть более системные проблемы с объединением библиотек PE, собранных внутренними компонентами go, и теми, которые созданы msvc. В частности, ссылка msvc: сдувает сегменты .bss (я думаю, что это может просто перебросить эти данные в .data), что является проблемой, поскольку похоже, что ассемблер go SB (псевдо-рег) ​​приводит к неправильной адресации, если .bss перемещается .

Моя первоначальная мысль заключалась в том, чтобы попытаться заставить ассемблер поместить вещи, которые будут помещены в .bss и .noptrbss, в .data и .noptrdata соответственно. Я даже не уверен, возможно ли это; моя возня с ним не увенчалась успехом, и адресация полностью пропала.

Не думаю, что на данный момент можно использовать link.exe. Думаю, стоит начать с lld-link.exe

Если за этим стоит мысль, что мы можем исправить lld-link, чтобы не перемещать данные .bss, я понимаю призыв. На самом деле, если цель состоит в том, чтобы поддерживать фактическую цепочку инструментов msvc, перейдите к внутренней компиляции, поместив данные в .bss / .noptrbss, поскольку необходимо будет решить эту проблему.

Разве мы не можем просто распространять lld-link.exe с помощью go? Это кажется наиболее безопасным путем для поддержки объектных файлов MSVC, если LTCG не включен. Я понимаю, что это не идеально, но мы сталкиваемся с ограниченными ресурсами.

Это также позволяет постепенно прогрессировать, что является лучшей стратегией.

Хорошо, у меня есть хорошие последующие новости, я смог потратить час на работу над этим за обедом.

На данный момент у меня есть пример из более ранней части проблемы:

- 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

Бинарный файл полностью построен с использованием инструментальной цепочки MSVC и Go (GCC или другой LLVM не установлен).

Выводы:

  • В конечном итоге, когда Go tools / link.exe выводит данные .bss для внутренних сборок в .data, было довольно тривиально.
  • Несколько частей ASM пришлось адаптировать для msvc.
  • Были добавлены прокладки для нескольких #def в GCC.
  • В некоторые файлы .c, сгенерированные cgo, пришлось внести несколько небольших изменений.
  • Для комплексных чисел необходимо использовать шиммеры, на данный момент они не поддерживаются.
  • Вероятно, что дополнительные флаги нужно будет добавить прямо для сборки или ссылки для поддержки msvc, ldflags и т. Д. Будет недостаточно

Следующие шаги:
Если у меня будет время в эти выходные, я буду работать над внесением моих изменений в вилку, а также над функциональностью, стоящей за флагами в сборке / ссылке. После этого я отправлю PR на проверку, чтобы мы могли определить типы. Я не на 100% уверен, что перемещение данных .bss куда-нибудь не повлияет.

Единственный недостаток, о котором я могу думать, это то, что это приведет к увеличению размера двоичного файла, но это должно быть нормально.

Хорошо!

Извините, мне потребовалась пара лишних дней, чтобы собрать это воедино. Итак, первый черновик патча можно найти здесь: https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 :: https://github.com/cchamplin/go/tree/msvc_toolchain_support

Это все еще грубо, но у меня есть успешная сборка кода с помощью msvc.

Было бы здорово, если бы люди могли начать тестировать это сейчас и сообщать мне об ошибках, чтобы я мог получить это в лучшем месте для апстрима. Также было бы замечательно, если бы кто-то захотел внести свой вклад в написание тестов!

Использование:

go build -compiler msvc [path]
  • Комплексные числа в настоящее время не поддерживаются, пока я не выясню, сможем ли мы заставить их работать.
  • Я понятия не имею, что произойдет, если вы попытаетесь создать среду выполнения go с компилятором msvc.
  • gcc по-прежнему нужен и используется gco для получения определений и ввода данных при компиляции, он не используется для создания чего-либо ). Я не знаю, сможем ли мы обойти это, у msvc нет ничего, что могло бы сделать тот же карлик и #define dumps кода ... если у кого-то есть идеи по этому поводу, это было бы здорово

Связанный патч создает проблему начальной загрузки.

@alexbrainman Как и где определяется, какие файлы будут скопированы в pkg/boostrap/src/bootstrap во время фазы повышения toolchain1 ?

Копия @alexbrainman

Связанный патч создает проблему начальной загрузки.

Я не знаю, как сейчас работает самонастройка. Но я уверен, что другие ( @rsc и @ianlancetaylor) могут помочь.

Интересно, как @cchamplin запускает make.bat, если начальная загрузка не работает.

Алекс

@xoviat Я не знаю, в чем проблема, но список каталогов начальной загрузки находится в cmd / dist / buildtool.go.

Привет, @alexbrainman , @ianlancetaylor , @xoviat, извините за это, полагаю, мне следовало проверить более тщательно.

Я обновил ветку здесь https://github.com/cchamplin/go/commit/69a5cfc1dd0106fd8a2928a83e4c7001e81e89b8 с исправлением проблемы начальной загрузки, я думаю, теперь она должна правильно загрузиться.

Мне пришлось скопировать некоторые каталоги / src / internal / syscall в cmd / internal / msvc. Это будет огромной проблемой? Я не уверен, как получить доступ к реестру без использования src / internal.

Мне пришлось скопировать некоторые каталоги / src / internal / syscall в cmd / internal / msvc. Это будет огромной проблемой? Я не уверен, как получить доступ к реестру без использования src / internal.

Я не знаю, как это делается сейчас, но подозреваю, что cmd / dist может сделать это без ручного копирования исходных файлов. Я уверен, что Расс или Ян помогут вам, когда вы будете готовы отправить код.

Я думаю, что @bradfitz и @ianlancetaylor пора решить, как действовать здесь. Хотим ли мы, чтобы Go поддерживал инструменты сборки Microsoft, а также gcc? Нам нужно будет установить соответствующие инструменты Microsoft на наших сборщиках (нам нужно будет сделать это до того, как мы начнем принимать CL). Возможно, нам придется ввести новые переменные окружения. Новая документация.

Если ответ положительный, то @cchamplin должен будет отправить свои изменения кода в соответствии с https://golang.org/doc/contribute.html. Вы бы хотели это сделать? Изменение довольно большое, поэтому его нужно разбить на более мелкие CL, чтобы их можно было просмотреть и отправить отдельно. Каждое изменение должно иметь all.bat PASS, прежде чем оно может быть отправлено. Было бы неплохо, если бы мы могли видеть все CL, прежде чем мы начнем отправлять первую CL.

Спасибо.

Алекс

Хотим ли мы, чтобы Go поддерживал инструменты сборки Microsoft, а также gcc?

Обратите внимание, что этот патч также поддерживает # 17014, для которого у меня уже есть патч.

Если ответ положительный, то @cchamplin должен будет отправить свои изменения кода в соответствии с https://golang.org/doc/contribute.html. Вы бы хотели это сделать? Изменение довольно большое, поэтому его нужно разбить на более мелкие CL, чтобы их можно было просмотреть и отправить отдельно.

Да, и разорвать это не должно быть большим делом. Мне просто нужно знать, вероятно ли это, прежде чем я приложу усилия, чтобы очистить весь код, написать документацию, создать тесты и т. Д.

Хотим ли мы, чтобы Go поддерживал инструменты сборки Microsoft, а также gcc?

На мой взгляд, да. Сами компиляторы бесплатны с VS Community, и отсутствие полной поддержки Windows действительно расстраивает. Мне не нужно вставать ящик Linux для компиляции github.com/Microsoft/hcsshim (например), потому что набор инструментов Windows не поддерживается.

В чем может быть причина не поддерживать набор инструментов Windows?

Я думаю, что в принципе нормально поддерживать объектные файлы MSVC. Нам нужен строитель.

Меня больше всего беспокоит то, насколько формат может измениться между выпусками Windows или MSVC. Формат ELF, используемый на большинстве других платформ, очень стабилен; нам очень редко приходится настраивать поддержку ELF каким-либо образом, кроме добавления поддержки новых процессоров. Является ли формат файла MSVC таким же стабильным?

Форматы, связанные с набором инструментов MSVC, довольно стабильны. Самая большая проблема будет в поддержке самих инструментов. Microsoft имеет тенденцию перемещать вещи (файлы и записи реестра) между выпусками Visual Studio. Большая часть этого настраивается (по крайней мере, в том патче, который я написал), но все еще существует вероятность того, что при выпуске новой основной версии Visual Studio она может быть несовместима в качестве инструментария сборки без изменений в Go. Однако все поддерживаемые предыдущие версии Visual Studio продолжат работу.

Насколько мне известно, формат COFF имеет разумную стабильность, если вы подвергаете себя только C ABI (а не C ++). Он также подробно документирован, а LLVM предоставляет эталонную реализацию.

@cchamplin Я бы рекомендовал потребовать от пользователей вызывать vcvarsall.bat перед связыванием с MSVC. Это значительно сократит техническое обслуживание до почти нулевого значения.

Нам нужен строитель.

@ianlancetaylor, как только будет доказано, что объекты MSVC работают по назначению, считаете ли вы, что понадобится и построитель msys / cygwin, и построитель MSVC, или будет только построитель MSVC?

Я уверен, что некоторые люди предпочтут использовать инструменты cygwin, и они уже работают, и мы хотим, чтобы они продолжали работать, поэтому я думаю, что нам нужны два сборщика.

Привет, из нижней части этой ветки видно, что у вас разобрались с проблемами MSVC. Но если у вас возникнут какие-либо проблемы, я в команде MSVC. Не стесняйтесь пинговать меня на github или по электронной почте ([email protected])

Нам нужен строитель.

да. И мы, вероятно, должны начать с изменения наших существующих сборщиков, чтобы установить инструменты сборки MS. Таким образом, мы можем использовать их, поскольку мы принимаем CL для этой проблемы.

Мы можем установить как инструменты gcc, так и инструменты Microsoft на всех наших сборщиках. Можем ли мы запустить all.bat, который тестирует инструменты gcc и microsoft за один раз? Если нет, тогда нам нужно будет настроить разные компоновщики для разных инструментов. Какие параметры определяют, какие внешние компиляторы и компоновщики используются?

Меня больше всего беспокоит то, насколько формат может измениться между выпусками Windows или MSVC.

Вы не устанавливаете компилятор с Windows. Вам придется установить его самостоятельно. Так же, как и с gcc. Устанавливаем любую понравившуюся версию. Мы даже могли запускать разные версии gcc на разных сборщиках.

Является ли формат файла MSVC таким же стабильным?

Я ничего об этом не знаю. Я подозреваю, что вы просто пользуетесь предоставленными инструментами.

Алекс

Меня больше всего беспокоит то, насколько формат может измениться между выпусками Windows или MSVC. Формат ELF, используемый на большинстве других платформ, очень стабилен; нам очень редко приходится настраивать поддержку ELF каким-либо образом, кроме добавления поддержки новых процессоров. Является ли формат файла MSVC таким же стабильным?

Да, COFF очень стабилен.

@bradfitz и @ianlancetaylor что нам нужно, чтобы получить конструктор Windows, доступный для тестирования изменений для этой проблемы? Смотрите мои вопросы на https://github.com/golang/go/issues/20982#issuecomment -370719472

Спасибо

Алекс

Go теперь поддерживает объект msvc?

Изменение https://golang.org/cl/110555 упоминает эту проблему: debug/pe: parse the import directory correctly

@alexbrainman @bradfitz @ianlancetaylor :

Я проделал большую часть необходимой работы, чтобы очистить патч и разбить его на более удобоваримые части. Думаю, я почти готов к подаче заявки на участие в проекте. Думаю, мне нужно знать, следует ли мне дождаться информации о ситуации со строителем перед отправкой кода или просто сделать это как можно скорее?

Вы можете отправить CL в любое время, но кто-то должен настроить конструктор. В противном случае у нас нет возможности их проверить.

@johnsonj , не могли бы вы добавить инструменты компилятора MSVC в наши образы Windows?

В идеале я бы хотел не добавлять новый тип хоста и просто сделать так, чтобы 1-3 из наших существующих типов хостов Windows имели инструменты MSVC в дополнение к Cygwin. И затем мы можем добавить больше конфигураций построителя поверх этих измененных типов хоста.

/ cc @andybons @bcmills как FYI (о том, как происходит Windows ... мы просим Джеффа о помощи :))

@johnsonj , не могли бы вы добавить инструменты компилятора MSVC в наши образы Windows?

@cchamplin Я предлагаю вам попробовать добавить все необходимые инструменты в конструктор самостоятельно. Никто другой, но вы знаете, что требуется. Вы можете посмотреть полные инструкции в каталоге golang.org/x/build/env/windows. В частности, вы, вероятно, захотите добавить больше строк в startup.ps1. Как только вы узнаете, что нужно изменить в этом директоре, внесите изменения и отправьте их на рассмотрение через https://golang.org/doc/contribute.html. После принятия мы сможем обновить конструкторы, используя эти инструкции.

В идеале я бы хотел не добавлять новый тип хоста и просто сделать так, чтобы 1-3 из наших существующих типов хостов Windows имели инструменты MSVC в дополнение к Cygwin. И затем мы можем добавить больше конфигураций построителя поверх этих измененных типов хоста.

У нас всегда были компилятор Mingw (gcc) C и компоновщик для Windows. У нас никогда не было другого набора инструментов для сборки C. После того как мы добавим поддержку компилятора Microsoft C, можно ли будет протестировать функции Mingw и Microsoft C с помощью одного запуска all.bat? Или Mingw или Microsoft C исключают друг друга? Придется ли нам устанавливать какую-либо переменную среды так, чтобы она указывала на Mingw или Microsoft, но не на то и другое одновременно? Полагаю, я пытаюсь понять, как нужно структурировать и тестировать код. Также это определит, сколько разных строителей нам нужно.

Алекс

Я займусь запеканием двоичных файлов в изображении

Изменение https://golang.org/cl/112036 упоминает эту проблему: env/windows: add visual studio tools to image

@johnsonj @bradfitz : Спасибо, что

@alexbrainman @bradfitz @ianlancetaylor : Что касается стратегии тестирования для этого, я не уверен, что именно делать. Мы можем пойти по пути запуска dist test для обеих инструментальных цепочек в окне и выполнить каждый тест дважды, или мы должны тестировать тесты cgo только дважды (один раз для gcc, один раз для msvc)?

Что касается стратегии тестирования для этого, я не совсем уверен, что делать. Мы можем пойти по пути запуска dist test для обеих инструментальных цепочек в окне и выполнить каждый тест дважды, или мы должны тестировать тесты cgo только дважды (один раз для gcc, один раз для msvc)?

@cchamplin У меня нет ответа на ваш вопрос. Я подозреваю, что Ян знает ответ.

Алекс

Какова стоимость выполнения всех тестов дважды, а не только cgo?

@mxplusb , мы можем просто запустить новую конфигурацию сборки для Windows, и она будет работать параллельно с нашей существующей 3. Новая конфигурация компоновщика в порядке. Добавляем их регулярно.

Просто скажите мне, как сделать это по-другому: установите другую / новую переменную среды, и тогда что-то уловит это, я полагаю?

Вероятно, потребуется несколько вещей, чтобы это заработало.

Либо нам нужно запустить внутри оболочки / среды, где тест go, который выполняет dist test, будет запущен внутри после того, как соответствующий vsvars.bat был запущен / вызван

Или мы можем сделать так, чтобы dist выполнял соответствующие vsvars и извлекал необходимые переменные среды, а затем устанавливал / передавал их для тестирования.

Мы также, вероятно, захотим, чтобы какая-то переменная среды сообщала dist или make.bat, что мы хотим запускать тесты с установленным -compiler msvc.

Либо нам нужно запустить внутри оболочки / среды, где тест go, который выполняет dist test, будет запущен внутри после того, как соответствующий vsvars.bat был запущен / вызван

Или мы можем сделать так, чтобы dist выполнял соответствующие vsvars и извлекал необходимые переменные среды, а затем устанавливал / передавал их для тестирования.

Я бы предпочел, чтобы мы не запускали командные файлы из dist.exe или go.exe. Работать с командными файлами сложно.

Мы также, вероятно, захотим, чтобы какая-то переменная среды сообщала dist или make.bat, что мы хотим запускать тесты с установленным -compiler msvc.

Я надеялся, что Ян узнает, какой подход здесь лучший. Насколько я знаю, мы также поддерживаем различные компиляторы C в Unix (gcc или clang). Конечно, наш процесс сборки позволяет нам тестировать разные компиляторы C.

Алекс

Раньше я не замечал, что вы планируете использовать go build -compiler msvc . В этом нет смысла. Параметр go build -compiler принимает имя компилятора Go (в настоящее время либо gc, либо gccgo). Это не требует имени компилятора C. Компилятор C передается в переменной окружения CC . Компилятор C по умолчанию устанавливается путем установки переменной окружения CC_FOR_TARGET при запуске make.bat, как описано в комментариях к make.bat.

Я ожидал, что у нас будет компоновщик, для которого мы установим для переменной среды CC_FOR_TARGET значение msvc перед запуском all.bat. Я не понимаю, зачем нам делать что-то еще.

Компилятор C передается в переменной среды CC. Компилятор C по умолчанию устанавливается путем установки переменной среды CC_FOR_TARGET при запуске make.bat, как описано в комментариях к make.bat.

Спасибо, Ян, за объяснение.

@cchamplin Надеюсь, вы сможете внести изменения в существующую модель. Сообщите нам, если у вас возникнут проблемы. Спасибо.

Я ожидал, что у нас будет компоновщик, для которого мы установим для переменной среды CC_FOR_TARGET значение msvc перед запуском all.bat.

У нас есть 3 конструктора окон amd64 на https://build.golang.org. Должны ли мы заменить один на MSVC? Хотим ли мы построить 386 MSVC?

Алекс

@ianlancetaylor @alexbrainman Разобрался с флагом -compiler. Я не думаю, что есть простой способ заставить работать CC="msvc" (или действительно CC="cl.exe" ). CC по-прежнему необходимо указать расположение GCC, чтобы сборки MSVC работали. В наборе инструментов компилятора msvc нет инструментов, позволяющих CGO выполнять необходимую интроспекцию (поиск определений, разрешение типов), поэтому GCC по-прежнему требуется в сборках MSVC, GCC просто не используется на фактической фазе компиляции / компоновки.

Будет ли приемлемо добавление нового флага для сборки и всего (набор инструментов или что-то в этом роде)? Думаю, мне уже пришлось добавить флаг цепочки инструментов в cgo.

Также установка CC_FOR_TARGET перед all.bat выглядит так, как будто это может иметь негативные последствия, потому что это повлияет на компилятор, используемый при начальной загрузке. Я не верю, что MSVC можно использовать во время процесса начальной загрузки (я не на 100% в этом, я на самом деле не пробовал, но я очень сомневаюсь, что это сработает)

Понятно, для MSVC нам нужны и GCC, и MSVC? Где GCC используется только инструментом cgo? Это кажется несколько неудачным, поскольку это означает, что мы полностью полагаемся на GCC и MSVC, реализующие один и тот же ABI, но я думаю, что это довольно вероятно.

Я думаю, мы могли бы добавить еще одну переменную окружения CC_FOR_CGO , для которой можно было бы установить GCC.

CC_FOR_TARGET используемый make.bat, будет использоваться для сборки runtime / cgo. Мне не ясно, как cgo вообще может работать, если runtime / cgo не создается компилятором C, который вы используете.

Возможно, нам следует начать с того, чтобы заставить все работать, когда вызывается make.bat, устанавливая CC_FOR_TARGET на cl и CGO_ENABLED на 0 .

Спасибо @ianlancetaylor :

Понятно, для MSVC нам нужны и GCC, и MSVC? Где GCC используется только инструментом cgo? Это кажется несколько неудачным, поскольку это означает, что мы полностью полагаемся на GCC и MSVC, реализующие один и тот же ABI, но я думаю, что это довольно вероятно.

Я согласен, что это прискорбно, и был бы рад узнать о какой-либо альтернативе, но я ее еще не нашел. Безусловно, такой способ построения связан с риском (например, создаваемый код cgo имеет различные определения типов или определения в зависимости от того, какой компилятор, по его мнению, создает). Таким образом, сборки не всегда могут быть успешными или работать правильно без некоторых настроек (в моей реализации есть механизм, позволяющий справиться с этим, но это немного ручной процесс). К сожалению, я думаю, что это риск, на который придется пойти людям, если они захотят использовать цепочку инструментов MSVC, и все, что мы можем сделать, это пока задокументировать это.

Аналогичным образом, до сих пор нет реального пути для обеспечения поддержки complex64 и complex128 в программах cgo, созданных с помощью MSVC, просто потому, что компилятор MSVC не совместим с c99.

Я думаю, мы могли бы добавить еще одну переменную окружения CC_FOR_CGO , для которой можно было бы установить GCC.

Таким образом, текущая реализация, которая у меня есть, заключается в том, что если go build предписано собирать с помощью MSVC, он по умолчанию будет искать cl.exe на пути, но это можно переопределить с помощью переменной среды MSCC. CGO продолжит использовать переменную среды CC, возвращающуюся к gcc / независимо от того, что находится в сгенерированном zdefaultcc.go

CC_FOR_TARGET используемый make.bat, будет использоваться для сборки runtime / cgo. Мне не ясно, как cgo вообще может работать, если runtime / cgo не создается компилятором C, который вы используете.

В текущей реализации cgo будет успешно работать с двоичными файлами msvc, даже если вся цепочка инструментов go была создана gcc. например, код MSVC добавлен в go / src. all.bat запускает сборку среды go с помощью gcc. После этого go / bin / go.exe можно использовать для сборки с помощью цепочки инструментов msvc (при условии наличия флагов). Возможно, я неправильно понимаю, что вы здесь говорите.

Сложность, связанная с этим, потому что сказать go, что мы хотим построить с помощью msvc, сложнее, чем просто переключить компилятор на cl. Набор инструментов MSVC сильно отличается от набора инструментов gcc. В MSVC среду необходимо настроить через запуск внутри vcvars.bat (или делать то, что делает v8, например, запускать vcvars.bat и извлекать всю необходимую информацию из переменных среды, которые он устанавливает, а затем использовать это в своей сборке процесс). После того, как мы оказались в среде MSVC, основным отличием стали сами инструменты, cl.exe используется для компиляции файлов C и C ++, ml.exe и ml64.exe используются для сборки файлов, и, наконец, link.exe (ms) используется для связать все вместе. Так что это больше, чем просто установка CC=cl.exe и передача ему правильных флагов. Это имеет смысл / помогает прояснить ситуацию?

Чтобы дополнительно прояснить

CC_FOR_TARGET, используемый make.bat, будет использоваться для сборки runtime / cgo. Мне не ясно, как cgo вообще может работать, если runtime / cgo не создается компилятором C, который вы используете.

go build выбирает соответствующие файлы из runtime / cgo во время процесса сборки (например, go build / go test / go run - не процесс построения), когда Был выбран набор инструментов msvc.

Я открыт для предложений о том, как это должно работать, но это не должно требовать новой опции командной строки для инструмента go. Можем ли мы написать программу на чистом языке Go, которая будет действовать как GCC в том, что касается инструмента go, но на самом деле запускает MSVC?

Можем ли мы написать программу на чистом языке Go, которая будет действовать как GCC в том, что касается инструмента go, но на самом деле запускает MSVC?

Я считаю, что это могло бы быть осуществимо, позвольте мне посмотреть, смогу ли я что-то продвинуть по этому пути.

Кроме того, я думаю, мне нужно уточнить, будет ли добавление флагов командной строки к другим инструментам также проблемой. На данный момент комплексный патч для этого создает несколько новых флагов командной строки в различных инструментах.

  • cmd / cgo

    • -toolchain [gcc, msvc] (по умолчанию gcc) Цепочка инструментов для использования при создании файлов вывода cgo

  • cmd / ссылка

    • -rlocbss (по умолчанию false) Переместить .bss в .data

    • -toolchain [gcc, msvc] (по умолчанию gcc) Цепочка инструментов, которая будет использоваться для внешних ссылок

мы также создаем следующие параметры сборки / переменные среды cgo:

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

После нескольких минут размышлений есть несколько препятствий, которые может быть трудно преодолеть, если мы просто проксируем команды компилятора, которые вместе продумали бы другую программу.

  1. go build необходимо знать, что такое внешняя инструментальная цепочка, чтобы определить, какие файлы времени выполнения / cgo нужно создавать, иначе в конечном итоге мы просто передадим несовместимые версии gcc в нашу прокси-команду. Мы могли бы обойти это внутри самого прокси, но он будет хрупким и может сломаться, если в runtime / cgo когда-либо будут добавлены дополнительные файлы.
  2. cmd / cgo необходимо знать, какая внешняя цепочка инструментов используется, чтобы выбрать, какую версию выходного кода C использовать.
  3. Прокси-программе потребуется какой-то механизм, чтобы знать, следует ли ей выполнять gcc (как при вызове с помощью cmd / cgo) или выполнять cl.exe, который может быть передан, но это означает, что вызывающий должен будет знать, что такое инструментальная цепочка есть, иначе cmd / cgo передает несуществующие флаги в gcc.
  4. go build вызывает cmd / link, который также должен знать, что такое инструментальная цепочка, чтобы он мог выполнять перемещение .bss в .data и чтобы он мог передавать определенные флаги компоновщику (мы могли бы справиться с этим последним часть в самом прокси)

Будет ли указание переменной среды использовать go build для определения работы сборок msvc? Хотя я думаю, что он устанавливает более высокую планку для тех, кто просто хочет создать программу с помощью msvc, поскольку теперь им нужно установить несколько переменных среды в дополнение к запуску внутри vsvars.bat (как минимум CC и UNDECIDED_TURN_ON_MSVC_BUILD_VAR )

Другой альтернативой было бы, чтобы go build запускал фиктивную команду noop на указанном CC а затем анализировал логотип / заголовок, чтобы определить, является ли он msvc или gcc, и продолжить соответствующие настройки инструментальной цепочки на этом этапе. ... не уверен, насколько это хрупко или как это будет работать с совместимыми с msvc инструментами, такими как clang.

Недавно обнаружил эту проблему Github, и эта работа мне очень нравится. Я надеюсь, что эта земля появится где-нибудь в ближайшем будущем.

Я намерен использовать CGo в Windows в качестве оболочки для некоторого стороннего кода, который был построен с использованием MSVC, который я не могу просто перестроить из источников, используя mingw-w64 . У меня есть несколько относительно серьезных тестовых примеров, чтобы запустить его, поэтому я могу его довольно хорошо проверить.

В любом случае, спасибо @cchamplin и всем, кто над этим работает, и, пожалуйста, дайте мне знать, что я могу помочь.

@cchamplin Я знаю достаточно, чтобы @deadprogram , поэтому у меня есть хороший расширенный тестовый стенд, когда мы будем готовы к тестированию.

Привет, @mxplusb , на самом деле патч более или менее готов к работе. Если я найду время, я отправлю изменения в gerrit сегодня вечером или завтра, что позволит нам приступить к рассмотрению, обновлению и утверждению всего.

Изменение https://golang.org/cl/133937 упоминает эту проблему: cmd/link: Add flag rlocbss to relocate .bss data to .data

Изменение https://golang.org/cl/133938 упоминает эту проблему: runtime/cgo: MSVC toolchain support in cgo native code

Изменение https://golang.org/cl/133939 упоминает эту проблему: cmd/cgo: Add toolchain flag to cgo command for MSVC support

Изменение https://golang.org/cl/133946 упоминает эту проблему: cmd/compile: Add support for MSVC toolchain to go build

Похоже, я опечатал проблему в некоторых коммитах. Я позволю процессу проверки начаться и определю лучший способ исправить.

Изменение https://golang.org/cl/133943 упоминает эту проблему: cmd/cgo: Add support for CC_FOR_CGO environment variable

Изменение https://golang.org/cl/133942 упоминает эту проблему: tests: Update various tests to prepare for MSVC compiler toolchain

Изменение https://golang.org/cl/133940 упоминает эту проблему: misc/cgo: Adjust tests to be compatible with MSVC toolchain support

Изменение https://golang.org/cl/133941 упоминает эту проблему: runtime: Add runtime.CompilerType to denote between host compiler type

Изменение https://golang.org/cl/133945 упоминает эту проблему: cmd/link: Add external toolchain support for MSVC

Изменение https://golang.org/cl/133944 упоминает эту проблему: cmd/compile, cgo: Add support for MSVC flags

@cchamplin, можешь описать, какое было окончательное решение? Как выглядит поддержка MSVC? Какие флаги командной строки будут добавлены? Что пользователь должен будет сделать со своей средой помимо загрузки MSVC? Спасибо

Кроме того, как мы можем попробовать этот патч? Я не смог найти ваши коммиты в репо.

@rasky Это все еще немного меняется, поскольку изменения проходят проверку. Скорее всего, не будет каких-либо конкретных флагов командной строки, которые необходимо установить, просто создайте приложения cgo, где переменная среды CC указывает на MSVC или CC не установлен, cl.exe находится на пути, а gcc - нет.

@blizzardplus Похоже на вышесказанное, сейчас с обзором многое меняется, так что, возможно, еще рано начинать опробовать его (хотя это зависит от вас). Все связанные изменения были опубликованы в этом выпуске gopherbot, вы можете найти их там.

@cchamplin есть ли поддержка кросс-компиляции с использованием gcc или clang ? Если да, то проходят ли они испытания?

@cchamplin Я не вижу никакой активности в CL с 11 сентября, есть ли прогресс в этом направлении или нужны дополнительные ресурсы?

@cchamplin, чтобы это работало для c-архива, раздел ctors следует изменить на .CRT $ XCU (https://msdn.microsoft.com/en-us/library/bb918180.aspx) .Если этого не сделать, то Среда выполнения golang не будет инициализирована. Кроме того, оказывается, что если вы установите это значение, он отлично работает и с gcc - gcc stil принимает эти функции, перемещает их в текстовый раздел и изменяет main, чтобы вызывать их перед настоящим main. Visual Studio может понимать файлы архива .a, и, поскольку интерфейс предварительно скомпилированных / собранных файлов - C, не должно быть проблем, просто имея это в архиве. Есть предупреждение о двух разделах .text, но простые случаи, похоже, работают нормально (требуется дополнительное тестирование для подтверждения отсутствия проблем).

Кроме того, чтобы это работало для c-shared, экспортируемые функции должны быть украшены __declspec (dllexport), но я не могу найти, где происходит это расширение // экспорта.

@blizzardplus Для поддержки clang-MSVC есть дополнительный патч. Я не уверен, что вы имеете в виду под кросс-компиляцией в этом случае? Вы не сможете использовать набор инструментов MSVC в системах, отличных от Windows. Другие функции кросс-компиляции не должны изменяться.

@kshelton К сожалению, это очень загруженное время года для меня, так как у меня есть другие проекты и конференции, на которых я представляю. Возможно, я не смогу вернуться к внесению необходимого рефакторинга в патч до декабря.

@kshelton Спасибо. Я дважды не проверял патч, я предполагаю, что я разработал его с предположением, что c-archive не будет работать на MSVC, или специально отключил его? Я пошел по пути, пытаясь правильно оформить экспорт, когда пытался заставить плагин / общий доступ к Windows. Я считаю, что есть и другие проблемы, но я мог бы объединить две проблемы. Существуют реальные проблемы с тем, как go размещает общий код в PLT / GOT для ELF по сравнению с Windows .edata, idata и EAT. Я считаю, что большинство проблем, с которыми я столкнулся, были связаны с переездом и невозможностью заставить их работать. Если у кого-то есть понимание в этом, это было бы замечательно. См. # 19282

@cchamplin Я пытался посмотреть, смогу ли я построить Go поверх вашего CL

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

Я использовал этот командный файл для настройки своей среды

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

и я получаю эту ошибку при запуске 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>

Что мне здесь не хватает?

Спасибо.

Алекс

@alexbrainman

Что мне здесь не хватает?

Вероятно, вам как минимум нужно установить CC_FOR_CGO = gcc. Я также никогда лично не пробовал строить go с MSVC. Я не уверен, что это сработает / должно поддерживаться.

-C

Вероятно, вам как минимум нужно установить CC_FOR_CGO = gcc.

Ваш https://go-review.googlesource.com/c/go/+/133940 содержит несколько тестов. Как я могу проверить прохождение тестов? Какие точные шаги?

Также сборщики Go https://build.golang.org запускают% GOROOT% \ src \ all.bat для проверки всех тестов (включая те, которые перечислены в https://go-review.googlesource.com/c/go/+/ 133940) пасс. Как вы предлагаете изменить код Go, чтобы% GOROOT% \ src \ all.bat запускал ваши настроенные тесты с https://go-review.googlesource.com/c/go/+/133940. Возможно, all.bat сможет протестировать как gcc, так и msvc версии тестов. Возможно, мы можем использовать некоторую переменную среды, которая сообщает all.bat, какую версию тестов следует запускать - и тогда мы могли бы иметь два разных сборщика, запускающих разные версии тестов. Вы думали обо всем этом?

Я также никогда лично не пробовал строить go с MSVC. Я не уверен, что это сработает / должно поддерживаться.

Вы можете запустить all.bat до успешного завершения без установленного gcc. Текущая версия Go требует для сборки только другую версию Go (по крайней мере, go1.4). Компилятор C нужен только Cgo, у меня сложилось впечатление, что ваши изменения реализуют версию Cgo, созданную MSVC. Но, возможно, я ошибаюсь. Пожалуйста, поправьте меня, если я ошибаюсь.

Спасибо.

Алекс

@alexbrainman

Ваш https://go-review.googlesource.com/c/go/+/133940 содержит несколько тестов. Как я могу проверить прохождение тестов? Какие точные шаги?

Возможно, all.bat сможет протестировать как gcc, так и msvc версии тестов. Возможно, мы можем использовать некоторую переменную среды, которая сообщает all.bat, какую версию тестов следует запускать - и тогда мы могли бы иметь два разных сборщика, запускающих разные версии тестов. Вы думали обо всем этом?

Да, именно этот механизм используется в https://go-review.googlesource.com/c/go/+/133946/. Поскольку все вызовы run.bat на windows, механизм вызова cgo-тестов был помещен туда. Итак, вы или разработчик начнете с обычной настройки CC = gcc. Затем вы должны установить GOTESTMSVC = 1 и GOVSVARSPATH = некоторый путь vsvars.bat. После этого сборка с all.bat должна пройти как тесты gcc, так и msvc cgo.

Вы можете запустить all.bat до успешного завершения без установленного gcc. Текущая версия Go требует для сборки только другую версию Go (по крайней мере, go1.4). Компилятор C нужен только Cgo, у меня сложилось впечатление, что ваши изменения реализуют версию Cgo, созданную MSVC. Но, возможно, я ошибаюсь. Пожалуйста, поправьте меня, если я ошибаюсь.

Ты прав. Сам Go должен строить нормально. Могут возникнуть проблемы, когда он попадет в тест, поскольку run.bat был изменен для установки некоторых переменных среды, когда GOTESTMSVC = 1. Вероятно, мы могли бы попытаться определить, собирается ли go просто с помощью msvc, а затем установить соответствующие переменные среды dist, чтобы тесты не завершились ошибкой.

Затем вы должны установить GOTESTMSVC = 1 и GOVSVARSPATH = некоторый путь vsvars.bat. После этого сборка с all.bat должна пройти как тесты gcc, так и msvc cgo.

Я пробовал это.

я использовал

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

Сначала я запускаю этот командный файл:

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

а затем запустите all.bat . all.bat не работает с

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

Также установка GOTESTMSVC и GOVSVARSPATH может работать для людей, выполняющих all.bat. Но что будут делать другие пользователи вашего изменения, когда им понадобится использовать MSVC для Cgo? Каковы ваши планы на это?

Алекс

@alexbrainman
Я не уверен, что происходит. Этот тест не проходит для меня на мастере

> 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

В help.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/internal/help/help.go#L37
он проходит через base.Go.Commands. Которая инициализируется в main.go https://github.com/golang/go/blob/c040786f37246f40ae29402fbdb6e97031a21713/src/cmd/go/main.go#L43
но я не уверен, как эта функция инициализации может когда-либо вызываться в тестовом исполняемом файле, поэтому я понятия не имею, как мастер проходит тесты прямо сейчас, так как я думаю, что это должно давать сбой по всем направлениям.


Также установка GOTESTMSVC и GOVSVARSPATH может работать для людей, выполняющих all.bat. Но что будут делать другие пользователи вашего изменения, когда им понадобится использовать MSVC для Cgo? Каковы ваши планы на это?

Итак, в ситуации, когда вы просто хотите создать некоторый Cgo-код с помощью MSVC

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

должно быть все, что тебе нужно, я думаю

Я не уверен, как эта функция init могла бы когда-либо вызываться в тестовом исполняемом файле, поэтому я понятия не имею, как мастер проходит тесты прямо сейчас, поскольку я думаю, что это должно давать сбой по всем направлениям.

При использовании go test с файлом в cmd / go инструмент go соберет пакет cmd / go, а затем построит тесты, сгенерирует тестовый драйвер, построит его и свяжет все вместе в новый основной пакет. Это происходит, даже если cmd / go сам по себе является основным пакетом. То есть основной пакет в cmd / go / *. Go будет рассматриваться как неосновной пакет в целях тестирования. Это позволяет тестам при необходимости вызывать функции, определенные в основном пакете.

Извините, я не спешу с ответом. Но у меня не было свободного времени, чтобы еще раз разобраться в этом.

Я не уверен, что происходит. Этот тест не проходит для меня на мастере

Я не использовал мастер. Я использовал ваш коммит e56d52f66b95b87001867a2487a11bd961f40d4d. Разве вы не запускали all.bat на этом коммите перед тем, как отправить его на проверку? У all.bat получилось? Можете ли вы снова попробовать запустить all.bat для этого коммита, чтобы увидеть, связано ли это с моей конфигурацией системы. Спасибо.

Итак, в ситуации, когда вы просто хотите создать некоторый Cgo-код с помощью MSVC

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

должно быть все, что тебе нужно, я думаю

2 переменные окружения, наверное, слишком сложны для обычного пользователя. И CC_FOR_CGO=gcc мне кажется странным - почему мы используем gcc для создания кода с помощью MSVC?

Алекс

@alexbrainman

Я не использовал мастер. Я использовал ваш коммит e56d52f66b95b87001867a2487a11bd961f40d4d. Разве вы не запускали all.bat на этом коммите перед тем, как отправить его на проверку? У all.bat получилось? Можете ли вы снова попробовать запустить all.bat для этого коммита, чтобы увидеть, связано ли это с моей конфигурацией системы. Спасибо.

Я думаю, что это было связано с конфигурацией моей системы, которая давала мне странные результаты при запуске тестов. Думаю, я решил проблему и добавил несколько обновлений в набор изменений.

2 переменные окружения, наверное, слишком сложны для обычного пользователя. И CC_FOR_CGO = gcc мне кажется странным - почему мы используем gcc для сборки кода с MSVC?

Вероятно, это должно быть CC_FOR_CGO = gcc.exe, моя ошибка. Но чтобы ответить на ваш вопрос; от геррит:

PS1, строка 1324:
cgo по-прежнему нужен gcc для анализа типов. Если CC установлен на компилятор MSVC, cgo необходимо средство для вызова GCC, которое предоставляется CC_FOR_CGO. К сожалению, в цепочке инструментов MSVC нет механизма для предоставления информации того же типа, которая собирается из gcc. Теоретически можно создать специальный инструмент для сбора информации о типах, которая используется cgo, но это может выходить за рамки и, возможно, требовать значительных усилий (я лично никогда не писал ничего для выполнения статического анализа типов кода C / C ++).

Я также, кажется, что-то сломал с чистым кешем между запусками для GCC и MSVC, я не уверен, почему некоторые тесты все еще действуют так, как если бы они были кешированы.

Думаю, я решил проблему и добавил несколько обновлений в набор изменений.

Эта настройка https://github.com/golang/go/issues/20982#issuecomment -447618566 на

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

ведет меня дальше, но все еще терпит неудачу с

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

Вероятно, это должно быть CC_FOR_CGO = gcc.exe, моя ошибка.

Меня не беспокоит .exe в gcc.exe. Мои проблемы

  • вам нужны инструменты gcc и MSVC для использования MSVC (было бы сложно объяснить это нашим пользователям), но я понимаю, что с этим ничего не поделать;

  • Мне нужно было установить обе переменные среды CC_FOR_CGO = gcc и CC = cl.exe - может быть, мы можем просто предположить, что CC_FOR_CGO всегда установлен на gcc?

Но чтобы ответить на ваш вопрос; от геррит:

Спасибо за объяснение.

Алекс

@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

Я не уверен, как могло бы появиться это предупреждение, если у вас не будет другой / старой копии msvc_libinit_windows.c. Можете ли вы подтвердить, что в нем есть эта строка:

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

C4710 должен быть отключен для включения stdio. Я вижу, что ваша версия MSVC немного отличается от моей, что также может быть причиной. Я не уверен, почему они активно игнорировали это подавление в другой версии.

Вы также можете попробовать внести изменения, чтобы включить подавление глобально, независимо от того, что

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

Мне нужно было установить обе переменные среды CC_FOR_CGO = gcc и CC = cl.exe - может быть, мы можем просто предположить, что CC_FOR_CGO всегда установлен на gcc?

Я думаю, что проверка gco, существует ли gcc, если CC_FOR_CGO не установлен, будет в порядке. CC_FOR_CGO больше подходит для людей вроде меня, у которых на пути нет gcc. Мой CC_FOR_CGO выглядит так: CC_FOR_CGO = I: \ Development \ tmd-gcc \ bingcc.exe. Если мы не хотим поддерживать вариант использования GCC, который не находится на пути к сборкам MSVC, дайте мне знать, и я могу полностью избавиться от переменной среды.

Я попробовал еще раз эту версию

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

и я получаю ту же ошибку

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

Можете ли вы подтвердить, что в нем есть эта строка:

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

Это начало моего файла 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>
...

Вы также можете попробовать внести изменения, чтобы включить подавление глобально, независимо от того, что

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

Я сделал это изменение:

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>

но я вижу ту же ошибку

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

Алекс

Я пытался воспроизвести это прошлой ночью, но не смог. Мне интересно, испытываете ли вы это: https://developercommunity.visualstudio.com/content/problem/35734/c-cannot-disable-specific-warnings-with-pragmas-wh.html

Возможно ли обновление до последней версии SDK и инструментов сборки? Я использую SDK 10.0.17763.0. и версия 15.9.28307.222 инструментов сборки / devenv

Я пытаюсь создать Windows DLL с MSVC, но похоже, что Go пытается отключить какое-то предупреждение с номером больше 65535 (или без номера), что приводит к остановке MSVC.

image

Нет. Werror - это опция GCC, которая рассматривает каждое предупреждение как ошибку.

Для MSVC вы должны использовать WX .

@pravic хороший вопрос, как мне это сделать? Я не настраиваю его, все, что я делаю, это:

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

@galich К сожалению, я не могу помочь, потому что не слежу за интеграцией MSVC.

Например, где патчи, относящиеся к этой ветке? В мастере или еще где?

@pravic, вы можете найти изменения здесь: https://go-review.googlesource.com/c/go/+/133946/5

@mxplusb спасибо за ссылку, похоже, моя конкретная проблема с / Werror решена там.
Вы знаете, когда выйдет бета-версия / ночная / стабильная версия?

Возможно ли обновление до последней версии SDK и инструментов сборки? Я использую SDK 10.0.17763.0. и версия 15.9.28307.222 инструментов сборки / devenv

@cchamplin, наконец, мне удалось обновить свой MSVC. У меня есть сейчас

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>

Я попробовал еще раз эту версию

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

и all.bat успешно завершается. Но я получаю эти предупреждения.

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

А еще я заметил, что вы выполняете все тесты дважды.

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

Почему?

Алекс

@alexbrainman Предупреждения, вероятно, могут быть подавлены для этих тестов, особенно в этом случае предупреждения Spectre.

Я считаю, что для тестов, выполняемых дважды, я считаю, что это было сделано таким образом для сборщика, прогоните тесты один раз с компиляцией gcc, а затем снова прогоните их с помощью MSVC (если он включен), чтобы убедиться, что компиляция с обоими инструментами работает. Я не уверен, что здесь нужно, поэтому я могу изменить его, чтобы при вызове all.bat с включенным MSVC мы запускали тесты только с MSVC, дайте мне знать. В этом случае я предполагаю, что дополнительные строители нужно будет добавить только для MSVC, в отличие от некоторых построителей, которые также строят с помощью MSVC?

Согласились, что в Windows потребуется запустить один конструктор с использованием набора инструментов MinGW-W64, а другой - с помощью набора инструментов MSVC, чтобы протестировать оба сценария.

Я считаю, что для сборщика это было сделано именно так: прогнать тесты один раз с компиляцией gcc, а затем снова запустить их с помощью MSVC (если он включен), чтобы гарантировать, что компиляция с обоими инструментами работает.

Я согласен, что это должно быть предпочтительным поведением, поэтому есть гарантия, что оно не нарушит существующие рабочие нагрузки, если присутствуют оба набора инструментов.

Предупреждения, вероятно, могут быть подавлены для этих тестов, особенно в этом случае предупреждения Spectre.

Команда Go не отображает предупреждений, поэтому предупреждения не должны отображаться.

Также я заметил, что команда go env не отображает переменную CC_FOR_CGO. Если CC_FOR_CGO влияет на работу сборки go, тогда CC_FOR_CGO должен отображаться вместе с другими. Нам действительно нужна переменная CC_FOR_CGO? Что еще, кроме CC_FOR_CGO = gcc, может быть?

Я считаю, что для тестов, выполняемых дважды, я считаю, что это было сделано таким образом для сборщика, прогоните тесты один раз с компиляцией gcc, а затем снова прогоните их с помощью MSVC (если он включен), чтобы убедиться, что компиляция с обоими инструментами работает.

Многие тесты не используют gcc. Когда тесты пакетов запускаются дважды без причины, это пустая трата времени людей / компьютеров. Как видно из https://github.com/golang/go/issues/20982#issuecomment -480569880 archive/zip , тесты пакетов выполнялись дважды - я не вижу необходимости во втором запуске.

Я не уверен, как это организовать, но, возможно, вам следует заменить вызов go tool dist test в run.bat, чтобы выполнить только набор тестов, необходимых для тестирования сборки MSVC. См., Например, go tool dist test -h о том, как можно выбрать только некоторые конкретные тесты. @bradfitz, возможно, мы могли бы создать какой-нибудь флаг или переменную среды, которая сообщит команде dist, что нужно запускать специальные тесты MSVC.

Но в целом ваш https://go-review.googlesource.com/c/go/+/133946/5 создает исполняемый файл для меня. Например, я могу создать исполняемый файл с помощью 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>

а затем я могу создать исполняемый файл с помощью 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>

Таким образом, сборка с помощью MSVC потребует от пользователей запуска командного файла MS для установки всех переменных среды (см. GOVSVARSPATH в моем выводе) - и это, я полагаю, стандартно и не имеет ничего общего с Go. И set CC=cl . Достаточно просто.

Единственная проблема, которую я вижу в этом подходе, заключается в том, что пользователям MSVC все равно потребуется установить gcc. gcc используется cmd / cgo для обнаружения всех интерфейсов C - эта часть не реализуется с помощью MSVC. Звучит необычно для людей, которые не знают, как работает cmd / cgo, но это то, что есть.

@ianlancetaylor и @bradfitz звучит ли все это разумно, чтобы продвигать это вперед? Должны ли мы попытаться сделать это доступным в go1.13?

Строители, у которых уже установлен MSVC, могут протестировать весь новый код. Другие строители просто пропустят тесты.

Алекс

gcc используется cmd / cgo для обнаружения всех интерфейсов C - эта часть не реализуется с помощью MSVC.

Как это можно преодолеть? В идеале было бы здорово, если бы не требовался gcc, только MSVC.

Как это можно преодолеть?

Части cmd / cgo, которые используют gcc, необходимо переписать для использования MSVC. Если это возможно.

Алекс

Мне было интересно, приближается ли эта функция к внедрению в производство? Я вижу, что он был помечен как 1.13, и это только что вышло. Я пытаюсь создать расширения Python с помощью сборки Go c-archive, которая связана с кодом расширения, но Python требует MSVC.

Я не знаю, в каком состоянии находится эта проблема. Его переносили от выпуска к выпуску, поэтому я собираюсь переместить его в незапланированный. Если попадет в 1.14 - отлично.

Даже с учетом требования двойного компилятора я бы хотел, чтобы текущая реализация была представлена ​​в следующем выпуске. По крайней мере, это позволяет компилировать исполняемые файлы / библиотеки с помощью MSVC, что лучше, чем ничего.

Даже с учетом требования двойного компилятора я бы хотел, чтобы текущая реализация была представлена ​​в следующем выпуске.

Думаю, это была бы хорошая «бета» реализация. Это позволит избавиться от ошибок и начать созревание реализации. Что еще нужно сделать, прежде чем он пройдет серьезную проверку?

Итак, с моей точки зрения и того, что я могу вспомнить из последнего раза, когда я смотрел на это (~ 6 месяцев назад), было около дюжины элементов очистки, которые необходимо было выполнить для процесса проверки кода. Дополнительная работа может также потребоваться для дедупликации некоторых тестов, которые в основном были скопированы с очень незначительными изменениями для работы с другим набором инструментов. Также необходимо просмотреть и отключить определенные предупреждения msvc.

Основные нерешенные проблемы включают:

Мы не можем проводить анализ типов без gcc, для этого нет простого или немедленного решения.

Завершение настройки и того, как все будет работать для строителей.

Я считаю, что за последние 6 месяцев в компилятор и компоновщик были внесены довольно значительные изменения, которые могут серьезно повлиять на текущую работу, проделанную для этого, но я не смог подтвердить это. Из-за сложности и высокой кривой обучения навигации по компилятору / компоновщику / инструментальной цепочке Go мне может потребоваться значительное время, чтобы набрать скорость, достаточную для того, чтобы оценить влияние любых изменений на этот объем работы.

Нет поддержки для сложных числовых типов. MSCV C lib просто несовместимы. Я считаю, что есть способ исправить это с помощью C ++, но я не уверен, возможно, кто-то из MS, знакомый с цепочками инструментов MSVC, может вмешаться.

К сожалению, жизнь и другие проекты довольно сильно мешают мне уделять этому больше времени, но я постараюсь потратить на это некоторое время в ближайшие недели.

@manbearian эта проблема

@ kesmit13 и @mxplusb

Этот

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

- это последний @cchamplin .

Моя текущая озабоченность по поводу кода заключается в том, что неясно, как его использовать. Какую команду вы запускаете? Как нужно настроить мою среду?

Я думаю, что следующий шаг - это попытаться использовать этот код и посмотреть, смогут ли они его использовать. Если это сработает, то шаги необходимо задокументировать, чтобы другие тоже могли использовать код. Может быть, это слишком сложно или не работает. Затем нам нужно соответствующим образом скорректировать код.

Как только мы будем довольны текущим состоянием кода, мы должны переустановить его на master. При изменении было скорректировано слишком много разных файлов, поэтому перебазировать будет непросто. Возможно, мы могли бы скорректировать изменение, чтобы сделать меньше изменений, чтобы было легче перебазировать.

Алекс

@mxplusb @ kesmit13 Текущая реализация была перебазирована по отношению к мастеру, и ее можно найти здесь: https://go-review.googlesource.com/c/go/+/133946/6

@alexbrainman

Моя текущая озабоченность по поводу кода заключается в том, что неясно, как его использовать. Какую команду вы запускаете? Как нужно настроить мою среду?

Я согласен с тем, что необходимо добавить документацию о том, как это использовать. Я не совсем уверен, куда его поставить, дайте мне знать, если у вас есть мысли. Idk, если он должен находиться в документации cmd / go для сборки / запуска через MSVC, или если он должен находиться в документации CGO, или, может быть, в другом месте?

Многие тесты не используют gcc. Когда тесты пакетов запускаются дважды без причины, это пустая трата времени людей / компьютеров. Как видно из # 20982 (комментарий), тесты архивов / zip-пакетов выполнялись дважды - я не вижу необходимости во втором запуске.

Я не уверен, как это организовать, но, возможно, вам следует заменить вызов go tool dist test в run.bat, чтобы выполнить только набор тестов, необходимых для тестирования сборки MSVC. См., Например, команду go tool dist test -h о том, как выбрать только некоторые конкретные тесты. @bradfitz, возможно, мы могли бы создать какой-нибудь флаг или переменную среды, которая сообщит команде dist, что нужно запускать специальные тесты MSVC.

Это изменение уже включает переменную среды, добавленную в dist, чтобы он знал, что мы делаем вещи MSVC "GO_TEST_TESTINGMSVC", я полагаю. В чем я не уверен, так это в том, как мы будем фильтровать тесты, которые будут выполняться, до тех вещей, на которые может повлиять только MSVC, если мы не запустим все тесты дважды. Потенциально просто ограничивая это тестами, связанными с CGO, но я считаю, что тесты CGO есть повсюду, и я не знаю, есть ли у dist механизм для их фильтрации?

Я не совсем уверен, куда его поставить, дайте мне знать, если у вас есть мысли.

Я думаю, прежде чем обновлять какую-либо документацию, вы должны просто описать здесь, как создавать Cgo-код с помощью MSVC. Для @mxplusb и @ kesmit13, чтобы они могли попробовать ваши изменения.

Например, чтобы использовать gcc для создания кода Cgo, я

  1. отрегулируйте мой% PATH%, чтобы включить gcc.exe
  2. сначала соберите Go, запустив make.bat из каталога %GOROOT%\src
  3. используйте стандартные команды go build и go install

Как мне сделать то же самое с MSVC?

В чем я не уверен, так это в том, как мы будем фильтровать тесты, которые будут выполняться, до тех вещей, на которые может повлиять только MSVC, если мы не запустим все тесты дважды. Потенциально просто ограничивая это тестами, связанными с CGO, но я считаю, что тесты CGO есть повсюду, и я не знаю, есть ли у dist механизм для их фильтрации?

Я бы начал с каталога% GOROOT% \ misc \ cgo. Какой бы источник вы ни построили, вы должны построить. Все, что выше, зависит от вас.

Алекс

@cchamplin, извините за задержки, я сделаю все возможное, чтобы протестировать его на этой неделе и расскажу, как это происходит.

Привет, ребята, извините за опоздание на вечеринку ... Я могу попытаться ответить на вопросы о функциональности MSVC или направить вас к людям, которые могут. Я прочитал разговор, но, к сожалению, я недостаточно знаком с go, чтобы понять, какие функции GCC требуются, которые могут отсутствовать или не отсутствовать в MSVC.

Привет народ,
Выпущена ли эта функция в Go 1.14?
В случае выпуска, пожалуйста, поделитесь любыми доступными документами, чтобы использовать их.
Если он еще не выпущен, есть ли идеи, когда он будет выпущен?
С нетерпением жду поддержки MSVC.
Заранее спасибо :)

Привет, никто никогда не ответил на мой запрос о дополнительной информации, поэтому я не уверен, что нужно. Может кто-нибудь заполнить меня, пожалуйста?

К сожалению, я не знаю, активно ли кто-нибудь работает над этим вопросом.

Привет, никто так и не ответил на мой запрос о дополнительной информации, ...

Привет @manbearian

Что это за запрос? Какая информация вам нужна?

Алекс

Я был отмечен ранее в этой ветке для информации, но я не знаю, что люди ищут, и не смог мне помочь. Если помощь не нужна - отлично. Просто дайте мне знать.

Просто дайте мне знать.

@manbearian

Спасибо за ваше предложение. Я не знаю, кто тебя пометил. Если им все еще нужна помощь, они снова отметят вас.

Алекс

Если он еще не выпущен, есть ли идеи, когда он будет выпущен?
С нетерпением жду поддержки MSVC.

@ dhinesherode91

Код есть и готов; Я считаю, что единственное, что действительно сдерживает это, - это люди, тестирующие изменения и предоставляющие отзывы, чтобы они могли быть должным образом рассмотрены и одобрены. Однако я не решаюсь перенастроить изменения поверх текущего мастера. Я проделывал это 5-6 раз, и это требовало очень много времени, а потом я не получал никаких тестов / отзывов. Если дополнительные стороны не захотят участвовать в тестировании, проблема может быть закрыта.

Если дополнительные стороны не захотят участвовать в тестировании, проблема может быть закрыта.

@cchamplin рассчитывает на меня для тестирования / отладки ваших изменений. У меня нет опыта работы с набором инструментов to go, но я просмотрел ваши коммиты, и они кажутся довольно хорошо структурированными и задокументированными.

@cchamplin Приятно слышать, что часть реализации завершена.
Мне интересно участвовать в тестировании, но я новичок в GoLang, а также хорошо разбираюсь в API Windows (началось за несколько недель до этого). Я планировал работать с windows api на MS C ++, так как похоже, что для него доступно множество официальных ресурсов. Но затем я начал искать язык (для моего системного программирования), на котором я мог бы использовать его для своего многоплатформенного системного программирования, и я впечатлен GoLang. Всегда готов к участию с моей стороны и очень нуждается в руководстве.

@cchamplin, если вы перебазируете, я попробую построить поверх него. Я бы хотел отказаться от требования mingw64 в некоторых моих проектах на работе. Все мои инструменты сборки настроены для MSVC, поэтому мне не пришлось бы ничего делать, кроме как использовать ваш патч.

@cchamplin также, я просмотрел ваши CL и не нашел ничего для инструмента cgo, поэтому я начал свой собственный патч. Есть ли предварительная работа?

@ericlagergren

@cchamplin также, я просмотрел ваши CL и не нашел ничего для инструмента cgo, поэтому я начал свой собственный патч. Есть ли предварительная работа?

Не уверен, что я понимаю, на https://go-review.googlesource.com/c/go/+/133946/6 многие из связанных коммитов напрямую касаются части cgo Go в той или иной степени.

@ccahoon, ладно, я, должно быть, скучал по ним. Если бы инструмент cgo не был обновлен, я бы предложил это сделать.

@ericlagergren

Я бы хотел отказаться от требования mingw64 в некоторых моих проектах на работе

Просто к вашему сведению. В

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

изменения по-прежнему нуждаются в Mingw, чтобы работать. Для использования изменения @cchamplin вам потребуются установленные инструменты Mingw и MSVC.

Алекс

@cchamplin , а зачем Мингв все еще нужен? Что потребуется для удаления этой зависимости?

@alexbrainman Я оговорился. Прямо сейчас мы должны использовать MSYS2 (который включает mingw64), потому что для процесса сборки без MSVC требуются автоинструменты. Было бы здорово отказаться от этого . Но также, как сказал @cglong , я не уверен, почему для этого также потребуется mingw64.

@ericlagergren @cglong CGO необходимо собрать и иметь доступную информацию о типе кода C, с которым он компилируется. У GCC есть флаг, который выводит данные типа в удобном для анализа формате. Насколько мне известно, MSVC не имеет возможности предоставлять ту же информацию. Создание инструментария в go потребует не только кода для лексирования / анализа кода C и C ++, но также для понимания и оценки директив препроцессора. Создать такое в Go было бы довольно сложно. Возможно, где-то уже есть библиотека, которую мы могли бы придумать, как ее принять?

@cchamplin gotcha , вот что я понял. Я знаю сторонние библиотеки, такие как libclang и cznic / cc. Но, к сожалению, libclang огромен, а cznic / cc не тестировался в Windows или macOS. PDB не предоставляет достаточно информации?

CGO необходимо собрать и иметь доступную информацию о типе кода C, с которым он компилируется. У GCC есть флаг, который выводит данные типа в удобном для анализа формате. Насколько мне известно, MSVC не имеет возможности предоставлять ту же информацию.

Возможно, @manbearian сможет дать здесь какие-нибудь указатели?

Я бы не сказал, что GCC испускает данные типа вывода в специальном формате. Он выдает отладочные данные DWARF, предназначенные для отладчиков, и cgo считывает эти данные с помощью пакета debug / dwarf. Предположительно, MSVC также имеет формат отладки. Если этот формат где-либо задокументирован, мы могли бы прочитать его, используя cgo, так же, как мы делаем данные DWARF.

@ianlancetaylor MSVC может Https://github.com/Microsoft/microsoft-pdb.

FWIW, чтение отладочных данных MSVC - это то, о чем я говорил, когда упомянул инструмент cgo в https://github.com/golang/go/issues/20982#issuecomment -648462003

Я бы не сказал, что GCC испускает данные типа вывода в специальном формате. Он выдает отладочные данные DWARF, предназначенные для отладчиков, и cgo считывает эти данные с помощью пакета debug / dwarf. Предположительно, MSVC также имеет формат отладки. Если этот формат где-либо задокументирован, мы могли бы прочитать его, используя cgo, так же, как мы делаем данные DWARF.

@ericlagergren @ianlancetaylor
Так что нам действительно нужны данные DWARF, которые составляют большую его часть. Однако теоретически мы могли бы получить ту же информацию из данных PDB.

Однако я конкретно имел в виду не только данные DWARF, которые производит GCC, но и вывод команды gcc -E -dM, которая выводит все значения #define после предварительной обработки. Возможно, что PDB сам по себе может предоставить ту же информацию ... я скептически отношусь к тому, сможем ли мы заставить MSVC выгружать отладочную информацию / информацию о типе в любом качестве без необходимости фактической компиляции код. Прямо сейчас CGO делает именно это с GCC.

По памяти / EP / d1PP должен выдавать что-то похожее на -E -dM.

По памяти / EP / d1PP должен выдавать что-то похожее на -E -dM.

Если это так, то, я полагаю, / d1PP - недокументированный флаг? Я никогда раньше этого не видел. Это просто оставило бы получение информации об аналогичном типе заранее.

@cchamplin да, это недокументировано. По-видимому, многие флаги / dXXX. Использование недокументированных флагов - неудача, но (IMO), по крайней мере, для Windows это не так уж и плохо. Я видел, как разработчики MSVC STL говорили об этом в ветке Reddit, но это также повсюду в Интернете.

Может ли кто-нибудь дать мне краткое описание текущего состояния поддержки MSVC? Я не очень разбираюсь во всем этом низкоуровневом компиляторе. Просто у меня есть библиотека go, которую я хочу использовать из C # / UWP, и она уже работает с go build и buildmode c-shared. НО: это приложение никогда не будет принято Магазином Windows, поскольку сгенерированная DLL из go пропускает некоторые флаги компилятора / компоновщика, которые (я предполагаю) могут быть установлены только с помощью цепочки инструментов MSVC.

Итак: как я могу проверить это здесь? Любой совет приветствуется! Спасибо!

это приложение никогда не будет принято Магазином Windows, поскольку сгенерированная DLL из go пропускает некоторые флаги компилятора / компоновщика, которые (я предполагаю) могут быть установлены только с помощью MSVC-toolchain.

@TopperDEL сообщает ли Магазин Windows, какие флаги компилятора отсутствуют? Если mingw-64 поддерживает их, вы всегда можете использовать -extldflags с правильными флагами при сборке dll.

@qmuntal Да, это так:
«Примените необходимые параметры компоновщика - SAFESEH, DYNAMICBASE, NXCOMPAT и APPCONTAINER - при связывании приложения».

Я уже пробовал
go build -ldflags="-s -w '-extldflags=-Wl,--dynamicbase,--high-entropy-va'" -o storj_uplink.dll -buildmode c-shared

Но это ничего не изменило в отношении отправки в магазин. И, насколько я понимаю, по крайней мере SAFESEH - это специфическая вещь для MSVC, верно?

«Примените необходимые параметры компоновщика - SAFESEH, DYNAMICBASE, NXCOMPAT и APPCONTAINER - при связывании приложения».

Я не знаю простого способа включить флаги SAFESEH или APPCONTAINER в Mingw-w64, возможно, этот проект https://github.com/status-im/mingw-windows10-uwp может дать вам некоторые рекомендации.

С другой стороны, DYNAMICBASE и NXCOMPAT будут включены по умолчанию в go 1.16 (см. # 41421), но уже могут использоваться с -extldflags как уже упоминалось, на самом деле я делаю это для некоторых проектов.

@qmuntal Спасибо! Так что, по крайней мере, мои extldflags выше должны быть правильными?
Я посмотрю mingw для windows 10-uwp.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги