Is this the correct syntax to make sure the dependent program is downloaded and installed?

If the package name is correct, this is the correct syntax to make make packages work. It does assume that the person running the program has sudo rights to execute apt-get. It also runs that command unconditionally for make packages, but that shouldn't be too much of a problem because apt-get will check if the package is already installed.

The main problem is that make all doesn't execute make packages, which can be accomplished with

all: myprogram.c packages
        # command

Since apt-get is inherently non-portable, it's correct if it works on your box :)

Answer from Fred Foo on Stack Overflow
Top answer
1 of 2
7

That is not what makefiles are for. Makefile only handles building the software and installing it into the system in a generic way (without a package manager). It does not care (and should not care) if you have the requirements to actually run the application. That is by design. Consider several points:

1) If your distribution uses a package managers (almost all of them do in some way), you should not call make install directly anyway, because that bypasses the package manager and pollutes your system. In that case make install is called in a "sandbox" environment when you build the package, the installation gets packaged and the package is installed and handled by your package manager of choice.

2) There should be no requirement of installing everything in the "correct" order. In fact, this will most certainly lead to circular dependencies and it will be impossible to install. Even package managers usually get too strict about this which leads to problems. Also, when you are building a package (a buildscript calls make install), you actually don't intend to run the program and probably don't have the requirements installed anyway. You are after all just building a package that will be installed on some other computer.

3) There isn't a portable way of doing this. How will your make install which is by definition platform-independent, know where to look for the requirements (Hardwired urls or something? That would break in a second!). It cannot go through the package manager because it must run on all possibilities, including the future ones you haven't anticipated - also the versions change.

4) There isn't a one and only decision what to install. Shared libraries can be provided by different packages. There is more than one libc, even. And more than one package that provides OpenGL functionality (different graphics cards), different packages for matrix algebra, different libraries for media playback (vlc vs. gstreamer), and I could go on for ages. It's your choice how you design your systems and what components you use, it's the beauty of this modular design (instead of the old windows classic of putting everything on one CD/DVD, and thus having every library installed a thousand times by different packages, and gigabytes of installation for every application that shouldn't exceed 10MB with a sane design).

5) It's not the job of make install, it's a different level of maintenance. configure && make && make install handles checking what you have installed (for build-time dependencies), compiling the code and showing you where files should be put. Requirements on what versions of other software you need falls into the domain of packaging and distribution, which is a separate process -- the package manager, or the system admin if he installs things the traditional way. You should never mix these two concepts - it would lead to chaos. If things are separated into well defined layers, the developers can change things independent of the packagers and distribution maintainters: if the distro decides to repackage things with different names and use different alternatives, put things in different directories, they shouldn't expect the application developer, who takes care of the makefile, to know or care about this.

In short - no matter if the dependencies are build-time dependencies (without which the make cannot run - which is usually detected by the configure script), or the runtime dependencies, it shouldn't be done at the makefile level. Please don't do things the wrong way and consider the standards. If you are dealing with something that has no package yet (check the user-provided packages, it may be there already), you should investigate what is needed and actually build the package - it's better for others as well, who can then enjoy the package you made.

2 of 2
0

This is a Makefile target that I sometimes use to deploy stuff in systems where i do not know exactly what installed packages I can rely on being already installed. I should be possible to extend this also beyond apt and pacman.

What you actually do is depending on the needed executable. The target for the executable is trying to fetch the correct package that contains it.

ifneq (,$(wildcard /usr/bin/apt))
# USE APT
/usr/bin/apt-file:
    $(warning $@ not installed. trying to install via apt ...)
    sudo apt install -y apt-file
    sudo apt-file update

/usr/bin/%: /usr/bin/apt-file
    $(warning $@ not installed. trying to install via apt ...)
    sudo apt install -y $(shell apt-file --fixed-string --package-only search $@)

else ifneq (,$(wildcard /usr/bin/pacman))
# USE PACMAN

