Makefile: undefined reference oraz nieznany format pliku

0

Witam ponownie. Do programu z semaforami i pamięcią dzieloną (z wątku o bad address) postanowiłem napisać nowy plik makefile, tym razem z dwiema opcjami kompilacji: biblioteka statyczna oraz biblioteka dzielona. Swój makefile wzorowałem na pliku (działającym) znalezionym w internecie. Niestety, make zwraca następujące błędy:

dla biblioteki statycznej:

ar rv libFunctions.a sem_func.o mem_func.o
ar: tworzenie libFunctions.a
a - sem_func.o
a - mem_func.o
mkdir -p ./libs
mv libFunctions.a ./libs
gcc -o mains.x -Wall -O sem_func.o mem_func.o -L./libs -lFunctions
/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o: In function _start': (.text+0x20): undefined reference to main'
collect2: error: ld returned 1 exit status
makefile recipe for target 'mains.x' failed
make: *** [mains.x] Error 1

a dla biblioteki dynamicznej:

gcc -shared -o libFunctions.so -Wall -O sem_func.h mem_func.h
mkdir -p ./libs
mv libFunctions.so ./libs
gcc -o maind.x -Wall -O sem_func.o mem_func.o -L./libs -lFunctions
./libs/libFunctions.so: file not recognized: Nieznany format pliku
collect2: error: ld returned 1 exit status
makefile recipe for target 'maind.x' failed
make: *** [maind.x] Error 1

Kompletnie nie wiem, co robię źle. Szukałem odpowiedzi w internecie, lecz nie znalazłem innego sposobu podobnego do użytego przeze mnie.
Proszę o pomoc, być może coś zostało przeze mnie źle zrozumiane.

Makefile:

CC=gcc

CFLAGS=-Wall -O -fPIC
LFLAGS=-Wall -O
LIBS=sem_func.h mem_func.h
EXTRAS= sem_func.o mem_func.o

NAME1=producer
NAME2=consumer
NAME3=main

DIR=`basename $(PWD)`

%.o: %.c %.h
	$(CC) -c $(CFLAGS) $<

%.o: %.c
	$(CC) -c $(CFLAGS) $<

#biblioteka statyczna

EX1s=$(NAME1)s.x
EX2s=$(NAME2)s.x
EX3s=$(NAME3)s.x

EX1d=$(NAME1)d.x
EX2d=$(NAME2)d.x
EX3d=$(NAME3)d.x

LIB_NAME=Functions
LIB_DIR=./libs

#biblioteka statyczna
LIB_STAT=lib$(LIB_NAME).a

#biblioteka dynamiczna
LIB_SHARED=lib$(LIB_NAME).so

AR=ar
ARFLG=rv

$(EXTRAS): $(LIBS)

$(LIB_STAT): $(EXTRAS)
	$(AR) $(ARFLG) $@ $?
	mkdir -p $(LIB_DIR)
	mv $(LIB_STAT) $(LIB_DIR)

$(LIB_SHARED): $(EXTRAS)
	$(CC) -shared -o $@ $(LFLAGS) $(LIBS)
	mkdir -p $(LIB_DIR)
	mv $(LIB_SHARED) $(LIB_DIR)

#wersja z biblioteką statyczną
$(EX1s): $(NAME1).o $(EXTRAS) $(LIB_STAT)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME)

$(EX2s): $(NAME2).o $(EXTRAS) $(LIB_STAT)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME)

$(EX3s): $(NAME3).o $(EXTRAS) $(LIB_STAT)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME)

run1: $(EX3s) $(EX1s) $(EX2s)
	./$(EX3s) $(EX1s) $(EX2s) $(in) $(out)
	make check
	make clean
	make diff


#wersja z biblioteką dynamiczną
$(EX1d): $(NAME1).o $(EXTRAS) $(LIB_SHARED)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME) -Wl,-R $(LIB_DIR)

$(EX2d): $(NAME2).o $(EXTRAS) $(LIB_SHARED)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME) -Wl,-R $(LIB_DIR)

$(EX3d): $(NAME3).o $(EXTRAS) $(LIB_SHARED)
	$(CC) -o $@ $(LFLAGS) $(EXTRAS) -L$(LIB_DIR) -l$(LIB_NAME) -Wl,-R $(LIB_DIR)

run2: $(EX3d) $(EX1d) $(EX2d)
	./$(EX3d) $(EX1d) $(EX2d) $(in) $(out)
	make check
	make clean
	make diff

clean:
	rm -f *.x *.o

check:
	ipcs -s
	ipcs -m

