CMake finds fftw library but cannot link - linker

I have problem linking the fftw library using cmake. I use a findFFTW.cmake file in order to find the library. I know this is successfully finding the library because I set the REQUIRED flag to be true for finding the library and the make process goes through fine.
Despite linking it with my executable, I am still getting undefined reference errors. Some related posts, whose solutions I have tried.
Undefined reference to "function name from external library"
http://answers.ros.org/question/171326/catkin-linking-order-undefined-reference-to-symbol/
Updates
Thanks to ComicSansMS, the CMake below should now model the dependencies correctly.
CMake file of project (updated 3/7)
cmake_minimum_required(VERSION 2.8.3)
project(gist_extractor)
## Find catkin macros and libraries
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
image_transport
cv_bridge
sensor_msgs
cmake_modules
)
find_package(OpenCV REQUIRED)
find_package(Eigen REQUIRED)
find_package(FFTW REQUIRED)
###########
## Build ##
###########
## Set GIST variables for building library
set(GIST_PATH /home/andy/Development/lear_gist-1.2)
## Specify additional locations of header files
include_directories(include ${catkin_INCLUDE_DIRS} ${GIST_PATH} ${FFTW_INCLUDES})
## Declare a gist library
add_library(gist SHARED ${GIST_PATH}/standalone_image.c ${GIST_PATH}/gist.c) # THIS IS NOT BEING BUILT
target_link_libraries(gist ${FFTW_LIBRARIES})
## Add cmake target dependencies of the library
#MESSAGE( STATUS "GIST_LIBRARY_PATH: " ${GIST_PATH})
## Declare a C++ executable
add_executable(gist_extractor src/gist_extractor.cpp)
target_link_libraries(gist_extractor ${catkin_LIBRARIES} gist)
EDITS 2
We now have a linking error if we use the above CMake file. Specifically the make process fails when I try running
target_link_libraries(gist_extractor ${catkin_LIBRARIES} gist)
I have a couple of observations. Firstly, my gist library is being built correctly based on the below console messages.
Linking C shared library /home/andy/Projects/ROS/robot_ws/devel/lib/libgist.so
[ 80%] Built target gist
Scanning dependencies of target gist_extractor
[100%] Building CXX object
`gist_extractor/CMakeFiles/gist_extractor.dir/src/gist_extractor.cpp.o
But we can see that there are undefined reference errors when we try to link our executable with the gist library.
Linking CXX executable gist_extractor
: undefined reference to `color_gist_scaletab'
Here's why I don't understand why this is occurring. In gist_extractor.cpp, I have included the header file that includes the 'color_gist_scaletab' function. Specifically, this 'color_gist_scaletab is in defined in 'gist.h' and implemented in 'gist.c'. I would think that building my library gist should give me access to 'color_gist_scaletab'. I have posted the relevant files below.
gist.h
#ifndef GIST_H_INCLUDED
#define GIST_H_INCLUDED
#include "standalone_image.h"
/*! Graylevel GIST for various scales. Based on Torralba's Matlab
* implementation. http://people.csail.mit.edu/torralba/code/spatialenvelope/
*
* Descriptor size is w*w*sum(n_orientations[i],i=0..n_scale-1)
*
* #param src Source image
* #param w Number of bins in x and y axis
*/
float *bw_gist_scaletab(image_t *src, int nblocks, int n_scale, const int *n_orientations);
/*! #brief implementation of grayscale GIST descriptor.
* Descriptor size is w*w*(a+b+c)
*
* #param src Source image
* #param w Number of bins in x and y axis
*/
float *bw_gist(image_t *scr, int nblocks, int a, int b, int c);
/*! #brief implementation of color GIST descriptor.
*
* #param src Source image
* #param w Number of bins in x and y axis
*/
float *color_gist(color_image_t *src, int nblocks, int a, int b, int c);
/*! Color GIST for various scales. Based on Torralba's Matlab
* implementation. http://people.csail.mit.edu/torralba/code/spatialenvelope/ */
float *color_gist_scaletab(color_image_t *src, int nblocks, int n_scale, const int *n_orientations);
#endif
gist_extractor.cpp
// color_gist_scaletab is defined in gist.h
// I'm including relevant header file
#include "/home/andy/Development/lear_gist-1.2/gist.h"
//SOME MORE STUFF
// This is where I call the function
float *gist_descriptor = color_gist_scaletab(im, nblocks, n_scale, orientations_per_scale);

