Создание файла объекта с `swift c -emit-object`, также испускающим реализацию` _main` - PullRequest
2 голосов
/ 27 марта 2020

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

swiftc -emit-object bar.swift

, где bar.swift выглядит так:

class Bar {
  var value: Int

  init(value: Int) {
    self.value = value
  }

  func plusValue(_ value: Int) -> Int {
    return self.value + value
  }
}

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

$ cc -o foobar foo.o bar.o
duplicate symbol '_main' in:
    foo.o
    bar.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Это означает, что swiftc добавляет реализацию main к объектному файлу, что можно подтвердить с помощью:

$ nm bar.o | grep _main
0000000000000000 T _main

Насколько я могу судить, эта добавленная функция делает очень мало:

$ otool -tV bar.o
bar.o:
(__TEXT,__text) section
_main:
0000000000000000    pushq   %rbp
0000000000000001    movq    %rsp, %rbp
0000000000000004    xorl    %eax, %eax
0000000000000006    movl    %edi, -0x4(%rbp)
0000000000000009    movq    %rsi, -0x10(%rbp)
000000000000000d    popq    %rbp
000000000000000e    retq
000000000000000f    nop
....snip...

Есть ли способ сказать swiftc -emit-object, чтобы не добавлять эту рудиментарную реализацию main

1 Ответ

2 голосов
/ 28 марта 2020

Короткий ответ

Аргумент командной строки, который мне не хватало, был:

-parse-as-library

Длинный ответ

В своем поиске ответа я обратился к поиску в исходном коде Swift на Github и, если повезет, обнаружил следующий вызов компилятора в наборе тестов:

// RUN: %target-build-swift %S/Inputs/CommandLineStressTest/CommandLineStressTest.swift -parse-as-library -force-single-frontend-invocation -module-name CommandLineStressTestSwift -emit-object -o %t/CommandLineStressTestSwift.o

Согласно swiftc --help, -parse-as-library вызывает компилятор для:

Разбор входных файлов в виде библиотек, а не сценариев

Это доказало свою эффективность, и единственное отличие в экспортируемых символах - это удаление _main:

$ diff -U1 <(swiftc -emit-object -module-name bar -o a.o bar.swift && nm a.o | cut -c18-) <(swiftc -emit-object -parse-as-library -module-name bar -o b.o bar.swift && nm b.o | cut -c18-)
--- /dev/fd/63  2020-03-28 17:13:08.000000000 +1100
+++ /dev/fd/62  2020-03-28 17:13:08.000000000 +1100
@@ -23,3 +23,2 @@
 U __objc_empty_cache
-T _main
 s _objc_classes

и в сгенерированной сборке единственное изменение - удаление кода _main:

$ diff -U1 <(swiftc -emit-object -module-name bar -o a.o bar.swift && objdump -d -no-leading-addr -no-show-raw-insn a.o) <(swiftc -emit-object -parse-as-library -module-name bar -o b.o bar.swift && objdump -d -no-leading-addr -no-show-raw-insn b.o)
--- /dev/fd/63  2020-03-28 17:19:03.000000000 +1100
+++ /dev/fd/62  2020-03-28 17:19:03.000000000 +1100
@@ -1,15 +1,5 @@

-a.o:   file format Mach-O 64-bit x86-64
+b.o:   file format Mach-O 64-bit x86-64

 Disassembly of section __TEXT,__text:
-_main:
-   pushq   %rbp
-   movq    %rsp, %rbp
-   xorl    %eax, %eax
-   movl    %edi, -4(%rbp)
-   movq    %rsi, -16(%rbp)
-   popq    %rbp
-   retq
-   nop
-
 _$S3bar3BarC5valueSivg:
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...