/usr/bin/%:
    $(warning $@ not installed. trying to install via pacman ...)
    sudo pacman -Fy
    sudo pacman -Sy $(shell sudo pacman -Fq $@)

else
# NO PACKAGE MANAGER SUPPORT
/usr/bin/%:
    $(error $@ not installed. please install manually and try again ...)

endif

With this in your makefile you can easily add other targets like this:

index.html: | /usr/bin/wget
    /usr/bin/wget www.google.de

You should only need to care about updating your package databases eventually.

Discussions

Make to install dependencies in multiple projects Makefile - Stack Overflow
I have a Makefile with multiple subprojects and set its build dependencies. Now I want to be able to selectively make install some of those subprojects but include the dependencies in the installa... More on stackoverflow.com
🌐 stackoverflow.com
September 12, 2012
How do I install makefile dependencies automatically?
Currently, I am compiling until there is another complaint of missing file. I know that the dependencies can also be found manually in the (complicated) makefile. What I would like is automatic resolution and installation of all dependencies. Is that possible, preferably without changing the ... More on discourse.brew.sh
🌐 discourse.brew.sh
0
0
December 25, 2018
build system - Why should makefiles have an "install" target? - Software Engineering Stack Exchange
Anyway: sometimes you want to install ... it has dependencies that would cause conflicts impossible to resolve using the package manager etc). make install usually installs under /usr/local (or even /opt) which are directories not handled by the "core OS/package management system". No idea whether Windows has some similar convention though. ... Many build scripts or Makefiles have an ... More on softwareengineering.stackexchange.com
🌐 softwareengineering.stackexchange.com
linux - Makefile: Target dependency - How to always-make it? - Stack Overflow
This will most probably be obvious and / or a banality. But since I am trying different approaches for hours without success... I am on Linux Mint 19. I am entirely new to Makefiles. Excuse me, if... More on stackoverflow.com
🌐 stackoverflow.com
🌐
GitHub
github.com › kuz › DeepMind-Atari-Deep-Q-Learner › pull › 4 › files
Using makefile to install dependencies by wecacuee · Pull Request #4 · kuz/DeepMind-Atari-Deep-Q-Learner
LUAROCKS_TARGETS:=$(foreach rock,$(LUAROCKS_TO_INSTALL),$(PREFIX)/lib/luarocks/rocks/$(rock)/.installed) $(PREFIX)/lib/libxitari.so: $(PREFIX)/bin/luarocks $(LUAROCKS_TARGETS) ... $(PREFIX)/lib/lua/5.1/libalewrap.so: $(PREFIX)/bin/luarocks $(LUAROCKS_TARGETS) $(PREFIX)/lib/libxitari.so ... dependencies: $(PREFIX)/lib/luarocks/rocks/luagd/.installed $(PREFIX)/lib/lua/5.1/libalewrap.so $(PREFIX)/lib/libxitari.so
Author   kuz
🌐
Thoughtbot
thoughtbot.com › blog › the-magic-behind-configure-make-make-install
The magic behind configure, make, and make install
August 5, 2024 - It makes sure all of the dependencies for the rest of the build and install process are available, and finds out whatever it needs to know to use those dependencies. Unix programs are often written in C, so we’ll usually need a C compiler to build them. In these cases, the configure script will establish that your system does indeed have a C compiler, find out what it’s called and where to find it. ... Once configure has done its job successfully, we can invoke make to build the software. This runs a series of tasks defined in a Makefile to build the finished program from its source code.
🌐
Medium
medium.com › @jaz1 › introduction-to-makefiles-a10035631f69
Introduction to Makefiles. A Makefile is a file with a list of… | by Jaz Allibhai | Medium
January 31, 2022 - For example, if you want to install ... you can define the task in the Makefile and run a simple make command (for example, ‘make install’) to install all the dependencies....
🌐
Mutantstargoat
nuclear.mutantstargoat.com › articles › make
Practical Makefiles, by example - John Tsiombikas
I promised in the beginning that ... makefile, to a release-quality build system. First of all, what do I mean by that. Surely in the last section we've seen many improvements that can be used to handle pretty much anything a project might need. We are missing however, some things that end-users expect; mainly "install" and "uninstall" rules, and build options. Writing installation rules for standalone programs is very easy. Simply make your install rule depend on the binary, ...
🌐
Homebrew
discourse.brew.sh › t › how-do-i-install-makefile-dependencies-automatically › 3721
How do I install makefile dependencies automatically? - Homebrew
December 25, 2018 - Currently, I am compiling until there is another complaint of missing file. I know that the dependencies can also be found manually in the (complicated) makefile. What I would like is automatic resolution and installation of all dependencies. Is that possible, preferably without changing the ...
Find elsewhere
🌐
GitHub
github.com › agda-attic › agda-makefile
GitHub - agda-attic/agda-makefile: An makefile with lightweight dependency management · GitHub
The makefile for foo begins by declaring its dependencies: pkgid = foo dependencies = bar baz and the dependency tarball URIs: export bar ?= http://example.com/bar.tgz export baz ?= http://example.com/baz.tgz then it downloads and imports the common makefile: export agdamakefileuri ?= https://github.com/agda/agda-makefile/raw/v0.0.1/Makefile export agdamakefile ?= $(CURDIR)/build/share/make/agda-makefile export CURL ?= curl $(agdamakefile): $(CURL) --create-dir -o $@ $(agdamakefileuri) include $(agdamakefile) At this point, foo's makefile has bootstrapped itself by downloading and including the master Makefile. The rest of the makefile is as per usual, but can make use of the target install-dependencies, which downloads and installs the dependent projects.
Author   agda-attic
🌐
Skand Hurkat
skandhurkat.com › post › makefile-dependencies
Handling dependencies in Makefiles | Skand Hurkat
August 2, 2017 - CPPFLAGS = -std=c++11 # Recipe for making .d files from .cc files %.d: %.cc $(CC) -MM $(CPPFLAGS) -o $@ $< # Include the required .d files in the current Makefile. include $(sources:.cc=.d) # Recipe for making .o files. Here, I introduce a dependency on the # primary source c++ file.
🌐
Medium
medium.com › @dmaioni › makefile-compile-and-install-projects-9ba10ce21566
Makefile, compile and install projects | by Daniel Maioni | Medium
June 6, 2023 - Which project has a makefile folder, and calling the make command will do what it was designed by the author to compile the project. Step 2: Install the dependencies: sudo apt-get install git-core build-essential liblz4-dev libuv1-dev zlib1g-dev · ...
🌐
Readthedocs
spack.readthedocs.io › en › latest › build_systems › makefilepackage.html
Makefile - Spack 1.2.0.dev0 documentation
September 23, 2025 - Also watch out for variables that control linking, such as LIBS, LDFLAGS, and INCLUDES. These variables need to be set to the installation prefix of a dependency, or to the correct linker flags to link to that dependency. ... If your Makefile has an install target, it needs some way of knowing where to install.
🌐
GNU
gnu.org › software › make › manual › html_node › Install-Command-Categories.html
Install Command Categories (GNU make)
$0 ~ /^(normal-install|post-install)[ \t]*$/ {on = 0} on {print $0} $0 ~ /^pre-install[ \t]*$/ {on = 1} Previous: Standard Targets for Users, Up: Makefile Conventions [Contents][Index]
🌐
IBM
ibm.com › docs › en › clearcase › 11.0.0
Declaring source dependencies in makefiles - IBM Documentation
March 10, 2026 - To alleviate this problem, some organizations include every header file dependency in their makefiles.
🌐
Earthly
earthly.dev › blog › python-makefile
Creating a Python Makefile - Earthly Blog
July 11, 2023 - If you now run pip install -r requirements.txt, the modules will be installed in the venv directory. Once you are done with the virtual environment, you can deactivate the environment by running the deactivate command.
🌐
MoldStud
moldstud.com › articles › developers faq › makefile developers questions › how do i specify dependencies in a makefile?
How do I specify dependencies in a makefile? | MoldStud
October 24, 2024 - There are several ways to specify dependencies in a makefile, depending on the structure of the project and the tools being used. One common method is to use the target: dependencies syntax to define dependencies for a specific target.
Top answer
1 of 6
25