It seems you did not model your dependencies correctly.
You use fftw from inside gist.c, which is part of the gist library target.
However, that target does not have a dependency to fftw, only the downstream target gist_extractor has. This is a recipe for trouble, especially in static builds, where toolchains are often picky about the order in which libraries appear on the linker command line.
Add fftw as a dependency to gist:
target_link_libraries(gist ${FFTW_LIBRARIES})
Also, there is no need to do this:
add_dependencies(gist_extractor gist)
target_link_libraries(gist_extractor ${GIST_PATH}/libleargist.a)
If both targets are built as part of the same project, simply do:
target_link_libraries(gist_extractor gist)
By using the target name instead of hardcoding the output file, you not only make your build script more portable, but also allow CMake to better track the inter-target dependencies for you.

Related

why is Separating my code into Static Library have much code size than within the main in C in terms of .bin or .out file or an executable?

I had a code inside the "main" that could be detached into a static library, so I separated this part into a new static library folder and included it with my main script.
as follows I had the example with a no-library version
#include "XXX_lib/XXX_Core.h"
void main(){
/* list of code that uses some functions from XXX_lib/XXX_Core.h library
* which is been found inside the main project as a sub folder and
* I included the main header file from this folder
*/
}
and the project tree was like
|-Main_Project_foler
|--- main.c
|--- XXX_LIB -> (folder)
|-------XXX_Core.h
|-------XXX_Core.c
|-------XXX_OS.h
|-------XXX_OS.c
|-------XXX_Patterns.h
|-------XXX_Patterns.c
|------- .....
afterward, I separated the XXX_lib files into a static library and generate an XXX_lib.lib file that I can use along with my main code as a static library and I can reuse it with other modules in my project so the project structure was like
|-STATIC_LIBRARY_XXX_folder
|--- Debug ->(folder)
|-------XXX_LIB.lib
|--- XXX_LIB -> (folder)
|-------XXX_Core.h
|-------XXX_Core.c
|-------XXX_OS.h
|-------XXX_OS.c
|-------XXX_Patterns.h
|-------XXX_Patterns.c
|------- .....
|
|-Main_Project_folder
|--- main.c
and I included the absolute path of my XXX_Lib directory for the compiler and the .lib file to the linker search path and the compiler is TI Arm C/C++ Compiler Version 18.12.5.LTS and the code are running on a 32-bit MCU ( TM4C129 ) and options passed to the compiler have many include paths so excluding them with ${manyIncludePaths} arg the flags are
-mv7M4 --code_state=16 --float_support=FPv4SPD16 -me -Ooff --opt_for_speed=2 ${manyIncludePaths} --define=PART_TM4C129XNCZAD --define=ccs --define=TIVAWARE --define=ccs="ccs" -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --gen_func_subsections=on --enum_type=packed --abi=eabi
and the linker flags are
-m"${ProjName}.map" --heap_size=0 --stack_size=512 -i"${INHERITED_LIBRARY_PATH}" -i"C:/ti/wolfssl/tirtos/packages/ti/net/wolfssl/lib" -i"${CG_TOOL_ROOT}/lib" -i"${CG_TOOL_ROOT}/include" --priority --reread_libs --diag_wrap=off --display_error_number --warn_sections --xml_link_info="${ProjName}_linkInfo.xml" --rom_model
these are the default linker flags and I added --lto and notice that the code size is reduced in both cases no-library and library versions.
after that, I noticed the final .out file generated by the compiler increased by twice the static library size with optimization set to level 2 for Static Library and main code
I checked the map file in both versions(no-library and with library versions) and found that my module in the library version had a file (XXX_Patterns.c) that had taken much size than usual (I mean than no-library version), so from this comparison, I noticed that this file had many static structures with #pragma allocating them to static SRAM cause my MCU has an EPI peripheral, so I used external memory (SRAM),
XXX_Patterns.c file is like
#pragma DATA_SECTION(objColor1, ".xram3");
static XXX_ColorType objColor1[XX_MAX_NUMBER];
#pragma DATA_SECTION(objColor2, ".xram3");
static XXX_ColorType2 objColor2;
static INT32U u32Count;
static INT32U u32MaxLoops;
static void XXX_func1(void);
static void XXX_func2(void);
...
so, How to eliminate that size difference between the no-library and library versions because the two examples I mentioned have the same functionality(the one with the library separated and the one that is not-separated)?
the problem was in compiler flags as it needs to separate each subsection of functions into a separate block obj so while the ".out" is generated it should link only the used sections in the main object file that is going to be linked so as you can see in the image below just enable this option and the code size would be the same as no-library version.

Linking FFTW to matlab using minGW

