C++ makefile script - c++

I have several very long compilation lines, and I want to make them a little more automatized and easier to use, by creating a script. I have found that makefile should be good for this purpose, however I am struggling with the file format.
My compilation line looks something like this:
g++ -std=c++11 -O3 -DNDEBUG \
-I /Users/whizzil/Desktop/proj/include \
-L /Users/whizzil/Desktop/proj/lib \
main.cpp \
-o program \
-lsdsl -ldivsufsort -ldivsufsort64 -Wno-inconsistent-missing-override
So I have several compiler flags, then include and lib parts, then linker options, and then ignore warnings flag.
I tried to write a makefile like this:
# what compiler to use
CC=g++
# options to the compiler
CFLAGS=-std=c++11 -03 -DNDEBUG
# include header files
INCLUDE=-I /Users/whizzil/Desktop/proj/include
# source lib files
LIB=-L /Users/whizzil/Desktop/proj/lib
# sources
SOURCES=main.cpp
#executable
EXECUTABLE=main
But I am not sure how to proceed. Could anyone help me out with the example makefile for this compile line, so I understand the concept?

Start with something simple and straightforward that works:
program:
g++ -std=c++11 -O3 -DNDEBUG \
-I /Users/whizzil/Desktop/proj/include \
-L /Users/whizzil/Desktop/proj/lib \
main.cpp \
-o program \
-lsdsl -ldivsufsort -ldivsufsort64 -Wno-inconsistent-missing-override
Then introduce a variable or two:
# what compiler to use
CC=g++
# options to the compiler
CFLAGS=-std=c++11 -03 -DNDEBUG
program:
$(CC) $(CFLAGS) \
-I /Users/whizzil/Desktop/proj/include \
-L /Users/whizzil/Desktop/proj/lib \
main.cpp \
-o program \
-lsdsl -ldivsufsort -ldivsufsort64 -Wno-inconsistent-missing-override
Then a few more:
# what compiler to use
CC=g++
# options to the compiler
CFLAGS=-std=c++11 -03 -DNDEBUG
# include header files
INCLUDE=-I /Users/whizzil/Desktop/proj/include
# source lib files
LIB=-L /Users/whizzil/Desktop/proj/lib
program:
$(CC) $(CFLAGS) $(INCLUDE) $(LIB) \
main.cpp \
-o program \
-lsdsl -ldivsufsort -ldivsufsort64 -Wno-inconsistent-missing-override
The variable LIB actually refers to a directory, so let's rename it LIBDIR and introduce LIBS:
# what compiler to use
CC=g++
# options to the compiler
CFLAGS=-std=c++11 -03 -DNDEBUG
# include header files
INCLUDE=-I /Users/whizzil/Desktop/proj/include
# source lib files
LIBDIR=-L /Users/whizzil/Desktop/proj/lib
LIBS = -lsdsl -ldivsufsort -ldivsufsort64
program:
$(CC) $(CFLAGS) $(INCLUDE) $(LIBDIR) main.cpp \
-o program $(LIBS) -Wno-inconsistent-missing-override
Further refinements are possible, once you have that much working.

Related

Trying to add a library to a make file

