Armadillo with wxWidgets: polyfit fails to link - wxwidgets

I have been using wxWidgets to make visual examples of a few of Armadillo's functions. Both matrix transpose and FFT worked perfectly, but when I tried to do a simple polyfit call, the linker fails with a series of errors like these:
> error LNK2019: unresolved external symbol sdot_ referenced in function "double __cdecl arma::blas::dot<double>(unsigned __int64,double const *,double const *)" (?? $dot#N#blas#arma##YAN_KPEBN1#Z)
However, the exact same calls link and run perfectly if I am not also using wxWidgets to display the result. I am using Windows 10 and Visual Studio 2022.
Here is the code that causes the link error. It compiles and links find if the polyfit line is commented out.
vector <double> xcoords = { 7,8,9,10,11,12,13,14,15,16,17 };
vector <double> ycoords = { 32,35,29,34,30,24,32,24,23,28,21 };
arma::vec x = arma::vec(xcoords);
arma::vec y = arma::vec(ycoords);
arma::vec p = arma::polyfit(x, y, 2);
When I installed Armadillo, I ran Cmake . to build the library, but since libopenblas.dll and .lib were already provided, it didn't create an armadillo.lib file. I also tried downloading the latest win64 OpenBLAS libraries, but the same link errors occurred.
I tried replacing the libopenblas.lib and dll from 2016 with those downloaded today. No change. It does not link if the polyfit function is called, but compiles fine if it is commented out.

You would think that a program that calls Armadillo functions would compile and run if you just tell the compiler where the includes are and the linker where the libraries are. This usually works, but for polyfit it does not.
The solution is to copy the example Visual Studio solution file example1_win64.sln and rename it. Then, open that solution and replace the example code with your own, and the program will compile and link.
It is probably a good idea to move that solution file into a directory you create where Visual Studio keeps all its projects, C:\Users\your_name\source\repos

Related

Cmake 3.1 + "Protobuf_IMPORT_DIRS" importing another .proto error

I'm still fairly new to CMAKE, but I'm using find_package(Protobuf Requried) to compile my .proto files as part of the build, and I'm having trouble getting imports to work, and I'm well and truly stumped.
I have 2 .proto files in the same direcotry, "protobuf" named "A.proto" and "B.proto"
Without an import, they compile fine.
If I change A.proto to have an import to B:
syntax = "proto3";
import "B.proto";
message MyMessage
{}
With a CMakeLists.txt file that sets the Protobuf_IMPORT_DIRS variable correctly (I think):
find_package(Protobuf REQUIRED)
set(Protobuf_IMPORT_DIRS ${Protobuf_IMPORT_DIRS} ${CMAKE_SOURCE_DIR}/protobuf)
...
protobuf_generate(TARGET ${MY_PROJECT_NAME})
I get this on build:
Running cpp protocol buffer compiler on protobuf/A.proto
B.proto: File not found.
protobuf/A.proto:3:1: Import "B.proto" was not found or had errors.
Any help would be much appreciated, as I feel like i'm taking crazy pills! :)
So i found the answer, although it took some hacking. Bascially I just read all the CMAKE files associated with Protobuf until I figured it out. There's probably better docs out there but I couldn't find.
Short Story:
if you call PROTOBUF_GENERATE_CPP, it respects setting a Protobuf_IMPORT_DIRS variable.
However if you directly call the protobuf_generate for a target as I do, the variable is ignored.
The answer is to call protobuf_generate with an argument of IMPORT_DIRS, such as:
protobuf_generate(TARGET ${MY_PROJECT_NAME} IMPORT_DIRS protobuf)
IMPORT_DIRS is a multi argument, you can supply several.
Here's the relevant code:
function(protobuf_generate)
include(CMakeParseArguments)
set(_options APPEND_PATH)
set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN)
if(COMMAND target_sources)
list(APPEND _singleargs TARGET)
endif()
set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS)
cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
I hope this will save someone headache in the future!

Successful build of Kicad 4.0.6 in Linux Mageia 5 via fixing a wx-3.0 symbol

