is it possible to create portable x86-64 Linux executable?

-----------------------

on my NixOS x86-64 disto i cerated four "hello world!" applications using:

   - ocamlopt compiler 
   - ghc compiler
   - gcc compiler
   - as compiler

my makefile:

      ocaml:
        ocamlopt mytest.ml -o ocaml_test
        
      haskell:
        ghc mytest.hs -o haskell_test

      ansiC:
        gcc mytest.c -o ansiC_test 

      asm:
        as -o asm_test.o mytest.s 
        ld -s -o asm_test asm_test.o

and all four work fine on the native machine

but i cannot execute the first three applications on the other x86-64 Linux computer - my applications cannot find system libraries on the target machine, so the system tells me that file does not exist

but the file exists and i can read it by readelf utilite:

----------------------------------------

for gcc created executable:

$> readelf -l ansiC_test 

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

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
                 0x0000000000000050 0x0000000000000050  R      0x1
      [Requesting program interpreter: /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000004f0 0x00000000000004f0  R      0x1000

$> ldd ansiC_test 
  linux-vdso.so.1 (0x00007ffee735f000)
  libc.so.6 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libc.so.6 (0x00007f8db6ca8000)
  /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 => /nix/store/xvj2l5llpmcgx99cl37v5xqpazs38195-glibc-multi-2.27/lib/ld-linux-x86-64.so.2 (0x00007f8db6e60000)

----------------------------------------

for ghc created executable:

$> readelf -l haskell_test

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

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
                 0x0000000000000050 0x0000000000000050  R      0x1
      [Requesting program interpreter: /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000


$> ldd haskell_test 
  linux-vdso.so.1 (0x00007ffe7840a000)
  libm.so.6 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libm.so.6 (0x00007f13eb093000)
  libgmp.so.10 => /nix/store/7mrq5v4nnqfkv1ka7a0kdw9mzvqs5w3c-gmp-6.1.2/lib/libgmp.so.10 (0x00007f13eaffd000)
  librt.so.1 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/librt.so.1 (0x00007f13eaff3000)
  libdl.so.2 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libdl.so.2 (0x00007f13eafee000)
  libffi.so.6 => /nix/store/kbbiky87bsdndh63m7919sxkf3gsh5zq-libffi-3.2.1/lib/libffi.so.6 (0x00007f13eafe1000)
  libpthread.so.0 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libpthread.so.0 (0x00007f13eafbe000)
  libc.so.6 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libc.so.6 (0x00007f13eae08000)
  /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 => /nix/store/xvj2l5llpmcgx99cl37v5xqpazs38195-glibc-multi-2.27/lib/ld-linux-x86-64.so.2 (0x00007f13eb22b000)

----------------------------------------

for ocamlopt created executable:

$> readelf -l ocaml_test

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

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000004002a8 0x00000000004002a8
                 0x0000000000000050 0x0000000000000050  R      0x1
      [Requesting program interpreter: /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000fb58 0x000000000000fb58  R      0x1000

$> ldd ocaml_test 
  linux-vdso.so.1 (0x00007ffc90657000)
  libm.so.6 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libm.so.6 (0x00007f1b01f0b000)
  libdl.so.2 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libdl.so.2 (0x00007f1b01f06000)
  libc.so.6 => /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libc.so.6 (0x00007f1b01d50000)
  /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/ld-linux-x86-64.so.2 => /nix/store/xvj2l5llpmcgx99cl37v5xqpazs38195-glibc-multi-2.27/lib/ld-linux-x86-64.so.2 (0x00007f1b020a3000)

----------------------------------------

and i dont have this problem with asembler created executable:

$> readelf -l asm_test

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

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000140 0x0000000000000140  R      0x1000
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x0000000000000022 0x0000000000000022  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000
                 0x000000000000000e 0x000000000000000e  RW     0x1000
  NOTE           0x0000000000000120 0x0000000000400120 0x0000000000400120
                 0x0000000000000020 0x0000000000000020  R      0x8

 Section to Segment mapping:
  Segment Sections...
   00     .note.gnu.property
   01     .text
   02     .data
   03     .note.gnu.property


$> ldd asm_test
  not a dynamic executable

as you can see no referencies to ld-linux-x86-64.so.2 library

--------------------------------

my question is: is it possible to create such "not a dynamic executable" application file with gcc, ghc and ocamlopt?  some compiler's options?  maybe some libs in the folder of application?

i dont have access to another machine - i can only provide tar.gz arhive to the end user - thats all. and absolutly no hope that the user will install ghc or ocaml on his/her machine

any suggestions?


FYI: src files

--------------------------------------------------

haskell:

        module Main where

        main = putStrLn "hello world!"

--------------------------------------------------

ocaml:

        print_string "hello world!" ;;
        print_newline () ;;

--------------------------------------------------

ansi C:

        #include 

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

--------------------------------------------------
  
asm:

        .code64
        .global _start 

        .text 

        _start:
                  movl    $len, %edx
                  movl    $msg, %ecx
                  movl    $1, %ebx 
                  movl    $4, %eax 
                  int     $0x80   

                  movl    $0, %ebx       
                  movl    $1, %eax      
                  int     $0x80        

        .data     

                 msg: .ascii    "hello, world!\n"
                 len = . - msg             

----------------------------------------------------------------------------------

today i met really interesting problem with my NixOS distro. i just wanted to create statically compiled ocaml progam and couldnt do that. then i tried to do that with ansi C canonical toy test "hello world!" application:



$> cat mytest.c
#include 

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



my distro:

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

$> gcc -v
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with:
Thread model: posix
gcc version 7.4.0 (GCC)



cannot produce static exec :

$> 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
any ideas?

usual "dynamically linked" program hello gcc generates - no problem

no problem with such things on Lubuntu. i was adviced to do such thing on different distro and test that exec is running on NixOS. i did it - produce exec with gcc on Lubuntu and start it on NixOS. so i think that the matter not in gcc but in NixOS

how NixOS treats this problem - generation statically compiled exec files?

and of couse i interested in results concerning ocamlopt compiler rather then gcc but i think that the problem is common for all compilers (i tried haskell ghc too btw - with just the same result)

brgs



UDP: from discussion on another thread:

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


can this be the reason?

UPD2: as concerning ocamlopt:

source file

$> cat mytest.ml
print_string "hello world!" ;;
print_newline () ;;
as you can see no special calls to anything. let try to make static exec:

$> 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
so ld just cannot link to static version of libc. and i cannot find libc.a in the hole system

any suggetions?

----------------------------------------------------------------------------------------


in https://vaibhavsagar.com/blog/2018/01/03/static-haskell-nix/ explained as you could obtain 
statical versions of sys libraries

nix-shell config file:


let
  pkgs = import  {} ;
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
  ] ;
}

after that in nix-shell copy needed sys libs into your folder

good with gcc:
  
gcc -static -L/home/.local/lib/ mytest.c -o ansiC_test

not so good but maybe working with ocaml:

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

dont work with ghc though :

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