Hi this is my make file (I have very little make file experience sorry)
PROJECT_ROOT = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))
OBJS = Angle.o \
AppControlTimer.o \
CableAngle.o \
CFunctionObject.o \
SonarDGCUArrayData.o \
SonarDGCUCommsTCP.o \
SonarDGCUEthernetClient.o \
SonarDGCUFinsPacket.o \
SonarDGCUMotorMemoryArea.o \
SonarDGCUSensorsData.o \
SonarDGCUSensorsMemoryArea.o \
SonarDGCUThread.o
LIB = libFins.a
INCPATH = ../../
INSTALL_DIR = /opt/s2193/lib64
ifeq ($(BUILD_MODE),debug)
CFLAGS += -g
else ifeq ($(BUILD_MODE),run)
CFLAGS += -O2
else ifeq ($(BUILD_MODE),linuxtools)
CFLAGS += -g -pg -fprofile-arcs -ftest-coverage
LDFLAGS += -pg -fprofile-arcs -ftest-coverage
else
$(error Build mode $(BUILD_MODE) not supported by this Makefile)
endif
CFLAGS += -MMD -Wall -Wextra -Wpedantic -Wno-vla
CFLAGS += -I$(PROJECT_ROOT)../target/nar/log4cxx-0.11.0.TUS1-noarch/include/ -c -Wall
CFLAGS += -I${INCPATH}include -DLINUX
LDFLAGS += -L$(PROJECT_ROOT)../target/libs/ -llog4cxx
CXXFLAGS += -DBUILD_WITHOUT_HAL -DDBG_LVL=7
CXX += -std=c++11
CC += -std=c11
.PHONY: all clean install
all: $(LIB)
$(LIB): $(OBJS)
$(AR) $(ARFLAGS) -o $# $^
%.o: $(PROJECT_ROOT)src/%.cpp
#echo ".cpp.o!! "$<
$(CXX) -c $(CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -o $# $<
%.o: $(PROJECT_ROOT)src/%.c
#echo ".c.o!! $<"
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $# $<
clean:
rm -fr $(LIB) $(OBJS) $(OBJS:.o=.d)
install: $(LIB)
install -m 755 -d $(INSTALL_DIR)
install -m 644 $(LIB) $(INSTALL_DIR)
-include $(OBJS:.o=.d)
when I use the file I get undefined reflectances I'm trying to use the library
LDFLAGS += -L$(PROJECT_ROOT)../target/libs/ -llog4cxx
but I'm not sure how to add it to the file for reference when building libfins.a
thanks in advance
liblog4cxx supports pkg-config like any other sanely packaged library.
Stop writing flags by hand for libraries that you haven't made.
CXXFLAGS += $(shell pkg-config --cflags liblog4cxx)
LDFLAGS += $(shell pkg-config --libs liblog4cxx)
If you are really curious about flags your library needs, go ahead and run these two commands in your terminal, then leave it at that. Flags needed on your system are not necessarily flags needed on mine, that's why pkg-config exists, and people who made the library know better than you what it needs or does not need.
At the same time, pkg-config allows to expect a specific version of a library and all dependencies of your dependency are resolved transparently, without you having to do anything about it, and in fact you cannot do anything about it, because you don't know when or how the library or any of its dependencies will change, this becomes even more insane to manage yourself if you're linking statically. When using pkg-config, you just tack on --static and it gives you all the extra necessary flags.

Problem linking when attempting to include btstack C files (.h & .c) in c++ program

I'm attempting to integrate an L2CAP server (in C - uses BlueKitchen's btstack) with a UDP server (in C++). To start, I've attempted to just add the code from the L2CAP server into the "main.cpp" file of the UDP server. I included all of the relevant C libraries and headers using extern "C" {...}. At first, I'd get errors on the include statements for the btstack files. I solved this by modifying the make file to include "INC = -I./directory/...". Next, I dealt with problems the g++ compiler found with the pasted C code (ex. adding spaces between literals and strings). After resolving those, it seems that none of the bstack files/functions are being linked properly as this is what I get when I attempt to "make":
"undefined reference to 'every single btstack function call in main.cpp'
My makefile. Note that a lot of this is probably unnecessary/does nothing. I was just trying anything and everything and borrowing lines from the btstack port makefile and seeing if they'd work.
CORE += \
btstack_chipset_bcm.c \
btstack_chipset_bcm_download_firmware.c \
btstack_control_raspi.c \
btstack_link_key_db_tlv.c \
btstack_run_loop_posix.c \
btstack_tlv_posix.c \
btstack_uart_posix.c \
btstack_slip.c \
hci_dump_posix_fs.c \
hci_transport_h4.c \
hci_transport_h5.c \
le_device_db_tlv.c \
main.c \
wav_util.c \
btstack_stdin_posix.c \
raspi_get_model.c \
rijndael.c
.INCLUDE : home/pi/udpDemo/inc/btstack-master/example/Makefile.inc
CC=g++
CFLAGS=-Wall -Wextra -pedantic -std=c++11
SRC=$(wildcard ./src/*.cpp)
OBJ=$(patsubst ./src/%.cpp, ./obj/%.o, $(SRC))
INC=-I./inc \
-I./inc/btsrc \
-I./inc/btsrc/ble \
-I./inc/btsrc/ble/gatt-service \
-I./inc/platform/embedded \
-I./inc/platform/posix \
-I./inc/chipset/bcm \
-I./inc/3rd-party/tinydir \
-I./inc/3rd-party/rijndael \
-I./inc/port/raspi \
-I./src
LDFLAGS += -lrt
VPATH += src
VPATH += inc/3rd-party/rijndael
VPATH += inc
VPATH += inc/btsrc \
VPATH += inc/btsrc/ble \
VPATH += inc/btsrc/ble/gatt-service \
VPATH += inc/platform/embedded \
VPATH += inc/platform/posix \
VPATH += inc/chipset/bcm \
VPATH += inc/3rd-party/tinydir \
VPATH += inc/3rd-party/rijndael \
VPATH += inc/port/raspi \
LIBS=
TARGET=test
bindir=/usr/local/bin
$(TARGET):$(OBJ)
$(CC) -o $# $^ $(CFLAGS)
$(OBJ):./obj/%.o:./src/%.cpp
$(CC) $(CFLAGS) -c $^ -o $# -I$(INC)
clean:
rm -rf $(TARGET) $(OBJ)
install:$(TARGET)
install -g root -o root $(TARGET) $(bindir)/$(TARGET)
uninstall:$(bindir)/$(TARGET)
rm $(bindir)/$(TARGET)
It looks like there are both makefile issues and compile issues here. Solving both at the same time is hard. Below is a simplified and commented (but untested) version of your makefile that might be a good starting point for you.
Your original makefile looks like it was including a lot of stuff from the btstack build system. It's usually not a good idea to mesh two separate projects together like that, both for technical and licensing reasons. The typical way to use third-party code is to compile that code into a library and then have your code link against that library. You'll have to consult the documentation for btstack for details on how to do that, I'm not familiar with that particular library.
# Which compiler to use
CC=g++
# Options to pass to the compiler
CFLAGS=-Wall -Wextra -pedantic -std=c++11
# Options to pass to the linker
LDFLAGS=-Wall -Wextra
LDFLAGS+=-lbtstack # Link with 'libbtstack.a'
LDFLAGS+=-L/path/to/btstack # Where to find the btstack libraries that were built separately
# Source files to compile (everything in 'src' directory)
SRC=$(wildcard src/*.cpp)
# Convert names of source files into their corresponding object files
OBJ=$(patsubst src/%.cpp, obj/%.o, $(SRC))
# Directories where headers are kept
INC=-Isrc
INC+=-I/path/to/btstack/headers
# Name of the program
TARGET=test
# Rule for linking the .o files together to build the program
$(TARGET): $(OBJ)
$(CC) $(LDFLAGS) -o $# $^
# Rule for making a .o file from a .cpp file
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $^ -o $# -I$(INC)
# Rule for deleting output and temporary files
clean:
rm -rf $(TARGET) $(OBJ)
This will compile all the .cpp files in your src directory and link them with libbtstack.a to create a program named test. After you build the btstack library, update the LDFLAGS and INC variables with the actual paths to the btstack library and headers, respectively.

How to correctly setup a make file for a project?

Vulkan SDK hosts a C++ header-only C-wrapped library. Problem is, it is really a heavy header, so it wastes a lot of compilation time.
So I looked into using a make file for my Vulkan project, which I never did before. I decided to programatically generate all the dependencies. Probably I messed up this part as well, making it too difficult to understand.
It does kind of work, probably there is an easier way to do the same thing(s).
Here comes the part I can't really work out with:
I generated all the .o (object) files for my project along with the .gch (precompiled headers)
Then I did the same for the vulkan.hpp and the glfw3.h. (Remember, that's where most of my compilation time is going into).
... And here is where I have several problems about this procedure:
Can I, somehow, force the g++ compiler to use .gch files? The combination of -I, -include doesn't seem to work at all and I cannot even debug what is going on with -H/-M/-MM because i have no output whatsoever from this commands.
I am using MSYS2 MINGW_64 release, if it makes a difference.
I'd be glad if someone could give me a tip or two about make files and, in particular, if there is something I completely misunderstood about the compilation process.
# Methods
define uniq =
$(eval seen :=)
$(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
${seen}
endef
# Compilation flags
_COMPILER := g++ -std=c++17
_FLAGS_WARNING := -Wall -Wextra -Wshadow
_FLAGS_COMPILE := -g -O0
_FLAGS_VULKAN := -lglfw3 -lvulkan
# Custom Flags
_FLAGS_DEBUG := -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0
# Output
_OUTPUT_NAME := test
# Directories
_TMP_DIR := _tmp
_O_DIR := ${_TMP_DIR}\.o
_GCH_DIR := ${_TMP_DIR}\.gch
_SOURCE_DIR := src
_BUILD_DIR := build
_DEBUG_DIR := ${_BUILD_DIR}\debug
_RELEASE_DIR := ${_BUILD_DIR}\release
# Files
_VULKAN_HPP := C:/VulkanSDK/1.2.148.1/Include/vulkan/vulkan.hpp
_GLFW_HPP := C:/msys64/mingw64/include/GLFW/glfw3.h
# Grouping Files
# .cpp & .o
_CPP_LIST := ${wildcard ${_SOURCE_DIR}/*.cpp ${_SOURCE_DIR}/*/*.cpp}
_CPP_LIST_NAME := ${notdir ${_CPP_LIST}}
_O_LIST := ${addprefix ${_O_DIR}/, ${patsubst %.cpp, %.o, ${_CPP_LIST_NAME}}}
# .hpp & .gch
_HPP_LIST := ${wildcard ${_SOURCE_DIR}/*.hpp ${_SOURCE_DIR}/*/*.hpp} ${_VULKAN_HPP}
_HPP_LIST_NAME := ${notdir ${_HPP_LIST}}
_GCH_LIST := ${addprefix ${_GCH_DIR}/, ${patsubst %.hpp, %.gch, ${_HPP_LIST_NAME}}}
# .h & .gch
_H_LIST := ${_GLFW_HPP}
_H_LIST_NAME := ${notdir ${_H_LIST}}
_C_GCH_LIST := ${addprefix ${_GCH_DIR}/, ${patsubst %.h, %.gch, ${_H_LIST_NAME}}}
_COMPILATION_BUNDLE_CPP = ${_FLAGS_WARNING} ${_FLAGS_COMPILE} ${_FLAGS_VULKAN} ${_FLAGS_DEBUG} -I ${_GCH_DIR}
_COMPILATION_BUNDLE_HPP = ${_FLAGS_COMPILE} -x c++-header ${_FLAGS_DEBUG} -I ${_GCH_DIR}
${_DEBUG_DIR}/${_OUTPUT_NAME}: ${_GCH_LIST} ${_C_GCH_LIST} ${_O_LIST}
${_COMPILER} ${_COMPILATION_BUNDLE_CPP} ${_O_LIST} ${addprefix -include , ${_GCH_LIST}} ${addprefix -include , ${_C_GCH_LIST}} -o $#
vpath %.cpp $(call uniq, ${dir ${_CPP_LIST}})
${_O_DIR}/%.o: %.cpp
${_COMPILER} ${_COMPILATION_BUNDLE_CPP} -c $< -o $#
vpath %.hpp $(call uniq, ${dir ${_HPP_LIST}})
${_GCH_DIR}/%.gch: %.hpp
${_COMPILER} ${_COMPILATION_BUNDLE_HPP} $< -o $#
vpath %.h $(call uniq, ${dir ${_H_LIST}})
${_GCH_DIR}/%.gch: %.h
${_COMPILER} ${_COMPILATION_BUNDLE_HPP} $< -o $#
The execution on a clean project (thus easier to follow along):
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch src/helper/helper.hpp -o _tmp\.gch/helper.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch src/renderer/renderer.hpp -o _tmp\.gch/renderer.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch C:/VulkanSDK/1.2.148.1/Include/vulkan/vulkan.hpp -o _tmp\.gch/vulkan.gch
g++ -std=c++17 -g -O0 -x c++-header -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch C:/msys64/mingw64/include/GLFW/glfw3.h -o _tmp\.gch/glfw3.gch
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch -c src/main.cpp -o _tmp\.o/main.o
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch -c src/helper/helper.cpp -o _tmp\.o/helper.o
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch -c src/renderer/renderer.cpp -o _tmp\.o/renderer.o
g++ -std=c++17 -Wall -Wextra -Wshadow -g -O0 -lglfw3 -lvulkan -D _DEBUG -D _DEBUG_SEVERITY=0 -D _DEBUG_TYPE=0 -I _tmp\.gch _tmp\.o/main.o _tmp\.o/helper.o _tmp\.o/renderer.o -include _tmp\.gch/helper.gch -include _tmp\.gch/renderer.gch -include _tmp\.gch/vulkan.gch -include _tmp\.gch/glfw3.gch -o build\debug/test
Using pre-compiled headers is actually fairly straight forward. It might be easiest to break it down into manual steps. You can even retro fit to an existing project pretty easily. The steps could be:
Create a PCH file including a bunch of std libs or other headers you want to pre-compile. Note: Compile your PCH with the same flags as your other c++ code is compiled with, otherwise it may not work.
Add the include flags for the PCH in your makefile... and that is basically it.
So lets try a practical example:
Start with a source file, src1.cpp and compile it: g++ -I. <other flags> src1.cpp -o src1.o
Create your pch file, call it pch.hpp (or whatever)
Compile your PCH file: g++ -I. <other flags> pch.hpp (same flags as the previous compile). This generates the pch.hpp.gch file.
Now you can use your PCH file in your original compile line: g++ -I. <other flags> src1.cpp -o src1.o -Winvalid-pch -include pch.hpp
Couple of things to note:
If you use -Winvalid-pch warning flag this usually gives you enough information to figure out why the pch is not used (like its missing, bad path, bad options etc...).
Use -include pch.hpp not -include pch.hpp.gch since g++ will figure that out. You can see that retro fitting it is easy - since you just append the include flags to your compiler lines.
If your .gch file is not generated then the code should still compile using the pch.hpp header directly...