I have managed to build the Kicad 4.0.6 in Linux Mageia 5.1 with gcc version 4.9.2. I first manually fixed two wxWidgets 3.0.2 header files in the /usr/include/wx-3.0/wx/ directory: regex.h and features.h. Kicad then compiled successfully. With the native wx-3.0 headers, the compiler generated the error in pcbnew/netlist_reader.cpp due to the undefined variable wxRE_ADVANCED.
The features.h header checks if the macro WX_NO_REGEX_ADVANCED is defined. If yes, features.h UNdefines wxHAS_REGEX_ADVANCED macro, and defines it, if no. The macro wxHAS_REGEX_ADVANCED, in turn, is used in regex.h to determine if among the enum constants wxRE_ADVANCED = 1 is present. The standard prebuilt Mageia 5 packages wxgtku3.0_0 and lib64wxgtku3.0-devel that I installed with the use of Mageia's software manager urpmi from Mageia repository WX_NO_REGEX_ADVANCED is defined, therefore wxHAS_REGEX_ADVANCED is undefined, and, hence, wxRE_ADVANCED is undefined either. Kicad 4.0.6 source package assumes wxRE_ADVANCED = 1, therefore the build process stops with the error.
Then I reverted /usr/include/wx-3.0/wx/regex.h and features.h to their original state and learned how to add the definition of wxRE_ADVANCED to CMakeLists.txt. However, I still have a question.
The recommended format of adding the definition to CMakeLists.txt I found at CMake command line for C++ #define is this:
if (NOT DEFINED wxRE_ADVANCED)
set(wxRE_ADVANCED 1)
endif()
add_definitions(-DwxRE_ADVANCED=$(wxRE_ADVANCED))
However, it did not work! The macro expansion for wxRE_ADVANCED in pcbnew/netlist_reader.cpp was empty. I printed it at compile time inserting the following lines into the netlist_reader.cpp file (this was hard to find, most of the recommended formats did not work. The correct one is in C preprocessor: expand macro in a #warning):
#define __STRINGIFY(TEXT) #TEXT
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT)
#define WARNING(VALUE) __WARNING(__STRINGIFY(wxRE_ADVANCED = VALUE))
Pragma (WARNING(wxRE_ADVANCED))
Finally, I simplified the CMakeLists.txt definition down to this, and it was a success:
if (NOT DEFINED wxRE_ADVANCED)
set(wxRE_ADVANCED 1)
endif()
add_definitions(-DwxRE_ADVANCED=1)
My question: what is the meaning of "-DwxRE_ADVANCED=$(wxRE_ADVANCED)" if it does not work? Is it possible not to use set(wxRE_ADVANCED 1), and simply write add_definitions(-DwxRE_ADVANCED=1)? Thank you.
P.S. Yes, the Kicad 4.0.6 build process successfully finished with only one line added to the top level CMakeLists.txt file:
add_definitions(-DwxRE_ADVANCED=1)
A variable is called via $variable or ${variable}. Note the curly brackets, not parentheses.
Also, it is recommended to use:
target_compile_definitions(mytarget PUBLIC wxRE_ADVANCED=1)
on a target directly, rather than the general add_definitions() command.

