How to make a library that has been generated with nx, buildable? - build

I generated a library with nx but i forgot to make it buildable.
I have no clue what to di to fix this

Related

Linker error when C++ executable links in Fortran library and main in C++ library

I have a CMake-based project consisting of three targets:
A static library FortLib written in Fortran.
A static library LibWithMain which is written in C++ and contains the definition of int main().
An executable App which links in both of the above libraries.
This is the contents of the CMakeList:
cmake_minimum_required(VERSION 3.7.2)
project(Mcve LANGUAGES C CXX Fortran)
add_library(FortLib STATIC fort.f90)
target_compile_options(FortLib PRIVATE /names:lowercase /assume:underscore /iface:cref)
add_library(LibWithMain STATIC main.cpp)
add_executable(App app.cpp)
target_link_libraries(App PRIVATE FortLib LibWithMain)
(For contents of the source files which can be used to reproduce the issue, see bottom)
My problem is that linking App results in the following linker error:
libifcoremdd.lib(for_main.obj) : error LNK2019: unresolved external symbol MAIN__ referenced in function main
Note that this reference comes from libifcoremdd.lib, an Intel Fortran library which apparently gets implicitly linked in.
This does not happen if the function main is defined directly in App. This can be shown by exchanging the files main.cpp and app.cpp in the CMakeList above (so that main is defined inside the app). Then everything builds and links successfully. It's the fact that the definition of main comes from LibWithMain that somehow gets the linker confused.
In my real code, LibWithMain is Boost.Test, so moving main out from it is not really an option for me.
The order of the static libraries does not matter: the error is present regardless of which lib follows which on the link line.
My toolchain is Visual Studio 2017 and Intel Fortran 18, my platform is Win64 ("x64" in Visual Studio terminology). No other compilers/platforms need to be supported at this point.
I am a C++ developer and know next to nothing about Fotran or the Intel Fortran ecosystem, so I have no idea what could be causing this or how to solve it. That is therefore my question:
What is causing the linker error, and how can I fix it?
These simple files, used in the CMakeList above, are enough to reproduce the issue:
fort.f90
integer function fortfunc
implicit none
fortfunc = 42
end function
main.cpp
#include <iostream>
int work();
int main()
{
std::cout << work() << std::endl;
return 0;
}
app.cpp
extern "C" int fortfunc_();
int work()
{
return fortfunc_();
}
I don't know how cmake works but I'm guessing that you need to do it the other way round. It is possible that main is special function in your toolchain and should not exist in a library.
build the fortran lib
build the c lib without main (app.cpp)
build the main using both c lib and fortran lib.
It probably won't moan about missing externals when building the c lib because it is a library and not everything needs to be resolved.
Also, in app.cpp, what you need to remember is that in Fortran, the callee unstacks the arguments but in C, the caller unstacks.
When the callee unstacks, you need __stdcall as part of the declaration. This used to be extern PASCAL on the older MS compilers. When a caller unstacks, you can optionally add __cdecl.

When do I need to use/have a makefile?

