How to call Makefile located in other directory? - linux

I am trying to do this:
I want to call a make (Makefile exists in some other directory, abc path can be used) from a shell script located in a different directory. How do I do this?
Since shell scripting does not allow me to cd into the Makefile directory and execute make, how can I write the shell command (by giving path to the Makefile to be executed) to execute make?

GNU make accepts many options, notably -C to change directory before running, and -f for giving the Makefile to follow.
Combine them appropriately.
Consider using remake to ease debugging (notably with -x) of Makefile related issues. With GNU make version 4 or better, also use make --trace...
You could have your own executable shell script (e.g. in your $HOME/bin/ which would be in your $PATH) which uses both cd and make).
You could consider other build automation tools (ninja perhaps)
Read also P.Miller's paper Recursive Make considered harmful

Related

Program independent of its path

How do developers usually deal with different paths for executable files?
My program is currently in /usr/local/bin and I am wondering how to make it work weather it is in /usr/local/bin or in /usr/bin while being able to access the config files from one of the etc folders (depends on the executable path).
I can't just use relative paths because I need to make it relative to the path of the executable file and even then, it wouldn't be enough because I would need to access /etc weather than /usr/local/etc.
Is there a common way to deal with this situation? Is it dealt with during the installation? Do I need to make a different version of my program for the local and for the global path?
In a shell script, you can detect the executable path of the script with
dirname `readlink -f $0`
and work with that.
If you run your program as root, then it should be able to access the configuration files on /etc/ or any other place without a problem. You could grep it from the script or whatever you need.
If your program is not run as root, then you should make sure that the configuration file being accessed on /etc/ gives the user the right to read it. See chmod man for more information.
Finally, your script should run fine from any of the locations you mentioned, although /usr/local/bin/ is generally where locally developed scripts should go. Just call your script by its full path and it will work: ex: /usr/local/bin/script
Note: don't forget to make your script executable: chmod +x /usr/local/bin/script

Makefile on Linux and Cygwin

I'm developing a little command-line tool for a friend. I'm on linux, but he's on Windows and I want to make the compilation process easy for him, as he's not used to having to compile stuff himself.
Building the tool works flawlessly, but now I want to add an 'install' target to the Makefile that copies the binary to his cygwin64/bin folder, which is (supposed to be) on his path. However, I want the Makefile to still run under linux. Is there a generic approach to his? Or should I grep, sed, cut and awk my way through the PATH string and extract the folder I'm looking for?

autoconf substitute path in script

