How to make a library in c++ in linux - c++

I am writing a small application in c++ and I have some questions regarding that. I am basically a Java developer now moving into c++.
If I use some library like boost, curl etc. can I make it run without installing that on the client machine (I mean something like including all library jar files inside the project in Java)
I have installed some library or software in linux. After that if I type in the terminal it pings the software. For example php, after you install it you can use php from terminal. How does this work? Can I use my simple c++ project to do so?

Yes. You use a process called static linking, which links all the libraries into one big executable. In ./configure scripts (from autotools), you use the --enable-static flag. When building your program, you use the -static flag. The static libraries are the ones with the .a suffixes; shared libraries use .so, sometimes with a version number suffix).
PHP is not a library, it is a language (i.e. executable) which provides its own command-line interface. Your C++ executable can work similarly, you just have to get the input from cin (in <iostream>) and write results to cout, using cerr for error messages.
Your title question, "How to make a library in c++ in linux" (as opposed to using a library): You use the ar program to link several .o files into a single .a library file. You can also use ranlib to clean up the .a file. Read the man pages for those commands to see how they are used.

1)Answer to your Q1 is compilation with libraries statically linked. For example with gcc Compiler:
# gcc -static myfile.c -o myfile
2)Answer to you Q2 is appending the absolute path of executable to $PATH Environment Variable. For example in Bash shell:
# export PATH=${PATH}:/home/user/pathofexecutable
The above setup will be temporary only for that terminal you do. To make it available to all terminal in you machine add the above export command to /home/user/.bashrc file.

For question 1, you want to compile the program as a static executable. (Just pass -static to g++.) It will make the program much larger since it needs to include a copy of stuff normally kept as libraries.
For question 2 I'm pretty sure what you mean is having a program in the PATH. Type echo $PATH to see the path on your current machine. If you install your program in one of those directories it will run from anywhere. (Most likely /usr/local/bin/)

Related

Haxe - Create a C++ Stand-alone executable

I have written a haxe program that tries to communicate with a remote server. I was able to compile to the C++ target successfully. The executable runs just fine on my system. However, when I try to run the same on another windows box, it fails with the following error
Error: Could not load module std#socket_init__0
I then installed haxe and hxcpp which worked like a charm. I was able to run the exe. I understand now that there is dependency on hxcpp.
That still did not solve my problem as I want to create a stand-alone application. After some research I found a file (ExampleMain.CPP) with the following instructions that I think might solve my problem. However, I am a novice and do not quite follow. Can some one walk me through with this? Thanks
ExampleMain.CPP
This is an example mainline that can be used to link a static version.
First you need to build the static version of the standard libs, with:
cd $HXCPP/runtime
haxelib run hxcpp BuildLibs.xml -Dstatic_link
Then the static verion of your application with (note: extra space before 'static_link'):
haxe -main YourMain -cpp cpp -D static_link
You then need to link the above libraries with this (or a modified version) main.
You may choose to create a VisualStudio project, and add the libraries from
$HXCPP/bin/Windows/(std,regexp,zlib).lib and your application library.
Note also, that if you compile with the -debug flag, your library will have a different name.
Linking from the command line for windows (user32.lib only required for debug version):
cl ExampleMain.cpp cpp/YourMain.lib $HXCPP/bin/Windows/std.lib $HXCPP/bin/Windows/zlib.lib $HXCPP/bin/Windows/regexp.lib user32.lib
From other OSs, the compile+link command will be different. Here is one for mac:
g++ ExampleMain.cpp cpp/Test-debug.a $HXCPP/bin/Mac/regexp.a $HXCPP/bin/Mac/std.a $HXCPP/bin/Mac/zlib.a
If you wish to add other static libraries besides these 3 (eg, nme) you will
need to compile these with the "-Dstatic_link" flag too, and call their "register_prims"
init call. The inclusion of the extra static library will require the library
in the link line, and may requires additional dependencies to be linked.
Also note, that there may be licensing implications with static linking
thirdparty libraries.
I'm not sure, but it seems that you are taking the same extra steps hxcpp does for you already. When you compile your standalone application it is actually standalone and doesn't have a dependency on hxcpp per se - but it has a dependency on the standard libraries within hxcpp you may have used. For instance, if you use regular expressions, you will need the regexp.dll that hxcpp has for it, as you noted. The haxe standard library is in the std.dll and the zlib is if you used compression from the zip packages.
If I am not mistaken, the default is to reference these components dynamically. In order for your application to be standalone as you suggest, you simply have to copy these dll's alongside your binary.
If you want to link to these library components statically, automatically from your haxe code, just import the types from the cpp.link package. This instructs hxcpp to automatically bring its libraries as part of the compilation, linking it statically into your binary instead of dynamically. No extra steps are necessary!
Short answer: add import cpp.link.StaticStd; and any other library components in the link package somewhere to your code. It can be anywhere as long as it's imported, it will be linked in.

