Search code examples
cwindowsshellgcccygwin

gcc in Windows cannot compile C program written for Unix/Linux


I am a Unix/Linux newbie who is trying to run a shell script written by a person who left no documentation and has since demised. This script contains line:

./search $opt1 $arg1 < $poly 2>&1 | tee $output

Which is trying to get the file $poly and call program ./search and divert the output to $output.

When I get to this line, I am given message: ./search: cannot execute binary file: Exec format error

search is a C program called from the script and is in the same folder as various other C programs to do with this project. Script and C programs were developed and originally executed on a Unix/Linux box which is no longer available, so I have been asked to try to resurrect this project but under Windows using gcc in NetBeans and cygwin.

The message : ./search: cannot execute binary file: Exec format error is most likely to do with the fact there is no executable file for search. When I try to build the C programs I get the following output:

C:\cygwin64\bin\make.exe -f Makefile
gcc -ansi -g -c cbuild.c
gcc -ansi -g -c complex.c
gcc -ansi -g -c mylib.c
gcc -ansi -g -c poly.c
gcc -ansi -g -c real.c
gcc -ansi -g -c zero.c
gcc -lgmp -lm -lrt -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o
real.o: In function `rabs':
/cygdrive/c/../progs/real.c:9: undefined reference to `__imp___gmpf_abs'
/cygdrive/c/../progs/real.c:9:(.text+0x1e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp___gmpf_abs'
real.o: In function `radd':

I assume that R_X86_64_PC32 refers to the environment I am using. I am using a 64 bit version of Netbeans with gcc 5.4.0 in a 64 bit version of cygwin on Windows 10.

Can anyone advise what I must to to resolve this so that I can build the C programs?


Solution

  • The problem is this:

    gcc -lgmp -lm -lrt -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o
    

    By default, the linker will link libraries and objects in the order specified on the command line, and, when linking a library, will only include symbols needed by things before it on the command line. Since -lgmp is first, there are (as yet) no outstanding symbols (except main), so nothing is included from the library. When later objects need the symbols from it, they won't see them.

    Change the order to

    gcc -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o -lgmp -lm -lrt
    

    and it should work. Alternately, use the -Wl,--as_needed linker option to get the linker to remember earlier libraries and relink them if more symbols from them are referenced by later object files (requires a recent version of the GNU linker -- I have no idea if it works with cygwin).


    This kind of misordering is usually a symptom of a broken Makefile. The normal Makefile structure has a bunch of variables that are set to control the default rules that know how to compile source files and link object files. The two variables relevant for linking are LDFLAGS and LDLIBS, and the difference is that LDFLAGS comes before all the object files on the command line and LDLIBS comes after all the object files.

    So in order to make things work, you need to ensure that all of the -l options and other libraries are in LDLIBS:

    LDLIBS = -lgmp -lrt -lm
    

    and NOT in LDFLAGS