Many build scripts or Makefiles have an installation target because they were created before package managers existed, and because even today lots of systems don't have package managers. Plus, there are systems where make install actually is the preferred way of managing packages.

2 of 6
5

A makefile might have no install target, and more importantly, you can have programs which are not even supposed to be installable (e.g. because they should run from their build directory, or because they can run installed anywhere). The install target is just a convention for usual makefile-s.

However, many programs require external resources to be run (for example: fonts, databases, configuration files, etc). And their executable often make some hypothesis about these resources. For example, your bash shell would generally read some initialization file from /etc/bash.bashrc etc.... These resources are generally in the file system (see hier(7) for conventions about the file hierarchy) and the default file path is built in your executable.

Try to use strings(1) on most executables of your system. You'll find out which file paths are known to it.

BTW, for many GNU programs using autoconf, you could run make install DESTDIR=/tmp/destdir/ without being root. Then /tmp/destdir/ is filled with the files that should be later packaged.

FWIW, I tend to believe that my bismon (GPLv3+ licensed) program (described in my bismon-chariot-doc.pdf report) cannot be "installed"; I am not sure to be able to prove that, and I cannot imagine how could I make that program installable.

🌐
GNU
gnu.org › software › make
Make - GNU Project - Free Software Foundation
You can also use Make to control installing or deinstalling a package, generate tags tables for it, or anything else you want to do often enough to make it worth while writing down how to do it. ... A rule in the makefile tells Make how to execute a series of commands in order to build a target file from source files. It also specifies a list of dependencies of the target file.
Top answer
1 of 3
3