How can I compile a C++ project (with g++) to use on other computers?

This may be obvious, but I want to make sure what to do before I do anything rash. I want to compile my C++ program, libraries and all, to a release executable such that the file can be run on any computer (running the same OS). Right now, I'm on Mac OS X (10.7.4) and I need to be able to run my executable on other Macs. The problem is I am using the OpenCV library in my project, and I only have it installed on this computer. Is there a way to compile with g++ such that if I open this program on a computer that doesn't have the OpenCV library installed, it will work anyway? As in, build all the dependencies into the executable. Or does this happen automatically?
I am also quite new to the ".o" object files, so can those have anything to do with it? I would prefer a way to get it all into a single file, but I'll settle for a package as long as it works.
Thank you.
To expand on molbdnilo's answer, you'll need to create an application bundle (see the Apple Bundle Programming guide). You'll need to move your console application to MyApp.app/Contents/MacOS/MyApp. There's also a Frameworks directory in which you'll need to add the OpenCV library as a framework. See the OpenCV Wiki for some information on the OpenCV framework. A framework (at its simplest) is pretty much a dynamic library wrapped in a particular directory structure.
I would suggest looking into using Xcode on the mac as it simplifies the construction of bundles and linking to frameworks compared to doing it yourself via scripting and Makefiles.
There are two ways to do this. You can static link if you aren't going to run into licensing issues with any of the libraries you are linking to. This is pretty easily handled by using g++ -o myApp -static -lopencv myapp.cpp However, this also depends on static libraries existing for the libraries you want to link to. Most distribute static libs with the shared libs these days.
The other way is to distribute the shared libraries and tell your application to force it to look in a certain spot for the shared library using -rpath. Note: I am telling you the Linux way to do this, it will probably work on a Mac but I have no way to test.
So say all of your shared libraries are in the same directory as your executable, you can compile with: g++ -rpath ./ -lopencv -o YourApp yourApp.cpp
I hope this helps.

Using 3rd Party Libraries in C++

