Solution to most not-found or undefined problems in C/C++ compilation

Many people have compilation errors. If you search "undefined reference to" in Google, or maybe StackOverflow alone, you will notice that those problems have been asked dozens if not hundreds of times. There are generally 4 problems:
  • was not declared in this scope
  • no such a file or directory
  • undefined reference to
  • error while loading shared library, or cannot open shared object file

The thing is actually very simple: the compiler is not told to find the right file at the right place. The discussion below is based on Linux using GCC for C and C++.

Problem 1: was not declared in this scope

Usually, this problem has nothing to do with your system settings or compiler configuration. It's a problem within your source code. On the top level, the function is not defined. The reason can vary.

One reason is that the file declaring (or defining, if the declaration is done together with definition) the functions is not specified, e.g., the header file is not included. This can be easily fixed by including such a file in your source code.

Another reason is that you used the function beyond its class or namespace.

Problem 2: No such a file or directory for a header file


If a header file is not found, the preprocessor or the preprocessor part of the compiler, will raise the error No such a file or directory. Depends on where the header files are supposed to be at, there are different solutions.

Most C/C++ compiles treat the quote form of #include and angle-bracket form of #include differently. Simply running
$ echo | gcc -E -Wp,-v -
will tell you the difference:
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

Those directories listed under the section #include <...> search starts here: are referred to as standard system directories [1]. They are from the convention of Linux systems' file hierarchy.

If you want to expand the search for angle-bracket form #include<...>, use the -I option. The preprocessor will search header files in directories followed by -I option before searching system directories. Hence, a header file in a -I-option directory will override its counterpart in system directories and be used to compile your code.

For quote form #include"...", the preprocessor will first search in the current directory that the source file is at and then all the directories specified after the -iquote option.

The example below will show you how -I and -iquote append search paths:
l$ echo | gcc -iquote/home/forrest/Downloads -I/home/forrest/Dropbox -E -Wp,-v -
#include "..." search starts here:
 /home/forrest/Downloads
#include <...> search starts here:
 /home/forrest/Dropbox
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

So, if you have the following macro in your code called mycode.c:
#include < xyz.h>
#include "abc/xyz.h"
and your GCC command is like this
gcc mycode.c -I/opq/ -iquote/uvw
then the GCC's preprocessor (again, it's part of the GCC) will look for header files in the following full paths (on Ubuntu Linux 16.04) in addition to the search in system directories:
/opq/xyz.h
 /uvw/abc/xyz.h
According to GCC document[1], it searches for header files in quote form #include"..." before searching for angle-bracket form #include"...".

Further specifications can be achieved using two other options -isystem and -idirafter. They are all well documented in GCC document[2].

Problem 3: Undefined reference to

You probably see an error like this
face.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x4b): undefined reference to `cv::Mat::deallocate()'
collect2: error: ld returned 1 exit status
This is a link-time error when the linker ld, which is called automatically when you use GCC, cannot find the binary library that contains at least one function called by your code.

To fix, first tell the compiler (actually it's linker part) the path containing library files using the -L option [2] and then library file names using the -l option [4]. If we denote the values after -l and -L options as X and Y respectively, the compiler will search for every file called libY.so under every directory X. That's why on (almost) all Linux systems, a shared library file begins with lib and ends with the appendix .so, such as libopencv_core.so.

For example, the command
$ g++ face.cpp -L/opencv/lib -lopencv_core -lopencv_videoio
will ask the linker to find the following binary library files:
/opencv/lib/libopencv_core.so
/opencv/lib/libopencv_videoio.so

Note that you may not be able to use some shell directives, such as ~ after the -L option.

In most cases, you do not need to use the -L and -l options because the compiler (again, its linker part) automatically searches in a set of system directories. When you have to, some tools can help you, such as pkg-config. I will write another blog post.

Problem 4: error while loading shared libraries or cannot open shared object file


Now, your program has been successfully compiled. When running it, you probably see an error like this:
./a.out: error while loading shared libraries: libopencv_core.so.3.3: cannot open shared object file: No such file or directory 
This problem is from the loader. Unlike the link-time error above, this problem is a run-time error. The shared library filenames are usually hardcoded into your binary program. To fix it, simply tell the loader where to find the specified shared library files. There are multiple ways.

Solution 1: Most Linux systems maintain an environment variable LD_LIBRARY_PATH and the loader will search for binary library files requested by a program in all directories listed in LD_LIBRARY_PATH, on top of a set of standard system directories, such as /lib or /usr/lib. To set LD_LIBRARY_PATH is like how you set any other environment variables, e.g., export on the Shell or edit and source ~/.bashrc.

Solution 2: Most Linux systems also maintains a shared library cache by a program called ld-config. It remembers where to find the default location of each shared library file. Simply run
$ ldconfig -p
it will tell you the mapping from shared library files to absolute paths in the system, e.g.,
2591 libs found in cache `/etc/ld.so.cache'
 libzzipwrap-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipwrap-0.so.13
 libzzipmmapped-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipmmapped-0.so.13
 libzzipfseeko-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipfseeko-0.so.13

