Undefined reference to `PaUtil_GetRingBufferReadAvailable' when compile paex_record_file.c from Portaudio using Eclipse - linux

I need to compile PortAudio's paex_record_file.c file using Eclipse and CDT on Ubuntu 12.04.5 LTS.
Dev libraries (libportaudio-dev) was installed via Synaptic.
I create new Eclipse project and create (copy) this only file to it (so project contains only one user source file 'paex_record_file.c', 1752 2011-09-08 03:21:55).
Then i use Eclipse's Pkg-config to add 'portaudio' (dev) library.
But it not compiles with error
../src/paex_record_file-test.c:47:27: fatal error: pa_ringbuffer.h: No such file or directory
Then source branch taken from git
$ git clone https://git.assembla.com/portaudio.git
./configure
make
sudo male install
But still get same error (no 'pa_ringbuffer.h').
Then during blind trials and errors i use Project - Properties - C build - Settings - Tool settings - Includes, and add '/home/test/portaudio/src/common' path which contains needed .h file, and (this) error disappear.
Question 1: Is this step is correct use of Eclipse settings in this case? (i believe not, because i never need to use this setting before).
But then it shows multiple errors like
/home/doc/prog/paex_record_file-test/Debug/../src/paex_record_file-test.c:110: undefined reference to `PaUtil_GetRingBufferReadAvailable'
and this is unrecoverable.
Question 2. How it can be fixed using Eclipse, BUT without copying all Portaudio source tree to my project?
I have pa_ringbuffer.o file somewhere in system, but no any something like pa_ringbuffer.so files.
I have compiled and running under Eclipse other PA apps which are do not use PA's ring buffer, and just
#include "portaudio.h"
and adding PA lib via PkgConfig is enough.
Thanks.

I had to add those 3 files to source code as well as main.c , then it compiled.
I use Code Block, Mingw c compiler
/portaudio/src/common/pa_allocation.c
/portaudio/src/common/pa_ringbuffer.c
/portaudio/src/os/win/pa_win_util.c
code block IDE view of 3 files added

Please have a look into the portaudio.git :
cd portaudio/
find . -name pa_ringbuffer.h
The reply is : ./src/common/pa_ringbuffer.h
... so you will have to copy the header to a location, where it can be found. But : Do not expect to compile a single file → often not possible with a complex application. I.e. the setup is meant for compiling the complete portaudio/.

Related

CMake cannot find source file, but file was not specified in CMakeLists.txt, in TFS build definition

I'm porting a large project to linux. I wrote all the CMakeLists.txt files, and everything compiles in my machine.
For whatever reason we still use TFS. The old version, not git with TFS.
I'm working in my own branch, but that branch has no build definition for linux. Before I check in, I want to be sure that everything compiles on the server too. So I need to merge my branch to another one, and submit that shelve set to the build job.
In my machine everything compiles fine. But when I run the build in the server, applying a shelveset to the branch that has a linux build definition, I get an error from the build, saying
CMake Error at
/myproject/subproject/CMakeLists.txt:165 (add_library):
Cannot find source file:
/myproject/subproject/IInternalTransactionManager.h
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
.hpp .hxx .in .txx
Indeed, that file is not there. Cmake complains about the file not being in the sources directory, which is true, because it is in another directory. But the fact is that I'm not asking for it either! My CMakeFiles.txt file does not include that file. That file is a header which is used in a few files, contains only classes definitions (no implementations), and the directory in which myHeader.h resides has been defined in include_directories. My CMakeLists.txt looks something like this:
set(PROJECT_NAME project)
project(${PROJECT_NAME})
include_directories(
../_include
)
set(source_files
main.cpp
file_that_includes_myHeader.cpp
)
add_library( ${PROJECT_NAME} STATIC ${source_files} )
and my file structure is something like:
/myproject/subproject/main.cpp
/myproject/subproject/file_that_includes_myHeader.cpp
/myproject/subproject/CMakeLists.txt
/myproject/_include/myHeader.h
So, why should cmake complaining about a missing file, if such file is not included in the CMakeLists.txt file? And why would this happen only the build in TFS? My guess is that there is something wrong when applying the shelvetset and is not related to my code, but I cannot prove it.
I compared the code after the shelveset is applyied, and still in that version the CMakeLists.txt does not mention myHeader.h
Or, there is some rule about including headers in CMakeLists.txt files which I'm not aware of.
So, after expending too much debuging I contacted the team in charge of the build process. And as it turns out, the building process in the TFS building definition was definetly NOT what I expected. And of course this was not documented.
Our development is mostly in windows (by far). The linux build has a step before building: a script is launched which parses each Visual Studio project file, gets the included files, and substitutes the source files in the CMakeLists.txt files with the one parsed from VS. Right or wrong, is just the way it is.
I could build the linux build in my local machine because everything was done correctly. The windows build worked too, even though the VS project files sometimes included some files which were not in the source directory but in some header only directory, and somehow that compiled. I guess because the directory was defined in the include directory. But When the CMakeLists.txt files were updated, cmake complained (rightly so) about not finding the files.
So, if anybody experiences similar issues, contact your devops team or whoever is in charge of such things.

