Cannot link an app using MGauge::FundtoHirep
I'm trying to do spectroscopy in the adjoint representation; I believe that to do this I would need to create a gauge field and then use MGauge::FundtoHirep<AdjointRepresentation> (aka MGauge::FundtoAdjoint) to re-represent it.
Initially this won't compile, as both FundtoAdjoint and FundtoHirep aren't recognised. Uncommenting the line:
//MODULE_REGISTER_TMP(FundtoAdjoint, TFundtoHirep<AdjointRepresentation>, MGauge);
from Hadrons/Modules/MGauge/FundtoHirep.hpp allows the app to compile, but it still fails to link due to undefined reference errors:
main.o: In function `std::_Function_handler<std::unique_ptr<Grid::Hadrons::ModuleBase, std::default_delete<Grid::Hadrons::ModuleBase> > (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >), Grid::Hadrons::MGauge::MGaugeFundtoAdjointModuleRegistrar::MGaugeFundtoAdjointModuleRegistrar()::{lambda(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)#1}>::_M_invoke(std::_Any_data const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)':
/home/dp208/dp208/dc-benn2/prefix2/include/Hadrons/Modules/MGauge/FundtoHirep.hpp:66: undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::TFundtoHirep(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
main.o: In function `void Grid::Hadrons::VirtualMachine::createModule<Grid::Hadrons::MGauge::FundtoAdjoint>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, Grid::Hadrons::MGauge::FundtoAdjoint::Par const&)':
/home/dp208/dp208/dc-benn2/prefix2/include/Hadrons/Modules/MGauge/FundtoHirep.hpp:66: undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::TFundtoHirep(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
main.o:(.rodata._ZTIN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTIN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x10): undefined reference to `typeinfo for Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x28): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::getInput[abi:cxx11]()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x38): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::getOutput[abi:cxx11]()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x68): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::setup()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x70): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::execute()'
I imagine this is due to the definition of TFundtoHirep being within the .cpp rather than the .hpp file, so needing an explicit template specialisation somewhere in the code. I tried adding one within FundtoHirep.cpp, but still get the errors above.
I'm probably missing something, but have spent a couple of hours going around in circles, so thought it worth asking what the correct way of doing this is!
I've had the chance to take a closer look at this today. Using nvcc --preprocess, it's clear that the symbols defined in FundtoHirep.cpp never get compiled—grep for Fund in the output gives the filename and nothing else.
Moving the definitions into FundtoHirep.hpp at least attempts to compile them, but fails to compile Application.o, because the line Rep TargetRepresentation(U._grid); (what would be line 72 in FundtoHirep.cpp) refers to Grid::LatticeAccelerator<vobj>::_grid, which is a private member.
Replacing that with U.Grid() (a change in Grid that seems to have been made shortly after this code was written) removes that error, but like a Hydra creates three more, to do with C++ templating semantics that I don't quite understand yet. I can try and continue to dig when I have time, but would appreciate any hints anyone has.
OK, the templating issue was due to a conflict in the envCreateLat4 macro (part of it included typename, another part didn't, so neither option was correct). While it would be nice to use a consistent envCreateLat macro as in other modules, for the purposes of debugging I've adjusted the definitions of setup and execute as:
// setup
void setup(void)
{
// envCreateLat(Rep::LatticeField, getName());
envCreate(typename Rep::LatticeField, getName(), 1, envGetGrid(Rep::LatticeField));
}
// execution
void execute(void)
{
LOG(Message) << "Transforming Representation" << std::endl;
auto &U = envGet(LatticeGaugeField, par().gaugeconf);
auto &URep = envGet(typename Rep::LatticeField, getName());
Rep TargetRepresentation(U.Grid());
TargetRepresentation.update_representation(U);
URep = TargetRepresentation.U;
}
This allows Hadrons to compile. Building my app against this gives a reduced, but still non-zero number of link errors:
main.o:(.rodata._ZTIN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTIN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x10): undefined reference to `typeinfo for Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x28): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::getInput[abi:cxx11]()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x38): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::getOutput[abi:cxx11]()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x68): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::setup()'
main.o:(.rodata._ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE[_ZTVN4Grid7Hadrons6MGauge13FundtoAdjointE]+0x70): undefined reference to `Grid::Hadrons::MGauge::TFundtoHirep<Grid::AdjointRep<2> >::execute()'
Since this class is now defined in a header, I'm confused as to how it can ever become an undefined symbol. That's not something I'll be able to fix this evening though.
I added an explicit instantiation to the FundtoHirep.hpp file and that now allows the program to link, so in principle it would be possible to submit a PR that fixes this issue. However, it's still strange to me that the instantiation in FundtoHirep.cpp gets ignored, when it doesn't for every other module. Ideally it would presumably be better for the module to follow the same structure used by every other one.
Edit: Redoing this from clean, having the instantiation in the .cpp file worked correctly. So the only barrier now is identifying a better replacement for envCreateLat.