To change the mapping, simply edit /etc/ld.so.conf and then run
$ sudo ldconfig
to rebuild the cache.

Solution 3: The two changes above are applied system-wide. A more flexible way is to specify the location of the shared libraries when linking your code using the
-Wl,-rpath
option, e.g.,
g++ face.cpp -idirafter ~/Downloads/opencv_TBB_install/include -L/home/forrest/Downloads/opencv_TBB_install/lib -lopencv_core -lopencv_objdetect -lopencv_highgui -lopencv_imgproc -lopencv_videoio -Wl,-rpath=/home/forrest/Downloads/opencv_TBB_install/lib

The disadvantage of Solution 3 is that if you change the location of the shared library, then you will run into error again.


References:
[1] Filesystem Hierarchy, https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] GCC options for directories https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html
[3] Shared Library How-To, http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
[4] GCC options for linking, https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

The correct dimensions of Hitec C1 spline

The C1 spline of 24 teeth is the standard shaft size for Hitec's servo motors, which are quite popular in maker community. Recently, I needed to design some parts that fits with it. However, finding it's accurate inner (basic) and outer (tip or addendum) diameters is very difficult. I don't know why this company does not simply release a drawing of it.

Some info floating on the Internet is not really accurate, such as this one: www.robotshop.com/blog/en/hobby-robot-industry-standards-hubs-patterns-18681

In the end, I reverse engineered from a design shared on GrabCAD and get the dimensions that work: https://grabcad.com/library/servo-horn-with-c1-spline-1

Here we go:
  • Inner radius: 2.520 mm
  • Outer radius: 2.845 mm. 
If you wanna 3D print an inner gear (a.k.a., annular gear) that fits with C1 spline, be sure to take the error or expansion that 3D printing can produce into consideration. In my case, I increased both inner and outer radii by 0.15 mm to 2.670 and 2.995mm respectively. 

Creating an arbitrary surface or any geometric element in FreeCAD

Creating an arbitrary geometric element, such as a surface or a polygon, is a task common in CAD.

FreeCAD provides two ways to do so in its Part module.

The first approach is called Create Primitives, where you specify the parameters to define a geometric element. The menu is Part -> CreatePrimitives. See https://www.freecadweb.org/wiki/Part_CreatePrimitives

An example is below.



The second approach is called Shape Builder, where you build a new shape from elements defined earlier, such as creating a face from edges or vertexes. The menu is Part -> Shapebuilder. See https://www.freecadweb.org/wiki/Part_Shapebuilder

A good reference of all functions that Part module provides can be found here https://www.freecadweb.org/wiki/Part_Module

Population of Northeast Ohio

Let's just look at some data of the population of northeast Ohio (NEO).

This is what the population distribution in NEO looks like:




In contrast, this is what the overall US population distribution looks like:




NEO is older than the other two big metros in Ohio, Cincinnati and Columbus:







This is what Dallas looks like:




The average ages in Cleveland, Cincinnati, and Columbus are: 41.1, 37.9, and 35.7. As a comparison, the average age of Dallas is 34.2. Cleveland population is 7 years older than that of Dallas.

The fertility rate of Cleveland, Cincinnati, and Columbus are: 4.8%, 5.2%, and 5.4%. As a comparison, the fertility rate of Dallas is 5.4%.

Hence, NEO has fewer women at birth age (15 to 50) than the national average and its fertility rate is under national average. The result? Fewer babies.

Bowtie index building problem for U's in sequences

I am having a weird problem with Bowtie index builder.

I have two entries in my FASTA file:
forrest@narnia:/bioinfo/out-house/miRBase$ cat 157.fa
>ath-miR157a-5p-U
UUGACAGAAGAUAGAGAGCAC
>ath-miR157a-5p_T
TTGACAGAAGATAGAGAGCAC

After building the index, I use bowtie-inspector to check the index.
forrest@narnia:/bioinfo/out-house/miRBase$ bowtie-build 157.fa  157 -q
forrest@narnia:/bioinfo/out-house/miRBase$ bowtie-inspect -s 157
Colorspace 0
SA-Sample 1 in 32
FTab-Chars 10
Sequence-1 ath-miR157a-5p-U 18
Sequence-2 ath-miR157a-5p_T 21

Strangely, the length of ath-miR157a-5p-U becomes 18 instead of 21. The 3 U's of it are missed.

Even more strangely, not all U's in all sequences are ignored. This problem happens for some but not all.