Reputation: 2028
Learning C++ lately, and I'm having trouble to compile my classes. I am currently getting the following obscure template error:
Undefined symbols for architecture x86_64:
"SmallWorld::AJV::validate(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer>*, nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer>*)", referenced from:
SmallWorld::Map::(anonymous namespace)::readMap(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in map.test.cpp.o
"std::__1::function<unsigned long (SmallWorld::Map::Graph<SmallWorld::Region>)> SmallWorld::Map::algorithm::dfs<SmallWorld::Region>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::function<bool (std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >&, std::__1::unordered_map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > > > const&)> const&)", referenced from:
creates_a_connected_graph_small_world_map_Test::TestBody() in map.test.cpp.o
"SmallWorld::Region::Region(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer>)", referenced from:
std::__1::shared_ptr<SmallWorld::Region> std::__1::shared_ptr<SmallWorld::Region>::make_shared<nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer> const&>(nlohmann::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long long, unsigned long long, double, std::__1::allocator, nlohmann::adl_serializer> const&&&) in map.test.cpp.o
ld: symbol(s) not found for architecture x86_64
which can be simplified to:
Undefined symbols for architecture x86_64:
"SmallWorld::AJV::validate(nlohmann::json*, nlohmann::json*)", referenced from:
SmallWorld::Map::(anonymous namespace)::readMap(string const&, string const&) in map.test.cpp.o
"std::function<size_t(Graph<Region>)> SmallWorld::Map::algorithm::dfs<SmallWorld::Region>(string const&, std::function<bool (string const&, std::set<string> const&, std::unordered_map<string, string> const&)", referenced from:
creates_a_connected_graph_small_world_map_Test::TestBody() in map.test.cpp.o
"SmallWorld::Region::Region(nlohmann::json)", referenced from:
std::shared_ptr<SmallWorld::Region> std::shared_ptr<SmallWorld::Region>::make_shared<nlohmann::json const&&&) in map.test.cpp.o
ld: symbol(s) not found for architecture x86_64
Which to me seems like it is saying that the method bool AJV::validate(json* schema, json* data)
does not exist on type AJV. However I have verified the common mistakes (different implementation from header declaration, different invocation from implementation), to no avail.
Here is the definition and implementation of the AJV class:
// AJV.h
#ifndef SMALLWORLD_AJV_H
#define SMALLWORLD_AJV_H
#include <nlohmann/json.hpp>
using nlohmann::json;
namespace SmallWorld {
class AJV {
public:
std::function<bool(json*)> compile(json* schema);
bool validate(json* schema, json* data);
json errors;
private:
json m_schema;
std::function<bool(json*)> m_validator;
};
};
#endif // SMALLWORLD_AJV_H
// AJV.cpp
#include <nlohmann/json.hpp>
#include "AJV.h"
using nlohmann::json;
namespace SmallWorld {
std::function<bool(json*)> AJV::compile(json* schema) {
return [](json* data){ return true; };
};
bool AJV::validate(json* schema, json* data){ return true; };
};
And here is the invocation:
//loader.cpp
json* readMap(const string& map_path, const string& schema_path) {
AJV ajv;
json* schema = readJSONFile(schema_path);
json* jmap = readJSONFile(map_path);
if(ajv.validate(schema, jmap)){
delete schema;
return jmap;
}else{
delete schema;
throw ajv.errors;
}
};
Setup:
Additional Details
Compilation is done via command line: mkdirp build && cd build && cmake .. && make
File AJV.h is within source tree at the specified include path.
How can I solve this problem?
Cheers ☀️
Upvotes: 0
Views: 1077
Reputation: 6993
When you register a project in CMake, you list both headers and source files. It will then deal with these as best it can for the respective IDE / build system that you tell it to use.
If you always have one header and one cpp file (there's no requirement to; you may find some objects are complex/large enough that you want to split it into multiple cpp files for your sanity) then you could list all your file names with no extension in the cmake and have it append the .cxx and .h to the end for you. This will leave you with just half the typing.
As an alternative there is a non-recommended route which is to to use the file command to scan the directory for files - but this is done only when cmake is run; and as such will not auto-update; leaving it possible to have a source tree that's building fine on one system; while not on another.
Upvotes: 1