sdel:
	ipcrm -S $(key)

mdel:
	ipcrm -m $(id)

diff:
	diff -s $(in) $(out)

1

Huh, ale bałagan, ale plus dla Ciebie, że przyznałeś się do skopiowania z internetu. Generalnie, żeby pisać makefile wymagane jest by wiedzieć jakie parametry przyjmuje kompilator, Ty tego nie wiesz i teraz masz przez to problemy.

gcc -o mains.x -Wall -O sem_func.o mem_func.o -L./libs -lFunctions
/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o: In function _start': (.text+0x20): undefined reference tomain'

W treści posta piszesz, że chcesz skompilować biblioteką statyczną, jednak w swoim Makefile napisałeś, że chcesz skompilować plik wykonywalny. By skompilować bibliotekę statyczną najpierw kompilujesz pliki .cpp do plików obiektów .o, a potem z użyciem ar pakujesz je do jednej "paczki". By skompilować do postaci .o do kompilatora przekazać flagę -c. Przykładowo, poniższe polecenie

$(OBJ)/%.o: ./test/%.cpp
	$(CXX) $(CXXFLAGS) $(TEST_FLAGS) -c -o $@ $^

wyprodukuje mi wszystkie .o dla wszystkich .cpp z folderu test.

Jeśli zaś chodzi o bibliotekę dynamiczną

gcc -o maind.x -Wall -O sem_func.o mem_func.o -L./libs -lFunctions
./libs/libFunctions.so: file not recognized: Nieznany format pliku

Podobnież jak z bilbioteką statyczną, próbujesz skompilować plik wykonywalny. By skompilować bibliotekę dynamiczną potrzebujesz użyć opcji -shared, np

gcc -o libfoo.so module1.o module2.o -shared 

Powyższy przykład jest bardzo uproszczony, -shared to opcja linkera, a nie kompilatora, do flag samego kompilatora powinieneś dodać jeszcze opcję -fPIC, doczytaj koniecznie co robi i dlaczego jest ważna szczególnie przy kompilowaniu bibliotek.

0

@several: Dzięki za pomoc :)
Postanowiłem napisać cały Makefile (tym razem działający) od zera, w taki sposób, by później nie głowić się, co jest od czego. Póki co tylko dla biblioteki statycznej, ale w niedługim czasie dopiszę też bibliotekę dynamiczną.

1

@nojaniewiem odkopałem swojego makefile'a którego kiedyś napisałem dla swojej mikro biblioteki, nie jest idealny ale działa. Możesz go użyć jako template.

CXX := clang++
MANUAL_FLAGS := -std=c++11 -frtti -fexceptions -Wno-deprecated-register -fPIC
FLAGS := $(MANUAL_FLAGS)


LDFLAGS := -L./3rd/linux/openssl-1.1.0e/lib
LDLIBS := -lcrypto -lssl -ldl -lz

OBJ_ROOT := ./obj
INCLUDES := -I./include -I./3rd/linux/openssl-1.1.0e/include

ifeq ($(MAKECMDGOALS),debug)
	OBJ = $(OBJ_ROOT)/debug
	BUILD = ./debug
	CXXFLAGS = $(FLAGS) $(INCLUDES) -g -Wall

else
	OBJ = $(OBJ_ROOT)/release
	BUILD = ./release
	CXXFLAGS = $(FLAGS) $(INCLUDES) -O3 -Wall
endif

.PHONY: all clean

DESTBIN := $(BUILD)/lib
DESTINCLUDE := $(BUILD)/include

all: dist $(DESTBIN)/libawesomelib.a headers 
debug: all

dist:
	@mkdir -p $(OBJ) $(DESTBIN) $(DESTINCLUDE)
	
clean:
	@rm -r $(OBJ_ROOT) ./debug ./release


OBJS := $(OBJ)/awesome_lib.o

$(DESTBIN)/libawesomelib.a: $(OBJS)
	llvm-ar-3.5 rc $@ $^

$(OBJ)/%.o: ./src/%.cpp
	$(CXX) -c -o $@ $^ $(CXXFLAGS)

headers:
	@cp ./include/awesome_lib.h $(DESTINCLUDE)
	@cp ./include/openssl_types.h $(DESTINCLUDE)
0

Właśnie udało mi się napisać Makefile działający zarówno dla biblioteki statycznej, jak i dynamicznej :D
Teraz walczę z zapisem biblioteki w oddzielnym folderze.

0

@nojaniewiem: Masz przeciez przyklad jak to zrobic w tym Makefile, ktorego wrzucilem wyzej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1