undefined reference to `zgesvd_' - BLAS issues in C compilation

I am having an issue with the LAPACK/BLAS libraries when compiling a C code that needs them.
The issues are, when I run "make", I get:
file.c:(.text+0x1c41): undefined reference to `zgesvd_'
file.c:(.text+0x1c9c): undefined reference to `zgetrf_'
../file.a(SpatialOrientation.o): In function `myfunction.c':myfunction.c:(.text+0x7be): undefined reference to `dsyev_'
And several other such lines, all referring to similar missing references.
I have chased this error down to being something to do with BLAS. I followed the directions given at this excellent link for installing BLAS and put the relevant directory on the path. I also changed my Makefile accordingly to find these libraries.
Any help on this issue would be really appreciated!
Just to update, I recently installed itpp as well, also following the instructional here, since it seemed my missing references were linked to that. No changes so far...
Thanks for your help!
The problem is solved! Hooray! I just danced around my office...
For those who have the same problem, here is what I did:
1) Follow the instructions given here to make the lapack and blas libraries. To paraphrase, for a scientific Linux 6 machine, they are:
wget http://www.netlib.org/lapack/lapack.tgz
tar xvzf lapack.tgz
cd lapack-3.3.0 //if version number changes, change here to the right directory
mv make.inc.example make.inc
2) Then (important bit, also recommended here):
edit make.inc and add -m64 -fPIC flag to fortran compiler options: FORTRAN, OPTS, NOOPT, LOADER
Then
make blaslib
make
Now, what you have is, in /lapack-3.6.1 (or whatever your directory is called after this process), two files:
librefblas.a , and liblapack.a.
3) The next thing I did was to copy librefblas.a and liblapack.a into some subdirectories - i.e. /lib/liblapack for liblapack.a and /lib/libblas for librefblas.a
4) Then, put those directories in your makefile, like this:
LIBDIR1 = /path/lib/lapack
LIBDIR2 = /path/lib/blas
LIBS = -L$(LIBDIR1) -llapack -L$(LIBDIR2) -lblas $(SYSLIBS)
LIBSMPI = -L$(LIBDIR1) -llapack -L$(LIBDIR2) -lblas $(MPILIBS) $(SYSLIBS)
I also added /path/lib/lapack and /path/lib/blas onto my LD_LIBRARY_PATH (and PATH, just-in-case...)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/lib/lapack:/path/lib/blas
export PATH=$PATH:/path/lib/lapack:/path/lib/blas
Then, go to wherever you Makefile is, and type
make
Yay yay yay!
By the way, with the latest version of lapack and blas, obtained in step 1), I compiled with gcc version 5.1.0 and the corresponding mpicc (openmpi 1.10.2).
Hope this helps someone else and shares the absolute delight.

How to link with chart director library with mingw

I am trying to build an application under mingw with Chart Director. My code compiles fine, but I get undefined reference errors from the linker.
The object file needs to link with ../ChartDirector.cpp/lib/chartdir51.lib
I have renamed this file to ../ChartDirector.cpp/lib/libchartdir51.a If I do not do this the linker cannot find it.
The result is:
mingw32-g++.exe -LJ:\wxWidgets-3.0.1\lib\gcc481TDM_dll
-L..\ChartDirector_cpp\lib -o ..\bin\plot.exe obj\Debug\plot.o
-lwxbase30u -lwxmsw30u_core -lchartdir51 -mwindows
obj\Debug\plot.o: In function `ZN3BoxC2EP11BoxInternal':
C:\Users\James\Documents\code\vase\plot/../ChartDirector_cpp/include/chartdir.h:804:
undefined reference to `Box2DrawObj'
obj\Debug\plot.o: In function `ZN7TextBoxC1EP15TextBoxInternal':
C:\Users\James\Documents\code\vase\plot/../ChartDirector_cpp/include/chartdir.h:832:
undefined reference to `TextBox2Box'
... and so on
To make things simpler, I changed to trying to build the simplebar demo application supplied by Chart Director. The build command now looks like this:
mingw32-g++.exe
C:\Users\James\Documents\code\vase\test\simplebar.cpp
-IC:\Users\James\Documents\code\vase\ChartDirector_cpp\include
-o C:\Users\James\Documents\code\vase\bin\test.exe
-LC:\Users\James\Documents\code\vase\ChartDirector_cpp\lib\
-lchartdir51
I still have the same undefineds.
Following this recipe I created a def file looking like this
EXPORTS
Box2DrawObj
TextBox2Box
CBaseChart_destroy
CBaseChart_makeChart
CAxis_setLabels
BarLayer2Layer
CXYChart_create
XYChart2BaseChart
CXYChart_xAxis
CXYChart_setPlotArea
CXYChart_addBarLayer
and used the dlltool to create a new libchartdir51.a
dlltool -d C:\Users\James\Documents\code\vase\ChartDirector_cpp\lib\chartdir.def
-l C:\Users\James\Documents\code\vase\ChartDirector_cpp\lib\libchartdir51.a
Well that fixed the undefined I saw before, but now I am getting something even more mysterious:
C:\Users\James\Documents\code\vase\ChartDirector_cpp\lib/libchartdir51.a(diaybs00001.o):(.idata$7+0x
0):
undefined reference to `_head_C__Users_James_Documents_code_vase_ChartDirector_cpp_lib_libchartd
ir51_a'
C:\Users\James\Documents\code\vase\ChartDirector_cpp\lib/libchartdir51.a(diaybs00009.o):(.idata$7+0x
0): undefined reference to `_head_C__Users_James_Documents_code_vase_ChartDirector_cpp_lib_libchartd
ir51_a'
... and so on
I tried downloading the linux version of chartdir. The result was:
mingw32-g++.exe
C:\Users\James\Downloads\ChartDirector\cppdemo\simplebar\simplebar.cpp
-IC:\Users\James\Downloads\ChartDirector\include
-o C:\Users\James\code\vase\bin\test.exe
C:\Users\James\Downloads\ChartDirector\lib\libchartdir.so.5.1.0
C:\Users\James\Downloads\ChartDirector\lib\libchartdir.so.5.1.0:
could not read symbols: File in wrong format
collect2.exe: error: ld returned 1 exit status
The problem was that I was trying to build with a 64 bit version of ChartDirector on a 32 bit mingw. Downloading the 32 bit library fixes the problem:
mingw32-g++
C:\Users\James\Downloads\chartdir_cpp_win32\ChartDirector\cppdemo\simplebar\simplebar.cpp
-IC:\Users\Jam es\Downloads\chartdir_cpp_win32\ChartDirector\include
-o C:\Users\James\code\vase\bin\test2.exe
-C:\Users\James\Downloads\chartdir_cpp_win32\ChartDirector\lib\chartdir51.dll
Normally undefined reference errors comes when the libs are not matching. Always get the latest libs from ChartDirector download page.

