iden3/circom

Fresh M2 (Apple Silicon) Mac Tutorial Issue regarding: Computing Witness w/ C++

adrianmcli opened this issue · 5 comments

When running make at the "Computing the witness with C++" part of the tutorial, I got the following error:

➜  multiplier2_cpp git:(master) ✗ make
g++ -c main.cpp -std=c++11 -O3 -I.
main.cpp:9:10: fatal error: 'nlohmann/json.hpp' file not found
#include <nlohmann/json.hpp>
         ^~~~~~~~~~~~~~~~~~~
1 error generated.
make: *** [main.o] Error 1

I tried to install the noted dependencies (nlohmann-json3-dev, libgmp-dev and nasm) with Brew, but actually had to install the Brew versions instead, which are named a little differently:

brew install nlohmann-json gmp nasm

However, I still ran into the same error as above. I tried a whole bunch of stuff until I found the solution.

It turns out the fix is that I need to do this to add Brew-installed binaries to the path:

export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/opt/homebrew/include/"

Source of fix: https://stackoverflow.com/questions/43967007/mac-c-include-cannot-find-file-installed-by-homebrew

Hope this saves someone some time and frustration 🥺.

Recommendation

Might be a good idea to update the docs to mention this. I can make a PR if the maintainers agree.

Actually, I encountered more errors. I had to add an extra line to my ~/.zshrc:

export LIBRARY_PATH=$LIBRARY_PATH:$(brew --prefix)/lib
export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:/opt/homebrew/include/"

It progressed further, but I eventually got stuck again. And here is where I am stumped:

1 warning generated.
nasm -fmacho64 --prefix _ fr.asm -o fr_asm.o
g++ -c multiplier2.cpp -std=c++11 -O3 -I.
g++ -o multiplier2 *.o -lgmp
ld: warning: ignoring file fr_asm.o, building for macOS-arm64 but attempting to link with file built for unknown-x86_64
Undefined symbols for architecture arm64:
  "_Fr_copy", referenced from:
      writeBinWitness(Circom_CalcWit*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) in main.o
      Multiplier2_0_run(unsigned int, Circom_CalcWit*) in multiplier2.o
  "_Fr_mul", referenced from:
      Fr_div(FrElement*, FrElement*, FrElement*) in fr.o
      Multiplier2_0_run(unsigned int, Circom_CalcWit*) in multiplier2.o
  "_Fr_q", referenced from:
      Fr_init() in fr.o
      writeBinWitness(Circom_CalcWit*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) in main.o
  "_Fr_rawCopy", referenced from:
      RawFr::exp(RawFr::Element&, RawFr::Element const&, unsigned char*, unsigned int) in fr.o
  "_Fr_rawFromMontgomery", referenced from:
      RawFr::toString(RawFr::Element const&, unsigned int) in fr.o
      RawFr::toMpz(__mpz_struct*, RawFr::Element const&) in fr.o
      RawFr::toRprBE(RawFr::Element const&, unsigned char*, int) in fr.o
  "_Fr_rawMMul", referenced from:
      RawFr::inv(RawFr::Element&, RawFr::Element const&) in fr.o
      RawFr::div(RawFr::Element&, RawFr::Element const&, RawFr::Element const&) in fr.o
      RawFr::exp(RawFr::Element&, RawFr::Element const&, unsigned char*, unsigned int) in fr.o
  "_Fr_rawMSquare", referenced from:
      RawFr::exp(RawFr::Element&, RawFr::Element const&, unsigned char*, unsigned int) in fr.o
  "_Fr_rawNeg", referenced from:
      RawFr::RawFr() in fr.o
  "_Fr_rawR3", referenced from:
      RawFr::inv(RawFr::Element&, RawFr::Element const&) in fr.o
      RawFr::div(RawFr::Element&, RawFr::Element const&, RawFr::Element const&) in fr.o
  "_Fr_rawToMontgomery", referenced from:
      RawFr::RawFr() in fr.o
      RawFr::set(RawFr::Element&, int) in fr.o
      RawFr::fromString(RawFr::Element&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> const&, unsigned int) in fr.o
      RawFr::fromUI(RawFr::Element&, unsigned long) in fr.o
      RawFr::fromMpz(RawFr::Element&, __mpz_struct const*) in fr.o
      RawFr::fromRprBE(RawFr::Element&, unsigned char const*, int) in fr.o
  "_Fr_toLongNormal", referenced from:
      writeBinWitness(Circom_CalcWit*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) in main.o
  "_Fr_toNormal", referenced from:
      Fr_toMpz(__mpz_struct*, FrElement*) in fr.o
      Fr_element2str(FrElement*) in fr.o
      Fr_idiv(FrElement*, FrElement*, FrElement*) in fr.o
      Fr_mod(FrElement*, FrElement*, FrElement*) in fr.o
      Fr_pow(FrElement*, FrElement*, FrElement*) in fr.o
      Fr_inv(FrElement*, FrElement*) in fr.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [multiplier2] Error 1

@adrianmcli did you overcome this issue?

@adrianmcli @tarassh Current implementation of c++ witnesscalc uses x86_64 assembly to optimize performance. We have ported assembly parts to arm64 here: https://github.com/0xPolygonID/witnesscalc
Plan is to merge this port into mainline and it's WIP, but so far no dates set.

@OBrezhniev thanks for the update! I had skipped that part of the tutorial thus far.

I look forward to closing this issue when the ported code is merged in!

I noticed that there has been some progress on the porting of the assembly parts to arm64 architecture in the witnesscalc project, as mentioned in the issue. I'm encountering a similar problem and I'm eager to know if the ported code has been merged into the mainline repository since then.

Could you provide an update on the status of this porting effort? Any information on when we can expect the merged code to be available would be greatly appreciated.

Thank you.