Build and Link using Makefiles for C/C++ in Linux - c++

Below is my makefile
#Makefile for beaglebone
#General tools
CC=gcc
CFLAGS = -g -Wall
RM = rm -fr
TARGET = beaglebone
# Source locations
BACNET_CORE = ../../src
BACNET_INCLUDE = ../../include
BACNET_HANDLER = ../../demo/handler
BACNET_OBJECT = ../../demo/object
BACNET_DEMO = ../../demo
# local files for this project
CSRC = main.c arcnet.c bip-init.c dlmstp.c dlmstp_linux.c ethernet.c rs485.c timer.c device.c
#common demo files needed
DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c $(BACNET_DEMO)/handler/h_npdu.c $(BACNET_DEMO)/handler/s_iam.c $(BACNET_DEMO)/handler/noserv.c
# core BACnet stack files
CORESRC = $(BACNET_CORE)/crc.c $(BACNET_CORE)/npdu.c $(BACNET_CORE)/bacdcode.c $(BACNET_CORE)/bacint.c $(BACNET_CORE)/bacreal.c \
$(BACNET_CORE)/bacstr.c $(BACNET_CORE)/iam.c $(BACNET_CORE)/rp.c $(BACNET_CORE)/wp.c $(BACNET_CORE)/whois.c $(BACNET_CORE)/bacaddr.c \
$(BACNET_CORE)/abort.c $(BACNET_CORE)/reject.c $(BACNET_CORE)/bacerror.c $(BACNET_CORE)/bacapp.c
## Include Directories
INCLUDES = -I. -I$(BACNET_INCLUDE)
INCLUDES += -I$(BACNET_OBJECT)
INCLUDES += -I$(BACNET_HANDLER)
# Source to Object conversion
COBJ = $(CSRC:.c=.o)
DEMOOBJ = $(DEMOSRC:.c=.o)
COREOBJ = $(CORESRC:.c=.o)
OBJECTS = $(COBJ) $(DEMOOBJ) $(COREOBJ)
#Build and Link the objects
all: $(TARGET)
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $*.c -o $#
$(TARGET) : $(OBJECTS)
$(CC) $(CFLAGS) $(INCLUDES) $(OBJECTS) -o $(TARGET)
.PHONY: clean
clean:
$(RM) *.o *~ $(TARGET)
when issue make I get the .o files created and it does not creates an executable. I get the output as follows:
s_iam.c:(.text+0xed): undefined reference to `bip_get_my_address'
../../demo/handler/s_iam.o: In function `Send_I_Am_Unicast':
s_iam.c:(.text+0x16c): undefined reference to `bvlc_send_pdu'
../../demo/handler/noserv.o: In function `handler_unrecognized_service':
noserv.c:(.text+0x14): undefined reference to `bip_get_my_address'
noserv.c:(.text+0x6b): undefined reference to `bvlc_send_pdu'
../../src/bacapp.o: In function `bacapp_copy':
bacapp.c:(.text+0x7ac): undefined reference to `datetime_copy_date'
bacapp.c:(.text+0x7bb): undefined reference to `datetime_copy_time'
../../src/bacapp.o: In function `bacapp_snprintf_value':
bacapp.c:(.text+0xba4): undefined reference to `bactext_object_type_name'
bacapp.c:(.text+0xbbc): undefined reference to `bactext_event_state_name'
bacapp.c:(.text+0xbce): undefined reference to `bactext_engineering_unit_name'
bacapp.c:(.text+0xbe1): undefined reference to `bactext_binary_polarity_name'
bacapp.c:(.text+0xbf0): undefined reference to `bactext_binary_present_value_name'
bacapp.c:(.text+0xbfa): undefined reference to `bactext_reliability_name'
bacapp.c:(.text+0xc04): undefined reference to `bactext_device_status_name'
bacapp.c:(.text+0xc0e): undefined reference to `bactext_segmentation_name'
bacapp.c:(.text+0xc18): undefined reference to `bactext_node_type_name'
bacapp.c:(.text+0xc45): undefined reference to `bactext_day_of_week_name'
bacapp.c:(.text+0xc84): undefined reference to `bactext_month_name'
bacapp.c:(.text+0xe28): undefined reference to `bactext_object_type_name'
../../src/bacapp.o: In function `bacapp_parse_application_data':
bacapp.c:(.text+0x10bd): undefined reference to `datetime_set_date'
collect2: error: ld returned 1 exit status
make: *** [beaglebone] Error 1
Kindly tell me where I am going wrong and many thanks for your help and suggestions!!!
Regards,
Gibson

