I'm a beginner in C++ and am coding a Snake for uni, and have to run unit tests.
FYI, I code on Xcode 7.1.1.
I manage to make sample tests run on my machine, but have a problem when it comes to creating a fixture for my snake. Here is the code I have :
#include "gtest/gtest.h"
#include "calc.h"
#include "Serpent.h"
#include "Map.h"
#include "Main.h"
using namespace std;
using namespace sf;
class Serpent_test_fixture: public ::testing::Test
{public:
Serpent* serpent_test;
Map* map_test;
Serpent_test_fixture(){
serpent_test = new Serpent(true);
RenderWindow window(VideoMode(WINDOW_WIDTH, WINDOW_HEIGHT, 32), "SnakeTest", Style::None);
map_test = new Map("", window, false);
}
virtual void SetUp(){
map_test->updateGameField(0, 0, HEAD_EAST);
serpent_test->setHead(*map_test, false);
int size_init = serpent_test->getSize();
}
virtual void TearDown(){
}
~Serpent_test_fixture(){
delete serpent_test;
delete map_test;
}
};
TEST_F(Serpent_test_fixture, cherry_action)
{
map_test->updateGameField(0,0,CHERRY);
Tiles head_tile_test = HEAD_EAST;
serpent_test->fruit_action(*map_test, head_tile_test);
EXPECT_EQ(20, 20);
}
int main(int argc, char * argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
The way I understand it is, I create my snake (serpent in French) from my class Serpent, then I create my map from my class Map.
UpdateGameField updates the tile in (0,0) of the map and puts "HEAD_EAST" on it.
Anyway, here is the message I have :
Undefined symbols for architecture x86_64:
"Map::updateGameField(int, int, Tiles)", referenced from:
Serpent_test_fixture_test_cherry_action_Test::TestBody() in main.o
Serpent_test_fixture::SetUp() in main.o
"Map::Map(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, sf::RenderWindow const&, bool)", referenced from:
Serpent_test_fixture::Serpent_test_fixture() in main.o
"Map::~Map()", referenced from:
Serpent_test_fixture::SetUp() in main.o
Serpent_test_fixture::~Serpent_test_fixture() in main.o
"Serpent::fruit_action(Map&, Tiles&)", referenced from:
Serpent_test_fixture_test_cherry_action_Test::TestBody() in main.o
"Serpent::getSize()", referenced from:
Serpent_test_fixture::SetUp() in main.o
"Serpent::setHead(Map, bool)", referenced from:
Serpent_test_fixture::SetUp() in main.o
"Serpent::Serpent(bool)", referenced from:
Serpent_test_fixture::Serpent_test_fixture() in main.o
"Serpent::~Serpent()", referenced from:
Serpent_test_fixture::~Serpent_test_fixture() in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can anyone help? It's my first time using Google tests and I'm having a hard time making it work.
The basic issue here is how to orchestrate the dependencies for a test project relative to the production code to be tested and the test framework. The dependency relationships drive the build system (compiler, linker, etc.).
You might want to take a look at my C++ Now! 2014 presentation on Test-Driven Development in C++. It uses Boost.Test instead of google test, but shows a CMake based recipe to orchestrate the dependencies between production code and test code. The workshop is designed for you to follow along at your computer, replicating the steps in the presentation -- I provide the code you use at each step.
The dependencies look like this for a typical testing project:
test executable
production code to be tested (static library or shared library)
test framework
In my workshop materials I show how to use CMake to create these dependencies using Boost.Test as the test framework, but the principle is the same with google test and the recipe is nearly identical as well.
Related
Update: Fixed. Very simple solution. I just have to add in my Add_Executable method. Here:
add_executable (POC eb_pms.cpp url_binder.cpp)
So this problem looks pretty small, yet, I am unable to find any solution of this. Or, I should say, none of articles explains it in a simple manner so I can understand. I have come from a strongly typed background like C#/Java. I am trying to build a Rest API in C++11 using Simple Web Server and RapidJSON. Since we are building this project to be a part of a bigger solution, I cannot use commandline to link the program. I have to use the CMakeLists to compile and run the program. It means, the linking has to be done through the CMakeLists.txt file. The whole source code can be found here at GitHub. My environment is Macbook Pro + VS Code. So I have two CPPs here: eb_pms.cpp, url_binder.cpp. The urlbinder has a namespace 'EBPMS' and eb_pms has none. Following is the code of ep_pms:
(header file)
#include "server_http.hpp"
#include "client_http.hpp" //client for testing the API code
#include <boost/property_tree/ptree.hpp> /*for the shared pointer*/
#include "url_binder.h"
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;
using HttpClient = SimpleWeb::Client<SimpleWeb::HTTP>;
using Binder = EBPMS::URLBinder;
void bindUrls(HttpServer *server);
cpp file:
# include "eb_pms.h"
using namespace boost::property_tree;
using namespace std;
using namespace EBPMS;
int main(){
HttpServer server;
server.config.port = 8081;
bindUrls(&server);
thread server_thread([&server]() {
server.start();
});
server_thread.join();
}
void bindUrls(HttpServer *server){
//URLBinder c;
Binder binder;
binder.bindURL_string();
}
the url binder h:
#include <boost/property_tree/ptree.hpp> /*for the shared pointer*/
#include "server_http.hpp"
#include "client_http.hpp"
#include <iostream>
namespace EBPMS{
class URLBinder{
public: URLBinder();
void bindURL_string();
};
}
the url binder cpp;
#include "url_binder.h"
using namespace boost::property_tree;
using namespace std;
namespace EBPMS{
URLBinder::URLBinder() {}
void URLBinder::bindURL_string(){ //HttpServer *server
std::cout << "Trying to log if it comes" << std::endl;
}
}
So all I need is basically, to find a way to link this file with NameSpace with my original cpp so I can use the method from url binder inside my main cpp class. I am trying to call function in eb_pms.cpp class. When I run make command, I get this error:
Scanning dependencies of target POC
[ 2%] Building CXX object CMakeFiles/POC.dir/eb_pms.cpp.o
[ 5%] Linking CXX executable POC
Undefined symbols for architecture x86_64:
"EBPMS::URLBinder::bindURL_string()", referenced from: _main in eb_pms.cpp.o
bindUrls(SimpleWeb::Server<boost::asio::basic_stream_socket<boost::asio::ip::tcp>> >*) in eb_pms.cpp.o
"EBPMS::URLBinder::URLBinder()", referenced from: _main in eb_pms.cpp.o
bindUrls(SimpleWeb::Server<boost::asio::basic_stream_socket<boost::asio::ip::tcp>> >*) in eb_pms.cpp.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[2]: *** [POC] Error 1
make[1]: ***
[CMakeFiles/POC.dir/all] Error 2
make: *** [all] Error 2
It has been hours since I am trying to research. But I am unable find that missing piece. Any help will be greatly appreciated.
I'm just guessing here since you don't show your CMakeLists.txt file...
I would say that you don't list your url_binder.cpp file as a source in the CMake add_executable command.
All source-files you want to be part of your program must be listed.
I want to provide my own main function while using Boost.Test. So I have included the following macros:
#define BOOST_TEST_ALTERNATIVE_INIT_API
#define BOOST_TEST_NO_MAIN
My main function looks like this:
int main(int argc, char* argv[])
{
int exitCode = ::boost::unit_test::unit_test_main(&initialise, argc, argv);
return exitCode;
}
I have also created the function initialise.
When built on OS X using Xcode 6 the following error is reported:
Undefined symbols for architecture x86_64:
"boost::unit_test::unit_test_main(bool (*)(), int, char**)", referenced from:
_main in main.o
I am linking-in the unit test framework library.
Can someone please help resolve the error?
There are two possible solutions:
1) Include <boost/test/included/unit_test.hpp> in the test module. This has the effect of building both the test framework and the test module simultaneously.
2) Rebuild the test framework library withBOOST_TEST_NO_MAINand BOOST_TEST_ALTERNATIVE_INIT_API.
According to the documentation the 2nd option is preferred.
A beginner to armadillo library and have two problems with it.
The first question is about the link of armadillo and c++. I installed armadillo by following the instructions in the package and the location is /usr/include/, I could successfully run the code:
#include <iostream>
#include "/usr/include/armadillo"
using namespace std;
int main()
{
arma::mat a = arma::randu<arma::mat>(3, 3);
cout << a << endl;
return 0;
}
but if I want to define a function, for example, the inverse of the matrix (there is a function I can call from the library but I just want to do a test).
#include <iostream>
#include "/usr/include/armadillo"
using namespace std;
arma::mat Inverse( arma::mat A){
return arma::inv(A);
}
int main()
{
arma::mat a = arma::randu<arma::mat>(3, 3);
arma::mat inv_a = Inverse(a);
cout << inv_a << endl;
return 0;
}
then the program failed with three error messages.
Undefined symbols for architecture x86_64:
"_wrapper_dgetrf_", referenced from:
void arma::lapack::getrf<double>(int*, int*, double*, int*, int*, int*) in main.o
"_wrapper_dgetri_", referenced from:
void arma::lapack::getri<double>(int*, double*, int*, int*, double*, int*, int*) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I checked by google and have tried some advices, like:" In miscellaneous MAC OS X linkers, I had to put "-01 -larmadillo" AND I had to deactivate the shared library settings!", to be honest, I can not find the miscellaneous option and deactivate the shared library settings as i am not familiar with Xcode. Then I followed install MacPorts and the library is installed to the folder /usr/local/include/, and I tried again, the first program is alright but the second program still has three errors, could anyone help me with this?
The second question would be the use of lapack when I am using armadillo in the same program, as I know armadillo is based on lapack, then if I declared the library armadillo, do I need to declare lapacke.h. Why do I ask this questions is that when I declared RcppArmadillo and lapacke.h, an error exists:
This file includes at least one deprecated or antiquated header. Please consider using of the 32 header found in section 17.4.1.2 of the C++ standard. Example include substituting the <X> header for the <X.h> hear for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated. [-W#warnings]
Line 11763 conflicting type for 'cgetrf'
Line 11765 conflicting type for 'zgetrg_'
...
I had the same problem, but eventually I solved it.
I didn't installed armadillo for my own purpose, but provided absolute path to include and library directories. Also, in a README there is a note that if you're on Mac then you should use Accelerate framework like this "-framework Accelerate". So after doing this all linker errors were gone.
I thought Ubuntu and OS X would have similar interfaces for compiling a C/C++ program with SDL but nothing I am trying, or finding on Google seems to be working.
I have found a solution for Xcode, but I am not using Xcode. I am writing my programs from Sublime Text 2 and compiling via command-line since I prefer it and work much faster that way.
Long story short, I am receiving an array of errors with each attempt and thus far I have copied SDL.framework into my /Library/Frameworks directory.
This is the closest I have gotten to actually compiling:
[ 674 / 174 / 0 ] $ compcpsdl
Undefined symbols for architecture x86_64:
"_SDL_main", referenced from:
-[SDLMain applicationDidFinishLaunching:] in ccYYA0Ea.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Terminal command (i.e. compcpsdl)
g++ -I/Library/Frameworks/SDL.framework/Headers main.cpp SDLmain.m -framework SDL -framework Cocoa
With the following project structure:
Project-Directory/
--- main.cpp
--- SDLMain.m
--- SDLMain.h
And lastly, the following source code:
#include <iostream>
#include <SDL/SDL.h>
using namespace std;
int main ()
{
cout << "Hello World!";
return 0;
}
It appears I'm doing everything correctly, yet nothing seems to be working.
Any ideas guys?
I Think SDL does sometimes a bit strange stuff with the main function it assumes the mainfunction is defined in one way. Notice that I added int argc and char** argv to the definition of you main function.
Try:
int main (int argc, char** argv)
{
cout << "Hello World!";
return 0;
}
I encountered this problem also once and it was quite mystifying.
for more info see this stackoverflow question: Why SDL defines main macro?
I'm trying to get into C++ programming, and I'm quite struggling against the little details. Right now, I'm trying to get the snippet below to work, and apparently it will compile, but not link. (error message is a the bottom of this post)
I'm using libsndfile to open audio files, and the linker doesn't seem to find the corrent library files for it. This is on OS X 10.5.
I've downloaded libsndfile from mega-nerd.com and installed it via the ususal configure, make, sudo make install procedure. Is there anything else I need to do?
Edit: I have macports installed on my system, if that's of any concern.
Here's my code:
#include <iostream>
#include <string>
#include <sndfile.h>
#include "stereoSplit.h"
using namespace std;
int stereoSplit(string filename)
{
cout << filename;
SF_INFO sfinfo;
sfinfo.format = 0;
SNDFILE * soundfile;
soundfile = sf_open( filename.c_str(), SFM_READ, &sfinfo );
return 0;
}
int main (int argc, char const *argv[])
{
return stereoSplit("testStereo.wav");
}
And here's the complete error message:
Undefined symbols:
"_sf_open", referenced from:
stereoSplit(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)in cc3hvkkk.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
You need to link in the library. Your compiler command should look something like:
g++ mystuff.cpp -lsndfile
To link the library in Xcode, select the project target, add a new item to Link binary with libraries, and find the libsndfile.1.dynlib on your computer.