是否可以使用 ocamlopt ghc 和 gcc 编译器创建可移植的 x86-64 Linux 可执行文件?
is it possible to create portable x86-64 Linux executable with ocamlopt ghc and gcc compiler?
在我的 NixOS x86-64 发行版上,我使用以下方法创建了四个 "hello world!" 应用程序:
- ocamlopt 编译器
- ghc 编译器
- gcc 编译器
- 作为编译器
我的生成文件:
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
并且所有四个在本机上都可以正常工作
但我无法在另一台 x86-64 Linux(准确地说 - Lubuntu x86-64)计算机上执行前三个应用程序 - 我的应用程序无法在目标机器上找到系统库,因此系统告诉我文件不存在
但是文件存在,我可以通过 readelf utilite 读取它:
为 gcc 创建的可执行文件:
$> 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)
对于 ghc 创建的可执行文件:
$> 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)
为 ocamlopt 创建的可执行文件:
$> 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)
我用汇编程序创建的可执行文件没有这个问题:
$> 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
如您所见,没有对 glibc.so.x 库的引用
我的问题是:是否可以使用 gcc、ghc 和 ocamlopt 创建这样的 "not a dynamic executable" 应用程序文件?一些编译器的选项?也许应用程序文件夹中有一些库?
我无法访问另一台机器 - 我只能向最终用户提供 tar.gz 存档 - 仅此而已。绝对不希望用户在 his/her 机器
上安装 ghc 或 ocaml
有什么建议吗?
仅供参考:源文件
haskell:
module Main where
main = putStrLn "hello world!"
ocaml:
print_string "hello world!" ;;
print_newline () ;;
ansi C:
#include <stdio.h>
int
main ()
{
puts ("hello world!") ;
}
asm:
.code64
.global _start
.text
_start:
movl $len, %edx
movl $msg, %ecx
movl , %ebx
movl , %eax
int [=19=]x80
movl [=19=], %ebx
movl , %eax
int [=19=]x80
.data
msg: .ascii "hello, world!\n"
len = . - msg
我自己没有测试过,但我认为 -ccopt
(from ocamlopt
) and -static
(from gcc
) 的组合可以解决问题。
- 来自
ocamlopt
手册
-ccopt option
Pass the given option to the C compiler and linker. For instance,-ccopt -Ldir causes the C linker to search for C libraries in directory dir.
- 来自
gcc
手册
-static
On systems that support dynamic linking, this overrides -pie and prevents linking with the shared libraries. On other systems, this option has no effect.
在我的 NixOS x86-64 发行版上,我使用以下方法创建了四个 "hello world!" 应用程序:
- ocamlopt 编译器
- ghc 编译器
- gcc 编译器
- 作为编译器
我的生成文件:
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
并且所有四个在本机上都可以正常工作
但我无法在另一台 x86-64 Linux(准确地说 - Lubuntu x86-64)计算机上执行前三个应用程序 - 我的应用程序无法在目标机器上找到系统库,因此系统告诉我文件不存在
但是文件存在,我可以通过 readelf utilite 读取它:
为 gcc 创建的可执行文件:
$> 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)
对于 ghc 创建的可执行文件:
$> 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)
为 ocamlopt 创建的可执行文件:
$> 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)
我用汇编程序创建的可执行文件没有这个问题:
$> 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
如您所见,没有对 glibc.so.x 库的引用
我的问题是:是否可以使用 gcc、ghc 和 ocamlopt 创建这样的 "not a dynamic executable" 应用程序文件?一些编译器的选项?也许应用程序文件夹中有一些库?
我无法访问另一台机器 - 我只能向最终用户提供 tar.gz 存档 - 仅此而已。绝对不希望用户在 his/her 机器
上安装 ghc 或 ocaml有什么建议吗?
仅供参考:源文件
haskell:
module Main where
main = putStrLn "hello world!"
ocaml:
print_string "hello world!" ;;
print_newline () ;;
ansi C:
#include <stdio.h>
int
main ()
{
puts ("hello world!") ;
}
asm:
.code64
.global _start
.text
_start:
movl $len, %edx
movl $msg, %ecx
movl , %ebx
movl , %eax
int [=19=]x80
movl [=19=], %ebx
movl , %eax
int [=19=]x80
.data
msg: .ascii "hello, world!\n"
len = . - msg
我自己没有测试过,但我认为 -ccopt
(from ocamlopt
) and -static
(from gcc
) 的组合可以解决问题。
- 来自
ocamlopt
手册
-ccopt option Pass the given option to the C compiler and linker. For instance,-ccopt -Ldir causes the C linker to search for C libraries in directory dir.
- 来自
gcc
手册
-static On systems that support dynamic linking, this overrides -pie and prevents linking with the shared libraries. On other systems, this option has no effect.