coin-or / CppAD

A C++ Algorithmic Differentiation Package: Home Page
https://cppad.readthedocs.io
Other
446 stars 94 forks source link

Problem to Link with CppAD and Ipopt #176

Closed smith-nekrald closed 3 weeks ago

smith-nekrald commented 1 year ago

After compiling and installing CppAD, there was a problem to link CppAD and Ipopt with C++ linker. Looks like the method std::string temp_file(void); in namespace CppAD::local is referenced withing CppAD include and is not present in the linking library. So far I have just grepped and copied this method to a separate header (and therefore linked), but I guess this is considered an issue.

bradbell commented 1 year ago

Take a look at the discussion https://github.com/coin-or/CppAD/discussions/175

In particular the suggestion 'From the description above it does not seem like you are including cppad_lib in the linking.'

smith-nekrald commented 1 year ago

But how exactly to include that particular library? Please see below my CMakeLists.txt. There is an entry called cppad_lib, but the problem remains.

cmake_minimum_required(VERSION 3.5.1
  FATAL_ERROR)

# It's actually not a true cmake way of making such things, but here its more comfortable :)
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")

add_compile_options(
    -Wall
    -std=c++20
    -pthread
    -DHAVE_CSTDDEF
    )

include_directories(
    "/usr/local/include/coin-or",
    "/usr/include/coin",
    )

link_directories(
  )

set(SEA_LIBRARIES
    "-lOsiCbc -lCbc -lCgl -lOsiClp -lOsi -lClp -lCoinUtils -lm -lz"
    "-lbz2 -llapack -lblas -ldl -lgflags -lipopt -pthread -lunwind -lwsmp64"
    "-luuid -llog4cpp -ljsoncpp -lstdc++fs -lcppad_lib"
    )

file(GLOB_RECURSE SOURCES "src/*.cpp")

add_executable(sea ${SOURCES})

target_compile_options(sea PUBLIC -O3 -march=native -fopenmp)

target_link_libraries(sea
    ${SEA_LIBRARIES}
    "cppad_lib"
    "cppad_ipopt"
    )
smith-nekrald commented 1 year ago

And this is how compiler error log sounds:

[  2%] Linking CXX executable sea
/usr/bin/ld: CMakeFiles/sea.dir/src/backend/ipopt/recalculate.cpp.o: in function `void CppAD::put_check_for_nan<double>(CppAD::vector<double> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std:
:allocator<char> >&) [clone .isra.0]':
recalculate.cpp:(.text+0x8d8e): undefined reference to `CppAD::local::temp_file[abi:cxx11]()'
/usr/bin/ld: CMakeFiles/sea.dir/src/backend/lagrangian_relaxation/gm_sea/gm_src/ufgm_optimizer.cpp.o: in function `void CppAD::put_check_for_nan<double>(CppAD::vector<double> const&, std::__cxx11::basic_string<c
har, std::char_traits<char>, std::allocator<char> >&) [clone .isra.0]':
ufgm_optimizer.cpp:(.text+0x6fde): undefined reference to `CppAD::local::temp_file[abi:cxx11]()'
/usr/bin/ld: CMakeFiles/sea.dir/src/backend/lagrangian_relaxation/gm_sea/sea_gm_apply.cpp.o: in function `void CppAD::put_check_for_nan<double>(CppAD::vector<double> const&, std::__cxx11::basic_string<char, std:
:char_traits<char>, std::allocator<char> >&) [clone .isra.0]':
sea_gm_apply.cpp:(.text+0x5b2e): undefined reference to `CppAD::local::temp_file[abi:cxx11]()'
/usr/bin/ld: CMakeFiles/sea.dir/src/backend/lagrangian_relaxation/gm_sea/sea_gm_apply.cpp.o: in function `void CppAD::put_check_for_nan<CppAD::AD<double> >(CppAD::vector<CppAD::AD<double> > const&, std::__cxx11:
:basic_string<char, std::char_traits<char>, std::allocator<char> >&) [clone .isra.0]':
sea_gm_apply.cpp:(.text+0x5f0e): undefined reference to `CppAD::local::temp_file[abi:cxx11]()'
/usr/bin/ld: CMakeFiles/sea.dir/src/backend/lagrangian_relaxation/lr_cppad.cpp.o: in function `void CppAD::put_check_for_nan<double>(CppAD::vector<double> const&, std::__cxx11::basic_string<char, std::char_trait
s<char>, std::allocator<char> >&) [clone .isra.0]':
lr_cppad.cpp:(.text+0x257e): undefined reference to `CppAD::local::temp_file[abi:cxx11]()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/sea.dir/build.make:849: sea] Error 1
make[1]: *** [CMakeFiles/Makefile2:84: CMakeFiles/sea.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
smith-nekrald commented 1 year ago

The only workaround I have found so far is to include the following header (copied from inside CppAD):

#pragma once

# include <vector>
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <cppad/configure.hpp>
# include <cppad/local/temp_file.hpp>
# include <filesystem>

# define DIR_SEP '/'

namespace CppAD {
namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE

std::string temp_file(void)
{  // path
   using std::filesystem::path;
   //
   // tmp_dir_path
   path tmp_dir_path = std::filesystem::temp_directory_path();
   //
   // tmp_dir_str
   std::string tmp_dir_str = tmp_dir_path.string();
   if( tmp_dir_str.back() != DIR_SEP )
      tmp_dir_str += DIR_SEP;
   //
   // pattern_str
   std::string pattern_str = tmp_dir_str;
   pattern_str            += "fileXXXXXX";
   //
   // pattern_vec
   std::vector<char> pattern_vec( pattern_str.size() + 1 );
   for(size_t i = 0; i < pattern_str.size(); ++i)
      pattern_vec[i] = pattern_str[i];
   pattern_vec[ pattern_str.size() ] = '\0';
   //
   // fd, pattrern_vec
   int fd = mkstemp( pattern_vec.data() );
   if( fd < 0 )
      return "";
   close(fd);
   //
   // file_name
   std::string file_name = pattern_vec.data();
   return file_name;
}
}
}
bradbell commented 1 year ago

