How to compile static binary? - d

DMD 2.60 on Ubuntu 12.04 ...
I want to create a static binary, so that I can run it in an ages old environment.
dmd doesn't have '-static' flag.
I tried passing '-static' flag to the linker with "dmd -L-static ..." - get error message
/usr/bin/ld: cannot find -lgcc_s
Compiling C code with "gcc -static ..." works fine.
Is it something I miss ?
Thanks !

It doesn't currently work if you use dmd to link due to how it passes the linker flags to the linker. You need to build everything with -c to generate object files and then link those manually with either gcc or ld.
I should point out though that in general, statically linking glibc is considered to be a bad idea. It may very well work and be the correct solution in your case, but it definitely has potential issues (I don't remember the details though). So, you probably shouldn't do it unless you actually need to.

Related

Difference between add_compile_options and add_link_options also flags each option supports

I've been using a .bat file to build my applications for years. Recently, switched to CMake for it's elegancy and I ran into a situation where I had to guess the flags that I should put into CMake's add_link_options and add_compile_options
Example flags that I've used in my BAT file,
-s WASM=1 --bind -s MODULARIZE=1
And, In CMake this flags have become (After trial and error),
add_compile_options("SHELL: -s WASM=1")
add_link_options("SHELL: --bind")
add_link_options("SHELL: -s MODULARIZE=1")
Honestly, I can't find any information regards flags that add_link_options and add_compile_options supports.
I know what is a linker is but lost when it comes to add_link_options or linker flags.
I'm used to compile everything in single line and now in CMake everything appear to be involve separate steps.
I am not sure what your problem is, but here is a full working sample from a Wasm project that sets project-wide strict mode and disabling of exception support:
if (EMSCRIPTEN)
add_compile_options(-fno-exceptions "SHELL:-s STRICT=1")
add_link_options("SHELL:-s STRICT=1")
endif()
Note in particular that, as it has a [compile+link] marker in the emscripten settings, -s STRICT=1 has to be used both for compiling and for linking, thus it appears in each.
The if(EMSCRIPTEN) around is there because this project can also be built for Windows and Linux.
The options you can pass to the compiler or linker depends on which compiler or linker you use. For example if you fork GCC and add a -Wstackoverflow-copy-pasta option, you can pass that option to add_compile_options(), but other people using standard GCC cannot.
So the answer to your question seems to be, read your compiler and linker documentation.

linaro compiler cannot find library when adding -static

I am trying to statically cross-compile an Application for ARM using the Linaro-Toolchain 7.1.1 . The final elf file is dependent on two shared-objects. I need to statically compile the application because there are dependencies that are not available on my target-system (eg. libstdc++). The -L and -I flags are in the makefile and everything works normally without the -static Flag. However when i use the -static flag, my linaro-linker tells me that it cannot find the dependencies, even though i know they are there as liba.so and libb.so. Any help or point to literature is appreciated, i feel like i did not fully understand what -static does, eventhough i did my research online.
Thanks
Thanks to your comments i was able to solve my problem and understand why i had it.
As user RPGillespie mentioned, the -static flag needs archived (libx.a) versions of the objects, so i had to compile the .o files to .a files using the ar-tool from the linaro toolchain.
Furthermore, as user RPGillespie refered me to, i had to specify the archives x using -l:libx.a instead of -lx in the g++ command.
Also it took me some time to notice that if the x.a files are not present, the linker will link dynamically. In my makefile the executable was compiled before the x.a file was available (because i just modified the makefile used to build the x.so).

What determines if a 32-bit library built on a 64-bit machine needs x86_64 or i386 dependencies?

I am updating some old C++ projects to build on a 64-bit Linux machine for the first time, and I don't have much Linux experience. I need to build everything as 32-bit binaries, so I'm building everything with -m32 in the compiler and linker flags. I'm finding that, when linking to their dependencies, some must link with i386 shared objects, and some must link with x86_64 shared objects. If I only include the wrong folder in the linking path (-L/path/to/wrong/folder), it says
/usr/bin/ld: skipping incompatible xxx.so when searching for -lxxx
which I've come to understand means the architecture doesn't match what I'm trying to build.
The makefiles are nearly identical for two such differing projects, so it doesn't seem like I'm doing something obviously wrong there, and -m32 appears in the calls to gcc and g++ in the terminal. What could be causing this difference? Should I be concerned, or is it typical for this to happen?
Let me know if more information is needed to answer; I'm not really sure, due to inexperience with Linux and gcc, so apologies in advance.
Thanks #Wyzard and #duskwuff for the tips. I was indeed able to find my problem by using file on my .o files. It was just a silly mistake; I had inadvertently reverted the changes I made to one of the projects' make files, which included adding the -m32 flag. I think I misunderstood what the "x86_64" libraries are for, and that confused me (I had assumed it meant "32-bit process for 64-bit machine").

Undefined reference to .. error (Linux) - Compiles fine in OSX

Have wasted almost full 4 days trying to compile this package. It compiles fine in OSX 10.6, but gives Undefined reference errors when I try to compile it on a linux (Kubuntu 10.04, 3.8.0.27 kernel) machine.
The error seem to be that the makefiles are ordered wrong, but AFAIK, I am the only one having trouble compiling it. So I'm trying to find what's making the difference. The software package is quite big and editing the Makefiles and moving 30-50 libraries here and there doesn't seem like a good idea.
Here's the differences I think I found so far
Compiler - gcc-4.7 (Linux) and llvm-gcc-4.2 (OSX)
Compiler flags --shared (Linux) and -dynamic -dynamiclib -undefined dynamic_lookup (OSX)
Anyone have any suggestions?
I tried using clang++ and llvm-gcc-4.7 as the compiler, but I think it still used the same linker (ld?). So I could try to specify to use llvm? How do I do that?
is --shared flag somehow different from the dynamic -dynamiclib -undefined dynamic_lookup flags in OSX?
Does the linux kernel or distribution matter? (I think they compiled it fine on a CentOS machine)
Please help.
Thanks a lot.
Compiled it with gcc 4.4 and worked flawlessly. I guess the order doesn't matter on 4.4 for the given package.
The undefined references type of errors can be caused by a symbol not being compiled in, not being linked or being linked out of order. The way to debug this is to check the linker line, the symbol that the linker complains about. The error message will probably tell you what object file has the dependency.
Now, you need to find out whether the symbol is compiled or linked, for that you will need to find if it is in any of the object files or in any of the libraries and which. You can use the nm command line tool to list the symbols that are defined in any given .o or library. If the symbol is not there, then you need to figure out what to add to the linker line and that will solve it.
If the symbol appears in one library, then identify which of the libraries depends on that symbol (from the linker error message) and the library that contains it. The former must be listed before the latter in the linker command line (assuming static linking).
As a simple hack, although I recommend against it, you can instruct the gcc linker to do multiple passes by using the --start-group and --end-group command line options. Although I really recommend that you figure out the order of dependencies, as that will also give you a better insight into your project.

C++ GNU linker errors

I'm trying to compile my program on Windows via Cygwin with the compilation command:
g++ ping.cpp -I./include -L./lib -lchartdir50
I'm using an API called ChartDirector which draws charts for me. I've never linked libraries this way before (usually I do it through Visual Studio), so I’m a little new to this. I've got a really large list of errors, so I won't list them all, but I’ll list one just to clarify the type of linker errors I’m getting:
(.text$_ZN9BaseChartD1Ev[BaseChart::~BaseChart()]+0x4f): undefined reference to '_CBaseChart_destroy'
All of these are undefined reference to 'xxx' errors.
I've got a bunch of header files in ./include and a library called chartdir50.lib in ./lib.
What’s wrong with my compilation line?
I never use that library before, but when I googled it, I noticed that other people trying like -lchartdir instead of -lchartdir50, so you should give it a try.
I am not sure, but .lib have been compiled with Visual C++?
If yes, I don't think it's compatible with GCC. You have to compile the library with GCC/G++ and use that file or to use a compatible binary if you don't have access to the source.
Hmm... that’s odd. I'm using a 64-bit system, but for some reason I tried it with the 32-bit library and it compiled. Thanks!
I assume that library was also created with GCC.
As far as I know, .lib is a static library, so you don't have to point it with the -l compiler switch.
Just use it as another file on the command line, like
g++ ping.cpp -I./include -L./lib {path to lib here}/chartdir50.lib