I am trying to get compile some C code from within Cygwin on 64-bit Windows and call the executable using some parameters. The compilation goes through fine (the Makefile is below). But when I run the executable, I get the error cannot execute binary file.
A quick shows that indeed the binary is built for Linux.
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.24,
BuildID[sha1]=0x7d39e30cb249d2047815de23a9df33fccf91a58f, not stripped
How can I change the Makefile so that it compiles for Windows?
Here is the Makefile
.SUFFIXES: .c .u
CC= gcc
CFLAGS = -g -Wall -O3 -DHAVE_INLINE -DGSL_RANGE_CHECK_OFF
# LDFLAGS = -lm -lgsl -latlas -lgslcblas
LDFLAGS = -lm -lgsl -lgslcblas
# LDFLAGS = -lm -lgsl -latlas -lcblas
LOBJECTS= a.o b.o c.o
LSOURCE= a.c b.c c.c
windows: $(LOBJECTS)
$(CC) $(LOBJECTS) -o stm $(LDFLAGS)
clean:
-rm -f *.o
cygwin is 32 bits, not 64 bits. This is the error you get when trying to run a 64 bit program in a 32 bit environment.
edit:
Oh, and you can't compile C for Windows from inside cygwin. There are C compilers for Windows, I know little about them.
Related
I am building a program from a single main.c file.
Errors appear when using make
Note - I have 64 bit library files in a folder lib.
Earlier 32 bit Linux platform I was working on.
Now it's 64 bit Linux version.
CC = gcc
INCLUDES = -I../include
LIBDIRS = -L../lib
LIBFILES = \. -lCAPI32 -lNCCOM -lNCMOCHA -lMOCHA -lMELCFG -lhiredis -lMELWIN
LIBS = $(LIBDIRS) $(LIBFILES)
DEFINES = -D_LINUX
CFLAGS = $(INCLUDES) $(DEFINES) -pthread -g -m32
all:
$(CC). $(CFLAGS) main.c $(LIBS)-ldl
chmod +X a.out
run: all (LD_LIBRARY_PATH=../lib/;. \ export LD_LIBRARY_PATH;\ .a.out)
Clean:
rm -f a.out
Error are:
Skipping incompatible ../lib//libNCAP32.so when searching for -lNCAP32
Cannot find -lNCAP32
a lot of time
Your problem comes from the -m32 option passed to gcc asking it to generate 32bits code.
I guess that the installed libraries are 64bits flavored
Just remove the -m32 from CFLAGS
I am porting a project written in C from a CentOS 7 (Core) to an Ubuntu 20.04.1 LTS (Focal Fossa) system. The project relies heavily on the <cpuset.h> library, and compiles and executes correctly on the CentOS system. However, when I try to use functions from cpuset.h on the Ubuntu system, I get 'undefined reference' errors.
The following code, stored in file test.c, compiles and runs correctly on CentOS:
#define _GNU_SOURCE
#include<stdio.h>
#include <cpuset.h>
int main(){
int x = cpuset_version();
printf("cpuset lib version: %d\n",x );
return 0;
}
How I compile:
gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
Output:
[xxxx#CentOS]$ ./test
cpuset lib version: 3
However, when I try to compile the same test.c file on the Ubuntu system, I get this error:
xxxx#Ubuntu:$ gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
/usr/bin/ld: /tmp/ccpxlk4F.o: in function `main':
test.c:8: undefined reference to `cpuset_version'
collect2: error: ld returned 1 exit status
Furthermore, this is not limited to the <cpuset.h> library. I tried to use a simple function from <pthread.h> and it also gave me the same error. Can anyone help with identifying why I cannot use shared libraries on the Ubuntu system? Thanks in advance
Since OP's issue is wrong order of parameters to GCC (many guides do show an incorrect order!), as discussed in the comments to the question, I believe showing a minimal Makefile to handle these is warranted:
CC := gcc
CFLAGS := -Wall -O2 -g
LDFLAGS := -lcpuset
TARGETS := test
.PHONY: all clean
all: $(TARGETS)
clean:
rm -f *.o $(TARGETS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
test: test.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that the indentation in Makefiles must use Tabs and not spaces. Since this forum converts Tabs to spaces, you will need to fix the above makefile, for example by running sed -e 's|^ *|\t|' -i Makefile.
If you want to compile say foo.c directly to an executable, the recipe is
foo: foo.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
You only need to run make (it defaults to using the Makefile in the current directory, and the default target is the first one, above the one named all), to recompile the TARGETS (here, test, but you can supply more by just adding them space-separated to the line).
You can also run make clean test to rebuild test from "scratch", i.e. removing all temporary files and all targets first.
You can override variables like CFLAGS by simply supplying them on the command line; for example, make CFLAGS="-Wall -Wextra -Os" clean all to recompile everything with different compilation flags.
I was following the osdev barebones tutorial and made a custom Makefile to it, but when I ran make kernel to compile the system into a .bin file, I ran into an error while linking.
Linker output: src/kernel.o: file not recognized: file format not recognized
Linker command: $HOME/opt/cross/bin/i686-elf-gcc -T linker.ld -o kernel.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
I took a quick look into it, and I found out that i686-elf-gcc cross-compiler produced a 64-bit file. Weird.
I tried compiling kernel.c with the same flags, and it worked just fine. What could the problem be?
CPARAMS:
-std=gnu99 -ffreestanding -O2 -Wall -Wextra
MAKEFILE: $(GCC) $(CPARAMS) -c $# -o $<
So the actual command looks like this $HOME/opt/cross/bin/i686-elf-gcc -std=gnu99 -ffreestanding -O2 -Wall -Wextra -c kernel.c -o kernel.o
File produced by running compiler via make: kernel.o: ELF 64-bit
LSB relocatable, x86-64, version 1 (SYSV), not stripped
File produced by running compiler from shell: kernel.o: ELF 32-bit
LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
I am using GNU g++ 4.9.2 compiler both on Solaris and Linux.
On Solaris platform, to create a shared library from a source file (a.c), I use the following command:
g++ -G a.c -o a
a becomes a shared library
a.c contains the following code:
void libfn1()
{
}
If I try not to use -G option i.e. compile as:
g++ a.c -o a
It gets a linker error: Undefined Symbol main
But, on Linux, if I do the same thing: it says:
g++: error: unrecognized command line option -G
How to create a shared library on Linux? What is the g++ option for that?
The g++ documentation says this:
These additional options are available on System V Release 4 for
compatibility with other compilers on those systems:
-G Create a shared object. It is recommended that -symbolic or -shared be
used instead.
Normally you want to generate position independent code too, for a shared library, with the -fPIC flag.
So you'd want to run:
g++ -fPIC -shared a.c -o liba.so
The process to create a shared library on a Linux system is a bit different.
Shared libraries on Linux are .so (for "shared object") files, not .g.
You do it like this:
First, you need to generate position-independent code from your C++ source. That is so your library works from wherever it is called. To do that, you should use g++'s -fPIC flag.
So, for each source file you want to be included in your library, you should only compile it to position-independent code. We'll handle linking later.
For each source file:
g++ -c -fPIC file.cpp
(The -c flag tells g++ "compile, don't link").
for each file.cpp, g++ will generate file.o, an object file containing position-independent code.
To then build the object files into a shared library, you should use
g++ -o -shared myLibrary.so {all_object_files}
So if you have file1.o, file2.o and file3.o, the command would be:
g++ -shared -o myLibrary.so file1.o file2.o file3.o
Of course, if you have a lot of files this can get pretty tedious, so you should write a Makefile to automate this process for you! Here's an example:
myLibrary.so: file1.o file2.o file3.o
$(CXX) -shared $^ -o $#
file1.o file2.o file3.o : CXXFLAGS+=-fPIC
I have problem link libgcc into a static linked .so
it only happens when linking 64bit module with -m64
Ubuntu 64bit 12.10 gcc 4.7
also failed on Ubuntu 64bit 12.04 gcc 4.6
32bit no problem
$gcc -fPIC -c -o hello.o hello.c -m32
$gcc -shared -m32 hello.o -o libhello.so -static-libgcc -Wl,-Bstatic -lc
$ ldd libhello.so
statically linked
64bit failed
$ make
gcc -fPIC -c -o hello.o hello.c
gcc -shared -m64 hello.o -o libhello.so -static-libgcc -Wl,-Bstatic -lc
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libc.a(iofclose.o): relocation R_X86_64_32 against `__gcc_personality_v0' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/libc.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [libhello.so] Error 1
hello.c
#include <stdio.h>
int f(){
FILE *out = fopen("/tmp/x.log", "wb");
fclose(out);
return 1;
}
Makefile
all: libhello.so
libhello.so: hello.o
gcc -shared -m64 hello.o -o libhello.so -static-libgcc -Wl,-Bstatic -lc
hello.o: hello.c
gcc -fPIC -c -o hello.o hello.c
clean:
rm -f hello.o libhello.so
The answer is basically "you can't do that." You're trying to link non-PIC code into a shared library, which is simply impossible on the x86_64 (amd64) architecture. You would need a static but PIC version of libgcc, and I suspect that would be only the start of your problems.
One of the reasons why libgcc is normally shared is that a given running executable has to have one and only one copy of some of the key data structures that libgcc maintains. Static linking makes sense for a final executable, since that one and only one copy will be the one statically linked into the executable, but the whole point of a dynamic object is to be loaded into another executable (which in turn will have its own copy of libgcc, either shared or static).