use -lstdc++ in a makefile - c++

here's my error
make
cc msgd.o -o msgd
msgd.o: In function `main':
/home/cam/Desktop/lab1/msgd.cc:37: undefined reference to `Server::Server(int, bool)'
/home/cam/Desktop/lab1/msgd.cc:39: undefined reference to `Server::~Server()'
msgd.o: In function `__static_initialization_and_destruction_0':
/usr/include/c++/4.7/iostream:75: undefined reference to `std::ios_base::Init::Init()'
/usr/include/c++/4.7/iostream:75: undefined reference to `std::ios_base::Init::~Init()'
msgd.o:(.eh_frame+0x13): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
make: *** [msgd] Error 1
The first two undefined references to Server:: are bogus, the code works and Server.h is included properly in msgd.cc.
However when I simply do "make server" it runs fine, and when I do "make client" it runs fine, but I want to be able to just do "make" and have it build both.
Here's my makefile. According to https://stackoverflow.com/a/10907227/2080104 I need to include -lstdcc++ but I can't seem to figure out how to do so in a makefile.
# Makefile for socket examples
CXX= g++ $(CCFLAGS)
msgd= msgd.o Server.o Data.o User.o Message.o Str.o
msg= msg.o Client.o Str.o
OBJS = $(msgd) $(msg)
CCFLAGS= -std=c++11 -g
all: msgd Server Data User Message Str msg Client
server:$(msgd)
$(CXX) -o msgd $(msgd)
client:$(msg)
$(CXX) -o msg $(msg)
clean:
rm -f $(OBJS) $(OBJS:.o=.d)
realclean:
rm -f $(OBJS) $(OBJS:.o=.d) msgd msg
# These lines ensure that dependencies are handled automatically.
%.d: %.cc
$(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< \
| sed '\''s/\($*\)\.o[ :]*/\1.o $# : /g'\'' > $#; \
[ -s $# ] || rm -f $#'
include $(OBJS:.o=.d)

You named a variable msgd when you had an object file named msgd.o, and then you got them mixed up. Oh, and you have a target server which doesn't actually build server, it builds msgd.
You have a default target (all) which builds things other than what you want the default target to build.
You want to Make to do something (i.e. use -lstdcc++) when either you don't know how to do it on the command line, or you don't know which part of the makefile corresponds to what you do on the command line.
I'd suggest specific changes to the makefile, but your intent is so unclear I'm afraid I'd do more harm than good.

What happens is that target all requires msgd.
all: msgd Server Data User Message Str msg Client
You don't have a rule for msgd, however, make figures it can build msgd from msgd.o from msgd.cc (or whatever extension your source has) using the built-in rule:
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
Your makefile should look more like the following:
CXX := g++
CXXFLAGS := -std=c++11 -g
CPPFLGS :=
LDFLAGS :=
LDLIBS := -g
all : msgd msg
msgd_obj := msgd.o Server.o Data.o User.o Message.o Str.o
msg_obj := msg.o Client.o Str.o
OBJ := ${msgd_obj} ${msg_obj}
msgd : ${msgd_obj}
msg : ${msg_obj}
# The rule to link the executables.
msgd msg :
${CXX} -o $# ${LDFLAGS} $^ ${LDLIBS}
# The rule to compile object files and produce dependencies.
%.o : %.cc
${CXX} -o $# ${CPPFLAGS} ${CXXFLAGS} -MD -MP $<
clean:
rm -f $(OBJS) $(OBJS:.o=.d)
realclean:
rm -f $(OBJS) $(OBJS:.o=.d) msgd msg
-include $(OBJS:.o=.d)
.PHONY: all clean realclean
Note that there should not be a specific rule to produce dependencies. Dependencies are produced as a by-product of compilation. On the first run dependencies are unnecessary because everything must be built anyway, on subsequent runs it uses dependencies from the previous run to determine what have changed since.

Related

why is GNU make not filling out the $^ variable here?

I can compile the project just fine if I run the project by hand with g++ source/* -lSDL2 -o bin/fly_fishing. When I do run make, I get
mkdir -p bin
g++ -lSDL2 -o bin/fly_fishing
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/12/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x17): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:20: bin/fly_fishing] Error 1
Which tells me that it's not populating from $^ for linking. So what have I missed here? Here's the makefile for reference.
SRC_DIR := source
OBJ_DIR := objects
BIN_DIR := bin
EXE := $(BIN_DIR)/fly_fishing
SRC := $(wildcard $(SRC_DIR)/*.c)
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
CXXFLAGS := -Wall
#CFLAGS := -Wall
LDLIBS := -lSDL2a
LDFLAGS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CXX) -c $(CXXFLAGS) $(CFLAGS) $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
Which tells me that it's not populating from $^ for linking.
That seems unlikely. Much more likely would be that $^ expands to nothing. Which would be the case if $(OBJ) expands to nothing. Which seems plausible because I don't see any corresponding objects being built (though perhaps you've omitted that, or they were built on a previous run). And $(OBJ) expanding to nothing implies that $(SRC) expands to nothing.
So what have I missed here?
That $(SRC) expands to nothing is not inconsistent with the data presented. I observe that the manual compilation command you present is
g++ source/* -lSDL2 -o bin/fly_fishing
That does seem to suggest that there are indeed source files in source/, but do they match the pattern source/*.c? Since you're compiling with g++, I bet not. It would be highly unconventional to name C++ source files to end with .c, and surely you would not attempt to compile C source files with a C++ compiler. I infer, then, that your source files are all named with .cpp, or maybe .cc or .C, all of which forms are conventions for C++ source names.
If all your source names follow one or another of those patterns then indeed, this ...
SRC := $(wildcard $(SRC_DIR)/*.c)
... will result in $(SRC) being empty.

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).

Makefile - .o: file not recognized: File truncated?

I'm just learning GNU make, but I'm having trouble linking when using .d (dependency) files. Can anyone point me in the right direction with this error:
...../part1.o: file not recognized: File truncated
recipe for target 'bin/target/prog' failed
It's a simple program containing: main.cpp, part1.cpp, part1.h, part2.cpp, part2.h
Where part1 and part2 have a method to print something.
This is from terminal when running make:
I don't get why I'm getting a warning for using #pragma once?
stud#GoldenImageASE:~/Desktop/ISU/L1/2$ make ARCH=target -f Makefile.th
Compiling...part2.cpp
arm-devkit-g++ -MTbuild/target/part2.o -MM -I. part2.cpp > build/target/part2.d
Compiling...part1.cpp
arm-devkit-g++ -MTbuild/target/part1.o -MM -I. part1.cpp > build/target/part1.d
Compiling...main.cpp
arm-devkit-g++ -MTbuild/target/main.o -MM -I. main.cpp > build/target/main.d
object file....main.o
arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o
part1.h:1:9: warning: #pragma once in main file
#pragma once
^
part2.h:1:9: warning: #pragma once in main file
#pragma once
^
object file....part1.o
arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o
object file....part2.o
arm-devkit-g++ -I. -c part2.cpp > build/target/part2.o
arm-devkit-g++ -I. -o build/target/main.o build/target/part1.o build/target/part2.o -o prog
build/target/part1.o: file not recognized: File truncated
collect2: error: ld returned 1 exit status
Makefile.th:27: recipe for target 'bin/target/prog' failed
make: *** [bin/target/prog] Error 1
My Makefile is found below:
# Variables
SOURCES=main.cpp part1.cpp part2.cpp
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
EXE=prog
CXXFLAGS =-I.
# Making for host
# > make ARCH=host
ifeq (${ARCH},host)
CXX=g++
BUILD_DIR=build/host
EXE_DIR=bin/host
endif
# Making for target
# > make ARCH= target
ifeq (${ARCH},target)
CXX=arm-devkit-g++
BUILD_DIR=build/target
EXE_DIR=bin/target
endif
$(addprefix ${EXE_DIR}/,$(EXE)): $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))
# << Check the $(DEPS) new dependency
#mkdir -p $(dir $#)
$(CXX) $(CXXFLAGS) -o $(addprefix ${BUILD_DIR}/,$(OBJECTS))
$(addprefix $(BUILD_DIR)/, %.o): %.cpp
#echo "object file...."$*.o
$(CXX) $(CXXFLAGS) -c $^ > $#
# Rule that describes how a .d ( dependency ) file is created from a .cpp
# Similar to the assigment %. cpp -> %.o
${BUILD_DIR}/%.d: %.cpp
#mkdir -p $(dir $#)
#echo "Compiling..."$<
$(CXX) -MT$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
debug:
#echo "DEPS: "$(DEPS)"\n"
#echo "OBJ: " $(addprefix ${BUILD_DIR}/,$(OBJECTS))"\n"
#echo "EXE: " $(addprefix ${EXE_DIR}/,$(EXE))"\n"
.PHONY:clean
clean:
rm -f $(EXE) $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))
ifneq ($(MAKECMDGOALS),clean)
-include $(addprefix ${BUILD_DIR}/,$(DEPS))
endif
You have two unrelated problems. The first one is that you have two conflicting -o options when linking.
The actual problem you ask about is something different, but still related to the -o option: Namely that you don't have one when attempting to create the object files.
When creating the object files, the generated object file is not written to standard output, therefore your redirection will not cause the gcc frontend program to create an object file with the name you think.
For example:
arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o
The above command will create an object file named part1.o in the current directory, and write the (empty) standard output to the file build/target/part1.o. That will leave build/target/part1.o empty, which is what the linker is complaining about (that's what it means when it says the file is truncated).
The command should instead look like
arm-devkit-g++ -I. -c part1.cpp -o build/target/part1.o
Note the use of the -o option to name the output file.
You need to modify the makefile to not use redirection when building the object files.
Also, you should not list the header files when building object files, only the source file you want to build, so the command
arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o
should really be
arm-devkit-g++ -I. -c main.cpp -o build/target/main.o
You're not compiling your object files correctly. g++ doesn't output the files to stdout, it writes them to the local directly. If you want to put the object files in a specific directory, you need to use the -o option:
$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c $^ -o $#
^^^^^^
$(BUILD_DIR):
#mkdir -p $#
Also you're building your executable incorrectly. The dependencies are insufficient and you don't have your target listed. You'll want this:
$(EXE_DIR)/$(EXE) : $(addprefix $(BUILD_DIR),$(OBJECTS)) | $(EXE_DIR)
$(CXX) $(CXXFLAGS) -o $# $^
$(EXE_DIR):
#mkdir -p $#
This will create an order-only dependency from your binary on the directory, and correctly build the binary. Note that you shouldn't have a dependency from your target on your .d files. That makes little sense. Instead, your rule for building the .os should simply also build the .ds (that rule suffers the same problem currently as your .o rule):
# build the .o and the .d in one go
$(BUILD_DIR)/%.o : %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -o $# -c $< -MP -MMD -MF $(#:.o=.d)
AS AN EDITORIAL ASIDE, THERE IS THIS COMMON TENDENCY TO WRITE ALL VARIABLES IN MAKEFILES IN SHOUTY_CAPS. THIS IS PROVABLY MUCH MORE DIFFICULT TO READ THAN USING JUST USING snake_case. Lower case letters work just fine.

Linker error - clang++

I've got a linker error that I'm having trouble understanding. Here's the error message:
duplicate symbol _main in:
objs/MyFile.o
/var/folders/h7/f0t4_h4130bcvkjm7ms7y9_w0000gp/T/MyFile-f334a7.o
ld: 1 duplicate symbol for architecture x86_64
At first after looking around for an answer, I thought I might have accidentally declared something in a header file. I went ahead and removed all of my own header files, but I'm still getting the error.
Coupled with the fact that the two files in the error message are not both /var/folder files like many of the declaration-in-header errors, this makes me think it might have something to do with my Makefile, which I have been recently playing around with.
Here's the Makefile:
CXX = clang++
LDFLAGS = -lm -lxml2
SRCDIR = src
OBJDIR = objs
SOURCES = $(wildcard src/*.cc)
HEADERS = $(wildcard src/*.h)
OBJECTS = $(patsubst src/%.cc,$(OBJDIR)/%.o,$(SOURCES))
objs/%.o : src/%.cc
#echo "Building object $#"
#$(CXX) $(CXXFLAGS) -o $# -c $<
TARGETS = src/MyFile
default: $(TARGETS)
src/MyFile: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# -I $^ $(LDFLAGS) src/MyFile.cc
Makefile.dependencies:: $(SOURCES) $(HEADERS)
$(CXX) $(CXXFLAGS) -MM $(SOURCES) > Makefile.dependencies
-include Makefile.dependencies
.PHONY: clean spartan
clean:
#rm -f $(TARGETS) $(OBJECTS) core Makefile.dependencies
spartan: clean
#rm -f *~ .*~
Any and all help in figuring out what could be causing this is much appreciated!
Overview
I don't understand this line and think that it causes the error:
$(CXX) $(CXXFLAGS) -o $# -I $^ $(LDFLAGS) src/MyFile.cc
Firstly, -I $^ doesn't make much sense as -I should be followed by include directory path, you probably want this to be -I . $^.
Secondly, you don't need src/MyFile.cc as it already should be present in $(OBJECTS) as objs/MyFile.o.
Solution
Changing linker command to this should help:
$(CXX) $(CXXFLAGS) -o $# -I . $^ $(LDFLAGS)
What is happening
Your final link command looks similar to:
compiler file.o file.cpp
Compiler driver (clang++ here) sees source file in argument list and compiles it placing output into temporary file (/var/folders/h7/f0t4_h4130bcvkjm7ms7y9_w0000gp/T/MyFile-f334a7.o here) and actual link command becomes:
linker file.o differently/named/file.o
Hence duplicated symbol error: you have two object files of the same source file in argument list for the linker.

Makefile for cross compilation linux

I have been asked to port our product into another application.(our s/w is running on linux virtualbox)
I have got a directory of their interface files and also a example code on trying to configure their software/hardware. I see their interface files under the s/w directory. In the reference code directory, I see a makefile with the reference to their reference code.
Trying to run their reference code makefile. getting error that
make: *** No rule to make target `../ main.o" :(
Btw donot understand why SIMUDIR = -I\..\custom_simcode\ this is done in the makefile ?
Also not much familiar with crosscompiler syntax !
ifndef CROSS_CC_PREFIX
CROSS_CC_PREFIX=$(CROSS_COMPILE)
endif
PROGRAM = customer_sim
CC=$(CROSS_CC_PREFIX)gcc
LD=$(CROSS_CC_PREFIX)ld
RANLIB=$(CROSS_CC_PREFIX)corelib
CFLAGS= -g
all: $(PROGRAM)
## Include path
SIMUDIR = -I\..\custom_simcode\
CUST_INT_INC = -I./../cust_Intf/DecHandler/inc \
-I./../CCPU
LIBDIR = -L./../cust_Intf \
-L./../cust_IntfApi
LIBS = -lpthread -customercif -customerapi
LDFLAGS= $(LIBDIR) $(LIBS)
SOURCE = ./../custom_simcode/main.c \
./../custom_simcode/custcode_primitives_init.c \
./../custom_simcode/custccp_primitives_init.c
CFLAGS += $(SIMUDIR) $(CUST_INT_INC) -DPRINT_IO_CONSOLE -UADAPT_CCPU_CUSTIF
OBJS = $(SOURCE:.c=.o)
$(PROGRAM): $(OBJS)
$(CC) -o $# $(OBJS) $(LDFLAGS)
main.o: $(SIMUDIR)/main.c $(SIMUDIR) $(CUST_INT_INC)
$(CC) -c -o /main.o $(SIMUDIR)/main.c
clean:
-rm -f $(OBJS) $(OBJS) $(PROGRAM)
Your $(OBJS) list dependencies for $(PROGRAMs) with directories included but your rule for main.o doesn't have same path.
It would be better to have a generic rule to compile C files like
%.o: %.c
$(CC) -c -o $# $<
Then simply assign extra dependencies for each file like:
$(OBJS): $(SIMUDIR) $(CUST_INT_INC)