Create a ready to use install package on linux with cmake or gcc, including shred dependencies

I have completed a small project that uses several libraries. the CMakeList.txt looks like this:
cmake_minimum_required(VERSION 3.5)
project(tf_ct_log C)
set(CMAKE_C_STANDARD 99)
include_directories(include /usr/local/include/hiredis /usr/include/openssl)
link_directories(/usr/lib/x86_64-linux-gnu)
set(HDR include/ct_logger.h)
add_executable(tf_ct_logger src/main.c src/ct_logger.c ${HDR})
find_package(OpenSSL REQUIRED)
find_package(Threads REQUIRED)
find_library(PostgreSQL REQUIRED)
find_library(jansson REQUIRED)
target_link_libraries(tf_ct_logger OpenSSL::SSL jansson pthread pq)
I would like to be able to build a package that can be installed in another machine, without downloading any dependencies. with ldd, I 've got all dependencies of the application and copied those files (libxyz.so...) into a subdirectory deps in my project. How can I create that package using those dependencies so that the end user will just use the object files of my project along with the dependencies libraries to create the executable?
It gets really hairy real quick when you need to create a native package for multiple flavors of installers (Debian, RH, Arch, etc.), especially if customization is involved.
If you just need a clean reproducible to get it on a box and run -- I would strongly suggest looking towards packaging it as a Docker container.
You start from some lightweight Linux distro container (Alpine is the latest trend), derive it into one with C and C++ runtime and anything else you depend on and call this "my prod container". From that you derive one with C++ compiler and debugger installed and call it "my dev container".
We actually wrote a little memo a while back, while making our open source hobby usable for others.
You will probably still need to clean up your CMake file to an extent that the "install" target works (mine is here).
I may have not expressed myself correctly. I just wanted to compile and build executables from my project, then find a way to copy it on another machine without having to install all dependencies before running the app.
The solution I found (with the help of a more experienced developer) was as follows:
1- Get all dependencies using ldd
2- Copy dependencies in a directory dependencies
3- On the target environment, copy content of dependencies into /usr/local/lib/myapp/
4- On the target environment, goto /etc/ld.so.conf.d/
5- create the file myapp.conf with one line in it: /usr/local/lib/myapp
6- run ldconfig
Then, the executable I created on my development machine runs here smoothly!
Of course all the steps I described up there must be listed in a script for automation

Finding my Linux shared libraries at runtime

