Issue
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
Solution
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.
Answered By - Glärbo