2

I am trying to compile the example code from the github page of docopt. I am getting a linker error though:

/tmp/test-d3ed6b.o: In function `main':
test.cpp:(.text+0xf3): undefined reference to `docopt::docopt(std::string const&, std::vector<std::string, std::allocator<std::string> > const&, bool, std::string const&, bool)'
test.cpp:(.text+0x1c8): undefined reference to `docopt::operator<<(std::ostream&, docopt::value const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I have a file test.cpp and a directory docopt with all the docopt files in it.

test.cpp:

#include <iostream>
#include "docopt/docopt.h"

static const char USAGE[] =
R"(Naval Fate.

Usage:
naval_fate ship new <name>...
naval_fate ship <name> move <x> <y> [--speed=<kn>]
naval_fate ship shoot <x> <y>
naval_fate mine (set|remove) <x> <y> [--moored | --drifting]
naval_fate (-h | --help)
naval_fate --version

Options:
-h --help     Show this screen.
--version     Show version.
--speed=<kn>  Speed in knots [default: 10].
--moored      Moored (anchored) mine.
--drifting    Drifting mine.
)";

int main(int argc, const char** argv)
{
    std::map<std::string, docopt::value> args
    = docopt::docopt(USAGE,
                     { argv + 1, argv + argc },
                     true,               // show help if requested
                     "Naval Fate 2.0");  // version string

    for(auto const& arg : args) {
        std::cout << arg.first <<  arg.second << std::endl;
    }

    return 0;
}

what is with that error? How can I fix that? I have tried clang-3.5 and g++

lo tolmencre
  • 3,804
  • 3
  • 30
  • 60

2 Answers2

1

I ran into this as well.

I resolved the problem using cmake and some specific configuration in my CMakeLists.txt. The following configuration worked for me:

cmake_minimum_required (VERSION 3.5)
project(my_project)
include(ExternalProject)

set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )

set(DOCOPT_ROOT ${PROJECT_SOURCE_DIR}/external/docopt)
set(DOCOPT_INCLUDE_DIRS ${DOCOPT_ROOT}/include/docopt)
set(DOCOPT_LIBRARIES ${DOCOPT_ROOT}/lib/libdocopt.a)
set(docopt_INSTALL_DIR "${DOCOPT_ROOT}")
set(docopt_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${docopt_INSTALL_DIR})

ExternalProject_Add(docopt
  PREFIX ${DOCOPT_ROOT}
  GIT_REPOSITORY https://github.com/docopt/docopt.cpp.git
  BINARY_DIR ${DOCOPT_ROOT}
  INSTALL_DIR ${DOCOPT_ROOT}
  CMAKE_ARGS ${docopt_CMAKE_ARGS}
  LOG_DOWNLOAD ON
  LOG_CONFIGURE ON
  LOG_BUILD ON
  LOG_INSTALL ON
)
add_library(libdocopt STATIC IMPORTED)
set_target_properties(libdocopt PROPERTIES IMPORTED_LOCATION ${DOCOPT_LIBRARIES})
add_dependencies(libdocopt docopt)

include_directories(${PROJECT_SOURCE_DIR})
include_directories(${DOCOPT_INCLUDE_DIRS})

file(GLOB projector_src
  "*.h"
  "*.cpp"
  )

add_executable(my_project ${my_project_src})
target_link_libraries(projector libdocopt)

Obviously, you don't need to use cmake, but instead you'll need to either put the source for docopt.cpp in with your own code or else you'll need to tell the linker where to look for it. cmake does take care of this for you, but it's one more thing to worry about.

0

Modified Jeremiah Peschka's answer to work out of the box independently of any other sources.


Project structure:

├── CMakeLists.txt
├── build
└── main.cpp


CMakeLists.txt

cmake_minimum_required (VERSION 3.5)
project(my_project)
include(ExternalProject)

set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )

set(DOCOPT_ROOT ${PROJECT_SOURCE_DIR}/external/docopt)
set(DOCOPT_INCLUDE_DIRS ${DOCOPT_ROOT}/include/docopt)
set(DOCOPT_LIBRARIES ${DOCOPT_ROOT}/lib/libdocopt.a)
set(docopt_INSTALL_DIR "${DOCOPT_ROOT}")
set(docopt_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${docopt_INSTALL_DIR})

ExternalProject_Add(docopt
  PREFIX ${DOCOPT_ROOT}
  GIT_REPOSITORY https://github.com/docopt/docopt.cpp.git
  BINARY_DIR ${DOCOPT_ROOT}
  INSTALL_DIR ${DOCOPT_ROOT}
  CMAKE_ARGS ${docopt_CMAKE_ARGS}
  LOG_DOWNLOAD ON
  LOG_CONFIGURE ON
  LOG_BUILD ON
  LOG_INSTALL ON
)

add_library(libdocopt STATIC IMPORTED)
set_target_properties(libdocopt PROPERTIES IMPORTED_LOCATION ${DOCOPT_LIBRARIES})
add_dependencies(libdocopt docopt)

include_directories(${PROJECT_SOURCE_DIR})
include_directories(${DOCOPT_INCLUDE_DIRS})

file(GLOB src
  "*.h"
  "*.cpp"
  )

add_executable(my_project ${src})
target_link_libraries(my_project libdocopt)
rhoeberg
  • 9
  • 1