undefined reference when calling a function of a static library

I have two c++ programs (mqsim.cpp and ramulator.cpp) which are the main programs of two large projects and I want to use the functions of them in a main.cpp. I have written makefiles for them to create static libraries (libmqsim and libramsim) of them. The libraries are created successfully.

The makefiles to create static libraries are provided as below:

Makefile to create libmqsim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CC        := g++
    LD        := g++
    CC_FLAGS := -std=c++11 -O3 -g
    
    MODULES   := exec host nvm_chip nvm_chip/flash_memory sim ssd utils
    SRC_DIR   := $(addprefix src/,$(MODULES)) src
    BUILD_DIR := $(addprefix build/,$(MODULES)) build
    
    SRC       := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp))
    SRC       := src/mqsim.cpp $(SRC)
    OBJ       := $(patsubst src/%.cpp,build/%.o,$(SRC))
    INCLUDES  := $(addprefix -I,$(SRC_DIR))
    
    current_dir = $(notdir $(shell pwd))
    
    OUT_DIR=./
    OUT=libmqsim.a
    
    vpath %.cpp $(SRC_DIR)
    
    define make-goal
    $1/%.o: %.cpp
    	echo "make-goal"
    	$(CC) $(CC_FLAGS) $(INCLUDES) -c $$< -o $$@
    endef
    
    
    .PHONY: all checkdirs clean
    
    all: checkdirs MQSim
    	echo "all make"   
    
    MQSim: $(OBJ)
    	echo "mqsim make"
    	ar rcs $(OUT_DIR)/$(OUT) $^
    	ar -t $(OUT_DIR)/$(OUT)
    
    checkdirs: $(BUILD_DIR)
    
    $(BUILD_DIR):
    	echo "build_dir make"
    	mkdir -p $@
    
    clean:
    	rm -rf $(BUILD_DIR)
    	rm -f MQSim
    	rm -f $(OUT_DIR)/*.a
    
    $(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir)))) */


Makefile to create libramsim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 SRCDIR := src
    OBJDIR := obj
    MAIN := $(SRCDIR)/ramulator.cpp
    
    OUT_DIR=./
    OUT=libramsim.a
    
    #This means to extract all cpp files except ramulator.cpp and Gem5Wrapper.cpp --> give all .cpp files
    SRCS := $(filter-out $(MAIN) $(SRCDIR)/Gem5Wrapper.cpp, $(wildcard $(SRCDIR)/*.cpp))
    #This changes every .cpp name to .o name --> give all .o files
    OBJS := $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRCS))
    
    
    # Ramulator currently supports g++ 5.1+ or clang++ 3.4+.  It will NOT work with
    #   g++ 4.x due to an internal compiler error when processing lambda functions.
    # CXX := clang++
    CXX := g++
    # CXX := g++-5
    CXXFLAGS := -O3 -std=c++11 -g -Wall
    
    .PHONY: all clean depend
    
    all: depend ramulator
    
    clean:
    	rm -f ramulator
    	rm -rf $(OBJDIR)
    	rm -f $(OUT_DIR)/*.a    
    
    depend: $(OBJDIR)/.depend
    
    #create .o files
    $(OBJDIR)/.depend: $(SRCS) 
    	@mkdir -p $(OBJDIR) #create obj directory
    	@rm -f $(OBJDIR)/.depend
    	@$(foreach SRC, $(SRCS), $(CXX) $(CXXFLAGS) -DRAMULATOR -MM -MT $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC)) $(SRC) >> $(OBJDIR)/.depend ;)
    
    ifneq ($(MAKECMDGOALS),clean)
    -include $(OBJDIR)/.depend
    endif
    
    
    ramulator: $(MAIN) $(OBJS) $(SRCDIR)/*.h | depend
    	ar rcs $(OUT_DIR)/$(OUT) $(OBJS)
    	ar -t $(OUT_DIR)/$(OUT)
    	#$(CXX) $(CXXFLAGS) -DRAMULATOR -o $@ $(MAIN) $(OBJS)
    
    #libramulator.a: $(OBJS) $(OBJDIR)/Gem5Wrapper.o
    #	libtool -static -o $@ $(OBJS) $(OBJDIR)/Gem5Wrapper.o
    
    $(OBJS): | $(OBJDIR)
    
    $(OBJDIR): 
    	@mkdir -p $@
    
    $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    	$(CXX) $(CXXFLAGS) -DRAMULATOR -c -o $@ $< */


A simple main.cpp program is just written to call the functions of the static libraries. I have two print_help() (in libmqsim) and print()(in libramsim) functions that simply print a message on the console.

The main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
    #include <fstream>
    #include <ctime>
    #include <string>
    #include <cstring>
    
    #include "include/mqsim/mqsim.h"
    #include "include/ramulator/ramulator.h"
    
    using namespace std;
    
    int main(int argc, const char* argv[]){
        
        print(); //from libramsim
        print_help(); //from libmqsim
        cout << "Everything Went Well!\n";
        return 0;
    
    }


The print_help() in the libmqsim is executed with no errors but when I call the print() for libramsim, I get the following error:

In function `main':
    main.cpp:(.text+0x1c): undefined reference to `print()'
    collect2: error: ld returned 1 exit status
    Makefile:38: recipe for target 'main.out' failed
    make: *** [main.out] Error 1


I have created ramulator.h and mqsim.h which which include only the function declarations of ramulator.cpp and mqsim.cpp. This is the makefile for the main.cpp that uses the aforementioned libraries:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

    CC			:= g++
    LD			:= g++
    
    include ./config.mk
    
    CFLAGS		:= -Wall -std=c++11
    LFLAGS		:= -lramsim -lmqsim 
    
    MODULES   := exec host nvm_chip nvm_chip/flash_memory sim ssd utils
    MQSIM_INC_DIR   := $(addprefix $(MQSIM_INC)/,$(MODULES)) $(MQSIM_INC)
    RAM_INC_DIR     := $(addprefix $(RAM_INC)/,headers) $(RAM_INC)
    
    INCLUDE 	:= $(addprefix -I,$(RAM_INC_DIR)) $(addprefix -I,$(MQSIM_INC_DIR)) 
    LIB			:= -L${RAM_LIB} -L${MQSIM_LIB}
    
    MODULE		:= main.out
    
    CPP_FILES := $(wildcard *.cpp)
    OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
    
    .PHONY: all clean
    	
    all: DIR $(MODULE)
    	@echo "all-make"
    
    DIR:
    	@echo "dir-make"
    	@echo ${CPP_FILES}
    	@echo ${OBJ_FILES}
    	if [ ! -d "./bin" ];then 	\
    		mkdir bin;				\
    	fi
    	if [ ! -d "./obj" ];then 	\
    		mkdir obj;				\
    	fi
    
    $(MODULE): $(OBJ_FILES)
    	@echo "module-make"
    	$(LD) -o bin/$@ $^ -static $(LIB) $(LFLAGS)  
    
    obj/%.o: %.cpp
    	@echo "obj-make"
    	$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
    
    clean:
    	@rm -rf *.o
    	@rm -rf *.d
    	@rm -rf *.out
    	@rm -rf bin
    	@rm -rf obj


How can I fix this issue?
Last edited on
Run "nm -C libramsim.a | grep print" and see if the libramsim indeed contains the print function, exactly as you expect to find it in main.
Topic archived. No new replies allowed.