Reading on Force Targets, I came up, hopefully, with a solution below:

If a rule has no prerequisites or recipe, and the target of the rule is a nonexistent file, then make imagines this target to have been updated whenever its rule is run. This implies that all targets depending on this one will always have their recipe run.

Hence, I created an empty target force-rebuild-hash-file:.

Thus, the SHA512SUM file will always be re-created when calling this target or distrib target which depends on it.

I think it is finally solved overall, feel free to comment, if not.

In case you or I, myself, find any errors, I will update this answer to reflect them.

To de-duplicate some code I came across this answer and applied it.

I renamed SHA512SUMS to SHA512SUM, it does not matter much, but I find it more used.

I found $@ to print target names a good way of keeping track of what targets are being run. For instance, if SHA512SUM does not exist and we install it like this:

make install PREFIX=./test

we get a very nice overview (output):

echo && echo Target: check && echo

Target: check

if [ -f SHA512SUM ]; then ( echo && sha512sum --check SHA512SUM && ( echo && echo "Ok. You may use 'sudo make install' or '(sudo) make install PREFIX=SomeDir' command now." ) || ( echo && echo "ERROR: Files hash sum mismatch!" && echo && exit 1 ) ) else make --file=Makefile SHA512SUM; fi
make[1]: Entering directory '/home/vlastimil/Development/sh/openssl-encryption'
echo && echo Target: SHA512SUM && echo

Target: SHA512SUM

sha512sum encrypt-file-aes256 decrypt-file-aes256 > SHA512SUM
make[1]: Leaving directory '/home/vlastimil/Development/sh/openssl-encryption'
echo && echo Target: install && echo

Target: install

echo && [ -d ./test ] || mkdir --parents ./test

install --verbose --mode=0755 --target-directory=./test encrypt-file-aes256 decrypt-file-aes256
'encrypt-file-aes256' -> './test/encrypt-file-aes256'
'decrypt-file-aes256' -> './test/decrypt-file-aes256'

Current Makefile