How to include tensorflow c++ ".so" file in makefile?

I have created a .so file using the bazel command:
bazel build -c opt --copt="-fPIC" :tensorFlow.so
Following is my makefile:
CFLAGS = -c -g -W -O3 -Wall -Wshadow \
-Wno-long-long -Wpointer-arith -D_REENTRANT \
-D_POSIX_PTHREAD_SEMANTICS -DLINUX2 \
-I ./acl/lib_acl_cpp/include
BASE_PATH=./acl
LDFLAGS = -L$(BASE_PATH)/lib_acl_cpp/lib -l_acl_cpp \
-L$(BASE_PATH)/lib_protocol/lib -l_protocol \
-L$(BASE_PATH)/lib_acl/lib -l_acl \
-lpthread -lprotobuf -ljsoncpp
redisConnection: redisConnection.o
g++ ./redisConnection.o ./UnifiedMetric.pb.o ./getMapFromFeatureDistribution.o ./featureStats.o $(LDFLAGS) -o redisConnection
redisConnection.o: redisConnection.cpp
g++ $(CFLAGS) redisConnection.cpp -o redisConnection.o
I went through various links but couldn't find any way. How do I include the .so file file created in the makefile and what other things have to be added?
Add the paths to header files in INCLUDEPATH.
This might be the exact replica for your problem.