Please take a look at the following https://github.com/coin-or/CppAD/discussions/175

Many other people are having this problem and I think I should put something in the documentation for this: https://cppad.readthedocs.io/en/latest/

Do you have a suggesiton ? Where did you look in the documentation ? Did you do a search for link error or temp_file ?

bradbell commented 1 year ago

Did the message above solve the problem for you ? If so, would you please close this issue.

smith-nekrald commented 1 year ago

No, the message above did not help. Sounds like the library does not have temp_file method inside for some reason. The problem was solved the other way: by directly compiling with adding the temp_file method to the header included in the entry point main.cpp.

bradbell commented 1 year ago

temp_file should be in cppad_lib. What system / compiler are you using and what does your link command look like ?

bradbell commented 3 months ago

Is this still a problem for you ?

Geryyy commented 3 weeks ago

Had the same issue. The workaround from @smith-nekrald as described above worked for me.

bradbell commented 3 weeks ago

@smith-nekrald and @Geryyy what do you get in response to the command ? pkg-config cppad --libs

Geryyy commented 3 weeks ago

@bradbell $ pkg-config cppad --libs -L/usr/local/lib -lcppad_lib -lcppad_ipopt -lipopt

bradbell commented 3 weeks ago

@Geryyy What happens when you add these flags to you link command (without the separate copy of temp_file mentioned above) ?

If you are using cmake to link your program, see the following: https://cmake.org/cmake/help/latest/module/FindPkgConfig.html#command:pkg_check_modules

Geryyy commented 3 weeks ago

Thank you for the hint!

Adding this to CMakeLists.txt fixed it for me:

find_package(PkgConfig REQUIRED)
pkg_check_modules(CPPAD REQUIRED cppad)

and target_link_libraries(${PROJECTNAME} ... ${CPPAD_LIBRARIES})

In CMakeCache.txt the lib paths are:

//Path to a library.
pkgcfg_lib_CPPAD_cppad_ipopt:FILEPATH=/usr/local/lib/libcppad_ipopt.a

//Path to a library.
pkgcfg_lib_CPPAD_cppad_lib:FILEPATH=/usr/local/lib/libcppad_lib.so

//Path to a library.
pkgcfg_lib_CPPAD_ipopt:FILEPATH=/usr/local/lib/libipopt.so
bradbell commented 3 weeks ago

@Geryyy Does this mean that this problem is solved for you ?

If so, I am going to close this issue and convert it to a discussion.

Geryyy commented 3 weeks ago

Yes, it is solved for me. Thank you!