I have a project where there are several helper scripts that call the main executable with different command-line options. Right now, the scripts assume the executable is in the same directory, so the calls to the executable in the script look like ./my_program. This, however, is not very flexible. What if the program is installed in the /usr/bin directory, and is not in the current directory?
Is there a way, using automake or autoconf, to generate these scripts, and substitute the calls to the executable with either ./my_program or just my_program, depending on whether or not the executable is already installed?
Sure. IMO the simplest solution with autotools would be:
create new m4 macro under m4/ folder that finds a path of your program, and sets it to a variable.
For example, you created a macro:
MY_PROGRAM_PATH_CHECK([action-if-found], [action-if-not-found])
This macro creates MY_PROGRAM_PATH variable if path is found.
configure.ac
MY_PROGRAM_PATH_CHECK(,[AC_MSG_ERROR([my_program path not found, woot?])
AC_SUBST(MY_PROGRAM_PATH)
AC_CONFIG_FILES([src/script1.sh], [chmod +x src/script1.sh])
AC_CONFIG_FILES([src/script2.sh], [chmod +x src/script2.sh])
convert your scripts to .in files, so the substitution would happen:
src/Makefile.am
bin_SCRIPTS = script1.sh script2.sh
src/script1.sh
#MY_PROGRAM_PATH#/my_program --option1
src/script2.sh
#MY_PROGRAM_PATH#/my_program --option2

Setting bash command-line variable to start my application

I'm pretty new to programming for Linux environments, so I don't exactly know what to search for in order to answer this question for myself. I need to understand how applications set the shell to accept a certain command to start them. For example, you can start Firefox from the command line by executing the command: firefox.
I don't know where this is defined. Makefile? Configure script? In the source code itself?
Any resources / reading on Linux programming tidbits like these would be greatly appreciated!
Thank you.
Firefox is launched by the command "firefox" because there is an executable file in one of the folders in the $PATH environment variable called "firefox".
Are you talking about the PATH variable? It seems like you are.
In linux, you should be able to type: "echo $PATH" (without quotes) and get a ":"-separated list of locations where programs are located (like firefox).
If you need to add something to your path, you should be able to do:
export PATH=$PATH:/another/directory
In your shell (which is most likely bash)
You can also type:
which firefox
To display the location of the firefox executable.
Typically the shell is going to have an environment variable called $PATH set. This is just an ordered list of all the directories to look when somebody types in a command. As soon as it finds an executable file (by which I mean a file for which you have execute permissions, not a file ending in .exe) with the same name as whatever was typed, it will run that file. Common directories in $PATH might be /bin, /usr/local/bin, ~/bin, etc.
So, when you type 'firefox', the shell looks through all the directories in $PATH until it finds /usr/local/bin/firefox, which it then runs. To make your own programs run the same way, you'll either need to put them (or a symbolic link to them) in a directory that is likely to be in every user's path (/usr/local/bin/ is a good choice), or you'll need to get your users to add your program's directory to their $PATH.
For a more complete description, see the Wikipedia article about the $PATH variable.
As an alternative to the modification of $PATH mentioned earlier, you could also copy or link your executable in one of the directories already in your $PATH. more specifically, /usr/local/bin/ is available on most UNIX system for pretty much this purpose (installing software outside the default package management of the operating system).
It has to be in the path as everyone else mentioned, but you might also need to make it executable with something like this:
chmod +x /path/to/file
And if it's a script there's usually a shebang at the top that tells the os what to use to execute it:
#! /usr/bin/python
Often, large packages are installed in /opt with a wrapper script or link somewhere in the PATH. For example, on my system, Google Picasa is installed in /opt/google/picasa and there is a symlink at /usr/bin/picasa to /opt/google/picasa/3.0/picasa
Firefox is at /usr/bin/firefox on my system and that's a symlink to /usr/bin/firefox-3.0 which is itself a symlink to /usr/lib/firefox-3.0.11/firefox.sh - That shell file fumbles around until it finally runs /usr/lib/firefox-3.0.11/firefox (unless it finds a reason to do something else). That, finally, is a binary executable. So /usr/lib is where firefox is installed, for me.
You can use this command to find out where a program is:
type -a firefox
Then, you can find out what kind of file it is using this:
file /usr/bin/firefox
Also see the Filesystem Heirarchy Standard for more information about recommended locations for files and programs.

How do Linux binary installers (.bin, .sh) work?

Some software (for ex. the NetBeans IDE) ship the Linux installers in .sh files. Curious about how exactly they 'package' a whole IDE into a 'shell script', I opened the file in an editor. I saw some plain text shell scripting code and then some random gibberish, which I reckon is 'binary' or non-plain text.
I am wondering how they mix plain shell scripts and then probably call the 'non-readable' stuff, which would be the binaries.
Any insight on this?
Basically, it's a shell script prepended to a compressed archive of some sort, such as a tar archive. You use the tail or sed command on yourself (the $0 variable in Bourne shell) to strip off the shell script at the front and pass the rest to your unarchiver.
For example, create the following script as self-extracting:
#!/bin/sh -e
sed -e '1,/^exit$/d' "$0" | tar xzf - && ./project/Setup
exit
The sed command above deletes all lines from the first line of the file to the first one that starts with "exit", and then passes the rest on through. If what starts immediately after the "exit" line is a tar file, the tar command will extract it. If that's successful, the ./project/Setup file (presumably extracted from the tarball) will be executed.
Then:
mkdir project
echo "#!/bin/sh" > project/Setup
echo "echo This is the setup script!" >> project/Setup
chmod +x project/Setup
tar czf - project >> self-extracting
Now, if you get rid of your old project directory, you can run self-extracting and it will extract that tar file and run the setup script.
You might want to check out makeself.sh
From the authors' notes.
makeself.sh is a small shell script that generates a self-extractable tar.gz archive from a directory. The resulting file appears as a shell script (many of those have a .run suffix), and can be launched as is. The archive will then uncompress itself to a temporary directory and an optional arbitrary command will be executed (for example an installation script).
Makeself archives also include checksums for integrity self-validation (CRC and/or MD5 checksums).
The makeself.sh script itself is used only to create the archives from a directory of files. The resultant archive is actually a compressed (using gzip, bzip2, or compress) TAR archive, with a small shell script stub at the beginning. This small stub performs all the steps of extracting the files, running the embedded command, and removing the temporary files when it's all over. All what the user has to do to install the software contained in such an archive is to "run" the archive [that is execute the script]
I am trying to keep the code of this script as portable as possible, i.e it's not relying on any bash-specific features and only calls commands that are installed on any functioning UNIX-compatible system. This script as well as the archives it generates should run on any Unix flavor, with any compatible Bourne shell, provided of course that the compression programs are available.
Finally, the makeself package itself comes as a self-extracting script called makeself.run.
Add a Binary Payload to your Shell Scripts
GNU sharutils:
http://www.gnu.org/software/sharutils/
is a toolset for creating shell archives, and provides some additional features that may be helpful (such as checksums to ensuring that the payload is not damaged in transit).
Protecting against malicious modifications is not really feasible when the final product has to be interpretable by the shell - anyone who understood the generation technique could modify the checksum as well.
There are also other/commercial software installer builder (like InstallAnywhere) they basically have their own version of shar/makeself.
Netbeans has their own installer engine, and part of it, which does the unpacking and launching is done in the NBI native launcher component: http://wiki.netbeans.org/NBINativeLaunchers
Creates a shell(script) archive for Linux/Unix/MacOS and native executable for Windows. You can use that tool for your own projects, also.

Resources