Binodeps

Makefile library for C/C++ — This library is supposed to simplify writing Makefiles for C and C++ programs.


Description

This is a library to simplify the creation and maintenance of Makefiles for C and C++ programs. You specify what programs and libraries to build, and what headers to export, and it works out how to build and install them.

Installation

git clone https://github.com/simpsonst/binodeps.git
cd binodeps
make
sudo make install

The default installation location is /usr/local. Set PREFIX to override it:

sudo make PREFIX=/opt/binodeps install

It will also attempt to read configuration from binodeps-env.mk in the include path.

Use

To use Binodeps in your project:

# In Makefile
include binodeps.mk

File hierarchy

Binodeps expects your project to have the following structure. C and C++ source and headers go in src/obj/, and can be nested in subdirectories. Scripts go in src/scripts/, and other architecture-independent files go in src/share/.

Files in out/ and tmp/ will be created automatically. (You might wish to instruct your revision control system to ignore these directories.) make clean will remove tmp/, and make blank will remove both. Both targets also depend on tidy, if you want to hang other housekeeping jobs off them, e.g.:

tidy::
        find . -name "*~" -delete
Variables controlling project structure
Directory Variable default Meaning
$$(BINODEPS_SRCDIR) src/obj Source and header files in C and C++
$$(BINODEPS_SCRIPTDIR) src/scripts Executable text scripts
$$(BINODEPS_SHAREDIR) src/share Static data files
$$(BINODEPS_DOCDIR) docs Documentation
$$(BINODEPS_SHAREDIR_RISCOS) src/riscos Static files for RISC OS, usually with hex type suffixes
$$(BINODEPS_OUTDIR) out Output directory
$$(BINODEPS_BINDIR) $$(BINODEPS_OUTDIR) Binary executables
$$(BINODEPS_LIBDIR) $$(BINODEPS_OUTDIR) Binary libraries, e.g., libfoo.a
$$(BINODEPS_HDRDIR) $$(BINODEPS_OUTDIR)/include Installed header files in C and C++
$$(BINODEPS_ZIPDIR_RISCOS) $$(BINODEPS_OUTDIR) RISC OS zip files, e.g., foo-riscos.zip
$$(BINODEPS_OUTDIR_RISCOS) $$(BINODEPS_OUTDIR)/riscos RISC OS application directories
$$(BINODEPS_TMPDIR) tmp Intermediate files
$$(BINODEPS_OBJDIR) $$(BINODEPS_TMPDIR)/obj Compiled files, e.g., foo.o
$$(BINODEPS_SRCDIR_DYN) $$(BINODEPS_OBJDIR) Generated ‘source’ and header files in C and C++

C programs

To build a C program, give its name, and list the local C modules that form it, and any library switches it needs:

binaries.c += foo

foo_obj += foo
foo_obj += bar
foo_lib += -lm

This expects to find the files foo.c and bar.c in src/obj/, along with any headers they use. Dependencies on these headers will be managed automatically. Global compilation options can be set with CPPFLAGS and CFLAGS. Global linking options can be set with LDFLAGS.

Create the program with:

make out/foo
# or
make installed-binaries

You will likely want to add installed-binaries to your default target:

all:: installed-binaries

When you run make install-binaries, out/foo will be installed in $$PREFIX/bin. If you want to install it in $$PREFIX/sbin or $$PREFIX/libexec instead, use admin_binaries.c or hidden_binaries.c respectively instead of binaries.c. If you don't want it installed at all, use test_binaries.c.

You can list the components used to build your program:

$$ make show-binary-foo
Binary executable foo:
  Libraries: -lm
  Modules: foo bar

You can also list the options for compiling C:

$$ make show-opts-c@default
           label: default
           modules: XXX.o
           executables: XXX
           libraries: libXXX.a
           Link flags: -L/opt/lib
           C: cc
           C flags: -O2 -g -std=gnu11 -fgnu89-inline -std=gnu11
           C flags: -D_XOPEN_SOURCE=600 -D_GNU_SOURCE=1 -pedantic -Wall -W
           C flags: -Wno-unused-parameter -D_BSD_SOURCE=1 -D_GNU_SOURCE=1
           C flags: -I/opt/include

