How to make a program run on other computers?

2.2k views Asked by At

I made a game using c++ and Allegro 5, it runs fine on my pc with Linux. I would like to know how to create a package that I could export to another Linux computer, and make it run without installing Allegro. Thanks

2

There are 2 answers

0
rcorre On

I had to figure this out a while ago, what follows is a guide based on the steps that worked for me. There may very well be a "better" way to statically link to allegro.

To start with, you'll need the static libraries for allegro. If your distro doesn't package these, you'll have to build them yourself:

  1. Clone the source code (lets say you clone it into a directory named allegro).
  2. Create a build directory: cd allegro && mkdir build && cd build
  3. cmake .. -DSHARED=off. This specifies that we want static (not shared) libraries
  4. make
  5. You should now see libraries ending with a .a extension under lib in your build directory.

Now you can link to the static libraries like so:

gcc main.c -o main -Lpath/to/allegro/build/lib -lallegro-static

Unless you install the static libraries in your standard library path (e.g. /usr/lib) you need the -L argument to provide the linker with a path to the static libraries you just built.

If you just try the above, you will notice a number of linker errors to other libraries. When linking statically, you will need to manually specify linker flags to allegro's dependencies. To be honest, I don't remember why this is, but I just know I have to do it.

To determine these dependencies, try building your program once with the shared libraries:

gcc main.c -o main -lallegro

Then run ldd on the resulting binary (main). You should see something like:

linux-vdso.so.1 (0x00007fff1dbfd000)
liballegro.so.5.2 => /usr/lib/liballegro.so.5.2 (0x00007f8b802ea000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f8b7ff4c000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f8b7fc48000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f8b7fa2b000)
...
libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f8b7c551000)

Translating each of these into linker flags, your final command will look like:

gcc main.c -o main -lallegro -lm -lpthread -lX11 ...

You will notice you don't have to link to everything in the output of ldd, you can play with it to find a minimal set of linker flags you need. You will need more linker flags if you are linking to additional modules. For example, linking to lallegro_audio-static will require flags like -lpng to link to the PNG library.

Eventually, you will find a set of flags that lets you link statically to allegro. To check the result, run ldd on your statically-linked binary; you should notice that allegro is no longer included in the output, as users will no longer need to link dynamically to allegro.

0
Katastic Voyage On

The answer for Allegro is the same for any library. It doesn't do anything special. The previous poster's answer goes into implementation details, so I'll hit it from a 10,000-ft perspective:

You have three options for ANY library.

  • Compile the library statically.

  • Compile the library "dynamically", and ship the Allegro library files with your program. (*.DLL for Windows, *.SO "shared object" file for Linux.) The files go in the same directory as the binary you're executing.

  • Compile the library "dynamically", same as before, but rely on the library being already installed on the system in a system directory. (windows\system32, for example)

In the first case, the library code is physically added into your program.

The second case and third case are identical except what you package with it. Your program is compiled (but without the Allegro library code included) and told it will "find" the library once it is run. On startup, the run-time linker (LD in Linux, run man ld for more info) takes your code's list of required symbols (external functions and global variables), checks for suitable matching libraries in your starting directory, if not, checks other system directories.

The second case puts the required files with your program.

The third case relies on the required files being already installed, or, shipping with an external "run-time distribution" installer which Microsoft very often does. (DirectX runtimes, Visual C++ runtimes, etc.)

So since you're targeting Linux, you can either use the first or second cases. Compile your specific version of Allegro into your code, or, ship the version you want with your code. The advantages to the second case, are that you can change the DLLs/SO files at a later date without necessarily compiling (for a patch/bugfix), and if you have multiple executables, you only need ONE set of library code.

It should be noted that not all libraries allow you (because of their license) to include the binaries inside your program. That's why you'll often see the "Microsoft Redistributables." However, Allegro's license does not care.