I'm using cmake in VSC on Ubuntu for a simple data cluster algorithm. For this I want to use the already existing Mlpack library. If I try to run my code I receive errors like this
main.cpp:(.text._ZN6mlpack8neighbor14NeighborSearchINS0_19NearestNeighborSortENS_6metric7LMetricILi1ELb0EEEN4arma3MatIdEENS_4tree6KDTreeENS9_15BinarySpaceTreeIS5_NS0_18NeighborSearchStatIS2_EES8_NS_5bound10HRectBoundENS9_13MidpointSplitEE17DualTreeTraverserENSH_19SingleTreeTraverserEE6SearchEmRNS7_ImEERS8_[_ZN6mlpack8neighbor14NeighborSearchINS0_19NearestNeighborSortENS_6metric7LMetricILi1ELb0EEEN4arma3MatIdEENS_4tree6KDTreeENS9_15BinarySpaceTreeIS5_NS0_18NeighborSearchStatIS2_EES8_NS_5bound10HRectBoundENS9_13MidpointSplitEE17DualTreeTraverserENSH_19SingleTreeTraverserEE6SearchEmRNS7_ImEERS8_]+0x6b4): Warnung: undefinierter Verweis auf »mlpack::Log::Info«
This seems to be an error because of false linking to Mlpack. I followed this example Getting Started with mlpack and created my own CmakeLists file
cmake_minimum_required(VERSION 3.8)
set (CMAKE_CXX_STANDARD 14)
project(HelloBoost)
set (VERSION_MAJOR 1)
set (VERSION_MINOR 0)
set(SOURCE main.cpp)
IF (MLPACK_INCLUDE_DIRS)
# Already in cache, be silent
SET(MLPACK_FIND_QUIETLY TRUE)
ENDIF (MLPACK_INCLUDE_DIRS)
FIND_PATH(MLPACK_INCLUDE_DIR core.hpp
PATHS /usr/local/include/mlpack
/usr/include/mlpack
)
SET(MLPACK_LIBRARY_DIR NOTFOUND CACHE PATH "The directory where the MLPACK libraries can be found.")
SET(SEARCH_PATHS
"${MLPACK_INCLUDE_DIR}/../lib"
"${MLPACK_INCLUDE_DIR}/../../lib"
"${MLPACK_LIBRARY_DIR}")
FIND_LIBRARY(MLPACK_LIBRARY NAMES mlpack PATHS ${SEARCH_PATHS})
INCLUDE (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(mlpack DEFAULT_MSG MLPACK_LIBRARY MLPACK_INCLUDE_DIR)
IF (MLPACK_FOUND)
SET(MLPACK_LIBRARIES "${MLPACK_LIBRARY}")
SET(MLPACK_INCLUDE_DIRS "${MLPACK_INCLUDE_DIR}")
ENDIF (MLPACK_FOUND)
find_package(Armadillo REQUIRED)
find_package(Boost 1.65.1.0 COMPONENTS thread regex system)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${MLPACK_INCLUDE_DIR})
include_directories(${Armadillo_INCLUDE_DIR})
add_executable(${PROJECT_NAME} ${SOURCE})
target_link_libraries(${PROJECT_NAME} ${Boost_THREAD_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${ARMADILLO_LIBRARIES} ${MLPACK_LIBRARY})
endif()
My main.cpp file looks like
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <string>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <mlpack/core.hpp>
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
using namespace std;
using namespace mlpack;
using namespace mlpack::neighbor;
using namespace mlpack::metric;
void mlModel(string filename)
{
// Armadillo is a C++ linear algebra library;
// mlpack uses its matrix data type.
arma::mat data;
/*
data::Load is used to import data to the mlpack,
It takes 3 parameters,
1. Filename = Name of the File to be used
2. Matrix = Matrix to hold the Data in the File
3. fatal = true if you want it to throw an exception
if there is an issue
*/
data::Load(filename, data, true);
/*
Create a NeighborSearch model. The parameters of the
model are specified with templates:
1. Sorting method: "NearestNeighborSort" - This
class sorts by increasing distance.
2. Distance metric: "ManhattanDistance" - The
L1 distance, the sum of absolute distances.
3. Pass the reference dataset (the vectors to
be searched through) to the constructor.
*/
NeighborSearch<NearestNeighborSort, ManhattanDistance> nn(data);
// in the above line we trained our model or
// fitted the data to the model
// now we will predict
arma::Mat<size_t> neighbors; // Matrices to hold
arma::mat distances; // the results
/*
Find the nearest neighbors. Arguments are:-
1. k = 1, Specify the number of neighbors to find
2. Matrices to hold the result, in this case,
neighbors and distances
*/
nn.Search(1, neighbors, distances);
// in the above line we find the nearest neighbor
// Print out each neighbor and its distance.
for (size_t i = 0; i < neighbors.n_elem; ++i)
{
std::cout << "Nearest neighbor of point " << i << " is point "
<< neighbors[i] << " and the distance is "
<< distances[i] << ".\n";
}
}
int main()
{
mlModel("../Example Data/collectedData_Protocol1.csv");
return 0;
}
Output off ldd "ProjectName"
linux-vdso.so.1 (0x00007ffcc7d1e000) libmlpack.so.3 => /usr/local/lib/libmlpack.so.3 (0x00007ff8b44d9000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff8b4150000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff8b3f38000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff8b3b47000) libarmadillo.so.8 => /usr/lib/libarmadillo.so.8 (0x00007ff8b393e000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff8b35a0000) libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007ff8b3371000) /lib64/ld-linux-x86-64.so.2 (0x00007ff8b4b54000) libblas.so.3 => /usr/lib/x86_64-linux-gnu/libblas.so.3 (0x00007ff8b3104000) liblapack.so.3 => /usr/lib/x86_64-linux-gnu/liblapack.so.3 (0x00007ff8b2866000) libarpack.so.2 => /usr/lib/x86_64-linux-gnu/libarpack.so.2 (0x00007ff8b261c000) libsuperlu.so.5 => /usr/lib/x86_64-linux-gnu/libsuperlu.so.5 (0x00007ff8b23ac000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff8b21a8000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff8b1f89000) libgfortran.so.4 => /usr/lib/x86_64-linux-gnu/libgfortran.so.4 (0x00007ff8b1baa000) libquadmath.so.0 => /usr/lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007ff8b196a000)
Output of nm
nm -D -C /usr/local/lib/libmlpack.so | grep Log::Info000000000044c2e0 B mlpack::Log::Info
Is there something I am missing ? The cmake build does work just fine. Does anyone has a working CmakeList file for using Mlpack wit Cmake on Ubuntu?
I missunderstood the concept of Cmake. I thought running my main.cpp will automatically link the necessary libraries after using Cmake. I know understand that I have to run the CMake Executable in order to get the desired output. This works as expected.
Just install mlpack
in your system and use FindMLPACK.cmake
provided in mlpack models repo. Your root CMakeLists.txt
should look like this:
cmake_minimum_required(VERSION 3.8)
set (CMAKE_CXX_STANDARD 14)
project(MlpackSample)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(MLPACK REQUIRED)
add_executable(mlpack_sample main.cpp)
target_link_libraries(mlpack_sample ${MLPACK_LIBRARY})
You just need to put FindMLPACK.cmake
file in cmake
directory of your project
*
- CMakeLists.txt
- main.cpp
* cmake
- FindMLPACK.cmake
I paste the content of the file here in case github link expires
#.rst:
# FindMLPACK
# -------------
#
# Find MLPACK
#
# Find the MLPACK C++ library
#
# Using MLPACK::
#
# find_package(MLPACK REQUIRED)
# include_directories(${MLPACK_INCLUDE_DIRS})
# add_executable(foo foo.cc)
# target_link_libraries(foo ${MLPACK_LIBRARIES})
#
# This module sets the following variables::
#
# MLPACK_FOUND - set to true if the library is found
# MLPACK_INCLUDE_DIRS - list of required include directories
# MLPACK_LIBRARIES - list of libraries to be linked
# MLPACK_VERSION_MAJOR - major version number
# MLPACK_VERSION_MINOR - minor version number
# MLPACK_VERSION_PATCH - patch version number
# MLPACK_VERSION_STRING - version number as a string (ex: "1.0.4")
include(FindPackageHandleStandardArgs)
# UNIX paths are standard, no need to specify them.
find_library(MLPACK_LIBRARY
NAMES mlpack
PATHS "$ENV{ProgramFiles}/mlpack/lib" "$ENV{ProgramFiles}/mlpack/lib64" "$ENV{ProgramFiles}/mlpack"
)
find_path(MLPACK_INCLUDE_DIR
NAMES mlpack/core.hpp mlpack/prereqs.hpp
PATHS "$ENV{ProgramFiles}/mlpack"
)
if(MLPACK_INCLUDE_DIR)
# Read and parse mlpack version header file for version number
file(STRINGS "${MLPACK_INCLUDE_DIR}/mlpack/core/util/version.hpp" _mlpack_HEADER_CONTENTS REGEX "#define MLPACK_VERSION_[A-Z]+ ")
string(REGEX REPLACE ".*#define MLPACK_VERSION_MAJOR ([0-9]+).*" "\\1" MLPACK_VERSION_MAJOR "${_mlpack_HEADER_CONTENTS}")
string(REGEX REPLACE ".*#define MLPACK_VERSION_MINOR ([0-9]+).*" "\\1" MLPACK_VERSION_MINOR "${_mlpack_HEADER_CONTENTS}")
string(REGEX REPLACE ".*#define MLPACK_VERSION_PATCH \"?([0-9x]+).*" "\\1" MLPACK_VERSION_PATCH "${_mlpack_HEADER_CONTENTS}")
unset(_mlpack_HEADER_CONTENTS)
set(MLPACK_VERSION_STRING "${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH}")
endif()
find_package_handle_standard_args(MLPACK
REQUIRED_VARS MLPACK_LIBRARY MLPACK_INCLUDE_DIR
VERSION_VAR MLPACK_VERSION_STRING
)
if(MLPACK_FOUND)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIR})
set(MLPACK_LIBRARIES ${MLPACK_LIBRARY})
endif()
# Hide internal variables
mark_as_advanced(
MLPACK_INCLUDE_DIR
MLPACK_LIBRARY
)