0

I had the following folder structure:

include/
src/
data/
binary-file
makefile

I would execute the binary like so: ./binary-file

But now I want my binary in it's own folder like so:

bin/ <- binary-file is in here now
include/
src/
data/
makefile

Everything goes fine when I execute it from the main folder like so: bin/binary-file

But if I am in another folder other than the main folder, the program will be ill-behaved and will not be able to locate the paths to #include's. For example, if I were in the bin/ folder, the program will be ill-behaved if I execute it like so: ./binary-file

My question is: How can I tell my makefile or binary file to execute like it was in the main folder, from anywhere on my system?

In my makefile, all I changed was:

$(CC) $(CFLAGS) -I$(IDIR) -I$(BDIR) -I$(DDIR) -o $(PROG) $^ $(LFLAGS)

to

$(CC) $(CFLAGS) -I$(IDIR) -I$(BDIR) -I$(DDIR) -o $(BDIR)/$(PROG) $^ $(LFLAGS)
brandonto
  • 125
  • 2
  • 10
  • 3
    Your makefile/compilation has nothing to do with this. Your binary needs to be able to find its data files either via absolute paths or via relative paths from its known directory structure. – Etan Reisner Feb 16 '15 at 18:47
  • @EtanReisner Does that mean I have to change all my #include "file.h" into #include "../file.h"? – brandonto Feb 16 '15 at 18:50
  • 2
    Those paths are used by the compiler not your binary. And no, those should be fine with those `-I` arguments assuming `IDIR` is a path to your `include` directory. – Etan Reisner Feb 16 '15 at 18:51
  • 3
    Once your program is compiled into the executable, the include files (those you include with `#include file.h` are totally meaningless. I strongly suspect you are confusing things. Are you confusing execution of the result of compilation or the execution of `make` to build the final product? – thurizas Feb 16 '15 at 18:53
  • @thurizas I have some data in my DDIR that my binary uses ("data/xml/file.xml"). When I execute the binary from the main folder: /bin/binary-file, everything works. But when I execute the binary file from the /bin/ folder: ./binary-file, it is unable to load "data/xml/file.xml". – brandonto Feb 16 '15 at 18:58

3 Answers3

1

Your data file name needs to be "../data/xml/file.xml".

The "../" is a relative path meaning "one folder back". "../../etc" would mean two folders back.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • I've tried to make the paths relative, to no avail. The current directory changes depending on where you are executing the file from: bin/SpaceShooter argc = 1 argv[0] = bin/SpaceShooter dirname(argv[0]) = bin and ./SpaceShooter argc = 1 argv[0] = ./SpaceShooter dirname(argv[0]) = . – brandonto Feb 16 '15 at 19:54
  • So, you changed the question and the executable is now somewhere else. Your path has to be either relative, absolute, or on a predefined default path, although that usually applies to executables, not data. – Weather Vane Feb 16 '15 at 20:01
  • No, the binary-file is still in the bin/ folder. But now I am not in the bin/ folder when executing the binary-file. My original question was how to make it so that you could execute the binary-file from anywhere on my system, regardless or which directory you are in when you type pwd. – brandonto Feb 16 '15 at 20:15
  • here is a clearer question if you wanted to submit an answer: http://stackoverflow.com/questions/28549606/relative-paths-from-binary-file – brandonto Feb 16 '15 at 20:25
1

Probably you are asking a wrong question: the build system has nothing to do with program execution.

However, if you look for an answer, how to make my program to correctly use data, that is located relative to program installation, than here is an answer.

When you program main gets executed, it gets the binary path as the first parameter (index 0). That path can be relative or absolute, but in any case it allows you to find the base directory.

These are also useful links:

Here how you can use first argument:

#include <linux/limits.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>

int main(int argc, char *argv[])
{
  char datadir[PATH_MAX];
  strncpy(datadir, argv[0], sizeof(datadir));
  dirname(datadir);
  strncat(datadir, "/../data", sizeof(datadir));

  printf("Data dir: %s\n", datadir);

  return 0;
}

The program assumes the following deployment:

ROOT <- Can be anywhere on file system
+--bin
|  +--- <- application is here...
+--data
   +--- <- Data files are located here...
Community
  • 1
  • 1
Valeri Atamaniouk
  • 5,125
  • 2
  • 16
  • 18
  • I've tried to make the paths relative, to no avail. argv[0] changes depending on where you are executing the file from: bin/SpaceShooter argc = 1 argv[0] = bin/SpaceShooter dirname(argv[0]) = bin and ./SpaceShooter argc = 1 argv[0] = ./SpaceShooter dirname(argv[0]) = . – brandonto Feb 16 '15 at 19:52
  • here is a clearer question if you wanted to submit an answer: http://stackoverflow.com/questions/28549606/relative-paths-from-binary-file – brandonto Feb 16 '15 at 20:23
1

OK, based on your most recent commnet

@thurizas I have some data in my DDIR that my binary uses ("data/xml/file.xml"). When I execute the binary from the main folder: /bin/binary-file, everything works. But when I execute the binary file from the /bin/ folder: ./binary-file, it is unable to load "data/xml/file.xml"

  1. hard code the absolute path to the data files (say something like /home/brandonto/projects/data/xml/file.xml .... assuming a *nix type file system). Obviously the plus is that regardless of where you executable is located it can find the data files. The down side, is that if you ever move the binary it will stop working.

  2. Add a command line option to set the data-path. For example, suppose that you choose that the default location for your applications data-files will be /usr/share/brandonto/myapp/data, which you can hard code into your application. Now allow the user to use command line arguments to adjust where the files are found. Your logic would be if the command line argument is given use it, otherwise use the default location. The plus side is that you can execute from any where, users can move stuff around to suit their personal preferences, and you can have two set of data files if you want (say one for testing and one for production). The downside, your program becomes a little bit more complex, and if the uses does move the data-files to someplace unusual the is going to have to type more every time he launches the application. So for example;

    ./myapp   -- would use the default location for the data files
    ./myapp -f <somepath> -- would use the files in <somepath> over ridding the default
    

There are some other options like a configuration file (which gets us back to something very similar to your initial question :) )

thurizas
  • 2,473
  • 1
  • 14
  • 15