I am trying to learn how to code on a Raspberry PI.
I am coming from coding using Windows and VS Code.
Now I am using Linux Mint 19.1 and ssh to access Raspbian 4.14.
The problem is that, after a long battle with downloading the library that I am trying to use, after installing a compiler, creating a file, and finding the right command to run and include paths I get undefined reference to errors.
I am trying to compile the simplest example code from https://github.com/hzeller/rpi-rgb-led-matrix
because I started with this project. I don't have any other code or example.
Here are the commands that I've wrote in command line:
sudo apt-get install g++
mkdir 4panel
cd 4panel
sudo nano main.cpp
git clone https://github.com/hzeller/rpi-rgb-led-matrix.git
sudo g++ -Wall -Irpi-rgb-led-matrix/include main.cpp -o main
The following commands should be:
sudo chmod +x main
./main
main.cpp contains the same code as https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/examples-api-use/minimal-example.cc
#include "led-matrix.h"
#include <unistd.h>
#include <math.h>
#include <stdio.h>
#include <signal.h>
using rgb_matrix::GPIO;
using rgb_matrix::RGBMatrix;
using rgb_matrix::Canvas;
volatile bool interrupt_received = false;
static void InterruptHandler(int signo) {
interrupt_received = true;
}
static void DrawOnCanvas(Canvas *canvas) {
/*
* Let's create a simple animation. We use the canvas to draw
* pixels. We wait between each step to have a slower animation.
*/
canvas->Fill(0, 0, 255);
int center_x = canvas->width() / 2;
int center_y = canvas->height() / 2;
float radius_max = canvas->width() / 2;
float angle_step = 1.0 / 360;
for (float a = 0, r = 0; r < radius_max; a += angle_step, r += angle_step) {
if (interrupt_received)
return;
float dot_x = cos(a * 2 * M_PI) * r;
float dot_y = sin(a * 2 * M_PI) * r;
canvas->SetPixel(center_x + dot_x, center_y + dot_y,
255, 0, 0);
usleep(1 * 1000); // wait a little to slow down things.
}
}
int main(int argc, char *argv[]) {
RGBMatrix::Options defaults;
defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat"
defaults.rows = 32;
defaults.chain_length = 1;
defaults.parallel = 1;
defaults.show_refresh_rate = true;
Canvas *canvas = rgb_matrix::CreateMatrixFromFlags(&argc, &argv, &defaults);
if (canvas == NULL)
return 1;
// It is always good to set up a signal handler to cleanly exit when we
// receive a CTRL-C for instance. The DrawOnCanvas() routine is looking
// for that.
signal(SIGTERM, InterruptHandler);
signal(SIGINT, InterruptHandler);
DrawOnCanvas(canvas); // Using the canvas.
// Animation finished. Shut down the RGB matrix.
canvas->Clear();
delete canvas;
return 0;
}
Errors:
/tmp/cci8MGL5.o: In function `main':
main.cpp:(.text+0x264): undefined reference to `rgb_matrix::RGBMatrix::Options::Options()'
main.cpp:(.text+0x2a8): undefined reference to `rgb_matrix::CreateMatrixFromFlags(int*, char***, rgb_matrix::RGBMatrix::Options*, rgb_matrix::RuntimeOptions*, bool)'
collect2: error: ld returned 1 exit status
Possible fixes that I found:
Link .cpp files in a strict order when compiling: sudo g++ main1.cpp main2.cpp
This
The need of a makefile
While searching for similar issues and hopefully finding some magic fix, I ended up more puzzled than before. I have no idea if what I did is what I was supposed to do.
What cpp files to link if I have just one ?
Do I need to link all the .cpp and .h files that the library has ?
I don't understand a thing about makefile or why it even exists.
My issue may be specific to my situation but I believe that the answers will help me with future projects.
You are free to answer all of my questions and misunderstandings and help me understand what is going on or answer just the question related to the title: Why makefile ?
The problem is that, after a long battle with downloading the library
that I am trying to use, after installing a compiler, creating a file,
and finding the right command to run and include paths I get undefined
reference to errors.
There are already numerous questions and answers on SO pertaining to such problems, especially What is an undefined reference/unresolved external symbol error and how do I fix it?
Possible fixes that I found:
Link .cpp files in a strict order when compiling: sudo g++ main1.cpp main2.cpp
[SO question with answers saying roughly the same as the previous]
Not typically relevant. Although link order of different objects / libraries is significant, that rarely affects the case when all the needed C and / or C++ source files are specified in the same compilation command.
The need of a makefile
Using make does not inherently solve the problem, and it is certainly not necessary for solving the problem. Writing a makefile that provides for a successful build, whether directly or via a build tool such as CMake or the Autotools, requires you to understand at least at a high level how compilers and linkers work, what their inputs and outputs are, and what their arguments and options mean.
What cpp files to link if I have just one ?
You do not link a .cpp (directly) at all. You compile it and link the result to any needed libraries and any other objects. g++ will try to do that all in one step by default, in which case the process is conventionally called "compiling", not "linking", even though both functions are performed. g++ can be made to compile only, without linking, by specifying the -c option to it (which is common in makefiles, as it turns out), and it will happily link objects and libraries without compiling anything if you don't name any source files to it.
Anyway, your case is not at all that of just one .cpp file. It is your one .cpp file plus all those of the library you are trying to use.
Do I need to link all the .cpp and .h files that the library has ?
You do not need to compile (directly) or link any .h files. But if you want to use the library whose sources you downloaded, you do need to compile all the sources, and you probably should link them into an actual library. Furthermore, unless you produce and use a static library, you should also install the library you build. It looks like the library sources include a makefile, so you would be well advised to use make to perform those steps.
I don't understand a thing about makefile or why it even exists.
A makefile is the input to make. A well-written one defines rules for how to build one or more "targets", and expresses the prerequisites (generally original sources or other targets) for doing so. make uses these, together with a set of built-in rules, to figure out what steps to take to build the target(s) you ask it to build, and also what steps it can skip. It is typical, for example, to write makefiles so that if you build a multisource project, modify only one source file, and then build again, only the modified source gets recompiled.
This may seem trivial when you're used to projects with only a handful of sources, but it becomes important in larger projects, where full rebuilds are expensive -- many hours, in some cases. But even if a full build takes only a few minutes, if you really only needed to spend a few seconds then that adds up to a lot of wasted time over a full day of work.
Overall, then:
When do I need to use/have a makefile?
Never. But providing a good one and using make to build your project has these among its advantages:
memorializing all the needed build commands, including options and arguments, in a persistent, actionable form, and therefore
providing for consistent, automated builds.
Those can also be achieved by a simple build script, but make also can give you
faster builds by building only those pieces that are out of date, and
built-in knowledge of how to build certain kinds of targets from corresponding sources.

use fftw3 with gfortran included in TDM-GCC-64

I am trying to use FFTW3 with gfortran compiler included in the TDM-GCC-64 suite in Windows 7 platform.
I have downloaded "fftw-3.3.4-dll64.zip" from the following page:
http://www.fftw.org/install/windows.html
I also created a fortran module described in the following tutorial:
http://www.fftw.org/doc/Defining-an-FFTW-module.html
Now, I tried to compile the following fortrans program
program test
use FFTW3
implicit none
integer N
parameter(N=4)
integer*8 plan
double complex in, out
dimension in(N),out(N)
integer i
write(*,*) 'Input array:'
do i = 1,N,1
in(i) = dcmplx(float(i),float(i+1))
write(*,*) ' in(',i,') = ',in(i)
enddo
call dfftw_plan_dft_1d ( plan, N, in, out, FFTW_FORWARD, FFTW_ESTIMATE )
call dfftw_execute ( plan )
write(*,*) 'Output array:'
do i = 1,N,1
write(*,*) ' out(',i,') = ',out(i)
enddo
call dfftw_destroy_plan ( plan )
call dfftw_plan_dft_1d ( plan, N, out, in, FFTW_FORWARD, FFTW_ESTIMATE )
call dfftw_execute ( plan )
write(*,*) 'Output array after inverse FFT:'
do i = 1,N,1
write(*,*) ' ',N,' * in(',i,') = ',in(i)
enddo
call dfftw_destroy_plan ( plan )
end
I tried to compile but the a couple of error messages popped up:
undefined reference to dfftw_plan_dft_1d_'
undefined reference todfftw_execute_'
...
The command used for compiling is:
gfortran test.f90 -ffree-form -o test_fftw.exe
I searched web up and down but have not found solutions to the problem. Could anyone help me out here? Thanks!!!
You need to learn the basics of compiling and linking programs with GCC
This tutorial refers to the GCC C compiler, gcc, and C++ compiler, g++, but the principles are the same for the Fortran compiler, gfortran.
Your program invokes functions, like dfftw_plan_dft_1d that are not defined
in your code but in the fftw3 library. You must therefore tell gfortran
to link that library with your program, after it is compiled, or no definitions will be found for
these functions, and no executable can be built. Instead, the linkage
fails with the undefined reference errors you are seeing.
The command you have used to build the program:
gfortran test.f90 -ffree-form -o test_fftw.exe
attempts to compile and link the program in a single command. You can do this,
if you clearly understand the underlying separate processes of compiling
and linking. If you don't, you should follow the better practice of compiling first,
and if that is successful, then linking. The command you have used fails in
its linkage step because it does not tell the linker that the fftw3 library
is needed (or where to find it) so no attempt is made to find it and link it.
You say you have downloaded fftw-3.3.4-dll64.zip. I presume you have
unzipped it somewhere on your system. Let's say you unzipped it to C:\fftw-3.3.4-dll64.
You also say you have made an FFTW3 module that apparently is being used successfully.
In that case, compile your program first:
gfortran -c -o test.o test.f90
generating an object file test.o. The option -c tells gfortran to compile only,
and not to link. (You do not need to specify --ffree-form: the file-extension .f90
implies it).
Next, link the object file test.o with the fttw3 library, to make an executable
program test_fftw.exe:
gfortran -o test_fftw.exe test.o -LC:\fftw-3.3.4-dll64 -lfftw3-3
The linker option:
-LC:\fftw-3.3.4-dll64
tells the linker to add C:\fftw-3.3.4-dll64 (where you unzipped the package)
to the list of directories that it will search to find libraries. And the linker option -lfftw3-3 tells it to link a library that matches the identifier fftw3-3. On Windows, the GCC linker
will match a library identfier name with any of the filenames:
libname.a (a static library)
libname.dll (a shared library)
name.dll (also a shared library)
name.lib (an import library for a shared library)
So, since C:\fftw-3.3.4-dll64 contains the shared library libfftw3-3.dll,
the linker will identify it in that directory as the one required by -lfftw3-3
Now, unless there are other problems, you program will link and you will have
an executable test_fftw.exe, which will run, provided that libfftw3-3.dll
can be found, at runtime, in one of the places where the Windows
loader will look for it.

Which library to link to user boost::intrusive_ptr

is there possibility to find out which library file to link for libs that are using boost::intrusive_ptr?
I tried to use the boost bcp tool, but that does not give any hint in which dylib boost::intrusive_ptr is compiled.
On my system, I have these boost libs compiled (Version 1.49.0):
/usr/local/Cellar/boost/1.49.0/lib/
libboost_chrono-mt.a libboost_iostreams-mt.a libboost_math_c99l-mt.dylib libboost_program_options-mt.a libboost_serialization-mt.dylib libboost_timer-mt.dylib
libboost_chrono-mt.dylib libboost_iostreams-mt.dylib libboost_math_tr1-mt.a libboost_program_options-mt.dylib libboost_signals-mt.a libboost_unit_test_framework-mt.a
libboost_date_time-mt.a libboost_locale-mt.a libboost_math_tr1-mt.dylib libboost_python-mt.a libboost_signals-mt.dylib libboost_unit_test_framework-mt.dylib
libboost_date_time-mt.dylib libboost_locale-mt.dylib libboost_math_tr1f-mt.a libboost_python-mt.dylib libboost_system-mt.a libboost_wave-mt.a
libboost_exception-mt.a libboost_math_c99-mt.a libboost_math_tr1f-mt.dylib libboost_random-mt.a libboost_system-mt.dylib libboost_wave-mt.dylib
libboost_filesystem-mt.a libboost_math_c99-mt.dylib libboost_math_tr1l-mt.a libboost_random-mt.dylib libboost_test_exec_monitor-mt.a libboost_wserialization-mt.a
libboost_filesystem-mt.dylib libboost_math_c99f-mt.a libboost_math_tr1l-mt.dylib libboost_regex-mt.a libboost_thread-mt.a libboost_wserialization-mt.dylib
libboost_graph-mt.a libboost_math_c99f-mt.dylib libboost_prg_exec_monitor-mt.a libboost_regex-mt.dylib libboost_thread-mt.dylib
libboost_graph-mt.dylib libboost_math_c99l-mt.a libboost_prg_exec_monitor-mt.dylib libboost_serialization-mt.a libboost_timer-mt.a
The lib names themselves do not always give a hint to find the file to be linked (e.g boost::asio is in lboost_system-mt). Obviously it cannot be senseful to link randomly. Is there any way to find dependencies if I use anything from boost?
Best,
Sebastian
intrusive_ptr is a part of Smart Pointers library, which is header-only, i.e. you don't need to link anything.
Boost.Asio is not in lboost_system-mt, it just uses Boost.System (which is documented).

How to compile MATLAB code to be used with QT C++

I have 2 sets of code:
MATLAB code, and
QT C++ code.
I have tried to compile the MATLAB code to a C++ library using the mcc command with the msvc2008 compiler. For my QT C++ code, I'm using mingw to compile. However, when I try to add in the MATLAB converted C++ code there seems to be a lot of problems.
Is it possible to mix these two types of code together? Does anyone have any experiences using a combination of these languages?
! have tried to use Octave but I would rather not recode my MATLAB code. I am trying to look for an alternative to run MATLAB code directly.
NB: I need to use mingw in QT as it is requirement and for matlab mcc command, I only have the choice to use msvc compiler. It would be best if I could make the program as a standalone for portability. The reason why I need to use MATLAB code is because there are some nice matrix math manipulation functions I need and also because it would be easier for me to do research using MATLAB.
When you compile matlab code using mcc (by default or when using the -m option), you get an executable. So from your C++ file, you can call the matlab executable with the C/C++ command exec.
If you use the -l option (using mcc), you get a shared library, and header.
For instance if you type (in matlab):
mcc -l test.m -W cpplib:test.h
This should produce a shared library test.lib or test.so, and a header test.h
In test.h you should have line similar to that:
bool MW_CALL_CONV mlxTest(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
You can call your matlab function using that.
In addition you have to add both shared libraries and headers in you msvc project.
I fixed the mxInt64 and mxUint64 by adding more typedefs to make the code recognize those as signed and unsigned integers 64 bytes long.