I'm porting an SDK written in C++ from Windows to Linux. There are other binaries, but at its simplest, our SDK is this:
core.dll - implicitly loaded DLL ("libcore.so" shared library on Linux)
tests.exe - an app use to test the DLL (uses google test)
All of my binaries must live in one folder somewhere that apps can find. I've achieved that on Windows. I wanted to achieve the same thing in Linux. I'm failing miserably
To illustrate, Here's the basic project tree. We use CMake. After I build I've got
mysdk
|---CMakeLists.txt (has add_subdirectory() statements for "tests" and "core")
|---/tests (source code + CMakeLists.txt)
|---/core (source code + CMakeLists.txt)
|---/build (all build ouput, CMake output, etc)
|---tests (build output)
|---core (build output)
The goal is to "flatten" the "build" tree and put all the binary outputs of tests, core, etc into one folder.
I tried adding CMake's "install" command, to each of my CMakeLists.txt files (e.g. install(TARGETS core DESTINATION bin). I then then executed sudo make install after my normal build. This put all my binaries in /usr/local/bin with no errors. But when I ran tests from there, it failed to find libcore.so, even though it was sitting right there in the same folder
tests: error while loading shared libraries: libcore.so: Cannot open shared object file: No such file or directory
I read up on the LD_LIBRARY_PATH environment variable and so tried adding that folder (/usr/local/bin) into it and running. I can see I've properly altered LD_LIBRARY_PATH but it still doesn't work. "tests" still can't find libcore.so. I even tried changing the PATH environment variable as well. Same result.
In frustration, I tried brute-force copying the output binaries to a temporary subfolder (of /mysdk/build) and running tests from there. To my surprise it ran.
Then I realized why: Instead of loading the local copy of libcore.so it had loaded the one from the build output folder (as if the full path were "baked in" to the app at build time). Subsequently deleting that build-output copy of libcore.so made "tests" fail altogether as before, instead of loading the local copy. So maybe the path really was baked in.
I'm at a loss. I've read the CMake tutorial and reference. It makes this sound so easy. Aside from the obvious (What am I doing wrong?) I would appreciate if anyone could answer any of the following questions:
What is the correct way to control where my app looks for my shared libraries?
Is there a relationship between my project build structure and how my binaries must then appear when installed?
Am I even close to the right way of doing this?
Is it possible I've somehow inadvertently "baked" (into my app) full paths to my shared libraries? Is that a thing? I use all CMAKE variables in my CMakeLists files.
You can run ldd file to print the shared object dependencies for file. It will tell you where are its dependencies being read from.
You can export the environment variable LD_LIBRARY_PATH with the paths you want the linker to look for. If a dependency is not found, try adding the path where that dependency is located at to LD_LIBRARY_PATH and then run ldd again (make sure you export the variable).
Also, make sure the dependencies have the right permissions.
Updating LD_LIBRARY_PATH is an option. Another option is using RPATH. Please check the example.
https://github.com/mustafagonul/cmake-examples/blob/master/005-executable-with-shared-library/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
# Project
project(005-executable-with-shared-library)
# Directories
set(example_BIN_DIR bin)
set(example_INC_DIR include)
set(example_LIB_DIR lib)
set(example_SRC_DIR src)
# Library files
set(library_SOURCES ${example_SRC_DIR}/library.cpp)
set(library_HEADERS ${example_INC_DIR}/library.h)
set(executable_SOURCES ${example_SRC_DIR}/main.cpp)
# Setting RPATH
# See https://cmake.org/Wiki/CMake_RPATH_handling
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${example_LIB_DIR})
# Add library to project
add_library(library SHARED ${library_SOURCES})
# Include directories
target_include_directories(library PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/${example_INC_DIR})
# Add executable to project
add_executable(executable ${executable_SOURCES})
# Linking
target_link_libraries(executable PRIVATE library)
# Install
install(TARGETS executable DESTINATION ${example_BIN_DIR})
install(TARGETS library DESTINATION ${example_LIB_DIR})
install(FILES ${library_HEADERS} DESTINATION ${example_INC_DIR})

Problems with porting a fortran program from ubuntu to windows

