cmdstan icon indicating copy to clipboard operation
cmdstan copied to clipboard

External c++ example fails

Open andrjohns opened this issue 3 years ago • 3 comments

Summary:

Attempting to run the external c++ example fails with:

andrew@Andrews-MacBook-Air cmdstan-2.30.1 % make STANCFLAGS=--allow-undefined USER_HEADER=examples/bernoulli/make_odds.hpp examples/bernoulli/bernoulli # on Windows add .exe

--- Translating Stan model to C++ code ---
bin/stanc --allow-undefined --o=examples/bernoulli/bernoulli.hpp examples/bernoulli/bernoulli.stan

--- Compiling, linking C++ code ---
clang++ -std=c++1y -Wno-unknown-warning-option -Wno-tautological-compare -Wno-sign-compare -D_REENTRANT -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -include-pch stan/src/stan/model/model_header.hpp.gch -include examples/bernoulli/make_odds.hpp -x c++ -o examples/bernoulli/bernoulli.o examples/bernoulli/bernoulli.hpp
examples/bernoulli/bernoulli.hpp:24:62: error: template parameter redefines default argument
          stan::require_all_t<stan::is_stan_scalar<T0__>>* = nullptr>
                                                             ^
./examples/bernoulli/make_odds.hpp:6:62: note: previous default template argument defined here
          stan::require_all_t<stan::is_stan_scalar<T0__>>* = nullptr>

Not sure whether this is a stanc3 or cmdstan issue sorry!

Current Version:

v2.30.1

andrjohns avatar Sep 23 '22 15:09 andrjohns

I can't reproduce this using gcc on Ubuntu 20.01, it's possible that this is compiler dependent. @rok-cesnovar - do you recall?

WardBrian avatar Sep 23 '22 16:09 WardBrian

I think it may be a Mac issue - maybe clang? Will take a look over the weekend.

rok-cesnovar avatar Sep 23 '22 19:09 rok-cesnovar

I seem to recall this being an issue with gcc being more permissive than clang in terms of multiple declarations.

There is a way around this (I believe) if you separate the compilation into multiple steps. If you add the manual template expansion

template double make_odds<double, nullptr>(const double&, std::ostream*);

to make_odds.hpp, you can then compile this to make_odds.o, then insert make_odds.o before bernoulli.o src/cmdstan/main.o in the final compile command. This should link properly, without the need to have two declarations in the same translation unit.

Full example:

  1. Add the above line to make_odds.hpp
  2. Run stanc --allow-undefined bernoulli.stan
  3. Compile bernoulli.hpp to bernoulli.o (this is the first step cmdstan does, see what command it uses)
  4. Compile make_odds.hpp to make_odds.o. This will probably use an almost identical command to the previous step, just with the files swapped out
  5. Compile the final executable, adding model.o to the list of sources. This is the second step cmdstan does.

On my machine, in full, the commands are (working from the top-level cmdstan directory with the model and header copied there):

bin/stanc --allow-undefined --o=bernoulli.hpp bernoulli.stan

g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -Wno-ignored-attributes   -x c++ -o bernoulli.o bernoulli.hpp

g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS          -c -Wno-ignored-attributes   -x c++ -o make_odds.o make_odds.hpp

g++ -std=c++1y -pthread -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes      -I stan/lib/stan_math/lib/tbb_2020.3/include    -O3 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.3.9 -I stan/lib/stan_math/lib/boost_1.78.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials    -DBOOST_DISABLE_ASSERTS                -Wl,-L,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb" -Wl,-rpath,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb"    make_odds.o  bernoulli.o src/cmdstan/main.o        -Wl,-L,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb" -Wl,-rpath,"/home/brian/Dev/cpp/cmdstan/stan/lib/stan_math/lib/tbb"   stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_nvecserial.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_cvodes.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_idas.a stan/lib/stan_math/lib/sundials_6.1.1/lib/libsundials_kinsol.a  stan/lib/stan_math/lib/tbb/libtbb.so.2 -o bernoulli

Edit: As an added bonus, since you're manually expanding the template here you don't really need to do the SNIFAE-style require magic. The following header will also compile just file:

#include <stan/model/model_header.hpp>
#include <ostream>

namespace bernoulli_model_namespace {
template <typename T0__, void* = nullptr>
stan::promote_args_t<T0__> make_odds(const T0__& theta,
                                     std::ostream* pstream__) {
  return theta / (1 - theta);
}

template double make_odds<double>(const double&, std::ostream*);

}  // namespace bernoulli_model_namespace

WardBrian avatar Oct 05 '22 19:10 WardBrian

@andrjohns if you have a local copy which has develop cmdstan / master stanc, would you mind trying the updated examples from https://github.com/stan-dev/docs/pull/626?

WardBrian avatar Mar 23 '23 18:03 WardBrian

@andrjohns if you have a local copy which has develop cmdstan / master stanc, would you mind trying the updated examples from https://github.com/stan-dev/docs/pull/626?

Brilliant! Both the templated make_odds and the my_dot_self derivative overloads are compiling without issue

andrjohns avatar Mar 23 '23 19:03 andrjohns

Great!

WardBrian avatar Mar 23 '23 19:03 WardBrian