My goal is to mex come c code which uses the library FFTW.
#include <matrix.h>
#include <mex.h>
#include "C:\Users\my_user_name\Documents\fftw-3.3.5-dll64\fftw3.h"
void mexFunction ( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i, j, bw, bw2_1, size, size2_1, nrow, ncol;
int data_is_real;
int cutoff;
int rank, howmany_rank;
double *rresult, *iresult, *rdata, *idata;
double *workspace, *weights;
fftw_plan dctPlan;
fftw_plan fftPlan;
fftw_iodim dims[1], howmany_dims[1];
bw = 2;
weights = (double *)malloc(sizeof(double) * 4 * bw);
rdata = (double *)malloc(sizeof(double) * 5 * bw);
dctPlan = fftw_plan_r2r_1d(2 * bw, weights, rdata, FFTW_REDFT10, FFTW_ESTIMATE);
}
I'm currently using minGW and not Visual C++. If (from Matlab) I call
>>mex -c -LC:\Users\my_user_name\Documents\fftw-3.3.5-dll64 demo_fftw.c
it compiles correctly, but running
>> mex -LC:\Users\my_user_name\Documents\fftw-3.3.5-dll64 demo_fftw.c
Building with 'MinGW64 Compiler (C)'.
Error using mex C:\Users\MPUTHA~1\AppData\Local\Temp\mex_200676192178726_4216\demo_fftw.obj:demo_fftw.c:(.text+0x40):undefined reference to `__imp_fftw_plan_r2r_1d'collect2.exe: error: ld returned 1 exit status
I think that the error is because although fftw_plan_r2r_1d is declared in fftw3.h, it is defined somewhere else where the linker can't find it. I know that if I'm using Visual C++, then the .lib files contain the definitions, but the the README only tells you to compile the lib's if you are using Visual C++, and says nothing about using mingw.
What's the equivalent of a .lib file for mingw? Do I still need .lib's? If so, how do I compile them?
I apologize if this question is a duplicate, but I've looked around a bit and find lots of advice that works if you are using visual C++, but none concerning mingw.
You already made it possible for the compiler to see the FFTW include header file.
Now, you need to link with the actual FFTW code.
Fortunately, FFTW creators are merciful for Windows users and provided pre-built distros available here: http://www.fftw.org/install/windows.html
We have created precompiled DLL files for FFTW 3.3.5 in single/double/long-double precision, along with the associated test programs. We hope that these are sufficient for most users, so that you need not worry about compiling FFTW
These DLLs were created by us, cross-compiled from GNU/Linux using MinGW; the 64-bit version is possible thanks to the mingw-w64 project. You should be able to call them from any compiler.
So MinGW is fine. In your case I would do (untested):
mex -LC:\Users\my_user_name\Documents\fftw-3.3.5-dll64 demo_fftw.c libfftw3-3.dll

C code structure evokes linking cycles with CMake

I am trying to build bozorth3 from NIST Biometric Image Software using CMake but having troubles with the linking. This software has on the one side an executable:
//bin/bozorth3.c:
int min_comp_minutiae = MIN_COMP_BOZORTH_MINUTIAE; // defines what libbozorth needs
//...
getopt_spec = malloc_or_exit( (int)strlen(default_getopt_spec) + 1,
"getopt() string" ); // uses a function from libbozorth
...on the other side a library:
//lib/bozorth3.c:
if ( pstruct->nrows < min_computable_minutiae ) { //uses a variable defined in bin
//lib/bz_alloc.c:
char * malloc_or_exit( int nbytes,
const char * what ) { // implements a function used in bin
//code
}
...and a common header:
//include/bozorth3.h
extern int min_comp_minutiae;
extern char *malloc_or_exit(int, const char *);
With the following filesets (exceprt from CMakeLists.txt)
set(LIB_SOURCE_FILES
src/lib/bozorth3/bozorth3.c
src/lib/bozorth3/bz_alloc.c #[[etc...]])
add_library(libbozorth3 ${LIB_SOURCE_FILES})
add_executable(bozorth3 src/bin/bozorth3/bozorth3.c)
Since the executable uses the library I have to add a link: target_link_libraries(bozorth3 libbozorth3). But this is results in an error:
Linking C shared library ..\..\bin\liblibbozorth3.dll
CMakeFiles\libbozorth3.dir/objects.a(bozorth3.c.obj):bozorth3.c:(.rdata$.refptr.min_computable_minutiae[.refptr.min_computable_minutiae]+0x0): undefined reference to `min_computable_minutiae'
It forces me to create a link vice-versa: target_link_libraries(libbozorth3 bozorth3) and overriding ENABLE_EXPORTS, which of course results in an error as well:
Linking C executable ..\..\bin\bozorth3.exe
CMakeFiles\bozorth3.dir/objects.a(bozorth3.c.obj): In function `main':
D:/git/ba-phmf/NBIS/bozorth3/src/bin/bozorth3/bozorth3.c:174: undefined reference to `malloc_or_exit'
And I cant have both because it obviously results in a cycle:
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
"libbozorth3" of type SHARED_LIBRARY
depends on "bozorth3" (weak)
"bozorth3" of type EXECUTABLE
depends on "libbozorth3" (weak)
At least one of these targets is not a STATIC_LIBRARY. Cyclic dependencies are allowed only among static libraries.
I can compile the package using the original makefiles but need to "translate" it into CMake in order to have integration into my project. I tried to analyze the makefiles but couldn't find a solution. The whole package can be found at github.
I am using CLion 2016.2.3, CMake 3.7.0-rc2, Msys2 20160921 with GCC 6.2.0 and ld 2.27 on Windows 7 Professional N x64
Solved it like this:
add_library(libbozorth3 STATIC ${LIB_SOURCE_FILES})
set_property(TARGET libbozorth3 PROPERTY OUTPUT_NAME bozorth3)
target_include_directories(libbozorth3 PRIVATE
include)
add_executable(bozorth3 ${BIN_SOURCE_FILEs})
target_include_directories(bozorth3 PRIVATE
include)
target_link_libraries(bozorth3
PRIVATE
libbozorth3
commonnbis)

