1

I have followed the elemental battles tutorial until lesson 2 step 4, and at the end of it, the tutorial instructs to compile the existing code with eosio-cpp -o destination.abi source.cpp -abigen (which makes no sense in that it seems to be putting a WASM into a .abi file)

I used eosio-cpp -o cardgame.wasm cardgame.cpp -abigen to try to compile but it did not work, giving me a long list of depreciation warnings (telling me to use eosio/* instead of eosiolib/*) and redefinition errors within the eosio files mostly.

At this point in the tutorial here is my code: cardgame.hpp

#include <eosiolib/eosio.hpp>

using namespace std;
using namespace eosio;
class [[eosio::contract]] cardgame : public eosio::contract {

  private:

    struct [[eosio::table]] user_info {
      name            username;
      uint16_t        win_count = 0;
      uint16_t        lost_count = 0;

      auto primary_key() const { return username.value; }
    };

    typedef eosio::multi_index<name("users"), user_info> users_table;

    users_table _users;

  public:

    cardgame( name receiver, name code, datastream<const char*> ds ):contract(receiver, code, ds),
                       _users(receiver, receiver.value) {}

    [[eosio::action]]
    void login(name username);

};

cardgame.cpp

#include "gameplay.cpp"

void cardgame::login(name username) {
  // Ensure this action is authorized by the player
  require_auth(username);

  // Create a record in the table if the player doesn't exist in our app yet
  auto user_iterator = _users.find(username.value);
  if (user_iterator == _users.end()) {
    user_iterator = _users.emplace(username,  [&](auto& new_user) {
      new_user.username = username;
    });
  } 
}

EOSIO_DISPATCH(cardgame, (login))

gameplay.cpp

#include "cardgame.hpp"

As hinted by the warning I tried to change eosiolib into eosio in my code:

#include <eosio/eosio.hpp>
// #include <eosiolib/eosio.hpp>

But that still gives me the following error:

$ eosio-cpp -o cardgame.wasm cardgame.cpp -abigen
Warning, empty ricardian clause file
Warning, empty ricardian clause file
Warning, action <login> does not have a ricardian contract
Warning, action <login> does not have a ricardian contract
In file included from /tmp/cardgame.cpp:1:
/tmp/./gameplay.cpp:6:7: error: redefinition of '__insert_eosio_abi'
        void __insert_eosio_abi(unsigned long long r, unsigned long long c, unsigned long long a){eosio_assert_code(false, 1);}
             ^
/tmp/./cardgame.hpp:34:7: note: previous definition is here
        void __insert_eosio_abi(unsigned long long r, unsigned long long c, unsigned long long a){eosio_assert_code(false, 1);}
             ^
1 error generated.
/usr/opt/eosio.cdt/1.6.1/bin/wasm-ld: error: cannot open /tmp/cardgame.cpp.o: No such file or directory

I however noticed that if I indicate the output wasm file to have a different name, the compilation would succeed(WHY?). However the .abi file is absent and therefore it is impossible to use this contract.

$ eosio-cpp -o cardgamee.wasm cardgame.cpp -abigen
Warning, empty ricardian clause file
Warning, empty ricardian clause file
$ ls
cardgame.cpp  cardgamee.wasm  cardgame.hpp  gameplay.cpp

What am I doing wrong in this case? How can I successfully compile this contract?

  • I just did a git pull of the lesson 2 and I got the exact same error as you, and the same solution, this is weird – Saxtheowl May 27 at 17:45
1

Okay, I have find the solution, it was a classic header include problems, so you just have to add -I. at the end like

eosio-cpp -o cardgame.wasm cardgame.cpp -abigen -I.

more information about the issue here:

https://github.com/EOSIO/eosio.cdt/issues/489

  • This does not seem to work. I still get the exact same error about redefining __insert_eosio_abi. Were you able to replicate this error before you used -I. ? – LemmeTestThat May 28 at 1:31
  • yes I got the same error from doing a git pull of the lesson 2 then I fixed it with this solution, still got all the warning though, you should pull a new copy without your old modification/test – Saxtheowl May 28 at 1:40
  • It still won't work for me after I copied all the code directly from the repository. Keeping eosiolib still gives me warnings and errors (you only mention warnings, does your compilation succeed at that point?), and using eosio gives me that error I mentioned again. I am using the cdt 1.6.1, is it possible I made a mistake during the setup? – LemmeTestThat May 28 at 1:53
  • Maybe you were not in the right directory ? I put all the step from start to end here pastebin.com/prKjY5pE – Saxtheowl May 28 at 2:02
  • I just followed your steps and still cannot compile successfully. I get 26 warnings and 1 error (the same one): pastebin.com/JLmqwene . When putting our warnings into a diffchecker, one difference stood out, although I am not sure it is relevant: you have In file included from ././gameplay.cpp:1: In file included from ./cardgame.hpp:1: but mine is In file included from /tmp/./gameplay.cpp:2: In file included from ././cardgame.hpp:1: – LemmeTestThat May 28 at 3:28
0

Here is a workaround for people who might have the same problem in the future (I do not consider this a real "solution"):

Simply put all the code into one file like so :

cardgame.cpp

// #include "gameplay.cpp"

#include <eosio/eosio.hpp>
// #include <eosiolib/eosio.hpp>

using namespace std;
using namespace eosio;
class [[eosio::contract]] cardgame : public eosio::contract {

  private:

    struct [[eosio::table]] user_info {
      name            username;
      uint16_t        win_count = 0;
      uint16_t        lost_count = 0;

      auto primary_key() const { return username.value; }
    };

    typedef eosio::multi_index<name("users"), user_info> users_table;

    users_table _users;

  public:

    cardgame( name receiver, name code, datastream<const char*> ds ):contract(receiver, code, ds),
                       _users(receiver, receiver.value) {}

    [[eosio::action]]
    void login(name username);

};

void cardgame::login(name username) {
  // Ensure this action is authorized by the player
  require_auth(username);

  // Create a record in the table if the player doesn't exist in our app yet
  auto user_iterator = _users.find(username.value);
  if (user_iterator == _users.end()) {
    user_iterator = _users.emplace(username,  [&](auto& new_user) {
      new_user.username = username;
    });
  } 
}

EOSIO_DISPATCH(cardgame, (login))

This probably betrays some programming best practice, but this is only a workaround and since smart contracts should be generally pretty simple and compact, it should not result in a monstrously large file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.