I previously had some troubles updating old code that still needed a not supported compiler and expensive libraries to a version with gfortran in Eclipse on Windows. I let it rest for a while and recently I took a whole other approach, rebuilding the program from scratch, developping on a ubuntu machine, but now I want to bring it back to a windows machine so that my co-workers can contribute on it.
The status:
Program compiles, runs and gives good results on an ubuntu machine with the GCC GNU compiler
Windows 7 machine, 64bit
Cygwin installation (for gnu fortran) with lapack and liblapack-devel (however, I don't use these, because I compile blas and lapack manually)
(C:/cygwin/lib added to windows Path)
Original Issue:
The program compiles in cygwin (by calling the make-command, calling the make command with the makefile situated here: http://thijsvandenbrande.be/phd/hamfemInstall/makefile
This returns the file hamfem.exe which returns the following error when runned by double-clicking on it in windows: The program can't start because cyglapack-0.dll is missing from your computer. Try reinstalling the program to fix this problem.
When running the executable from cygwin, by calling the ./hamfem.exe command the executable starts to run. However, I want a solution so that I can give this executable to my co-workers so that they can change the input files (located in a folder in that has a relative path to the executable).
Going further on the comments below, I tried the next things:
Adding the exact path to the C:\cygwin\lib\lapack\cyglapack-0.dll file in windows path and even rebooting afterwards doesn't help.
adding a -static to the makefile before calling the library, resulting in dependency errors because I use two commands of the lapack library that depend on quite a lot of other commands (DPBTRF and DPBTRS). These commands are used in the mainprog.f90 module. The error: /usr/lib/gcc/i686-pc-cygwin/4.7.3/../../../liblapack.a(dpbtrf.f.o): In function 'dpbtrf':
/usr/src/debug/lapack-3.4.2-1/SRC/dpbtrf.f:277: undefined reference to 'dtrsm_'
and a couple of more lines stating the dependencies.
add the liblapack.a file to the src folder, but compiler always goes back to the lapack in cygwin
On the website of lapack you can normally download the functions with their dependencies (example DPBTRF), but these are not available anymore. Does anyone have another idea how to include these two functions and their dependencies in a static library-file that I can compile beforehand and add to the src-folder?
Current (semi-)Fix
The next thing worked (a bit) for me: following the instructions on http://gcc.gnu.org/wiki/GfortranBuild to manually build libblas.a and liblapack.a in the /usr/src folder of Cygwin and refering to this folder in the makefile. The updated makefile can be found here: http://thijsvandenbrande.be/phd/hamfemInstall/makefileNew
The code compiles nicely on Windows by running the make command from cygwin (next step in the process, running it out of Eclipse) and i get a .exe file that can be run by double clicking it and that keeps running if I move it with its folder to another location. Because this process is quite labour intensive, figuring it all out, I added the answer here below, stating the commands you have to parse to cygwin in order to make it work.
For your information: my file structure looks like this (after the build, I move the .exe file one folder up, both in the linux version as the windows version):
hamfem.exe
in
input.txt
NGCR_building01.txt
out
(empty folder for output files of the routine)
src
hamfem.f90 (main file)
mainprog.f90 (file that contains the commands from lapack)
...(a bunch of other modules)
makefile
I figured things out myself, with some pointers from all over stackoverflow. In order for others to help them resolve similar issues, I would like my work method here so that the question is fully documented.
The issue can be resolved by clean building the Lapack library !and the Blas library on your local machine in cygwin and pasting the liblapack.a and libblas.a file to the library folder that you refer to in the makefile. The errors that were casted by calling Lapack staticly where a result of some routines of Blas used in the two commands.
These are the steps I followed:
download the lapack.tgz and blas.tgz files from the website and past them in the C:\Cygwin\usr\src folder
Extract these files with the following commands in cygwin:
cd /usr/src
tar -xvzf lapack.tgz
tar -xvzf blas.tgz
Build the two library files with the commands shown below in Cygwin. Compiling Lapack can take a while and will result in some errors in the end because of some missing links in the test files. These tests are run for accuracy tools. A more detailed look into the make.inc file is needed to resolve these issues.
cd $HOME
cd /usr/src/BLAS
make
mv blas_LINUX.a ../libblas.a
cd ../lapack-3.4.2
mv make.inc.example make.inc
make
mv liblapack.a ../liblapack.a
check the makefile included in this repository for the correct linking to the libraries. These should say /usr/src and -static -llapack -lblas, the other options are for the linux compiler.

Building a Win32 DLL from a Linux library source

I'm trying to build a Win32 DLL from an audio-DSP related Linux library (http://breakfastquay.com/rubberband/). There are makefiles and config scripts for Linux, but no help for Windows. The author provides a Win32 binary of a sample app using the library, and I see a number of "#ifdef MSVC" and "#ifdef WIN32" scattered around, so I don't think I'm starting completely from scratch but I'm stuck nevertheless.
As my programming knowledge in either platform is rather limited, I'd appreciate any help.
First of all, what is the right way to get started here? Visual Studio? Cygwin? Initially I started off creating a Win32 DLL project in Visual Studio, adding the source files, thinking about adding a .def file, etc, but at some point I felt like this was going nowhere.
As for Cygwin, this was the first time using it, and I don't even know if this is the sort of thing that Cygwin is designed for. Is it?
On Cygwin, I ran ./configure and got stuck at something like this:
"checking for SRC... configure: error: Package requirements (samplerate) were not met: No package 'samplerate' found"
After looking through the log, it appears that pkg-config is looking for samplerate.pc. How do I handle packages in Windows? libsamplerate is just an open source library, and I have source and a DLL for this. But I'm not sure how to use them to satisfy the dependency requirements for librubberband (which is what I'm trying to build)
I'm completely lost at this point and if anyone can give me a nudge in the right direction... and, is there an easier way to do this?
Many thanks in advance.
If you're still stuck on this I can throw a little light.
You may have to build everything from sources (or have the libraries installed in your environment). You're using Cygwin, I would recommend MinGW and MSYS too, but sometimes it's just not possible to use this combination to build the program or library.
So if using Cygwin, first ensure that you have a proper environment installed. This is that you have the correct development headers installed.
Then download libsndfile. Extract the sources to a directory and from the Cygwin bash shell navigate to that directory. There perform:
./configure
make
make install prefix=/cygdrive/c/cygwin
Notice that I use a prefix, that prefix should point to the directory Cygwin is installed in order to correctly install the libraries (the same happens to MinGW and MSYS, the prefix should point to the MinGW installation directory). Maybe using the usr directory in the prefix works too, I've never tried it.
Now download FFTW, as it will be needed for libsamplerate and rubberband. Same procedure as with libsndfile: extract, configure, make & make install using the prefix. Now copy the header files of FFTW (in the example they'd be in /cygdrive/c/cygwin/include) to the include directory in the usr directory (in the example /cygdrive/c/cygwin/usr/include).
Next SRC (libsamplerate), same procedure.
Then the Vamp plugin SDK. In order to compile the it you may need to edit the file src\vamp-hostsdk\PluginLoader.cpp, deleting RTLD_LOCAL from a dlopen() call (it's safe, it's already the default behaviour).
Also, you may need to install it by hand (in my experiences it didn't like the prefix). Or set the environmental variable PKG_CONFIG_PATH pointing to the paths of pkgconfig, e.g.:
set PKG_CONFIG_PATH=/cygdrive/c/cygwin/lib/pkgconfig:/usr/local/lib/pkgconfig
Now, create a file called ladspa.h in the include directory with the contents of the LADSPA header
Finally, configure and build rubberband, it should find everything it needs.
To build in MSYS using MinGW follow the same procedure, using the according prefix. Using Visual Studio is another alternative, but you may need to use some of the pre-built libraries (for example for libsndfile) as building Linux libraries natively in Windows may be complicated or even impossible (without hacking the source code) in VS.
Anyway, the autor of rubberband provides binaries; I think you should consider use them instead of going through all of this.
Linux to w32 is mostly a tricky thing.
For each of your dependencies, download the source and:
./configure
make
sudo make install
Also, I recommend you to use MinGW + msys in place of CygWin (as the latter produces executables that depend on its libraries). However in your situtation, use the VS approach -- 't will save you a lot of time.

Resources