I have just learn about makefile and I want to write a makefile to build both file c and c . But when I try to make, the error is occurs. I'm sure about my code is run exactly because when I change main.cpp to main.c and make, it's built successfully. I'm glad to see your answer, thanks very much.
My directory struct
inc
|_linked_list.h
src
|_linked_list.c
|_main.cpp
Makefile
makefile.mk
main.cpp
#include <bits/stdc .h>
#include "linked_list.h"
using namespace std;
int main(){
printf("Makefile\n");
LList_create();
LList_add(5);
LList_add(9);
LList_add(6);
LList_add(4);
Data_t find_list = LList_search(5)->data;
Data_t after_list = LList_search(5)->next->data;
printf("%d after %d\n", find_list, after_list);
printf("remove data 4\n");
printf("print list: ");
LList_remove(4);
LList_add(7);
LList_print();
printf("\n");
return 0;
}
linked_list.h
#ifndef _LINKED_LIST_H
#define _LINKED_LIST_H
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef int32_t Data_t;
struct LinkedList
{
Data_t data;
struct LinkedList * next;
};
typedef struct LinkedList LList_t;
extern void LList_create(void);
extern void LList_add(Data_t dataInsert);
extern LList_t * LList_search(Data_t dataSearch);
extern void LList_remove(Data_t dataRemove);
extern LList_t * LList_headInfo(void);
extern void LList_print(void);
#ifdef __cplusplus
} //extern "C"
#endif
#endif /* _LINKED_LIST_H */
Makefile
PRO_DIR := .
PROJ_NAME := gnu_build_cxcpp
BUILD := build
$(shell mkdir -p $(BUILD))
BUILD_DIR := $(PRO_DIR)/$(BUILD)
INC_DIR := $(PRO_DIR)/inc
SRC_DIR := $(PRO_DIR)/src
CC := gcc
C99 := -std=c99
CFLAGS = $(GDB_OPT) -Wall -c
CXX := g
CXX11 := -std=c 11
CXXFLAGS = $(GDB_OPT) -Wall
GDB_OPT := -g
#include
-include makefile.mk
SOURCE_C = $(notdir $(SRC_C_PATH))
SOURCE_CXX = $(notdir $(SRC_CXX_PATH))
OBJ = $(patsubst %.c, $(BUILD_DIR)/%.o, $(SOURCE_C))
OBJ = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(SOURCE_CXX))
TARGET := $(BUILD_DIR)/$(PROJ_NAME)
.PHONY: all
all: $(TARGET)
file $<
@echo "finished."
$(TARGET): $(OBJ)
# $(CC) $(C99) $^ -o $@
$(CXX) $(CXX11) $^ -o $@
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
run:
$(TARGET)
debug:
gdb $(TARGET)
.PHONY: clean
clean:
rm -rf $(BUILD_DIR) folder
@echo "Clean done"
print-%:
@echo $($(subst print-,,$@))
makefile.mk
CFLAGS = -I./inc
CXXFLAGS = -I./inc
VPATH = src
VPATH = inc
# FILE .c
SRC_C_PATH = src/linked_list.c
# FILE .cpp
SRC_CXX_PATH = src/main.cpp
erro occurs:
g -g -Wall -I./inc src/main.cpp -o build/main.o
/usr/bin/ld: /tmp/ccOdDhI3.o: in function `main':
/home/hung/Documents/coding/src/main.cpp:26: undefined reference to `LList_create'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:27: undefined reference to `LList_add'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:28: undefined reference to `LList_add'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:29: undefined reference to `LList_add'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:30: undefined reference to `LList_add'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:31: undefined reference to `LList_search'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:32: undefined reference to `LList_search'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:36: undefined reference to `LList_remove'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:37: undefined reference to `LList_add'
/usr/bin/ld: /home/hung/Documents/coding/src/main.cpp:38: undefined reference to `LList_print'
collect2: error: ld returned 1 exit status
make: *** [Makefile:48: build/main.o] Error 1
CodePudding user response:
Add a -c
flag (compile only) to your %.o: %.c
and %.o: %.cpp
rules. Without it, the compiler does linking as well which you intended to do in a separate step.
I see that for .c you already have it in CFLAGS so it's technically missing only in CXXFLAGS but it's probably better to have it in the rule:
$(BUILD_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
CodePudding user response:
When you're attempting to build your object files, you're actually telling gcc to create an executable, not an object file. You need to add the -c
option for that:
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
$(BUILD_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@