YAML with VC++ 2010 will compile to Release, but not to Debug

I'm trying to learn YAML with C++, i made the given yaml-cpp files into a .dll and .lib file with VC++ Express 2010 by using CMake. I have set up my project the same way i set up other libraries like SFML.
My issue is, when i try to build a Release version of the example code given on the yaml-cpp site i get:
Ogre
Dragon
Wizzard
However, when i try to build a Debug version, i get:
Assertion failed: false, file d:\microsoft visual studio 10.0\vc\include\yaml-cp
p\nodeimpl.h, line 39
I don't know how to handle this. Do i need to build a debug version of the library? If yes, how? I don't know which project options could affect this if i managed to change something.
When i'm compiling, i get a warning:
d:\microsoft visual studio 10.0\vc\include\yaml-cpp\conversion.h(51): warning C4146: unary minus operator applied to unsigned type, result still unsigned
With alot of template printouts, f.e. :
1> d:\microsoft visual studio 10.0\vc\include\yaml-cpp\nodereadimpl.h(35) : see reference to function template instantiation 'bool YAML::ConvertScalar<T>(const YAML::Node &,T &)' being compiled
1> with
1> [
1> T=unsigned int
1> ]
Is this a problem on my side? Bad CMake file and compilation?
> yaml_test.exe!main() Line 108 C++
yaml_test.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C
yaml_test.exe!mainCRTStartup() Line 371 C
kernel32.dll!7c817077()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
Aborts at:
doc[i] >> monster;
The program doesn't try to enter the overloaded function.
In my own code it breaks when i try to use my first >> operator, which is the build in one for int.
I'm using the code from http://pastebin.com/PdKWDgQa, though for the original yaml-cpp example code it does the same. The output in Release mode is right, Debug stops and returns the same assert code.
For reference, the stack call in Release mode at the { bracket in the >> function for monster looks like this:
> yaml_test.exe!operator>>(const YAML::Node & node={...}, Monster & monster={...}) Line 36 C++
yaml_test.exe!main() Line 109 C++
msvcr100.dll!_initterm(void (void)* * pfbegin=0x00000001, void (void)* * pfend=0x003a5050) Line 873 C
yaml_test.exe!__tmainCRTStartup() Line 555 + 0x17 bytes C
kernel32.dll!7c817077()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
EDIT:
Actually, i have rebuilt the yaml-cpp project i made with CMake as Debug, everything runs fine when i use it now. I'm sorry if this is obvious, i'm new to these kind of issues.