Compiling library version into .so file

I have a C linux API library that I distribute both to end users and to servers. When a user needs to use this library, they compile and build a .so file that they send to our servers to be run. I would like a way to compile in the version number of the library into their .so file such that my server can check what version they compiled on. This way if the server is incompatible with the user's .so file, I can refuse to load the library. I'm not sure what options I even have to achieve this and was hoping for any type of suggestion. Please let me know if any more information would be helpful in solving this issue.
It's common for libraries to have a getLibraryVersion function that returns some constant value, be it a string, integer, or whatever. This would get you the version you linked against (i.e. your .so version). You could have an additional macro to get the version you compiled against (i.e. your server's version).
For example, SDL's API has a version struct and the following function defined in one of its headers:
#define SDL_MAJOR_VERSION 1
#define SDL_MINOR_VERSION 2
#define SDL_PATCHLEVEL 15
typedef struct SDL_version {
Uint8 major;
Uint8 minor;
Uint8 patch;
} SDL_version;
/**
* This macro can be used to fill a version structure with the compile-time
* version of the SDL library.
*/
#define SDL_VERSION(X) \
{ \
(X)->major = SDL_MAJOR_VERSION; \
(X)->minor = SDL_MINOR_VERSION; \
(X)->patch = SDL_PATCHLEVEL; \
}
/**
* Use this function to get the version of SDL that is linked against
* your program.
*/
extern void SDL_GetVersion(SDL_version* ver);
In one of your .so's .c files:
void SDL_GetVersion(SDL_version* ver)
{
SDL_VERSION(ver);
}
Example use:
SDL_version compiled;
SDL_version linked;
SDL_VERSION(&compiled);
SDL_GetVersion(&linked);
printf("We compiled against SDL version %d.%d.%d ...\n",
compiled.major, compiled.minor, compiled.patch);
printf("We are linking against SDL version %d.%d.%d.\n",
linked.major, linked.minor, linked.patch);
On a side note; it's a little dangerous to be running somebody else's code on your servers.

Can't compile multiple files for Arduino

I'm having an issue with compiling code for Arduino if the code is in multiple files. What I have been doing in the past is have a script concatenate the files in another directory and make the project there. I would like to be able to compile directly from my build folder without having to jump through hoops of making sure everything is defined in the right order, etc.
I'm using avrdude to compile from Linux command line, because the Arduino IDE doesn't work very well with my window manager. When I make with multiple files (with appropriate #include statements, I get errors of the following nature, but for all of my methods and variables.
./../lib/motor.ino:3:21: error: redefinition of ‘const long unsigned int MOVE_DELAY’
./../lib/motor.ino:3:21: error: ‘const long unsigned int MOVE_DELAY’ previously defined here
The only other place that MOVE_DELAY is used is inside the void loop() function, and it doesn't redefine it there. The code also compiles fine if concatenate it into one file and run make in that directory, but not if they are in separate files with includes.
I believe your problem is solvable by declaring the objects with the "extern" prefix or external. For example. I often use the SdFat library, in which it is included in both my main sketch and instanced in other libraries.
/**
* \file test.ino
*/
#include <SdFat.h>
#include <foo.h>
SdFat sd;
...
Where I also use the same object in other libraries, such as foo.h.
/**
* \file foo.h
*/
#include <SdFat.h>
extern SdFat sd;
...
If it was not for the prefix of "extern" it would error like yours, as "sd" can not exist twice. Where the extern prefix tells the linker don't make a new instantiation, rather link to the externally instance elsewhere.

Resources