This question already has answers here:
Why does the order in which libraries are linked sometimes cause errors in GCC?
(9 answers)
Closed 6 years ago.
I have a project with several .cpp and .h files, and I am trying to split the source into core / generic stuff, and application specific code. Based on that, I separated the code files into a Common folder and compiled it as a library. Below is the Makefile for that lib:
CFLAGS=-std=c++11 -g -c -pedantic -Wall -Wextra -I../boost_1_57_0 -L../boost_1_57_0/stage/lib
SOURCES = $(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
OUTPUTFILE=libcommon.a
all: $(OUTPUTFILE)
$(OUTPUTFILE): $(OBJECTS)
ar rcs $(OUTPUTFILE) $(OBJECTS)
.cpp.o:
$(CC) $(CPPFLAGS) $(CFLAGS) $< -o $# $(GPROF)
clean:
rm -f $(OBJECTS) $(OUTPUTFILE)
Then I created a sample main file just to try out the compilation of an app using that library.
Here is the code of the main source file:
#include "../Common/Functions.h"
#include "../Common/Logger.h"
int main() {
Logger::Init(false, false);
Logger::Debug("Test");
string path = Functions::GetAppPath();
Logger::Debug("App Path: ", path.c_str());
return 0;
}
The functions file that is being referenced uses boost, and here is the makefile for this app that uses the library:
CC=g++
CFLAGS=-Wl,--verbose -std=c++11 -g -c -pedantic -Wall -Wextra -I../boost_1_57_0 -L../boost_1_57_0/stage/lib
LDFLAGS=-I../boost_1_57_0 -L../boost_1_57_0/stage/lib -L../boost_libs/lib -L/usr/lib64 -L/usr/kerberos/lib -L/usr/lib -L../Common
LIBS=-lz -lkrb5 -lk5crypto -lcom_err -lresolv -lm -lpthread -lrt -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -rdynamic -lcurl -lcommon
SOURCES = $(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=testApp
GPROF=-pg
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $# $(LIBS) $(GPROF)
.cpp.o:
$(CC) $(CPPFLAGS) $(CFLAGS) $< -o $# $(GPROF)
clean:
rm -rf *o $(OBJECTS)
When I try to compile, I get the following errors, complaining about undefined references to boost:
g++ -Wl,--verbose -std=c++11 -g -c -pedantic -Wall -Wextra -I../boost_1_57_0 -L../boost_1_57_0/stage/lib main.cpp -o main.o -pg
g++ -I../boost_1_57_0 -L../boost_1_57_0/stage/lib -L../boost_libs/lib -L/usr/lib64 -L/usr/kerberos/lib -L/usr/lib -L../Common main.o -o testApp -lz -lkrb5 -lk5crypto -lcom_err -lresolv -lm -lpthread -lrt -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -rdynamic -lcurl -lcommon -pg
../Common/libcommon.a(Functions.o): In function `Functions::GetAppPath()':
/media/software/Robots/Common/Functions.cpp:43: undefined reference to `boost::filesystem::path::parent_path() const'
../Common/libcommon.a(Functions.o): In function `boost::filesystem::initial_path()':
/media/software/Robots/Common/../boost_1_57_0/boost/filesystem/operations.hpp:583: undefined reference to `boost::filesystem::detail::initial_path(boost::system::error_code*)'
../Common/libcommon.a(Functions.o): In function `boost::filesystem::system_complete(boost::filesystem::path const&)':
/media/software/Robots/Common/../boost_1_57_0/boost/filesystem/operations.hpp:655: undefined reference to `boost::filesystem::detail::system_complete(boost::filesystem::path const&, boost::system::error_code*)'
../Common/libcommon.a(Functions.o): In function `unsigned short boost::date_time::month_str_to_ushort<boost::gregorian::greg_month>(std::string const&)':
/media/software/Robots/Common/../boost_1_57_0/boost/date_time/date_parsing.hpp:67: undefined reference to `boost::gregorian::greg_month::get_month_map_ptr()'
../Common/libcommon.a(Logger.o): In function `Logger::Cleanup()':
/media/software/Robots/Common/Logger.cpp:84: undefined reference to `boost::thread::interrupt()'
../Common/libcommon.a(Logger.o): In function `Logger::InitFile(std::string, bool, std::_Ios_Openmode)':
/media/software/Robots/Common/Logger.cpp:186: undefined reference to `boost::filesystem::path::parent_path() const'
/media/software/Robots/Common/Logger.cpp:187: undefined reference to `boost::filesystem::path::parent_path() const'
../Common/libcommon.a(Logger.o): In function `Logger::Process()':
/media/software/Robots/Common/Logger.cpp:241: undefined reference to `boost::this_thread::interruption_point()'
../Common/libcommon.a(Logger.o): In function `boost::detail::thread_data_base::thread_data_base()':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/pthread/thread_data.hpp:143: undefined reference to `vtable for boost::detail::thread_data_base'
../Common/libcommon.a(Logger.o): In function `boost::thread::start_thread()':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/detail/thread.hpp:179: undefined reference to `boost::thread::start_thread_noexcept()'
../Common/libcommon.a(Logger.o): In function `boost::thread::~thread()':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/detail/thread.hpp:254: undefined reference to `boost::thread::detach()'
../Common/libcommon.a(Logger.o): In function `boost::thread::get_id() const':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/detail/thread.hpp:741: undefined reference to `boost::thread::native_handle()'
../Common/libcommon.a(Logger.o): In function `boost::thread::join()':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/detail/thread.hpp:767: undefined reference to `boost::thread::join_noexcept()'
../Common/libcommon.a(Logger.o): In function `boost::filesystem::exists(boost::filesystem::path const&)':
/media/software/Robots/Common/../boost_1_57_0/boost/filesystem/operations.hpp:404: undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
../Common/libcommon.a(Logger.o): In function `boost::filesystem::create_directories(boost::filesystem::path const&)':
/media/software/Robots/Common/../boost_1_57_0/boost/filesystem/operations.hpp:523: undefined reference to `boost::filesystem::detail::create_directories(boost::filesystem::path const&, boost::system::error_code*)'
../Common/libcommon.a(Logger.o): In function `boost::detail::thread_data<void (*)()>::~thread_data()':
/media/software/Robots/Common/../boost_1_57_0/boost/thread/detail/thread.hpp:90: undefined reference to `boost::detail::thread_data_base::~thread_data_base()'
../Common/libcommon.a(Logger.o):(.rodata._ZTIN5boost6detail11thread_dataIPFvvEEE[_ZTIN5boost6detail11thread_dataIPFvvEEE]+0x10): undefined reference to `typeinfo for boost::detail::thread_data_base'
collect2: error: ld returned 1 exit status
Needless to say that the project as a whole compiles with no issue.
This is my first attempt at building a c++ linux library and using it in another application, so I might be doing a rookie mistake, so bear that in mind.
Help is very much appreciated.
Thank you.
The order of libraries on the command line is significant to the linker. It processes libraries from left to right, resolving as-yet unresolved references already known to it against any functions provided by the current library.
Moreover, and particularly relevant here, if a given library contains references to functions that it does not itself provide then the linker does not resolve those against libraries it has already processed. That's why you have unresolved references: you have -lcommon last among your libraries, so function references therein will be resolved against only the C standard library.
It is valid to list libraries more than once in the link command, and sometimes that is needed, but in this case I think it makes sense simply to put -lcommon as the first library instead of the last. That will resolve the issue. You can even conceptualize this as putting the library most closely related to the main program closest to it in the link command.
Related
I just implemented the distributed version of a database project using gRPC. When I tried to make with my makefile, I keep getting the undefined reference errors with protobuf and gRPC. Parts of the outputs of make is below. I only included a portion of it because of the word limits.
g++ -o rundb benchmarks/ycsb_query.o benchmarks/tpcc_wl.o benchmarks/ycsb_wl.o benchmarks/ycsb_store_procedure.o benchmarks/tpcc_query.o benchmarks/tpcc_helper.o benchmarks/tpcc_store_procedure.o concurrency_control/lock_manager.o concurrency_control/tictoc_manager.o concurrency_control/row_f1.o concurrency_control/row_lock.o concurrency_control/f1_manager.o concurrency_control/row_tictoc.o storage/catalog.o storage/index_hash.o storage/index_btree.o storage/index_base.o storage/row.o storage/log.o storage/table.o system/stats.o system/manager.o system/cc_manager.o system/thread.o system/global.o system/logging_thread.o system/store_procedure.o system/txn.o system/worker_thread.o system/parser.o system/workload.o system/txn_table.o system/main.o system/caching.o utils/helper.o utils/semaphore_sync.o utils/packetize.o grpc/grpc_async_client.o grpc/grpc_sync_server.o grpc/grpc_async_server.o grpc/grpc_sync_client.o -Wall -L./libs -pthread -lrt -std=c++0x -O3 -ljemalloc -lprotobuf -Wall -g -std=c++11 -I. -I./benchmarks -I./concurrency_control -I./storage -I./system -I./transport -I./utils -I./grpc -I./grpc_system -D NOGRAPHITE=1 -O3 -g -ggdb
/usr/bin/ld: concurrency_control/lock_manager.o: in function `google::protobuf::internal::GenericTypeHandler<sundial_rpc::SundialRequest_TupleData>::New(google::protobuf::Arena*)':
/usr/local/include/google/protobuf/repeated_field.h:802: undefined reference to `sundial_rpc::SundialRequest_TupleData* google::protobuf::Arena::CreateMaybeMessage<sundial_rpc::SundialRequest_TupleData>(google::protobuf::Arena*)'
/usr/bin/ld: system/stats.o: in function `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const& sundial_rpc::SundialRequest_RequestType_Name<unsigned int>(unsigned int)':
/home/libin/Sundial/./grpc_system/sundial_grpc.pb.h:105: undefined reference to `sundial_rpc::SundialRequest_RequestType_descriptor()'
/usr/bin/ld: system/stats.o: in function `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const& sundial_rpc::SundialResponse_ResponseType_Name<unsigned int>(unsigned int)':
/home/libin/Sundial/./grpc_system/sundial_grpc.pb.h:136: undefined reference to `sundial_rpc::SundialResponse_ResponseType_descriptor()'
/usr/bin/ld: system/txn.o: in function `google::protobuf::internal::GenericTypeHandler<sundial_rpc::SundialResponse_TupleData>::New(google::protobuf::Arena*)':
/usr/local/include/google/protobuf/repeated_field.h:802: undefined reference to `sundial_rpc::SundialResponse_TupleData* google::protobuf::Arena::CreateMaybeMessage<sundial_rpc::SundialResponse_TupleData>(google::protobuf::Arena*)'
/usr/bin/ld: system/txn.o: in function `TxnManager::RemoteNodeInfo::~RemoteNodeInfo()':
/home/libin/Sundial/system/txn.h:102: undefined reference to `sundial_rpc::SundialResponse::~SundialResponse()'
/usr/bin/ld: /home/libin/Sundial/system/txn.h:102: undefined reference to `sundial_rpc::SundialRequest::~SundialRequest()'
/usr/bin/ld: system/txn.o: in function `sundial_rpc::SundialRequest::SundialRequest()':
/home/libin/Sundial/./grpc_system/sundial_grpc.pb.h:494: undefined reference to `sundial_rpc::SundialRequest::SundialRequest(google::protobuf::Arena*)'
/usr/bin/ld: system/txn.o: in function `sundial_rpc::SundialResponse::SundialResponse()':
/home/libin/Sundial/./grpc_system/sundial_grpc.pb.h:909: undefined reference to `sundial_rpc::SundialResponse::SundialResponse(google::protobuf::Arena*)'
/usr/bin/ld: system/txn.o: in function `TxnManager::send_remote_read_request(unsigned long, unsigned long, unsigned long, unsigned long, access_t)':
/home/libin/Sundial/system/txn.cpp:301: undefined reference to `sundial_rpc::SundialRequest::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:302: undefined reference to `sundial_rpc::SundialResponse::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:309: undefined reference to `sundial_rpc::SundialResponse::SundialResponse(sundial_rpc::SundialResponse const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:309: undefined reference to `sundial_rpc::SundialRequest::SundialRequest(sundial_rpc::SundialRequest const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:309: undefined reference to `sundial_rpc::SundialRequest::~SundialRequest()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:309: undefined reference to `sundial_rpc::SundialResponse::~SundialResponse()'
/usr/bin/ld: system/txn.o: in function `google::protobuf::internal::GenericTypeHandler<sundial_rpc::SundialRequest_ReadRequest>::New(google::protobuf::Arena*)':
/usr/local/include/google/protobuf/repeated_field.h:802: undefined reference to `sundial_rpc::SundialRequest_ReadRequest* google::protobuf::Arena::CreateMaybeMessage<sundial_rpc::SundialRequest_ReadRequest>(google::protobuf::Arena*)'
/usr/bin/ld: system/txn.o: in function `TxnManager::process_2pc_phase1()':
/home/libin/Sundial/system/txn.cpp:351: undefined reference to `sundial_rpc::SundialRequest::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:352: undefined reference to `sundial_rpc::SundialResponse::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:362: undefined reference to `sundial_rpc::SundialResponse::SundialResponse(sundial_rpc::SundialResponse const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:362: undefined reference to `sundial_rpc::SundialRequest::SundialRequest(sundial_rpc::SundialRequest const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:362: undefined reference to `sundial_rpc::SundialRequest::~SundialRequest()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:362: undefined reference to `sundial_rpc::SundialResponse::~SundialResponse()'
/usr/bin/ld: system/txn.o: in function `TxnManager::process_2pc_phase2(RC)':
/home/libin/Sundial/system/txn.cpp:420: undefined reference to `sundial_rpc::SundialRequest::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:421: undefined reference to `sundial_rpc::SundialResponse::Clear()'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:429: undefined reference to `sundial_rpc::SundialResponse::SundialResponse(sundial_rpc::SundialResponse const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:429: undefined reference to `sundial_rpc::SundialRequest::SundialRequest(sundial_rpc::SundialRequest const&)'
/usr/bin/ld: /home/libin/Sundial/system/txn.cpp:429: undefined reference to `sundial_rpc::SundialRequest::~SundialRequest()'
/usr/bin/ld: /home/libin/Sundial/grpc/grpc_sync_client.cpp:37: undefined reference to `sundial_rpc::Sundial_GRPC_SYNC::Stub::contactRemote(grpc_impl::ClientContext*, sundial_rpc::SundialRequest const&, sundial_rpc::SundialResponse*)'
/usr/bin/ld: /home/libin/Sundial/grpc/grpc_sync_client.cpp:36: undefined reference to `grpc_impl::ClientContext::~ClientContext()'
/usr/bin/ld: grpc/grpc_sync_client.o: in function `sundial_rpc::Sundial_GRPC_SYNC::Stub::~Stub()':
/home/libin/Sundial/./grpc_system/sundial_grpc.grpc.pb.h:73: undefined reference to `vtable for sundial_rpc::Sundial_GRPC_SYNC::Stub'
/usr/bin/ld: grpc/grpc_sync_client.o: in function `sundial_rpc::Sundial_GRPC_SYNC::Stub::~Stub()':
/home/libin/Sundial/./grpc_system/sundial_grpc.grpc.pb.h:73: undefined reference to `vtable for sundial_rpc::Sundial_GRPC_SYNC::Stub'
/usr/bin/ld: grpc/grpc_sync_client.o: in function `Sundial_Sync_Client::contactRemote(unsigned long, sundial_rpc::SundialRequest, sundial_rpc::SundialResponse)':
/home/libin/Sundial/grpc/grpc_sync_client.cpp:36: undefined reference to `grpc_impl::ClientContext::~ClientContext()'
collect2: error: ld returned 1 exit status
make: *** [Makefile:20: rundb] Error 1
I did read some other previous posts suggesting it is caused by not linking the protobuf library but I did include it in LDFLAGS. The makefile is below.
CC=g++
CFLAGS=-Wall -g -std=c++11
.SUFFIXES: .o .cpp .h
SRC_DIRS = ./ ./benchmarks/ ./concurrency_control/ ./storage/ ./system/ ./transport/ ./utils/ ./grpc/ ./grpc_system/
INCLUDE = -I. -I./benchmarks -I./concurrency_control -I./storage -I./system -I./transport -I./utils -I./grpc -I./grpc_system
CFLAGS += $(INCLUDE) -D NOGRAPHITE=1 -O3 -g -ggdb
LDFLAGS = -Wall -L./libs -pthread -lrt -std=c++0x -O3 -ljemalloc -lprotobuf
LDFLAGS += $(CFLAGS)
CPPS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)*.cpp))
OBJS = $(CPPS:.cpp=.o)
DEPS = $(CPPS:.cpp=.d)
all:rundb
rundb : $(OBJS)
$(CC) -o $# $^ $(LDFLAGS)
-include $(OBJS:%.o=%.d)
%.d: %.cpp
$(CC) -MM -MT $*.o -MF $# $(CFLAGS) $<
%.o: %.cpp %.d
$(CC) -c $(CFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f rundb *.o */*.o *.d */*.d
So I thought LDFLAGS = -Wall -L./libs -pthread -lrt -std=c++0x -O3 -ljemalloc -lprotobuf would resolve this but it did not.
You can try following these two steps:
Step 1:
Add the below two lines in your makefile:
CFLAGS += `pkg-config --cflags protobuf grpc`
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
Please refer this Makefile (C++ grpc example for load balancing): https://chromium.googlesource.com/external/github.com/grpc/grpc/+/HEAD/examples/cpp/load_balancing/Makefile
Your Makefile should look like this:
CC=g++
CFLAGS=-Wall -g -std=c++11
# Add the below line
CFLAGS += `pkg-config --cflags protobuf grpc`
.SUFFIXES: .o .cpp .h
SRC_DIRS = ./ ./benchmarks/ ./concurrency_control/ ./storage/ ./system/ ./transport/ ./utils/ ./grpc/ ./grpc_system/
INCLUDE = -I. -I./benchmarks -I./concurrency_control -I./storage -I./system -I./transport -I./utils -I./grpc -I./grpc_system
CFLAGS += $(INCLUDE) -D NOGRAPHITE=1 -O3 -g -ggdb
LDFLAGS = -Wall -L./libs -pthread -lrt -std=c++0x -O3 -ljemalloc -lprotobuf
LDFLAGS += $(CFLAGS)
# Add the below line
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc`\
-lgrpc++_reflection\
-ldl
CPPS = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)*.cpp))
OBJS = $(CPPS:.cpp=.o)
DEPS = $(CPPS:.cpp=.d)
all:rundb
rundb : $(OBJS)
$(CC) -o $# $^ $(LDFLAGS)
-include $(OBJS:%.o=%.d)
%.d: %.cpp
$(CC) -MM -MT $*.o -MF $# $(CFLAGS) $<
%.o: %.cpp %.d
$(CC) -c $(CFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f rundb *.o */*.o *.d */*.d
Step 2:
In your command prompt, you need to find the path of two files:
Path of "protobuf.pc"
Path of "grpc.pc"
You can find the path using these commands:
sudo find / -name "protobuf.pc"
Example output: /usr/local/lib/pkgconfig
sudo find / -name "grpc.pc"
Example output: /usr/lib/pkgconfig"
At last, you need to add these two paths separated by colon (:) in the environment variable "PKG_CONFIG_PATH" by running this command:
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:/usr/lib/pkgconfig"
Now, you can run your commands and proceed further.
NOTE:
In step 2, if both protobuf.pc and grpc.pc are present in the same directory,
then you need to specify only that directory in the environment variable.
Example:
sudo find / -name "protobuf.pc"
Example output: /lib64/pkgconfig
sudo find / -name "grpc.pc"
Example output: /lib64/pkgconfig
In this case, you can set environment variable as:
export PKG_CONFIG_PATH="/lib64/pkgconfig"
There are a couple similar problems to this but they all seem to have answers that don't work.
I've installed opencv4 onto an image of Ubuntu and I know the opencv files are install correctly
$ pkg-config --cflags opencv
-I/usr/include/opencv
and have a proper .cp file
/usr/local/lib/pkgconfig$ ls
gpr.pc grpc++.pc grpc++_unsecure.pc protobuf-lite.pc
grpc.pc grpc_unsecure.pc opencv4.pc protobuf.pc
But even though it's all installed correctly it's giving me this error.
~/neuralink/neuralink-image-service-prompt/proto$ make g++ -std=c++11 `pkg-config --cflags opencv protobuf grpc` -L/usr/local/lib `pkg-config --libs opencv protobuf grpc++` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl foo.cpp -o foo
/tmp/ccnfoOEl.o: In function `main':
foo.cpp:(.text+0x48): undefined reference to `cv::imread(cv::String const&, int)'
/tmp/ccnfoOEl.o: In function `cv::String::String(char const*)':
foo.cpp:(.text._ZN2cv6StringC2EPKc[_ZN2cv6StringC5EPKc]+0x4d): undefined reference to `cv::String::allocate(unsigned long)'
/tmp/ccnfoOEl.o: In function `cv::String::~String()':
foo.cpp:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x14): undefined reference to `cv::String::deallocate()'
/tmp/ccnfoOEl.o: In function `cv::String::operator=(cv::String const&)':
foo.cpp:(.text._ZN2cv6StringaSERKS0_[_ZN2cv6StringaSERKS0_]+0x28): undefined reference to `cv::String::deallocate()'
/tmp/ccnfoOEl.o: In function `cv::Mat::~Mat()':
foo.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): undefined reference to `cv::fastFree(void*)'
/tmp/ccnfoOEl.o: In function `cv::Mat::release()':
foo.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x4b): undefined reference to `cv::Mat::deallocate()'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'foo' failed
make: *** [foo] Error 1
Some people have already tried answering similar questions (such as Undefined reference to cv::imread(cv::String const&, int) and linking opencv libraries with g++) however these don't help, as the user didn't add opencv to their makefile and I have.
Here is my make makefile
LDFLAGS = -L/usr/local/lib `pkg-config --libs opencv protobuf grpc++`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
CXX = g++
CPPFLAGS += `pkg-config --cflags opencv protobuf grpc`
CXXFLAGS += -std=c++11
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
all: foo
client: image.pb.o image.grpc.pb.o client.o
$(CXX) $^ $(LDFLAGS) -o $#
server: image.pb.o image.grpc.pb.o server.o
$(CXX) $^ $(LDFLAGS) -o $#
%.grpc.pb.cc: %.proto
protoc --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
%.pb.cc: %.proto
protoc --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h client server
And I wrote a simple program that still throws the error
#include <opencv2/opencv.hpp>
#include <stdio.h>
int main() {
cv::Mat frame = cv::imread("sylvania.png", cv::IMREAD_UNCHANGED);
printf("Image size is %i x %i\n", frame.rows, frame.cols);
}
Everything seems to compile fine but I keep getting this linker issue. I don't seem to get the issue when I compile it on another computer (my mac) for what it's worth. Also I have the gRPC and Protoc files because I need them for the project, I just didn't use those file as an example since they're quite long.
I agree with Micka, here is a Makefile of one of my projects:
CPPFLAGS=-g -Wall -I. -DDEBUG
LDFLAGS=-g
LDLIBS=-lopencv_core -lopencv_calib3d -lopencv_highgui -lopencv_imgproc -lopencv_stitching -lopencv_video
main: main.o AffineKalmanLP.o
g++ $(LDFLAGS) -o main main.o AffineKalmanLP.o $(LDLIBS)
main.o: main.cpp main.h
g++ $(CPPFLAGS) -c main.cpp
AffineKalmanLP.o: AffineKalmanLP.cpp AffineKalmanLP.h
g++ $(CPPFLAGS) -c AffineKalmanLP.cpp
clean:
rm main main.o AffineKalmanLP.o
You need to add it to LDLIBS.
If I remove that line, I get undefined reference for various things as well.
I'm compiling a program with 3 source files: main.cpp, DataHandler.cpp and DataHandler.h.
I use a makefile that contains the following code to build:
Makefile
OBJECTS = main.o DataHandler.o
CC = g++
DEBUG = -g
CFLAGS = -c -std=c++11
LFLAGS = -lopendnp3 -lopenpal -lasiodnp3 -lasiopal -lpthread -std=c++11
lvoutstation : $(OBJECTS)
$(CC) $(LFLAGS) $(OBJECTS) -o lvoutstation
main.o : main.cpp DataHandler.h
$(CC) $(CFLAGS) main.cpp
DataHandler.o : DataHandler.cpp DataHandler.h
$(CC) $(CFLAGS) DataHandler.cpp
.PHONY : clean
clean :
rm lvoutstation $(OBJECTS)
It build main.o and DataHandler.o fine, but when it gets to compiling the action executable, it gives linking erros to all my asiodnp3 and opendnp3 namespace function / class calls.
When I run the following command:
g++ -o lvoutstation main.o DataHandler.o -lopendnp3 -lopenpal -lasiodnp3
-lasiopal -lpthread -std=c++11
It works fine..
I don't understand where the linking error comes in?
EDIT
Upon request for the error message:
g++ -lopendnp3 -lopenpal -lasiodnp3 -lasiopal -std=c++11 main.o DataHandler.o -o lvoutstation
main.o: In function `main':
main.cpp:(.text+0x85): undefined reference to `asiodnp3::DNP3Manager::DNP3Manager(unsigned int, openpal::ICryptoProvider*, std::function<void ()>, std::function<void ()>)'
main.cpp:(.text+0xb7): undefined reference to `asiodnp3::DNP3Manager::AddLogSubscriber(openpal::ILogHandler*)'
main.cpp:(.text+0xf0): undefined reference to `opendnp3::ChannelRetry::Default()'
main.cpp:(.text+0x123): undefined reference to `asiodnp3::DNP3Manager::AddTCPServer(char const*, unsigned int, opendnp3::ChannelRetry const&, std::string const&, unsigned short)'
main.cpp:(.text+0x19f): undefined reference to `opendnp3::EventBufferConfig::AllTypes(unsigned short)'
main.cpp:(.text+0x1d6): undefined reference to `opendnp3::DefaultOutstationApplication::Instance()'
main.cpp:(.text+0x2c8): undefined reference to `asiodnp3::DNP3Manager::~DNP3Manager()'
main.o: In function `opendnp3::LinkConfig::LinkConfig(bool, bool)':
main.cpp:(.text._ZN8opendnp310LinkConfigC2Ebb[_ZN8opendnp310LinkConfigC5Ebb]+0x75): undefined reference to `openpal::TimeDuration::Seconds(long)'
main.cpp:(.text._ZN8opendnp310LinkConfigC2Ebb[_ZN8opendnp310LinkConfigC5Ebb]+0x87): undefined reference to `openpal::TimeDuration::Minutes(long)'
main.o: In function `opendnp3::OutstationConfig::OutstationConfig()':
main.cpp:(.text._ZN8opendnp316OutstationConfigC2Ev[_ZN8opendnp316OutstationConfigC5Ev]+0x14): undefined reference to `opendnp3::OutstationParams::OutstationParams()'
main.cpp:(.text._ZN8opendnp316OutstationConfigC2Ev[_ZN8opendnp316OutstationConfigC5Ev]+0x56): undefined reference to `opendnp3::EventBufferConfig::EventBufferConfig(unsigned short, unsigned short, unsigned short, unsigned short, unsigned short, unsigned short, unsigned short, unsigned short)'
main.o: In function `asiodnp3::ConsoleLogger::Instance()':
main.cpp:(.text._ZN8asiodnp313ConsoleLogger8InstanceEv[_ZN8asiodnp313ConsoleLogger8InstanceEv]+0x5): undefined reference to `asiodnp3::ConsoleLogger::instance'
DataHandler.o: In function `DataHandler::ReadMeasurements(asiodnp3::IOutstation*)':
DataHandler.cpp:(.text+0xfe): undefined reference to `asiodnp3::MeasUpdate::MeasUpdate(asiodnp3::IOutstation*)'
DataHandler.cpp:(.text+0x11d): undefined reference to `opendnp3::Analog::Analog(double)'
DataHandler.cpp:(.text+0x137): undefined reference to `asiodnp3::MeasUpdate::Update(opendnp3::Analog const&, unsigned short, opendnp3::EventMode)'
DataHandler.cpp:(.text+0x159): undefined reference to `asiodnp3::MeasUpdate::~MeasUpdate()'
DataHandler.cpp:(.text+0x17b): undefined reference to `asiodnp3::MeasUpdate::~MeasUpdate()'
collect2: error: ld returned 1 exit status
make: *** [lvoutstation] Error 1
The makefile just works as expected. Your action becomes actually different from your command line sample
$(CC) $(LFLAGS) $(OBJECTS) -o lvoutstation
will expand to
g++ -lopendnp3 -lopenpal -lasiodnp3 -lasiopal -lpthread -std=c++11 \
main.o DataHandler.o -o lvoutstation
The order of object files and libraries matters for the linking process.
You can fix the linker errors providing the libraries after the object files:
$(CC) $(OBJECTS) $(LFLAGS) -o lvoutstation
I have been struggling to compile and link a C++ application that uses Boost libraries under a Ubuntu Server 11.01 64-bit edition.
At first not suceeding with prepackaged Boost libraries, I decided to compile it on my own. Boost compiles with no problem, but when I try to compile an application, linker starts spewing out errors as though no libraries were included.
builtinFunctions.o: In function `__static_initialization_and_destruction_0(int, int)':
builtinFunctions.cpp:(.text+0xcaab): undefined reference to `boost::system::generic_category()'
builtinFunctions.cpp:(.text+0xcab7): undefined reference to `boost::system::generic_category()'
builtinFunctions.cpp:(.text+0xcac3): undefined reference to `boost::system::system_category()'
builtinFunctions.o: In function `boost::system::error_code::error_code()':
builtinFunctions.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x17): undefined reference to `boost::system::system_category()'
builtinFunctions.o: In function `boost::filesystem3::exists(boost::filesystem3::path const&)':
...
This is a Makefile that I use:
CC=g++
CFLAGS=-std=c++0x -c -Wall -I . -I ./boost_1_48_0/ -DBOOST_THREAD_USE_LIB
all: project
project: builtinFunctions.o main.o operators.o conversionUtils.o
$(CC) -L./boost_1_48_0/stage/lib/ \
-lpthread -lboost_date_time-gcc46-mt-s-1_48 -lboost_program_options-gcc46-mt-s-1_48 \
-lboost_filesystem-gcc46-mt-s-1_48 -lboost_system-gcc46-mt-s-1_48 builtinFunctions.o \
main.o operators.o conversionUtils.o -o project
main.o: main.cpp
$(CC) $(CFLAGS) main.cpp
operators.o: operators.cpp
$(CC) $(CFLAGS) operators.cpp
conversionUtils.o: conversionUtils.cpp
$(CC) $(CFLAGS) conversionUtils.cpp
builtinFunctions.o: builtinFunctions.cpp
$(CC) $(CFLAGS) builtinFunctions.cpp
clean:
rm -rf *o project
Anything else I could try besides an earlier version of GCC? Thank you.
The order of libraries on link line matters, and yours is wrong.
I'm current working on a C++ that I edit locally on my Mac but run on an Ubuntu server. I always make sure that the code compiles on my mac before uploading it to the server to compile it there, where I have to use a makefile to link with libraries that are installed in my local directory. Basically, I had edited a significant portion of my code, found that it compiled on my mac, and uploaded it to the server to compile, but it doesn't compile! Luckily, I had a backup version of the code, so I tried that on the server, and that won't compile anymore either! In between the last time I knew that my code compiled on the server and now, I know that they ran some updates, but that's all I can think of that's different. For reference, here's my make file:
LOCAL_INCLUDE = /home/schraiber/.local/include
LOCAL_LIB = /home/schraiber/.local/lib
CXXFLAGS = -I$(LOCAL_INCLUDE)
CXX_LDFLAGS = -L$(LOCAL_LIB) -lgsl -lm -lgslcblas -lpthread
CoalHMMgf: main.o IOUtilities.o parameters.o Algorithms.o Optimization.o probabilities.o RNGUtilities.o Data.o ThreadData.h
g++ $(CXXFLAGS) $(CXX_LDFLAGS) main.o IOUtilities.o parameters.o Algorithms.o Optimization.o probabilities.o RNGUtilities.o Data.o -o CoalHMMgf
main.o: main.cpp IOUtilities.h parameters.h Algorithms.h Optimization.h probabilities.h ThreadData.h Data.h
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c main.cpp
IOutilities.o: IOUtilities.h IOUtilities.cpp parameters.h data.h
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c IOUtilities.cpp
parameters.o: parameters.h parameters.cpp
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c parameters.cpp
Algorithms.o: Algorithms.h Algorithms.cpp
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c Algorithms.cpp
Optimization.o: Optimization.h Optimization.cpp Algorithms.h parameters.h probabilities.h RNGUtilities.h ThreadData.h IOUtilities.h
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c Optimization.cpp
probabilities.o: probabilities.h probabilities.cpp parameters.h
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c probabilities.cpp
RNGUtilities.o: RNGUtilities.h RNGUtilities.cpp
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c RNGUtilities.cpp
Data.o: Data.h Data.cpp
g++ $(CXXFLAGS) $(CXX_LDFLAGS) -c Data.cpp
and the error:
g++ -I/home/schraiber/.local/include -L/home/schraiber/.local/lib -lgsl -lm -lgslcblas -lpthread main.o IOUtilities.o parameters.o Algorithms.o Optimization.o probabilities.o RNGUtilities.o Data.o -o CoalHMMgf
main.o: In function `main':
main.cpp:(.text+0xbf1): undefined reference to `pthread_create'
main.cpp:(.text+0xd0e): undefined reference to `pthread_join'
Optimization.o: In function `my_df(gsl_vector const*, void*, gsl_vector*)':
Optimization.cpp:(.text+0x3149): undefined reference to `gsl_vector_alloc'
Optimization.cpp:(.text+0x316b): undefined reference to `gsl_vector_get'
Optimization.cpp:(.text+0x3180): undefined reference to `gsl_vector_set'
Optimization.cpp:(.text+0x31bc): undefined reference to `gsl_vector_get'
Optimization.cpp:(.text+0x31ec): undefined reference to `gsl_vector_set'
Optimization.cpp:(.text+0x323b): undefined reference to `gsl_vector_set'
Optimization.cpp:(.text+0x327e): undefined reference to `gsl_vector_set'
Optimization.cpp:(.text+0x32c9): undefined reference to `gsl_vector_set'
Optimization.o: In function `MHthreaded(void*)':
Optimization.cpp:(.text+0x3489): undefined reference to `gsl_rng_env_setup'
Optimization.cpp:(.text+0x3490): undefined reference to `gsl_rng_default'
Optimization.cpp:(.text+0x360b): undefined reference to `gsl_rng_uniform'
Optimization.cpp:(.text+0x3653): undefined reference to `gsl_ran_gaussian'
Optimization.cpp:(.text+0x3686): undefined reference to `gsl_ran_gaussian'
Optimization.cpp:(.text+0x377f): undefined reference to `gsl_rng_uniform'
RNGUtilities.o: In function `AllocRNG(gsl_rng*&, gsl_rng_type const*, int)':
RNGUtilities.cpp:(.text+0x9a): undefined reference to `gsl_rng_alloc'
RNGUtilities.cpp:(.text+0xba): undefined reference to `gsl_rng_set'
RNGUtilities.o: In function `FreeRNG(gsl_rng*&)':
RNGUtilities.cpp:(.text+0xe3): undefined reference to `gsl_rng_free'
collect2: ld returned 1 exit status
make: *** [CoalHMMgf] Error 1
and just to verify that gsl is installed in the local directory:
schraiber#trump:~/test_rsync$ ls ~/.local/lib
libbpp-core.a libbpp-core.so.2.0.0 libbpp-seq.so.9 libgslcblas.a libgslcblas.so.0 libgsl.so pkgconfig
libbpp-core.so libbpp-seq.a libbpp-seq.so.9.1.0 libgslcblas.la libgslcblas.so.0.0.0 libgsl.so.0 python2.7
libbpp-core.so.2 libbpp-seq.so libgsl.a libgslcblas.so libgsl.la libgsl.so.0.16.0
schraiber#trump:~/test_rsync$ ls ~/.local/include/
Bpp gsl
An interesting thing to note is that my program is also supposed to link with Bpp, and it does that just fine as far as I can tell.
Your "-lfoo" parameters should come last on your "g++" command line. So, for example, make this change in your makefile:
CoalHMMgf: main.o IOUtilities.o parameters.o Algorithms.o Optimization.o probabilities.o RNGUtilities.o Data.o ThreadData.h
g++ $(CXXFLAGS) main.o IOUtilities.o parameters.o Algorithms.o Optimization.o probabilities.o RNGUtilities.o Data.o -o CoalHMMgf $(CXX_LDFLAGS)
Libraries have to be defined on the link line such that the library containing no other references is the very last one. Libraries that depend on code from a second library need to be listed first. They must be listed after the .o files, or else the .o files are assumed to be self-contained and don't need the libraries.