как создать исполняемый файл stati c на NixOS - PullRequest
0 голосов
/ 28 мая 2020

Сегодня я встретил действительно интересную проблему с моим дистрибутивом NixOS. Я просто хотел создать статически скомпилированную программу ocaml и не мог этого сделать. затем я попытался сделать это с помощью ANSI C canonical toy test "hello world!" приложение:

$> cat mytest.c 
#include <stdio.h>

int
main ()
{
  puts ("hello world!") ;
}

мой дистрибутив:

$> uname -a
Linux cat 4.19.36 #1-NixOS SMP Sat Apr 20 07:16:05 UTC 2019 x86_64 GNU/Linux

компилятор:

$> gcc -v
Using built-in specs.
COLLECT_GCC=/nix/store/myq0x6mjbdzxr9fckqn6kgy89kz19nkp-gfortran-7.4.0/bin/gcc
COLLECT_LTO_WRAPPER=/nix/store/myq0x6mjbdzxr9fckqn6kgy89kz19nkp-gfortran-7.4.0/libexec/gcc/x86_64-unknown-linux-gnu/7.4.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: 
Thread model: posix
gcc version 7.4.0 (GCC)

не может создавать stati c exe c:

$> gcc -static mytest.c -o hello
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

любые идеи?

обычная «динамически связанная» программа hello g cc генерирует - нет проблем

нет проблем с такими вещами в Lubuntu. Мне посоветовали сделать это в другом дистрибутиве и проверить, работает ли exe c на NixOS. Я сделал это - создал exe c с g cc на Lubuntu и запустил его на NixOS. поэтому я думаю, что дело не в g cc, а в NixOS

, как NixOS решает эту проблему - генерацию статически скомпилированных файлов exe c?

и, конечно, меня интересуют результаты, касающиеся ocamlopt компилятора, а не g cc, но я думаю, что проблема общая для всех компиляторов (я тоже пробовал haskell gh c кстати - с тем же результатом)

brgs

UDP: из обсуждения в другой ветке:

  1 @Ston17 You may have the .so but not the .a – norok2 
  2 
  3 yes - i have .so what the difference? can the presence of .a improve the situation? – Ston17
  4 
  5 Yes. You typically need .a library to have the static linking work correctly – norok2


$> find /nix/store/ -name *libc.a.*
$> 

может это быть причиной?

UPD2: что касается ocamlopt:

исходный файл

$> cat mytest.ml
print_string "hello world!" ;;
print_newline () ;;

так как вы не видите никаких специальных вызовов ни к чему. давайте попробуем сделать stati c exe c:

$> ocamlopt -ccopt -static mytest.ml -o ocaml_test
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: cannot find -lm
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: cannot find -ldl
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

, поэтому ld просто не может ссылаться на stati c версию lib c. и я не могу найти lib c .a в дырочной системе

какие-либо предложения?

1 Ответ

0 голосов
/ 28 мая 2020

здесь https://vaibhavsagar.com/blog/2018/01/03/static-haskell-nix/ объясняется, как вы можете получить в NixOS статические версии системных библиотек

файл конфигурации nix-shell:

let
  pkgs = import <nixpkgs> {} ;
in pkgs.buildFHSUserEnv {
  name = "fhs" ;
  targetPkgs = pkgs: with pkgs; [
    pkgs.glibc.static
    pkgs.zlib.static
    pkgs.libffi
    pkgs.libtool
    pkgs.musl
    pkgs.ghc
    pkgs.gcc
    pkgs.ocaml
  ] ;
}

после этого в nix-shell вы запускаете ch root FHS и копируете необходимые системные библиотеки в свою папку и закрываете ch root FHS

и после этого скомпилируете свой файл статически

хорошо с g cc :

$> gcc -static -L/home/.local/lib/ mytest.c -o ansiC_test
$> ldd ansiC_test 
  not a dynamic executable

не очень хорошо, но возможно работает с ocaml:

ocamlopt -ccopt -static -cclib -L/home/.local/lib mytest.ml -o ocaml_test

