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.
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
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)
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
I'm starting a new project using C++ and OpenGL to make a simple game and to teach myself OpenGL. I do not want to use GLUT, and would rather use SDL for making windows and such. I'm having a lot of weird trouble with the Makefile, however. Currently, when I type make, I get this response when I include $(LFLAGS) $(LDFLAGS) in my G++ commands:
g++-5 tetris.o -o tetris -std=c++14
Undefined symbols for architecture x86_64:
"_SDL_CreateWindow", referenced from:
_main in tetris.o
"_SDL_GL_CreateContext", referenced from:
_main in tetris.o
"_SDL_Init", referenced from:
_main in tetris.o
"_SDL_PollEvent", referenced from:
game_loop(SDL_Window*) in tetris.o
"_glewGetErrorString", referenced from:
_main in tetris.o
"_glewInit", referenced from:
_main in tetris.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
make: *** [tetris] Error 1
and this response when I do not:
g++-5 -Wall -framework SDL2 tetris.o -o tetris -std=c++14
ld: framework not found SDL2
collect2: error: ld returned 1 exit status
make: *** [tetris] Error 1
Here is my new Makefile:
CC = g++-5
CFLAGS = -Wall -c -Wno-deprecated-declarations
LFLAGS = -Wall
LDFLAGS = -framework SDL2
LDLIBS= -lSDL2 -lglew -lGL
INCLUDES = -I/Library/Frameworks/SDL2.framework/Headers/
STD = -std=c++14
all: tetris
tetris: tetris.o
$(CC) $(LFLAGS) $(LDFLAGS) tetris.o -o tetris $(STD)
tetris.o: tetris.cpp
$(CC) $(CFLAGS) $(LDFLAGS) -o $# tetris.cpp $(STD)
.PHONY: clean
clean:
rm tetris *.o
And the headers part of my .cpp file:
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <unistd.h>
#include <iostream>
maybe you need to add
LDFLAGS = -framework GLUT
to your Makefile
Just use freeglut, you don't need to use SDL so that you can get started with OpenGL.
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...)