Showing posts with label Compiler. Show all posts
Showing posts with label Compiler. Show all posts

Thursday, October 25, 2018

Compiling C++ Codes into shared Library and Linking Them


Compiling C++ Codes into shared library and linking them

Let's say you have files print.h and print.cpp, shown below that contains C++ codes you wish to compile as .so (shared object) file and they are stored in ~/demo/lib folder.

#ifndef __PRINT__
#define __PRINT__

#include <iostream>
#include <stdio.h>
void print(const char* p, bool endl = true);

#endif
#include <print.h>

void print(const char* p, bool endl)
{
std::cout << "print: " << p;
if (endl) std::cout << std::endl;
}

You can compile the above code into .o (static library) file with the command

~/demo/g++ -o lib.o -c ./lib/print.cpp

But we want to compile it as .so (shared library) file so we use the command instead

~/demo/g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp

Note that with the above commands, liblib.so and lib.o is created in ~/demo/lib folder upon successful compilation.

Now let's say you have another set of C++ files loop.cpp and loop.h, shown below and you wish to compile them together with another C++ file into an .so file...

#ifndef __LOOP__
#define __LOOP__

#include <iostream>
#include <unistd.h>

class loop
{
public:
loop()
{
std::cout << "loop constructor"<< std::endl;
}
virtual ~loop()
{
std::cout << "loop destructor"<< std::endl;
}

void run(int i, int r);
};

#endif

#include <loop.h>

void loop::run(int i, int r)
{
while(r)
{
sleep(i);
std::cout << "loop..." << std::endl;
r--;
}
}

To compile print.cpp and loop.cpp files into a single .so file, do the command as shown below

~/demo/g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp ./lib/loop.cpp

Now that we have .so file already, let's create a C++ program that will use this shared library and use the function and class it contains.
The C++ file below will be our C++ program. It is stored as main.cpp in ~/demo folder.
It uses print() from print.cpp to print "hello world" and uses loop class to perform a loop of 5 intervals.

#include <iostream>
#include <print.h>
#include <loop.h>

int main()
{
print("hello world");
loop p;
p.run(1,5);
return 0;
}

Let's compile this code and link the shared library with it. The command below shows how to compile it into "run".

g++ -o run main.cpp -L/lib -llib -I./lib -I./

If compile is successful, and executable named 'run' should appear in ~/demo folder. If you execute it, you might encounter an error as shown below. This is because when executing a program that has dependency on a shared library, it needs to know where the library is.

run: error while loading shared libraries: liblib.so: cannot open shared object file: No such file or directory

To fix this, you can do either of the two possible solutions

1. Copy the liblib.so into any folder listed in the system's LD_LIBRARY_PATH environment variable. This is a more consistent solution because you only do this once.

2. add ~/demo/lib folder into LD_LIBRARY_PATH environment variable. You have to keep setting this every time you try to execute your program in a new terminal. To do this, follow the command below:

~/setenv LD_LIBRARY_PATH ~/demo/lib:${LD_LIBRARY_PATH}

Now try to run the program again.

Using Makefile 

You can create a makefile to simplify this process. Copy the code below into ~/demo/makefile

all: so main

so : ./lib/print.cpp ./lib/loop.cpp
g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp ./lib/loop.cpp -I./lib

main : ./lib/liblib.so
g++ -o run main.cpp -L./lib -llib -I./lib -I ./

Then just call 'make' and the whole compiling process will be done.


Linking the Shared Library (.so) in Unison

In this guide, we will link a share library (.so) in a Unison test program and use the functions and classes defined in the shared library.

1. Optional: copy the .so file as well as its .h header files into test program folder

2. After loading test program, open TestTool



3. In the TestTool, select the application library you want to link the .so file. double-click it to open its settings. Below shows that I selected ST_DLOG application library from my test program.



4.  Click on "Compiler and Linker" tab. Click the "Add Path.." button and select the path where the .so file is located.



5. Once done, you will see the path in the "Linker Paths" list box.



6. In the "Linker Flags" list box, click an empty row. then type -L<.so path> -l<.so name w/o lib prefix>. The -l flag lets me specify the filename of the .so file I want to use, but I without the 'lib' prefix and .so extension. My .so file's filename is liblib.so so removing the prefix and extension, it becomes -llib.



7. Click "Include Paths" tab.



8. Click the "Add Path.." button and select the path where the .h file is selected. Once done, you will see the path in the "Include Paths" list box.



9. Add the include file in the application library's source code. Below shows I declared the include on ST_Datalog.cpp. I included the 2 header files from my shared library - loop.h and print.h



10. Somewhere in ST_Datalog.cpp, i called mydemo::print() function which is defined in the shared library.


11. Finally, compile your application library.










Wednesday, November 22, 2017

How To Compile EVXA (cxx_examples) Code In Any Terminal In Unison

Copy the LD_LIBRARY_PATH env parameter on Unison's xterm (Optool>Tools>Xterm) and add it as first line in makefile. Below is example

LD_LIBRARY_PATH=/lib:/usr/lib:/usr/X11R6/lib:/usr/local/lib:/opt/ltx/releases/U4.2.B4/x86_64_linux_2.6.32/customer/lib:/opt/ltx/releases/U4.2.B4/x86_64_linux_2.6.32/customer/lib:/opt/ltx/releases/U4.2.B4/x86_64_linux_2.6.32/lib/VX6/FX1:/opt/ltx/releases/U4.2.B4/x86_64_linux_2.6.32/lib/VX6

CC=/usr/bin/g++

CFLAGS=-m32 -fpermissive -g -Wall -Wno-return-type -Wno-unknown-pragmas -DLINUX_TARGET
LFLAGS=-m32 -lcrypt -lnsl -lm -lrt

Monday, May 1, 2017

How To Compile a C++ Source Code in CentOS

  • Linux (CentOS)
    • g++ <source code>
      • g++ foo.c where foo.c is the source code, output will be a.out
    • g++ -o <output> <source code>
      • g++ -o foo foo.c where foo is executable, and foo.c is the source code