Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External c++ example fails #1119

Closed
andrjohns opened this issue Sep 23, 2022 · 6 comments · Fixed by stan-dev/docs#626
Closed

External c++ example fails #1119

andrjohns opened this issue Sep 23, 2022 · 6 comments · Fixed by stan-dev/docs#626

Comments

@andrjohns
Copy link
Contributor

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

@WardBrian
Copy link
Member

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

@rok-cesnovar
Copy link
Member

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

@WardBrian
Copy link
Member

WardBrian commented Oct 5, 2022

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
Copy link
Member

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

@andrjohns
Copy link
Contributor Author

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

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

@WardBrian
Copy link
Member

Great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants