I've been trying to fix this for a couple days so any insight would be greatly appreciated. I am building a project with an ESP32 board and VSCode's esp-idf framework. I am having trouble getting access to an outside library's functions. For example, I have implemented an FFT-noise-filter program in c, and now i want to bring it into the esp-idf framework. I think it has something to do with my unfamiliarity with CMake, and I have tried all sorts of different "CMakeLists.txt", but not sure what it should look like. I've been through cmake tutorials, but I just can't figure it out. Here's my current 'CMakeLists' inside main folder
idf_component_register(SRCS "hello_world_main.c"
INCLUDE_DIRS ".")
I took an example project 'hello_world' from esp-idf's examples, and wrote my own code inside of the 'hello_world_main.c'. It is weird because in my "hello_world_main.c" the complier seems to know some data types such as 'FFTW_Complex', which are only found in the library I'm trying to use. However, when I call any functions like FFTW's 'malloc' from that same library, I get an error "undefined reference to fftw_malloc()"
excerpt from hello_world_main.c's 'app_main():
//complex: double[2] = {real_part,imag_part}
fftw_complex *in, *out; //no errors here for some reason
fftw_plan p;
//initialize the arrays-> "in" is an array of fftw_complex type (basically a pair of doubles)
//in is f (set of points we know) -> out is fhat (complex fourier coefficents) with magnitude and phase
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); //'undefined reference to fftw_malloc'
Error message:
[5/7] Linking CXX executable hello_world_2.elf
FAILED: hello_world_2.elf
cmd.exe /C "cd . && C:\Users\bgreenwood.espressif\tools\xtensa-esp32-elf\esp-2021r2-patch3-8.4.0\xtensa-esp32-elf\bin\xtensa-esp32-elf-g++.exe
-mlongcalls -Wno-frame-address #CMakeFiles\hello_world_2.elf.rsp -o hello_world_2.elf && cd ."
c:/users/bgreenwood/.espressif/tools/xtensa-esp32-elf/esp-2021r2-patch3-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: esp-idf/main/libmain.a(hello_world_main.c.obj):(.literal.app_main+0x1c): undefined reference to
`fftw_malloc'
so my question is, how can I get my main to recognize the function calls I am making?
Add your libcode.c to:
idf_component_register(SRCS "hello_world_main.c" “libcode.c”
INCLUDE_DIRS ".")
And add a reference to libcode.h:
#include “libcode.h”
Libcode is an artificial name, change it by the correct one and you could also add a directory if needed like “libcode/libcode.h”
Hope this answers your question; with more code it’s easier to understand your problem.
To check what the minimal component would look like, you can create one using idf.py create-component NAME. The component named NAME will be made, and you can check what is missing in your external library.
Related
I'm trying to use Visual Studio Code to develop Fortran MPI programs. However, while I can successfully build and run them just fine, it would be very helpful for me if I can use intellisense/autocompletion features for MPI (as well as other external modules). I have /usr/lib/openmpi/ (which contains mpi_f08.mod) as part of fortran.includePaths in my settings.json. However, when I use mpi_f08, I get the problem message from VS Code Module "mpi_f08" not found in project. Here is a minimal CMake build example:
! hello.f90
program hello
use mpi_f08
implicit none
integer :: ierror, nproc, my_rank
call MPI_Init()
call MPI_Comm_size(MPI_COMM_WORLD, nproc, ierror)
call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierror)
print*, "hello from rank ", my_rank
call MPI_Finalize()
end program hello
# CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(hello_mpi)
enable_language(Fortran)
find_package(MPI REQUIRED)
add_executable(hello_mpi hello.f90)
include_directories(${MPI_Fortran_INCLUDE_PATH})
target_link_libraries(hello_mpi PUBLIC ${MPI_Fortran_LIBRARIES})
I would like to be able to (i) get rid of the warning/message and more importantly (ii) enable suggestions from MPI when I press CTRL+space as it would if I was calling from an internal module.
I'll post a partial answer since it's better than nothing, hopefully this helps someone else and/or enables someone else to answer my question fully.
It seems the issue relates to the Fortran language server, which can be configured by adding a .fortls JSON file, as explained on its Github README: https://github.com/hansec/fortran-language-server
I added the following, which allowed it to find not only local modules but also MPI (and the external module json-fortran):
{
"source_dirs": ["src", "."],
"ext_source_dirs": [
"/path/to/json-fortran/src",
"/path/to/openmpi-4.1.2/ompi/mpi/fortran/use-mpi-f08",
]
}
This doesn't capture all functions in json-fortran, which I think is because of its .inc files, as it doesn't give me function pointers like json_file::get at autocomplete.
As for MPI, this kind of works, as it gives me all the functions I can think of needing, but with _f08 appended to the end of it. I don't know the inner workings of OpenMPI but I guess e.g. MPI_Init wraps MPI_Init_f08 for reasons of backward compatibility. For now I can simply autocomplete to the _f08 version and remove that bit manually. (I also tried adding openmpi-4.1.2/ompi/mpi/fortran/use-mpi-tkr and openmpi-4.1.2/ompi/mpi/fortran/mpif.h but no luck).
Would be nice to get this detail sorted though. It is also mildly annoying that I must manually include the source dirs now (removing it makes it not find local modules).
I'm using XS to create a Perl Module which uses a C library.
For testing purposes, I've created a test library which has two simple functions:
void kzA() (does a simple printf)
void kzB(int i, char *str) (does a printf of the received parameters)
I've also created some glue in XS, in order, for now, to access the kzA() function:
(I'm only showing the function itself, but the includes are there, too, in the XS)
void
ka()
CODE:
printf("Before kzA()\n");
kzA();
printf("After kzA()\n");
So, I compiled the test library as fc.so, and it is in the same directory as my xs file, and my Makefile.PL (/workspace/LirePivots)
In my Makefile.PL, I set the LIBS key to ['-L/workspace/LirePivots -l:fc.so'], but when executing it with perl (perl Makefile.PL), it says "Warning (mostly harmless): No library found for -l:fc.so"
It then writes a Makefile which does NOT mention said library. And then, after compiling (with "make") and installing (with "sudo make install"), when I run my test script which calls the ka() function from my module, I get the line "before", but the kzA() function isn't called, obviously, because it cannot find the kzA symbol, and the program stops there.
Creating a C test program which I would link with the very same arguments (-l:fc.so -L/workspace/LirePivots) does work, and, as long as I put the path in LD_LIBRARY_PATH, it finds the function and runs it correctly.
I also tried renaming the library libfc.so, and changing the -l part to "-lfc", but it didn't work either. It never manages to find the library.
Does anyone know what I do wrong ?
EDIT:
As requested, I created a minimum example: https://github.com/kzwix/xsTest
To run it, you'll need to have a Linux with Perl 5, along with XS (package perl-devel, on Redhat). And a C compiler, and make, obviously.
Ok, I still don't know the reason why it wouldn't find the library. But I found a workaround:
By adding the test library as "libfc.so" to /usr/lib, then running "sudo ldconfig", the library got added to the cache (when named fc.so, even if in /usr/lib, ldconfig would not add it. Also, it wouldn't work with symbolic links, either, I had to really copy it there).
After the library got added to the cache, "perl Makefile.PL" would still not find the library. I had to use "-L/usr/lib" in addition to "-lfc" for it to at long last find the library, and "agree" to add the parameters to the link step of the library.
After this happened, I could compile with "make", and executing the test program did work as originally intended (I saw both the "before" and "after" printf, and I saw the one from the function in the kzA() function from libfc.so)
Thanks Håkon Hægland for helping.
(I can't provide the Dockerfiles, they link to images internal to my organization, which I'm not allowed to share)
Sorry for the noob question. I am trying to learn how to integrate a C function in Modelica model. I am having trouble understanding how to specify the path to my external functions.
I created an external C function and saved in a different directory than my model directory or the working directory. I thought that using the IncludeDirectory annotation would allow me to refer to where that C function is located, but I can't get it to work.
impure function computeHeat "Modelica wrapper for an embedded C function controller"
input Real T;
input Real Tbar;
input Real Q;
output Real heat;
external "C"annotation(Include="#include<ComputeHeat.c>",IncludeDirectory="E:/temp/source_C");
end computeHeat;
When I tried to compile a demo example model, I got the following message.
Compiler message:
Compiling and linking the model (Visual C++).
dsmodel.c
dsmodel.c(10): fatal error C1083: Cannot open include file: 'ComputeHeat.c': No such file or directory
Error generating Dymosim.
The IncludeDirectory should be an URI and only modelica-URIs are currently supported in Dymola.
So, store your function computeHeat in e.g. e:/temp/computeHeat.mo
And use IncludeDirectory="modelica://computeHeat/source_C"
In general I would assume computeHeat would be part of a package, MyPackage, stored as e:/temp/MyPackage/package.mo (and more files, e.g. computeHeat.mo).
In that case create e:/temp/MyPackage/Resources/source_C and use IncludeDirectory="modelica://MyPackage/source_C" The latter case is the recommended one, since you can copy MyPackage as a directory and the source follows.
I have a problem very similar to this question. I need to tell the linker to add the static lib, despite the fact that to reference to its symbols seems to be made.
The reason for that is that the library contains an function in .init or using ( __attribute__ ((constructor))) to perform its initialisation, which in turn, is going to call a register() function from the main program to register its functionality (read: pass other function pointers).
So despite the fact that no symbol from the library seems to be used in the main program, the main program will call functions from the library as soon as the latter are registered via the library init function.
But I am using libtool...
So taking the example given in the previously mentionned question, I'd need to write something like:
bin_PROGRAMS = pktanon
pktanon_SOURCES = main.cpp
pktanon_DEPENDENCIES = $(lib_LIBRARIES)
pktanon_LDADD = libpktanon.la $(LDADD)
Note the "la" extension instead of "a" for the lib.
Now, how shall I pass the --whole-archive option to the linker? The answer suggested in the question assumes the path to the archive (.a file) is known... It does not feel right to hard code a path like .libs/libptanon.a in the Makefile.am...
And the linker does not like meeting a .la file in its whole-archive otpion if trying:
pktanon_LDFLAGS = -Wl,--whole-archive,libpktanon.la,--no-whole-archive
Any suggestions?
The use of --whole-archive is not portable, so why not create a Libtool convenience library instead? In your Automake Makefile.am, add noinst_ to the library, then instead of creating a (possibly non-pic) static archive, it will take all the object files in the library and add it to anything that links to it. It is portable, and should work for this case, as it doesn't seem like you want a library here at all.
I am trying to get my feet wet in SimScript simulation.
I wrote a simple code contains a function that returns the its first parameter.
This is my code:
preamble
define Normal.fn as a double function
end
function Normal.fn (means, f)
define means, f as double variables
return (means)
end
main
let x = Normal.fn(2.1,3.1)
end
However, when I execute the project, I got an error message states:
The executable file MyProject.exe is missing
I build and rebuild the project many times, but I am still having this problem.
I noticed in my executable folder, the MyProject.exe has not been generated.
I don't know what is going on, I am new to this programming language.
Could you help please?
I found the solution myself,
It was a missing library in the simscript version 3, i check the simscript version 2 libraries through file system and I found it, it is the one named "IDebugC.c"