DESTDIR ?=
PREFIX ?= /usr/local/bin
install_path := $(DESTDIR)$(PREFIX)
encrypt_script := encrypt-file-aes256
decrypt_script := decrypt-file-aes256
distrib_name := openssl-encryption
this_file := $(lastword $(MAKEFILE_LIST))

.PHONY: check install uninstall distrib

# https://stackoverflow.com/a/27132934/1997354
check: $(encrypt_script) $(decrypt_script)
    echo && echo Target: $@ && echo
    if [ -f SHA512SUM ]; then ( echo && sha512sum --check SHA512SUM && ( echo && echo "Ok. You may use 'sudo make install' or '(sudo) make install PREFIX=SomeDir' command now." ) || ( echo && echo "ERROR: Files hash sum mismatch!" && echo && exit 1 ) ) else $(MAKE) --file=$(this_file) SHA512SUM; fi

install: check
    echo && echo Target: $@ && echo
    echo && [ -d $(install_path) ] || mkdir --parents $(install_path)
    install --verbose --mode=0755 --target-directory=$(install_path) $(encrypt_script) $(decrypt_script)

uninstall:
    echo && echo Target: $@ && echo
    rm $(install_path)/$(encrypt_script) $(install_path)/$(decrypt_script)
    rmdir --ignore-fail-on-non-empty $(install_path)

distrib: SHA512SUM check $(encrypt_script) $(decrypt_script) Makefile
    echo && echo Target: $@ && echo
    # https://english.stackexchange.com/a/468131/319970
    # https://stackoverflow.com/a/52782747/1997354
    if [ $$(id --user) -eq 0 ]; then ( echo && echo "Target 'distrib' has to be run as normal user!" && echo && exit 1 ) fi
    rm --force $(distrib_name).tar.xz
    rm --force $(distrib_name).tar.xz.asc
    rm --force --recursive $(distrib_name)
    mkdir $(distrib_name)
    cp $(encrypt_script) $(decrypt_script) Makefile SHA512SUM $(distrib_name)
    wget --quiet --output-document=$(distrib_name)/LICENSE https://git.io/fxByv
    wget --quiet --output-document=$(distrib_name)/README https://git.io/fxByJ
    chmod 755 $(distrib_name)/$(encrypt_script) $(distrib_name)/$(decrypt_script)
    chmod 644 $(distrib_name)/Makefile $(distrib_name)/SHA512SUM $(distrib_name)/LICENSE $(distrib_name)/README
    tar --create --file=$(distrib_name).tar $(distrib_name)
    xz --format=xz -9 --extreme --check=sha256 $(distrib_name).tar
    rm --force --recursive $(distrib_name)
    gpg --local-user 7D2E022E39A88ACF3EF6D4498F37AF4CE46008C3 --sign --armor --output $(distrib_name).tar.xz.asc --detach-sig $(distrib_name).tar.xz

# https://www.gnu.org/software/make/manual/html_node/Force-Targets.html
force-rebuild-hash-file:

# real target file
SHA512SUM: force-rebuild-hash-file
    echo && echo Target: $@ && echo
    sha512sum $(encrypt_script) $(decrypt_script) > SHA512SUM
2 of 3
0

You could also declare SHA512SUM as order-only prerequisite of check, not a prerequisite of distrib but add $(MAKE) --always-make SHA512SUM to your distrib recipe:

check: $(encrypt_script) $(decrypt_script) | SHA512SUM
    ...

distrib: check $(encrypt_script) $(decrypt_script) Makefile
    $(MAKE) --always-make SHA512SUM
    ...
🌐
Bargsten
bargsten.org › python › makefile-python-project
Managing your Python project with a Makefile | jw bargsten
June 16, 2024 - # if you work with requirements.txt deps: $(VENV)/init $(VENV)/requirements $(VENV)/requirements: requirements.txt $(VENV)/init ## install requirements $(PIP) install -r $< touch $@ The deps (short for dependencies) target requires the file $(VENV)/requirements.