Looks like your object files are in a bit of a random order, so that later object files refer to symbol defined in earlier object files and this is why the link fails.
Try the following. Replace:
$(TARGET) : $(OBJECTS)
$(CC) $(CFLAGS) $(INCLUDES) $(OBJECTS) -o $(TARGET)
With:
$(TARGET) : $(OBJECTS)
$(CC) -o $# -Wl,--start-group $(OBJECTS) -Wl,--end-group
That is going to make ld to scan the object files for missing symbols a few times (like MSVC does).

Related

How to cross compile from Linux to 32-bit Windows executable

For context, I'm trying to compile source to a 32-bit executable for Windows using a Linux machine. I'm using the current mingw-w64 via apt-get. Here's the project I'm trying to compile ftp://ftp.thegpm.org/projects/tandem/source. More specifically the 17-02-01 zip files contain the source I'm interested in.
My first attempt was to just edit with the Makefile_ubuntu under the tandem-linux and swap out the gcc with the one provided by mingw and fix header reference issues that cropped up by adding #includes to .cpp files that threw errors. Super hacky. Can someone show me a brighter path?
Here's the makefile I'm using:
#makefile for c++ programs
#change the name of the executable to use for "any" project
EXECUTABLE = ../bin/tandem.exe
#EXECUTABLE = ../bin/p3.exe
LINKCC = $(CXX)
#CXXFLAGS denotes flags for the C++ compiler
CXX = /usr/bin/i686-w64-mingw32-g++-win32
#uncomment this line if you are using gcc 4.x
CXXFLAGS = -m32 -std=gnu++11
#CXXFLAGS = -w -O2 -DGCC4_3
#CXXFLAGS = -w -O2 -DGCC4_3 -DX_P3
#ubuntu 64 bit version
#LDFLAGS = -L/usr/lib/x86_64-linux-gnu/libexpat.a
LDFLAGS = -lpthread -lm -L/usr/lib/x86_64-linux-gnu/libexpat.a
#LDFLAGS = -lpthread -L/usr/lib -lm -lexpat
SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
DEPS := $(patsubst %.o,%.d,$(OBJS))
all: $(EXECUTABLE)
#define the components of the program, and how to link them
#these components are defined as dependencies; that is they must be up-to-date before the code is linked
$(EXECUTABLE): $(DEPS) $(OBJS)
$(LINKCC) $(CXXFLAGS) -o $(EXECUTABLE) $(OBJS) $(LDFLAGS)
#specify the dep files depend on the cpp files
%.d: %.cpp
$(CXX) -M $(CXXFLAGS) $< > $#
$(CXX) -M $(CXXFLAGS) $< | sed s/\\.o/.d/ > $#
clean:
-rm $(OBJS) $(EXECUTABLE) $(DEPS) *~
explain:
#echo "The following info represents the program:"
#echo "Final exec name: $(EXECUTABLE)"
#echo "Source files: $(SRCS)"
#echo "Object files: $(OBJS)"
#echo "Dep files: $(DEPS)"
depend: $(DEPS)
#echo "Deps are now up-to-date."
-include $(DEPS)
And here is the error(s):
sudo make -f Makefile_ubuntu
/usr/bin/i686-w64-mingw32-g++-win32 -m32 -std=gnu++11 -o ../bin/tandem.exe tandem.o p3mprocess.o saxmzdatahandler.o mspectrumcondition.o masscalc.o mprocess.o mreport.o mscore_tandem.o loadmspectrum.o mplugin.o msequenceserver.o saxtaxhandler.o msequencecollection.o mscore.o mrefine.o xmltaxonomy.o mbiomlreport.o saxtandeminputhandler.o saxhandler.o msequtilities.o base64.o saxmodhandler.o mtermmods.o xmlparameter.o saxsaphandler.o saxmzxmlhandler.o saxmzmlhandler.o mxxcleavage.o p3msequenceserver.o mzid_report.o saxbiomlhandler.o p3.o mpmods.o saxgamlhandler.o stdafx.o MSNumpress.o mpam.o -lpthread -lm -L/usr/lib/x86_64-linux-gnu/libexpat.a
saxhandler.o:saxhandler.cpp:(.text+0x100): undefined reference to `XML_ParserCreate'
saxhandler.o:saxhandler.cpp:(.text+0x11d): undefined reference to `XML_SetUserData'
saxhandler.o:saxhandler.cpp:(.text+0x13b): undefined reference to `XML_SetElementHandler'
saxhandler.o:saxhandler.cpp:(.text+0x151): undefined reference to `XML_SetCharacterDataHandler'
saxhandler.o:saxhandler.cpp:(.text+0x1cf): undefined reference to `XML_ParserFree'
saxhandler.o:saxhandler.cpp:(.text+0x344): undefined reference to `XML_Parse'
saxhandler.o:saxhandler.cpp:(.text+0x37f): undefined reference to `XML_Parse'
saxhandler.o:saxhandler.cpp:(.text+0x3bd): undefined reference to `XML_GetErrorCode'
saxhandler.o:saxhandler.cpp:(.text+0x3d4): undefined reference to `XML_GetCurrentLineNumber'
collect2: error: ld returned 1 exit status
Makefile_ubuntu:33: recipe for target '../bin/tandem.exe' failed
make: *** [../bin/tandem.exe] Error 1
You are (incorrectly) linking with /usr/lib/x86_64-linux-gnu/libexpat.a which is a Linux library (in ELF format). You need to get some Windows version of it.
BTW -L/usr/lib/x86_64-linux-gnu/libexpat.a is incorrect. Since -L should give a directory not a library to link
At last, recent versions of Windows might have WSL which could be useful to you (you'll compile a Linux, mostly statically linked, executable, and it might run on the command line on Windows).

error compiling AEScrypt using mingW-w64 in windows

I downloaded AESCrypt library in order to compile with MingW:
https://github.com/paulej/AESCrypt/tree/master/Windows
I receive this error message:
C:\Users\MyPC\AppData\Local\Temp\cclSPvvW.o:aescrypt.c:(.text+0xa2): undefined re
ference to `sha256_starts(sha256_context*)'
C:\Users\MyPC\AppData\Local\Temp\cclSPvvW.o:aescrypt.c:(.text+0xc0): undefined re
ference to `sha256_update(sha256_context*, unsigned char*, unsigned long)'
C:\Users\MyPC\AppData\Local\Temp\cclSPvvW.o:aescrypt.c:(.text+0x815): undefined r
eference to `aes_encrypt(aes_context*, unsigned char*, unsigned char*)'
C:\Users\MyPC\AppData\Local\Temp\cclSPvvW.o:aescrypt.c:(.text+0x829): undefined r
eference to `sha256_update(sha256_context*, unsigned char*, unsigned long)'
C:/Program Files (x86)/mingw-w64/i686-6.1.0-posix-dwarf-rt_v5-rev1/mingw32/bin/.
./lib/gcc/i686-w64-mingw32/6.1.0/../../../../i686-w64-mingw32/lib/../lib/libming
w32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined refe
rence to `WinMain#16'
collect2.exe: error: ld returned 1 exit status
I am on Windows 7 x64, I am using MingW-w64 6.1.0.
This kind of error means you forgot to link the file containing the code of the missing symbol. It is usually a .o or .lib/.a file.
In your case one of the symbols is: sha256_starts(sha256_context*), which is probably in sha256.o. Check the actual link command and make sure it includes this file or the library which includes it.
A makefile like this should make the trick:
COMP = gcc
RM = rm -f
OBJS = aes.o sha256.o stdafx.o AESCrypt.o AESCryptShellExt.o AESCryptWorkerThreads.o BufferedFile.o ErrorHandling.o PasswdDialog.o ProgressDialog.o
LDFLAGS = -mwindows
SERVERLDFLAGS =
TARGET = aes.exe
all : $(TARGET)
$(TARGET) : $(OBJS)
$(COMP) $(LDFLAGS) $(DEBUGFLAGS) -o $(TARGET) $^
clean :
$(RM) *.o
%.o : %.c %.h
$(COMP) $(CFLAGS) -c $<
%.o : %.cpp %.h
$(COMP) $(CFLAGS) -c $<