I'm totally spinning my wheels with getting a couple of 3rd party libraries to work with my c++ programs. I'm looking for some general advice (40,000 foot level) about the general steps that one needs to take when implementing libraries.
First, some specifics: I am using code::blocks in Windows as my IDE. I like this IDE and really don't want to switch to anything else if I don't have to (I've tried visual c++ and also some things in linux). The libraries that I am trying to use are GMP and crypto++.
OK. What I think I know is this: After downloading the library, I unzip the file to a folder. I've been unzipping directly to C:\ with each zip file extracted to its own folder (e.g. c:\cryptopp and c:\gmp). I think that the next step is to build the library, but this is where I get totally stuck. How is this done? There are no executable files among those extracted. From what I can tell, I believe that I do this in code::blocks, but I have no idea how?
Finally, assuming that I can get this done, which I believe creates the .lib files, the last step before actually using the library in my code, is to link into the library. This part, I believe that I understand.
So, my question is broad: do I understand this process overall? And if so, how do I go about building these libraries, if in fact that it the thing that I am missing.
Thanks very much for indulging my ignorance. I'm totally rudderless right now and despite hours and hours on google, I'm making no progress. Also, feel free to correct anything that I have stated as fact that is not correct. Thanks a lot!
Usually libraries have a special file called makefile in them, and are built with a utility called Make (or one of it's variations, whatever works uder windows).
Usually all you have to do is to run Make in the directory where you have unpacked the source files, and it will do the rest itself.
If those libraries you mention (GMP and crypto++; disclaimer: I'm not familiar with either of them) don't have project files for code::blocks then you may still be able to compile them under Windows with MinGW.
If you have installed MinGW you use the MinGW shell to navigate to the appropriate directories which would be /c/cryptopp/ and /c/gmp in your examples - The MinGW shell works like a Unix shell, and has different naming conventions.
Then you need to compile the libraries. Check whether there's a Makefile in those directories, if there isn't you can check whether there's a configure script, which will generate the Makefile. If you have the Makefile you can type make which will compile the libraries with MinGW's port of the GCC compiler.
When the compilation is complete you should have a library in the form of a .a file (say libcryptopp.a) that you can link to your project. In code::blocks you would set the linker path (the -L command line option in GCC) to C:\cryptopp\bin or wherever the library has been compiled, and then add libcryptopp.a to the list of libraries you want to link (this is associated with the -l option in GCC). The convention is to leave out the lib prefix and the .a extension, so you would just add cryptopp to your library list. In the end your linker options should look like -LC:\cryptopp\bin -lcryptopp along with the
Also, to be able to use the libraries you need to add the path to the headers directory to the include path of your project. This is associated to the -I command line option in GCC, so your compiler's command line options would have something like -IC:\cryptopp\include somewhere.
Of course, all of the above assumes that you use code::blocks with GCC. If you're using it with VisualC++ then the principles are the same, but the specific steps differ.

Convert .a file to .dll

This question is surely answered here somewhere, but I couldn't find it. I've been writing Java for over a decade now and my C experience was on Unix, so I'm kinda at square one here. In my Unix experience, someone else wrote the makefile and it just worked.
I have downloaded the C source code for libtar-1.2.11 from feep and ran make on it from inside of cygwin. This created a .a file and a .exe file. The EXE file appears to essentially be tar to run on Windows, but what I wanted was for the libraries to read and process the file in my own code.
If I remember correctly, those should be in the .a file (archive??) and this needs to be linked into a library that I can use from my C++ program. So I'm looking for a way to do that.
I am writing a library that will use a .tgz file and so I want to use this library. I think I'd like to turn libtar into a DLL as well as create a DLL myself for use in other languages.
So, how do I turn my .a file into something usable by other apps, and how do I access it from inside my code?
The generated libmylib.a is actually an archive of all *.o for libtar-1.2.11.
you can verify this by doing nm libmylib.a, it will print all the *.o files.
Write your code, and link:
gcc -o my_application my_application.o -lmylib
You generated this with cygwin, you can't generate a dll out of that as far as i know.
Well, a DLL is the equivalent of a shared library in Unix (a .a is a library for static linking, the Windows equivalent being a .LIB file), so you want to build a shared library.
Indeed, when you build as
make LDFLAGS=-shared
the resulting libtar/libtar.exe will actually be a misnamed DLL.
Note, however, that a cygwin-translated DLL is something different from a native Windows DLL and will always depend on Cygwin DLLs (and potentially even an installed Cygwin environment) to run, so if you plan on including it in native Windows code, this is probably not an approach you want to pursue.
May I suggest that you switch from the plenty dead (last release in 2003) libtar to libarchive, which comes with native Windows build instructions?

How to change the library include path of a binary from bash?

I have a software properly installed on Kubuntu.
Now, I am patching and testing some of its libraries.
How can I start the software from bash so that it loads my patched libraries instead of the official libs?
e.g.:
the official libs are locate in /usr/lib/
my patch libraries (used during test development) are in /home/user/dev/lib/
I tried:
$ set LD_LIBRARY_PATH=/home/user/dev/lib/
$ binary_app &
but to no avail.
I'd prefer a solution that can be set from the bash, but if it's not possible, I could also modify the cmake file of this C++ software.
The aim is to allow me to easily start the application either with the vanilla libs, or with my patched libs to see the differences.
Edit: it's a KDE .so file
The library I am testing is a KDE4 library. The official lib is in /usr/lib/kde4/ . In that directory, none of the library start with the lib prefix.
Whether I do:
/lib/ld-linux-x86-64.so.2 --list --library-path PATH EXEC
or
ldd EXEC
The library is not listed at all.
On the other hand, if if move the original library away from /usr/lib/kde4/, the application starts but the corresponding functionality is missing.
Are KDE4 libraries loaded in a specific way? Maybe the variable to set is different...
Edit 2
All the answers are good and useful... unfortunately, it turned out that the problem does not appear to be related to the lib path setting. I'm dealing with a plugin architecture and the .so loading path appears to be hard-coded somewhere in the application. I need to spend more time within the source code to understand what's happening... Thanks and +1 to all.
From 'man bash':
When a simple command other than a builtin or shell function is to
be executed, it is invoked in a
separate execution environment that
consists of the following. Unless
otherwise noted, the values are
inherited from the shell.
[....]
ยท shell variables and functions marked for export, along
with variables exported for the
command, passed in the environment
You need to 'export' a variable if it is to be seen by programs you execute.
However, you can also try the following:
/lib/ld-linux.so.2 --library-path PATH EXECUTABLE
See http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
Try export LD_LIBRARY_PATH=... instead of set.
I already put this in a comment but after thinking about it I think the best way to do this (using a different library just for testing/debugging) is using LD_PRELOAD, see What is the LD_PRELOAD trick?
From the man page:
LD_PRELOAD
A whitespace-separated list of additional, user-specified, ELF shared libraries to be loaded before all others. This can be used to selectively override functions in other shared libraries. For set-user-ID/set-group-ID ELF binaries, only libraries in the standard search directories that are also set-user-ID will be loaded.
Update:
After the updated question it seems the application is using dlopen to open the library using a absolute path. I don't think you can do anything about it. See man dlopen
Update2:
Maybe there is something you can do: you might be able to LD_PRELOAD your own dlopen function which modifies the path to your own library...
Isn't you app setuid or setgid by chance? In this case LD_LIBRARY_PATH will be ignored.
Put everything on one line:
LD_LIBRARY_PATH=foo binary_app&