Building library with static lib and c++ sourse code

I have a static library (lwip) compiled with this makefile:
CCDEP=g++
CC=g++
#To compile for linux: make ARCH=linux
#To compile for cygwin: make ARCH=cygwin
ARCH=unix
CFLAGS=-g -Wall -D$(ARCH) -DIPv4 -DLWIP_DEBUG -fpermissive \
-Wparentheses -Wsequence-point -Wswitch-default \
-Wextra -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast \
-Wc++-compat -Wwrite-strings -Wold-style-definition \
-Wmissing-prototypes -Wredundant-decls -Wnested-externs
# not used for now but interesting:
# -Wpacked
# -Wunreachable-code
# -ansi
# -std=c89
LDFLAGS=-lpthread -lutil -lboost_thread
CONTRIBDIR=../../../..
LWIPARCH=$(CONTRIBDIR)/ports/unix
ARFLAGS=rs
#Set this to where you have the lwip core module checked out from CVS
#default assumes it's a dir named lwip at the same level as the contrib module
LWIPDIR=$(CONTRIBDIR)/../lwip/src
CFLAGS:=$(CFLAGS) \
-I. -I$(CONTRIBDIR)/apps/httpserver_raw -I$(CONTRIBDIR)/apps/shell \
-I$(CONTRIBDIR)/apps/tcpecho -I$(CONTRIBDIR)/apps/udpecho \
-I$(LWIPDIR)/include -I$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-I$(LWIPDIR) -I$(CONTRIBDIR)
# -I$(CLASSDIR)/inc
# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/raw.c $(LWIPDIR)/core/stats.c \
$(LWIPDIR)/core/sys.c $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c \
$(LWIPDIR)/core/tcp_out.c $(LWIPDIR)/core/udp.c $(LWIPDIR)/core/dhcp.c \
$(LWIPDIR)/core/init.c $(LWIPDIR)/core/timers.c $(LWIPDIR)/core/def.c \
CORE4FILES=$(wildcard $(LWIPDIR)/core/ipv4/*.c) $(LWIPDIR)/core/ipv4/inet.c \
$(LWIPDIR)/core/ipv4/inet_chksum.c
# SNMPFILES: Extra SNMPv1 agent
SNMPFILES=$(LWIPDIR)/core/snmp/asn1_dec.c $(LWIPDIR)/core/snmp/asn1_enc.c \
$(LWIPDIR)/core/snmp/mib2.c $(LWIPDIR)/core/snmp/mib_structs.c \
$(LWIPDIR)/core/snmp/msg_in.c $(LWIPDIR)/core/snmp/msg_out.c
# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \
$(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c \
$(LWIPDIR)/api/netdb.c
# NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/etharp.c $(LWIPDIR)/netif/slipif.c
# NETIFFILES: Add PPP netif
NETIFFILES+=$(LWIPDIR)/netif/ppp/auth.c $(LWIPDIR)/netif/ppp/chap.c \
$(LWIPDIR)/netif/ppp/chpms.c $(LWIPDIR)/netif/ppp/fsm.c \
$(LWIPDIR)/netif/ppp/ipcp.c $(LWIPDIR)/netif/ppp/lcp.c \
$(LWIPDIR)/netif/ppp/magic.c $(LWIPDIR)/netif/ppp/md5.c \
$(LWIPDIR)/netif/ppp/pap.c $(LWIPDIR)/netif/ppp/ppp.c \
$(LWIPDIR)/netif/ppp/randm.c $(LWIPDIR)/netif/ppp/vj.c \
$(LWIPARCH)/netif/sio.c
# ARCHFILES: Architecture specific files.
ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)/netif/tapif.c $(LWIPARCH)/netif/tunif.c
$(LWIPARCH)/netif/unixif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c)
# APPFILES: Applications.
APPFILES=$(CONTRIBDIR)/apps/httpserver_raw/fs.c
$(CONTRIBDIR)/apps/httpserver_raw/httpd.c \
$(CONTRIBDIR)/apps/udpecho/udpecho.c $(CONTRIBDIR)/apps/tcpecho/tcpecho.c \
$(CONTRIBDIR)/apps/shell/shell.c
# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(SNMPFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
#LWIPOBJS+=$(notdir $(LWIPFILESW:.cpp=.o))
LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
#APPOBJS+=$(notdir $(APPFILES:.cpp=.o))
%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)
all ipv4 compile: liblwip4.a
#all ipv4 compile: simhost
.PHONY: all
clean:
rm -f *.o $(LWIPLIB) $(APPLIB) simhost simnode simrouter *.s .depend* *.core core
depend dep: .depend
include .depend
$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?
$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?
.depend: simhost.c simnode.c simrouter.c $(LWIPFILES) $(APPFILES)
$(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend
simhost: .depend $(LWIPLIB) $(APPLIB) simhost.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -o simhost simhost.o $(APPLIB) $(LWIPLIB)
simrouter: .depend $(LWIPLIB) $(APPLIB) simrouter.o
$(CC) $(CFLAGS) $(LDFLAGS) -o simrouter simrouter.o $(APPLIB) $(LWIPLIB)
simnode: .depend $(LWIPLIB) $(APPLIB) simnode.o
$(CC) $(CFLAGS) $(LDFLAGS) -o simnode simnode.o $(APPLIB) $(LWIPLIB)
Many of these things are not needed - that was example of application in 'contrib' folder. So... I get liblwip4.a library - for now all fine.
With this Library I made some test application - a class that uses lwip lib for different connections. I used eclipse IDE (added all includes, the liblwip4.a and so on) and it works fine.
Now I want to make a my_lwiplib.a or my_lwiplib.so with this lwip lib and my class. I made directory with 3 folders - lwip(sourse files), contrib-1.4.1(platform dependent files and so on) and lwipClass(my .h and .cpp file). wrote makefile:
CC = g++
CFLAGS = -fPIC -g -fpermissive
LDFLAGS = -shared
READYLIB = ./contrib-1.4.1/ports/unix/proj/unixsim/liblwip4.a
SOURCES = $(wildcard lwipClass/src/*.cpp)
INCLUDES = -I./lwipClass/inc/ -I./lwip/src/include/ -I./lwip/src/include/lwip/
OBJECTS = $(SOURCES:.cpp=.o)
CFLAGS += $(INCLUDES)
TARGET_SO = libmy_lwip.so
TARGET_STATIC = libmy_lwip.a
clean:
rm -f $(OBJECTS) $(TARGET_SO) $(TARGET_STATIC)
shared : $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) $(READYLIB) -o $(TARGET_SO) $(LDFLAGS)
static : $(OBJECTS)
ar rcs $(TARGET_STATIC) $(OBJECTS) $(READYLIB)
When I do 'make shared' I get:
sudo make shared
g++ -fPIC -g -fpermissive -I./lwipClass/inc/ -I./lwip/src/include/ -
I./lwip/src/include/lwip/ lwipClass/src/lwipClass.o ./contrib-
1.4.1/ports/unix/proj/unixsim/liblwip4.a -o libmy_lwip.so -shared
/usr/bin/ld: lwipClass/src/lwipClass.o: relocation R_X86_64_32 against `.bss' can not be
used when making a shared object; recompile with -fPIC
lwipClass/src/lwipClass.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [shared] Error 1
What's wrong here?
ADDED 14.08
Tryed to compile static lib. It compils ok.
Linked it to eclipse test project and made test application.
classA *myClass;
myClass->getInstance();
When i Try co compile I get
make all
Building file: ../src/test.cpp
Invoking: GCC C++ Compiler
g++ -fpermissive -I/home/user/lwip/lwipClass/inc -O0 -g3 -Wall -c -fmessage-length=0 -
MMD -MP -MF"src/test.d" -MT"src/test.d" -o "src/test.o" "../src/test.cpp"
Finished building: ../src/test.cpp
Building target: test
Invoking: GCC C++ Linker
g++ -o "test" ./src/test.o /home/user/lwip/libmy_lwip.a -lpthread -lboost_thread
/home/user/lwip/libmy_lwip.a(lwipClass.o): In function
`lwipImpl::tcpecho_thread(void*)':
lwipClass.cpp:(.text+0x85): undefined reference to `netbuf_data'
lwipClass.cpp:(.text+0xb9): undefined reference to `netbuf_next'
lwipClass.cpp:(.text+0xce): undefined reference to `netbuf_delete'
lwipClass.cpp:(.text+0xef): undefined reference to `netconn_recv'
That means there are no such functions.
I do
user:~/lwip$ objdump -t (some way /)/liblwip4.a |grep netbuf_data
00000000000003df g F .text 0000000000000103 netbuf_data
Than I do
usr:~/lwip$ objdump -t (some way/)lwip/libmy_lwip.a |grep netbuf_data
0000000000000000 *UND* 0000000000000000 netbuf_data
objdump: liblwip4.a: File format not recognized
wtf?????
In order to construct a shared library, you must first compile the source code and produce position-independent object files. That's what the -fPIC flag is for. You can't build a shared library out of "ordinary" object files, and you can't change that property of an object file later-- at least not easily.
In your example, you are trying to construct a shared library out of position-dependent object files, via a static library (). You can construct a static library from these objects, but if you want to build a shared library, as the linker is telling you, you must recompile with -fPIC.