I have an implicit gnu-makefile side by side with my Cross-platform build file so that I can debug either with the other.
I am trying to keep my architecture constrained such that my builds are implicit in gnu make. This will help restrict any wild build patterns.
I have managed to make everything implicit except for the executable. My makefile is:
CXX=c++
CXXFLAGS+=-std=c++17
CXXFLAGS+=$(shell pkg-config --cflags tesseract)
LDFLAGS+=$(shell pkg-config --libs tesseract)
CXXFLAGS+=$(shell pkg-config --cflags lept)
LDFLAGS+=$(shell pkg-config --libs lept)
main: main.o
ocr-memtest: ocr-memtest.o
However, the last implicit step (the executable) is not linking the standard library (my guess):
in ocr-memtest.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string()", referenced from:
_main in ocr-memtest.o
"operator delete[](void*)", referenced from:
_main in ocr-memtest.o
"operator delete(void*)", referenced from:
_main in ocr-memtest.o
"operator new(unsigned long)", referenced from:
_main in ocr-memtest.o
"___gxx_personality_v0", referenced from:
_main in ocr-memtest.o
Dwarf Exception Unwind Info (__eh_frame) in ocr-memtest.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [ocr-memtest] Error 1
With a virtually identical makefile:
CXX=c++
CXXFLAGS+=-std=c++17
CXXFLAGS+=$(shell pkg-config --cflags tesseract)
LDFLAGS+=$(shell pkg-config --libs tesseract)
CXXFLAGS+=$(shell pkg-config --cflags lept)
LDFLAGS+=$(shell pkg-config --libs lept)
main: main.o
ocr-memtest: ocr-memtest.o
$(CXX) -o $# $< $(CXXFLAGS) $(LDFLAGS) # only change
I am able to compile and run the same code successfully.
The respective compiler output for the two methods on this mac with brew installed packages is:
#implicit, non-working
c++ -std=c++17 -I/usr/local/Cellar/tesseract/5.0.1/include -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -c -o ocr-memtest.o ocr-memtest.cpp
cc -L/usr/local/Cellar/tesseract/5.0.1/lib -L/usr/local/Cellar/libarchive/3.5.2/lib -ltesseract -larchive -lcurl -L/usr/local/Cellar/leptonica/1.82.0/lib -llept ocr-memtest.o -o ocr-memtest
# manual, working
c++ -std=c++17 -I/usr/local/Cellar/tesseract/5.0.1/include -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -c -o ocr-memtest.o ocr-memtest.cpp
c++ -o ocr-memtest ocr-memtest.o -std=c++17 -I/usr/local/Cellar/tesseract/5.0.1/include -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -I/usr/local/Cellar/leptonica/1.82.0/include/leptonica -L/usr/local/Cellar/tesseract/5.0.1/lib -L/usr/local/Cellar/libarchive/3.5.2/lib -ltesseract -larchive -lcurl -L/usr/local/Cellar/leptonica/1.82.0/lib -llept
I suspect I have some misunderstanding that has resulted in me doing something subtly different than expected... How would I configure this make to render the code implicitly all the way to the executable?
There's no way a recipe that only knows the executable name and object file prerequisites can guess what compiler front-end should be used to link: C, C++, Fortran, whatever.
You can find the implicit rules via:
make -f/dev/null -p
You'll see that an executable uses this built-in rule:
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
Then if you look for LINK.o you'll see:
# default
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
So, the default recipe uses CC.
You can either use:
CC = $(CXX)
Or you can redefine LINK.o:
LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)
Related
I get the following error when trying to compile my simple program with make all:
❯ make all
clang++ --std=c++11 -Wall main.cpp
Undefined symbols for architecture arm64:
"file_reader::read_file()", referenced from:
_main in main-99040e.o
"file_reader::file_reader(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
_main in main-99040e.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main.o] Error 1
I can compile the program manually if I do clang++ --std=clang++11 main.cpp file_reader.cpp (and the executable works correctly), so I don't think it's an architecture error like it suggests. I think it might be a problem with my makefile, which I will include below, so if anyone has any insight that would be really helpful. I looked up several conventions for makefiles and none of them helped. The structure is pretty basic with main.cpp creating an object of type file_reader and then referencing one of its methods, so I use #include "file_reader.h" in my main.cpp.
makefile:
# compiler
CXX = clang++
# compiler flags:
# --std=clang++11 : verion
CXXFLAGS = --std=c++11 -Wall
all: main.out
main.out: main.o file_reader.o
$(CXX) main.o file_reader.o -o main
main.o: main.cpp file_reader.h
$(CXX) $(CXXFLAGS) main.cpp
file_reader.o: file_reader.cpp file_reader.h
$(CXX) $(CXXFLAGS) file_reader.cpp
clean:
rm -rf *.o restaurant
In my cpp project, I have header file with #include <boost/asio.hpp>.
i also got a makefile attached to the project:
CFLAGS:=-c -Wall -Weffc++ -g -std=c++11 -Iinclude
LDFLAGS:=-L/Users/user/Downloads/boost_1_61_0
all: EchoClient
g++ -o bin/echoExample bin/connectionHandler.o bin/echoClient.o $(LDFLAGS)
EchoClient: bin/connectionHandler.o bin/echoClient.o
bin/connectionHandler.o: src/connectionHandler.cpp
g++ $(CFLAGS) -o bin/connectionHandler.o src/connectionHandler.cpp
bin/echoClient.o: src/echoClient.cpp
g++ $(CFLAGS) -o bin/echoClient.o src/echoClient.cpp
.PHONY: clean
clean:
rm -f bin/*
What I need to to in order to make the program compile and run?
Do i need to download boost and put it in some folder?
Do i need to change the value LDFLAGS that inside the makefile to the download boost destination?
This is what i did so far, but it seems wrong because when I run make I get this error:
g++ -o bin/echoExample bin/connectionHandler.o bin/echoClient.o -L/Users/user/Downloads/boost_1_61_0
Undefined symbols for architecture x86_64:
"boost::system::system_category()", referenced from:
boost::asio::error::get_system_category() in connectionHandler.o
boost::system::error_code::error_code() in connectionHandler.o
___cxx_global_var_init.2 in connectionHandler.o
boost::asio::error::get_system_category() in echoClient.o
___cxx_global_var_init.2 in echoClient.o
"boost::system::generic_category()", referenced from:
___cxx_global_var_init in connectionHandler.o
___cxx_global_var_init.1 in connectionHandler.o
___cxx_global_var_init in echoClient.o
___cxx_global_var_init.1 in echoClient.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [all] Error 1
Am i doing it OK?
I'm tring to run it both in mac and in windows
The folder boost_1_61_0 contains folders: boosts, libs, status, more, tools and more
After adding a C++ component to my Swift application that is being compiled and run via the command line, I now need to compile the C++ and Objective-C++ (*.mm) files and link them with the Swift application.
Makefile:
all: foo-renderer
clean:
rm -f foo-renderer cpp.o objc.o
cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
clang++ -c -o $# $^
objc.o: cpp.o FooRenderer/FooRenderer/FooLibraryWrapper.mm
clang++ -c -framework Foundation -o $# $^
foo-renderer: objc.o FooRenderer/FooRenderer/*.swift
xcrun -sdk macosx swiftc -import-objc-header FooRenderer/FooRenderer/FooRenderer-Bridging-Header.h -o $# $^
The compiler fails with these errors:
ld: warning: object file (objc.o) was built for newer OSX version (10.12) than being linked (10.9)
Undefined symbols for architecture x86_64:
"__ZN11FooLibrary23printifyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE", referenced from:
-[FooLibraryWrapper printify:] in objc.o
"__ZN11FooLibrary8optimizeERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE", referenced from:
-[FooLibraryWrapper optimize:] in objc.o
"__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm", referenced from:
-[FooLibraryWrapper printify:] in objc.o
-[FooLibraryWrapper optimize:] in objc.o
"__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev", referenced from:
-[FooLibraryWrapper printify:] in objc.o
-[FooLibraryWrapper optimize:] in objc.o
"__ZSt9terminatev", referenced from:
___clang_call_terminate in objc.o
"___cxa_begin_catch", referenced from:
___clang_call_terminate in objc.o
"___gxx_personality_v0", referenced from:
-[FooLibraryWrapper printify:] in objc.o
-[FooLibraryWrapper optimize:] in objc.o
Dwarf Exception Unwind Info (__eh_frame) in objc.o
ld: symbol(s) not found for architecture x86_64
My first instinct was that the standard C++ libraries weren't being included. I tried adding these lib flags to the following command, but to no avail:
cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
clang++ -c --std=c++14 -lstdc++ -lc++ -stdlib=libstdc++ -o $# $^
What am I missing?
One problem is that cpp.o is missing from the last command line. Adding it to the dependency list should do the trick:
foo-renderer: objc.o FooRenderer/FooRenderer/*.swift cpp.o
xcrun -sdk macosx swiftc -import-objc-header FooRenderer/FooRenderer/FooRenderer-Bridging-Header.h -o $# $^
That's because the linker needs the definitions of the symbols found in the C++ code.
Adding the -l... flags to the command for the cpp.o target is unnecessary because those are linker flags, and at that point you are just compiling.
Also, you likely don't need the cpp.o dependency for the objc.o target, since you are still compiling and compilation doesn't depend on other object files. You could probably do OK without -framework Foundation, but it doesn't hurt anything.
Though I am not very familiar with objc/clang/swift, but i have some pointers for you on how to proceed,
> "__ZN11FooLibrary23printifyERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE",
> referenced from:
> -[FooLibraryWrapper printify:] in objc.o
The above says that in objc object file in function printify, you have an undefined symbol, which could be FooLibrary::printify::basic_string::char_traits, so most probably you are missing a c++ library, try adding libc++ library in your linking command.
cpp.o: FooRenderer/FooRenderer/FooLibrary.cpp
clang++ -c --std=c++14 -lstdc++ -lc++ -stdlib=libstdc++ -o $# $^
And there is no meaning to add linker flags/libraries during compile time.
I would like to use tinyxml. I have used it in the past, and it works great. The only problem is I was developing on my Linux box which is a laptop. I have a mac mini and I have that set up as my desktop, so I would like to use it for a big chunk of development.
I have a simple tinyxml example that one of my instructors gave me. With this example came a Makefile like so:
ifeq ("$(shell whoami)", "malloy")
CXX = clang++
else
CXX = g++
endif
# Warnings frequently signal eventual errors:
CXXFLAGS=`sdl-config --cflags` -g -W -Wall -Weffc++ -Wextra -pedantic -O0
ifeq ("$(shell uname)", "Darwin")
LDFLAGS = -framework Foundation -framework GLUT -framework OpenGL -lm
else
ifeq ("$(shell uname)", "Linux")
LDFLAGS = `sdl-config --libs` -lm -lSDL_ttf -lSDL_image -ltinyxml
endif
endif
OBJS = \
main.o
EXEC = run
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
$(EXEC): $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $(OBJS) $(LDFLAGS)
main.o: main.cpp
clean:
rm -rf $(OBJS)
rm -rf $(EXEC)
And when I try to make this simple project I get all of these Undefined symbol errors.
This is what terminal outputs after I type make:
g++ `sdl-config --cflags` -g -W -Wall -Weffc++ -Wextra -pedantic -O0 -o run main.o - framework Foundation -framework GLUT -framework OpenGL -lm
Undefined symbols for architecture x86_64:
"TiXmlString::nullrep_", referenced from:
TiXmlString::quit() in main.o
"TiXmlDocument::LoadFile(TiXmlEncoding)", referenced from:
_main in main.o
"TiXmlDocument::TiXmlDocument(char const*)", referenced from:
_main in main.o
"TiXmlNode::Clear()", referenced from:
_main in main.o
"TiXmlNode::~TiXmlNode()", referenced from:
TiXmlDocument::~TiXmlDocument() in main.o
"TiXmlElement::Attribute(char const*) const", referenced from:
_main in main.o
"TiXmlNode::FirstChildElement() const", referenced from:
TiXmlNode::FirstChildElement() in main.o
"TiXmlNode::NextSiblingElement() const", referenced from:
TiXmlNode::NextSiblingElement() in main.o
"vtable for TiXmlDocument", referenced from:
TiXmlDocument::~TiXmlDocument() in main.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [run] Error 1
I know it is a linker error that is about it. I used Homebrew to install tinyxml. It was actually giving me problems so after I got the tar-ball for tinyxml I extracted it and put the folder in /usr/local/include. g++ doesn't complain about finding the files. Just stuff with the v-table.
Any help is greatly appreciated! Thanks in advance!!!
You should modify the makefile and instruct the linker to use tinyxml (-ltinyxml) in the "Darwin" case. AFAIK, tinyxml is not bundled with OSX so you may need to find or build that. Instead, you can use expat (simpler-easier) or libxml2 (faster-detailed), which already come with OSX (you can also use (c++) wrappers, google them...)
I keep getting error
make: *** No rule to make target `all'. Stop.
I am sure my makefile works perfectly, because I did run it on the terminal and everything fine. But when I try to import everything into eclispe by create an Empty Makefile Project, I couldn't compile the program. So did I miss something in eclipse configuration ?
Anyway, this is my makefile, please take a look, and correct me. Thanks
CC = g++
prog: legrec.o game.o board.o piece.o
$(CC) legrec.o game.o board.o piece.o -Wall -Werror -pedantic -o legrec
legrec.o: legrec.cpp game.h
$(CC) -Wall -Werror -pedantic -c legrec.cpp
game.o: game.cpp game.h board.h piece.h move.h player.h
$(CC) -Wall -Werror -pedantic -c game.cpp
board.o: board.cpp board.h piece.h move.h player.h
$(CC) -Wall -Werror -pedantic -c board.cpp
piece.o: piece.cpp piece.h board.h move.h player.h
$(CC) -Wall -Werror -pedantic -c piece.cpp
EDIT: Thanks for all replies, I did change the first line into all:legrec, and the previous error message was gone, however another errors came out
cc legrec.o -o legrec
Undefined symbols for architecture x86_64:
"game::game()", referenced from:
_main in legrec.o
"game::printMenu()", referenced from:
_main in legrec.o
"game::printBoard()", referenced from:
_main in legrec.o
"game::nextMove()", referenced from:
_main in legrec.o
"game::ended()", referenced from:
_main in legrec.o
"game::printWinner()", referenced from:
_main in legrec.o
"game::~game()", referenced from:
_main in legrec.o
"std::terminate()", referenced from:
_main in legrec.o
"std::ios_base::Init::Init()", referenced from:
__static_initialization_and_destruction_0(int, int)in legrec.o
"std::ios_base::Init::~Init()", referenced from:
___tcf_0 in legrec.o
"___gxx_personality_v0", referenced from:
Dwarf Exception Unwind Info (__eh_frame) in legrec.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
make: *** [legrec] Error 1
I just don't understand why running same platform but the program performs differently. Before I was run on the terminal and edit on there that seems very well, but after porting into Eclipse, it drives me insance with the weird errors.
Your very first rule is not really good.
You could rename it to all and it would "work". But a better approach would be:
all: legrec
legrec: legrec.o game.o board.o piece.o
$(CC) legrec.o game.o board.o piece.o -Wall -Werror -pedantic -o legrec
i.e. the rule name should match the output produced.
If you type just make on the command line, the very first rule encountered is run (that's why it works for you). I'm guessing your IDE is running make all, and you haven't defined such a rule.
I am not an expert, but I'll try to help.
Rename the maketarget prog to legrec"
Try adding the following lines
.PHONY: all clean
all: legrec
Also your makefile doesn't have clean target. For that looking at your make file I suggest adding
clean:
#rm *.o legrec
You can improve the makefile in a number of ways to reduce duplication.
make knows how to turn a cpp file into an object file so you dont need to tell it. Just define the compiler and the options to use: I have added CPPFLAGS.
make will build the first target it finds in the makefile - in this case 'legrec'. The $# in the LD (link) command refers to legrec. The $^ refers to the prerequisites (ie the list of objects)
Here is my version:
CC = g++
CPPFLAGS = -Wall -Werror -pedantic
LDFLAGS =
legrec: legrec.o game.o board.o piece.o
$(LD) $(LDFLAGS) $^ -o $#
legrec.o: game.h
game.o: board.h piece.h move.h player.h game.h
board.o: board.h piece.h move.h player.h
piece.o: board.h piece.h move.h player.h
.PHONY: clean
clean:
#rm -f *.o legrec
Note that you can add -g or -O etc to the CPPFLAGS line. By the way, there are many more warnings that the compiler can give you than are produced by -Wall. For C, I normally use:
-Wall \
-Wextra \
-Wshadow \
-Wstrict-prototypes \
-Wmissing-prototypes \
-Wundef \
-Wunreachable-code \
-Wunused \
-Wcast-qual