C++ programs

To build a C++ program, give its name, and list the local C and C++ modules that form it, and any library switches it needs:

binaries.cc += foo

foo_obj += foo
foo_obj += bar
foo_lib += -lm

This expects to find the files foo.c/foo.cc and bar.c/bar.cc in src/obj/, along with any headers they use. Dependencies on these headers will be managed automatically. Global compilation options can be set with CPPFLAGS and CXXFLAGS. Global linking options can be set with LDFLAGS. Using the suffix .cc in binaries.cc only affects the linking process, causing LINK.cc to be used instead of LINK.c.

Create the program with:

make out/foo
# or
make installed-binaries

You will likely want to add installed-binaries to your default target:

all:: installed-binaries

When you run make install-binaries, out/foo will be installed in $$PREFIX/bin. If you want to install it in $$PREFIX/sbin or $$PREFIX/libexec instead, use admin_binaries.cc or hidden_binaries.cc respectively instead of binaries.cc. If you don't want it installed at all, use test_binaries.cc.

The command make show-opts-cc@default will show C++ compilation options.

C and C++ libraries

To build a static library, list its name with libraries, and then list the C and C++ modules that form it, and the headers that should be installed with it:

libraries += foo

foo_mod += foo
foo_mod += bar

headers += foo/types.h
headers += foo/core.h
headers += foo/entry.h
headers += foo.h

Make the library with:

make out/libfoo.a
# or
make installed-libraries

You will likely want to add installed-libraries to your default target:

all:: installed-libraries

To install:

make install-libraries install-headers

If you don't want it installed at all, list it under test_libraries instead, and don't list its headers. All installed libraries all use the same headers list.

If you want to use a different name for a library to what you refer to it by internally, you can define an alias for it:

foo_libname=zonga

The target to make is now out/libzonga.a, and installed-libraries has it as a prerequisite instead of out/libfoo.a.

You can show the composition of a library:

$$ make show-library-foo
Binary library foo:
  Modules: foo bar

Submodels

You can compile for several submodels of your target architecture, or even other architectures, in a single working directory. You just need to introduce a mnemonic for a new submodel, e.g., bpf, and specify how it differs from the default submodel:

SUBMODELS += bpf
SUBMODEL_OBJSFX@bpf=.bo
SUBMODEL_SFX@bpf=.bpf
SUBMODEL_LABEL@bpf=BPF
CPPFLAGS@bpf += -target bpf
CC@bpf=clang

include binodeps.mk

This says that object files for ‘BPF’ programs will use the suffix .bo, for example. The executables themselves will use the suffix .bpf.

All the usual user-defined variables like binaries.c and CFLAGS now have duals in the form of binaries.c@bpf and CFLAGS@bpf. Variables like CFLAGS@bpf inherit from their unsuffixed counterparts, while compiler variables such as CC@bpf merely default to their counterparts. Note that the default submodel is identified by default, and variables like binaries.c@default, for example, inherit from their unsuffixed counterparts, binaries.c, for backward compatibility with earlier versions of Binodeps.

The command make show-submodels will list details of all submodels.

Scripts

Put your scripts to be installed in $$PREFIX/bin, $$PREFIX/sbin or $$PREFIX/share into src/scripts/. List them under scripts, admin_scripts or hidden_scripts respectively.

To install, use the following, respectively:

make install-scripts
make install-admin-scripts
make install-hidden-scripts

They will be installed with mode 0755.

Data

Put your data files to be installed in $$PREFIX/share into src/share/, and list them with datafiles:

datafiles += foo.dat
datafiles += stuff/bar.xsl

To install:

make install-data

RISC OS applications

Cross-compiling and packaging of RISC OS applications with GCCSDK is supported. List the zips to be created:

riscos_zips += foo

That indicates that a zip called out/foo-riscos.zip is to be built. By default, a zip only contains one application, with the same name as the zip, but you can list multiple applications explicitly:

foo_apps += fullapp
foo_apps += viewer

By default, an application appears in a directory of the same name, e.g., out/riscos/fullapp/ and out/riscos/viewer/. You can specify an alternative name:

fullapp_appname=!Foo
viewer_appname=!FooViewer

So now the application will appear in out/riscos/!Foo/ and out/riscos/!FooViewer/.

The contents of each application must be listed. You can specify source files, to be copied from src/obj/:

# From src/obj/bar.c
fullapp_rof += Source/c/bar,fff

# From src/obj/bar.h
fullapp_rof += Source/h/bar,fff

You can specify exported header files, also copied from src/obj/:

# From src/obj/foo/bar.h
fullapp_rof += Library/foo/h/bar,fff

# From src/obj/foo/bar.hh
fullapp_rof += Library/foo/hh/bar,fff

If you already have lists of the files relative to src/obj/, you can generate the equivalent RISC OS names like this:

# List headers to install.
headers += foo/bar.h
headers += foo/bar.hh

# Find source files which are not installed headers.
SOURCES:=$$(filter-out $$(headers),$$(shell $$(FIND) src/obj \( -name "*.c" -o -name "*.cc" -o -name "*.h" -o -name "*.hh" \) -printf '%P\n'))

# Installed headers should also be part of the RISC OS application fullapp.
fullapp_rof += $$(call riscos_hdr,$$(headers))

# Source files should be included in the RISC OS application fullapp.
fullapp_rof += $$(call riscos_src,$$(SOURCES))

Copying of source and header files should work on hierarchies of any depth. Copying of library archives only works at the top level, however:

# From out/libfoo.a
fullapp_rof += Library/o/foo,ffd

More generally, you can generate the RISC OS names of libraries like this:

fullapp_rof += $$(call riscos_lib,$$(libraries))

This will work even if a library has an alias set with foo_libname.

Some files come from special locations:

# From docs/README.html
fullapp_rof += README,faf

# From docs/COPYING
fullapp_rof += COPYING,fff

# From docs/VERSION
fullapp_rof += VERSION,fff

# From docs/HISTORY
fullapp_rof += HISTORY,fff

For an application runimage:

ELF2AIF=elf2aif

# Converted from out/prog
fullapp_runimage += prog

For a compiled command:

# From out/myprog
fullapp_rof += Library/myprog,ff8

For all binary executables:

fullapp_rof += $$(call riscos_bin,$$(EXPORT_BINARIES@default))

Everything else is copied from src/riscos/fullapp/:

# From src/riscos/fullapp/!Boot,feb
fullapp_rof += !Boot,feb

# From src/riscos/fullapp/Messages,fff
fullapp_rof += Messages,fff

# From src/riscos/fullapp/Templates,fec
fullapp_rof += Templates,fec

To make the applications in out/riscos/:

make riscos-apps

To make the zips in out/ as well:

make riscos-zips

You will likely want to add one of these to your default target, e.g.:

all:: riscos-zips

To install:

make install-riscos

RISC OS relocatable modules

A submodel called riscos-rm is predefined with the following:

SUBMODEL_SFX@riscos-rm=.rm
SUBMODEL_OBJSFX@riscos-rm ?= .mo
SUBMODEL_LABEL@riscos-rm=RISC OS RM
CPPFLAGS@riscos-rm += -mlibscl -mmodule
CPPFLAGS@riscos-rm += -mfloat-abi=$$(FPABI@riscos-rm)
ASFLAGS@riscos-rm += -mfloat-abi=$$(FPABI@riscos-rm)
FPABI@riscos-rm ?= hard

Rules exist to generate file.s and file.h from file.cmhg, which describes a module. At the moment, file.cmhg does not get preprocessed. You can then define the module from that together with (say) foo.c and bar.c with:

test_binaries.c@riscos-rm += mymodule
mymodule_obj += file
mymodule_obj += foo
mymodule_obj += bar

To make the relocatable module mymodule part of an application directory:

riscos_zips += myproj
myproj_apps += system
system_appname=!System
system.mymodule.modloc=Modules/310/MyModule

This simply specifies that out/mymodule.rm should be copied to out/riscos/!System/Modules/310/MyModule,ffa.


Files

File Size Last modified Description Requirements and recommendations
Source (Git) GNU Make Linux