undefined references when linking with static library with OTL using a makefile

I want to link my project to a static library (msodbcsql11.lib), and I want to include it's header (msodbcsql.h) and another header file of a framework otlv4.h) using a simple makefile, but it looks like it can't find the library. Here is my makefile:
CC=g++
LDFLAGS=
CFLAGS=-c -Wall
SOURCES=main.cpp
LIBB = C:\temp\lib
LIBINCL = C:\temp\include
CFLAGS += -I$(LIBINCL)
LDFLAGS += -L$(LIBB)
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=main
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
And here is my c++ code:
#include <iostream>
#define OTL_ODBC_MSSQL_2008 // Compile OTL 4/ODBC, MS SQL 2008
#include <otlv4.h>
int main(){
otl_connect db; //undefined reference errors
}
Here is the build when I declared otl_connect:
18:42:33 **** Incremental Build of configuration Default for project mak ****
make all
g++ -c -Wall -IC:\temp\include main.cpp -o main.o
g++ -LC:\temp\lib main.o -o main
main.o:main.cpp:(.text$_ZN8otl_connD1Ev[_ZN8otl_connD1Ev]+0x66): undefined reference to `SQLFreeHandle'
main.o:main.cpp:(.text$_ZN8otl_connD1Ev[_ZN8otl_connD1Ev]+0x66): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `SQLFreeHandle'
main.o:main.cpp:(.text$_ZN8otl_connD1Ev[_ZN8otl_connD1Ev]+0x9e): undefined reference to `SQLFreeHandle'
main.o:main.cpp:(.text$_ZN8otl_connD1Ev[_ZN8otl_connD1Ev]+0x9e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `SQLFreeHandle'
main.o:main.cpp:(.text$_ZN8otl_conn6logoffEv[_ZN8otl_conn6logoffEv]+0x54): undefined reference to `SQLDisconnect'
main.o:main.cpp:(.text$_ZN8otl_conn6logoffEv[_ZN8otl_conn6logoffEv]+0x54): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `SQLDisconnect'
main.o:main.cpp:(.text$_ZN8otl_conn5errorER7otl_exc[_ZN8otl_conn5errorER7otl_exc]+0x70): undefined reference to `SQLGetDiagRec'
main.o:main.cpp:(.text$_ZN8otl_conn5errorER7otl_exc[_ZN8otl_conn5errorER7otl_exc]+0x70): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `SQLGetDiagRec'
main.o:main.cpp:(.text$_ZN8otl_conn6commitEv[_ZN8otl_conn6commitEv]+0x23): undefined reference to `SQLEndTran'
main.o:main.cpp:(.text$_ZN8otl_conn6commitEv[_ZN8otl_conn6commitEv]+0x23): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `SQLEndTran'
collect2: error: ld returned 1 exit status
makefile:14: recipe for target 'main' failed
make: *** [main] Error 1
18:42:35 Build Finished (took 1s.993ms)
What is wrong with my makefile? What should I do?
edit: I updated based on #Jonathan Wakely's answer:
LIBB = C:\temp\lib
LIBFILE = msodbcsql11
LDFLAGS += -L$(LIBB) -l$(LIBFILE)
I'm still getting the same errors
Update: Updated makefile as suggested by #Jonathan Wakely, but still getting errors. BTW, I changed the file format of libmsodbcsql11.lib to libmsodbcsql11.a because the compiler can't detect the .lib version
CC=g++
LDFLAGS=
CFLAGS=-c -Wall
SOURCES=main.cpp
LIBB = C:\temp\lib
LIBFILE = msodbcsql11
LIBINCL = C:\temp\include
CFLAGS += -I$(LIBINCL)
OBJECTS=$(SOURCES:.cpp=.o)
LDFLAGS += -L$(LIBB) -l$(LIBFILE)
EXECUTABLE=main
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) $(LDFLAGS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
The -L flag only tells the linker where to look for libraries, you need to use -l to tell it which library to link to.
This might be helpful...
Apparently the OTL library requires the odbc32.lib file to call ODBC functions. It's a little confusing because the microsoft ODBC driver have this msodbcsql11.lib, apparently it is not what's needed. Regardless the previous versions of my makefile did not call any library, so I accepted #Jonathan Wakely's answer.

c++ Makefile with external h and o files

I have project files and I need to use an external test file named TestSuite1.cpp that includes an external header file SignalMasker.h (Was given it and it's object file SignalMasker.o) and my main header file uthreads.h.
I'm still getting undefined refrences such as:
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
This means my Makefile isn't including the SignalMasker.o file that resides in the same directory.
This is my Makefile:
CC = g++
FLAGS = -Wall -g
OBJECTS = uthreads.o Thread.o Scheduler.o SchedulerStarter.o TestSuite1.o
.PHONY : clean
all: test1
test1: $(OBJECTS)
g++ $(FLAGS) $(OBJECTS) SignalMasker.o -L . -o test1
TestSuite1.o : TestSuite1.cpp SignalMasker.h uthreads.h
$(CC) -c $(FLAGS) TestSuite1.cpp
uthreads.o : uthreads.cpp uthreads.h SchedulerStarter.h Scheduler.h Thread.h
$(CC) -c $(FLAGS) uthreads.cpp
Scheduler.o : Scheduler.cpp Scheduler.h Thread.h
$(CC) -c $(FLAGS) Scheduler.cpp
SchedulerStarter.o : SchedulerStarter.cpp SchedulerStarter.h Scheduler.h
$(CC) -c $(FLAGS) SchedulerStarter.cpp
Thread.o : Thread.cpp Thread.h uthreads.h translateAdd.h
$(CC) -c $(FLAGS) Thread.cpp
clean:
rm -f $(OBJECTS) *~
And now I'm getting:
~/Desktop/tests$ make
g++ -Wall -g uthreads.o Thread.o Scheduler.o SchedulerStarter.o TestSuite1.o SignalMasker.o -L . -o test1
/usr/bin/ld: error: SignalMasker.o: incompatible target
TestSuite1.cpp:36: error: undefined reference to 'SignalMasker::SignalMasker(int)'
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:68: error: undefined reference to 'SignalMasker::SignalMasker(int)'
TestSuite1.cpp:111: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:111: error: undefined reference to 'SignalMasker::~SignalMasker()'
collect2: ld returned 1 exit status
EDIT:
I'm now pondering with the idea that maybe incompatible target means they compiled it under 64bit. My machine is 32bit
you are missing rule to compile SignalMasker.cpp in your makefile. you have to write a rule, the same way you have written for
SchedulerStarter.o, Thread.o
SignalMasker.o : SignalMasker.cpp SignalMasker.h
$(CC) -c $(FLAGS) SignalMasker.cpp
This will ensure the SignalMasker.o is generated with the same compilation flags that you build other objects. It will eliminate incompatibility issues in case of 32-bit/ 64-bit variants.
if you are copying this SignalMasker.o from elsewhere, check the compilation flags used for generating the object. Use the same flags in your makefile.

Apache thrift undefined reference to apache::thrift::server::TNonblockingServer

I'm trying to compile a piece of code that creates a TNonblockingServer and I get the following compile error. Any idea what's wrong?
something_server.cpp:(.text+0x1ad): undefined reference to `apache::thrift::server::TNonblockingServer::serve()'
something_server.cpp:(.text+0x1c1): undefined reference to `apache::thrift::server::TNonblockingServer::~TNonblockingServer()'
something_server.cpp:(.text+0x280): undefined reference to `apache::thrift::server::TNonblockingServer::~TNonblockingServer()'
I performed the steps outlined here while installing thrift.
http://thrift.apache.org/docs/install/os_x/
Here's my makefile
GEN_SRC := Something.cpp something_constants.cpp something_types.cpp
GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))
THRIFT_DIR := /usr/local/include/thrift
BOOST_DIR := /usr/local/include
INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)
.PHONY: all clean
all: something_server something_client
%.o: %.cpp
$(CXX) -Wall -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $< -o $#
something_server: something_server.o $(GEN_OBJ)
$(CXX) $^ -o $# -L/usr/local/lib -lthrift
something_client: something_client.o $(GEN_OBJ)
$(CXX) $^ -o $# -L/usr/local/lib -lthrift
clean:
$(RM) *.o something_server something_client
As pointed out by Dmitry, if we add -lthriftnb to compiling command, it solves the problem. These missing references are found in libthriftnb.so This file has references to libevent. So I had to include -levent to compiling command. Without -levent linker generates multiple error messages. Some of the messages are as follows -
/usr/local/lib/libthriftnb.so: undefined reference to `event_set'
/usr/local/lib/libthriftnb.so: undefined reference to `evbuffer_new'
/usr/local/lib/libthriftnb.so: undefined reference to `evhttp_free'
.
.
.
.
/usr/local/lib/libthriftnb.so: undefined reference to `event_del'