ocamlopt -ccopt -static -cclib -L/home/nomad/.local/lib mytest.ml -o ocaml_test
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: /nix/store/j1v6kkxq081q4m4fw7gazaf6rb3vy87p-ocaml-4.06.1/lib/ocaml/libasmrun.a(unix.o): in function `caml_dlopen':
/build/ocaml-4.06.1/asmrun/unix.c:273: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

$> ldd ocaml_test 
  not a dynamic executable

не работает с gh c хотя:

ghc -static -optl-static -L/home/.local/lib/ mytest.hs -o haskell_test
[1 of 1] Compiling Main             ( mytest.hs, mytest.o )
Linking haskell_test ...
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: /nix/store/wfgrz42bpcl1r635dasfk7r236hm83az-ghc-8.6.4/lib/ghc-8.6.4/rts/libHSrts.a(Linker.o): in function `internal_dlopen':
Linker.c:(.text.internal_dlopen+0x7): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/nix/store/0y7jmqnj48ikjh37n3dl9kqw9hnn68nq-binutils-2.31.1/bin/ld: cannot find -lffi
collect2: error: ld returned 1 exit status
`cc' failed in phase `Linker'. (Exit code: 1)
make: *** [makefile:5: haskell] Error 1

нормально. ocaml работает:

lubuntu@lubuntu:~/Documents$ ./ocaml_hello_nix 
hello world!

lubuntu@lubuntu:~/Documents$ readelf -l ocaml_hello_nix 

Elf file type is EXEC (Executable file)
Entry point 0x4017a0
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000005d8 0x00000000000005d8  R      0x1000
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x0000000000107275 0x0000000000107275  R E    0x1000
  LOAD           0x0000000000109000 0x0000000000509000 0x0000000000509000
                 0x00000000000db191 0x00000000000db191  R      0x1000
  LOAD           0x00000000001e5140 0x00000000005e6140 0x00000000005e6140
                 0x0000000000008a18 0x000000000001dfe0  RW     0x1000
  NOTE           0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x0000000000000020 0x0000000000000020  R      0x4
  NOTE           0x0000000000000258 0x0000000000400258 0x0000000000400258
                 0x0000000000000020 0x0000000000000020  R      0x8
  TLS            0x00000000001e5140 0x00000000005e6140 0x00000000005e6140
                 0x0000000000000020 0x0000000000000060  R      0x8
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000

                     0x0000000000000000 0x0000000000000000  RW     0x10
      GNU_RELRO      0x00000000001e5140 0x00000000005e6140 0x00000000005e6140
                     0x0000000000002ec0 0x0000000000002ec0  R      0x1

     Section to Segment mapping:
      Segment Sections...
       00     .note.ABI-tag .note.gnu.property .rela.plt 
       01     .init .plt .text __libc_freeres_fn __libc_thread_freeres_fn .fini 
       02     .rodata .eh_frame .gcc_except_table 
       03     .tdata .init_array .fini_array .data.rel.ro .got .got.plt .data __libc_subfreeres __libc_IO_vtables __libc_atexit __libc_thread_subfreeres .bss __libc_freeres_ptrs 
       04     .note.ABI-tag 
       05     .note.gnu.property 
       06     .tdata .tbss 
       07     
       08     .tdata .init_array .fini_array .data.rel.ro .got 

haskell работает. Причина в том, что двоичный пакет NixOS был создан без поддержки FFI. Я установил gh c из исходников, и все стало нормально:

lubuntu@lubuntu:~/Documents$ ./haskell_hello_nix 
hello world!

lubuntu@lubuntu:~/Documents$ readelf -l haskell_hello_nix 

Elf file type is EXEC (Executable file)
Entry point 0x405d40
There are 6 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000188ba4 0x0000000000188ba4  R E    0x1000
  LOAD           0x0000000000188ec0 0x0000000000589ec0 0x0000000000589ec0
                 0x00000000000104c0 0x000000000001ac98  RW     0x1000
  NOTE           0x0000000000000190 0x0000000000400190 0x0000000000400190
                 0x0000000000000020 0x0000000000000020  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  TLS            0x0000000000188ec0 0x0000000000589ec0 0x0000000000589ec0
                 0x0000000000000070 0x00000000000000b8  R      0x8
  GNU_RELRO      0x0000000000188ec0 0x0000000000589ec0 0x0000000000589ec0
                 0x0000000000003140 0x0000000000003140  RW     0x20

 Section to Segment mapping:
  Segment Sections...
   00     .note.ABI-tag .rela.plt .init .plt .text __libc_thread_freeres_fn .fini .rodata .gcc_except_table .eh_frame 
   01     .tdata .data.rel.ro.local .fini_array .init_array .data.rel.ro .preinit_array .got .got.plt .data .tm_clone_table __libc_IO_vtables __libc_atexit __libc_thread_subfreeres .bss __libc_freeres_ptrs 
   02     .note.ABI-tag 
   03     
   04     .tdata .tbss 
   05     .tdata .data.rel.ro.local .fini_array .init_array .data.rel.ro .preinit_array .got 

хорошо. спасибо всем, кто был обеспокоен. Вы экономите мне $ 1028 *

...