icmake(1)

πŸ’… icmake(1) β€” A program maintenance utility πŸ’…

okay so bestie, you're looking at icmake β€” it's the manual page for the icmake program, a program maintenance (make) utility using a C-like grammar. No cap, this page is long, so buckle up 🫢


✨ NAME ✨

icmake β€” A program maintenance (make) utility using a C-like grammar 🌸

✨ SYNOPSIS ✨

icmake option(s) [source [dest]] [args]

🌸 DESCRIPTION 🌸

Icmake(1) is a generic tool for program maintenance which can be used as an alternative for, e.g., make(1). It's "generic" in the sense that icmake-scripts β€” written in a language closely resembling the C programming language β€” can perform tasks that are traditionally the domain of scripting languages. iconic behavior honestly πŸ’…

This man-page consists of the following sections:

  • ICMAKE V. 13.00.00 covers the changes since icmake version 12.03.00;
  • OPTIONS covers icmake's options;
  • EXECUTING ICMAKE SCRIPTS covers how to call icmake scripts;
  • ICM-DEP describes the icm-dep support program;
  • ICM-MULTICOMP describes the icm-multicomp support program;
  • ICM-SPCH describes the icm-spch support program;
  • ICM-UN describes the icm-un support program;
  • FILES provides an overvieuw of the locations of icmake and its support programs (as used by the Debian Linux distribution);
  • EXAMPLES contains references to locations containing some examples;
  • SEE ALSO contains references to man-pages of icmake support programs and man-pages of programs related to icmake. In particular
    • icmstart(1), describes how to initialize a directory for (C++ or C) program development;
    • icmbuild(1), covers how to use icmake for the maintenance of such programs.
    • icmscript(7) covers the syntax and facilities of icmake's scripting language, allowing you to write your own icmake scripts.

Icmake allows programmers to use a scripting language (closely resembling the well-known C-programming language) to define the actions that are required for (complex) program maintenance. For this, icmake offers various special operators as well as a set of support functions that have shown their usefulness in program maintenance. it's giving "I contain multitudes" πŸ¦‹

⚠️ Icmake should not be confused with an Integrated Development Environment (IDE). Icmake merely performs tasks for which scripts can be written, and a minimal set of pre-defined scripts (icmstart and icmbuild) that have proven their usefulness when developing and maintaining programs are included in icmake's distribution. she's a tool, not a whole personality πŸ’€

When using icmbuild(1) for program maintenance the following icmake support programs are used:

  • icm-comp β€” byte-code compiling an icmake script;
  • icm-dep β€” handling class-dependencies;
  • icm-exec β€” executing a byte-code compiled icmake script;
  • icm-multicomp β€” (optionally) using multi-threaded source file compilation;
  • icm-pp β€” pre-processing an icmake script;
  • icm-spch β€” (optionally) constructing a project-wide Single Pre-Compiled Hbeader file (SPCH).

In addition to the above programs the icmake project provides

  • the icmodmap program can be used when developing C++ programs using modules (cf. the icmodmap(1) man-page);
  • icm-un disassembling compiled icmake byte-code files (bim-files). icm-un is primarily used for illustration, education, and debugging and is called by icmake when specifying its option --unassemble or -u (see also section ICMUN).

Some make-utilities by default recompile sources once header files are modified. When developing C++ programs this is often not required, as adding new member functions to classes does not require the recompilatopm of all source files of those classes. Class dependencies are optionally inspected by icmbuld(1) (they are inspected when the USE_ALL, SPCH, and/or (now deprecated) PRECOMP #define directives in the icmconf file are activated (cf. the icmconf(7) man-page for details). 🧚


πŸŽ€ ICMAKE V. 13.00.00 πŸŽ€

In icmake version 13.00.00 the following modifications were implemented w.r.t. its version 12.03.00 β€” glow-up era fr fr ✨

  • option --all (-a) was added to the icm-spch program performing in sequence the actions of its --list, --precompile, and --soft-link options. Several existing options were altered. See the ICM-SPH section for details. πŸ‘‘
  • the (internal) headers inspected by icmake --spch (or -S) are not modified anymore. πŸ™ˆ
  • to remove the (now obsoleted) #ifndef SPCH_ specifications from files listed in existing spch files written by previous versions of icm-spch the program noifndef.cc, available in the icmake source distribution in its support/ sub-directory can be used to remove existing #ifnef SPCH_ sections from a project's .ih files; 🧹
  • icmake --source compiles the icmake script to a temporary .bim file; πŸ’…
  • the support program icmun was renamed to icm-un (called by icmake when specifying the --unassemble (-u) option, so in practice the name change is automatically handled). πŸ’–
  • The icmconf(7) script can use -o in its #define SPCH specification. All (space character delimited) words following -o are passed to icm-spch as separate -o word options; πŸŽ€
  • When developing C++ programs the environment variable ICMAKE_CXXFLAGS is no longer used. Instead the environment variable ICMAKE_CPPSTD is used. Use this latter environment variable to define one point of maintenance specifying the version of the C++ standard used when compiling sources; ⭐
  • When using Debian (or a comparable distributions) the script 'rebuild' can be used to rebuild icmake's binaries after installing 'libbobcat-dev', resulting in a reduction of their sizes of about 40%. πŸ”₯
  • The icmake program itself was redesigned. main character energy tbh 🌈
  • --about (-a) β€” shows you some info about icmake and then dips out, donezo ✨
  • --compile (-c) [options] source [bim-file] β€” your icmake script gets pre-processed first (peep --preprocess below for the tea β˜•), and then the pre-processed file gets compiled by icm-comp, which spits out a bim-file. Didn't name a bim-file? No stress β€” source's base-name gets the extension .bim and that's your new file πŸ’…. If source is already a pre-processed file, you can throw in option -P to skip the pre-processing step entirely. Like:
icmake -c -P source dest.bim

And lowkey the icon behaviour: if the bim-file already exists and is younger than source, then source does not get compiled. Periodt.

  • --dependencies (-d) [options] action β€” calls up icm-dep, the program that figures out the dependencies among your classes πŸ•΅οΈβ€β™€οΈ. Every single option and argument that comes after this one gets forwarded straight to icm-dep. Wanna know more? Slide to the ICM-DEP section of this man-page, iykyk.
  • --execute (-e) [option] bim-file [arguments] β€” runs the bim-file, obviously πŸ’…. Before you specify bim-file you can drop --no-version-check (or its short twin -n) to let the main version of icmake and the icmake version that compiled the bim-file not match β€” yeah, they're allowed to differ 🌈. Any command-line arguments you put beyond bim-file get forwarded as arguments to the bim-file's main function (check the icmscript(7) man-page for the deets on writing icmake-scripts 🫢).
  • --force (-f) [options] source [bim-file] β€” same energy as --compile, but compilation is always performed, even if the bim-file is already up-to-date. No skipping, no shortcuts, we compile πŸ”₯
  • --help (-h) β€” shows you usage info and then icmake peaces out πŸ‘‹. Plot twist: you also get usage info when you start icmake with no arguments at all.
  • --multicomp (-m) [options] jobs 'compiler-spec' β€” the optional options here are the ones passed to the icm-multicomp program (cf. section ICM-MULTICOMP below). Also peek the icomonf(7) man-page's #define MULTICOMP directive: when that's specified, threaded compilation gets used automatically 🧡✨
  • --no-process (-N) β€” implies option --verbose (see below ⬇️). This one is recognized by options --dependencies, --execute, --source and -t β€” either as two separate options, or by "gluing" both options together, like -Ne. When you specify it, the support program is not run, and instead the command(s) that would have been used are shown to the standard output πŸ‘€. Manifesting without the side effects, honestly.
  • --no-version-check (-n) β€” available with the action options --execute, --source, --unassemble, and -t. When specified, the main versions stored in the specified icm-bim file and icmake itself are allowed to differ. Ngl you should normally not need this one β€” it was primarily added for development purposes πŸ™ˆ
  • --preprocess (-p) [options] source [pim-file] β€” the file you pass as the first argument gets pre-processed, producing a .pim file πŸŽ€. If you give a second filename argument, that file becomes the .pim file. If you don't, then the first filename gets used with the extension .pim. With this option you can use pre-processor symbol-defining options: symbols whose values you can then use in source. E.g., when you issue the command
icmake -p -d one --define two source dest.pim

icmake pre-processes source, defines the pre-processor symbols one and two (each having value 1), and produces the pim-file dest.pim. Note that instead of the long options --define, the short options -d work too πŸ’β€β™€οΈ

  • --spch (-S) ... β€” a SPCH gets built πŸ› οΈ. Everything after --spch is forwarded to the icm-spch support program (cf. section ICM-SPCH below). Also check the icomonf(7) man-page's #define SPCH directive: when that's specified, a SPCH is automatically constructed ✨
  • --source (-s) [options] source [arguments] β€” icmake uses --compile to compile the icmake source file you passed as the first argument (constructing a temporary bim-file), and then uses --execute to execute that bim-file, forwarding any subsequent arguments as arguments to the bim-file's main function 🫢. After the --source option you can specify options that are available for icmake's --compile command. After those options, you can specify options of icmake's --execute options β€” and those latter ones must be preceded by --execute or -e. E.g., when you issue the command
icmake -s -d one -en source

then icmake first compiles source after defining the pre-processor symbol one, and then executes the bim-file, passing --no-version-check to icm-exec.

When you're merely compiling icmake source files (using icmake -c), the compiled file by default receives the extension .bim. But when you use icmake -s, temporary files are used β€” which get removed after executing the constructed binary file πŸ—‘οΈ. When compilation errors show up, the name of the temporary file gets reported. It's made of three parts: the directory receiving icmake's temporary files; the filename of the icmake script which is passed to icmake -s; and a random 6-character extension. E.g., when calling icmake -s script, error messages may refer to /tmp/script.2JS49A 😭

  • -t tmpspec [options] source [arguments] β€” this option is intended for icmake-scripts, although it can also be used in a command-line icmake call. The -t option can be used in quite a few different ways, which is covered in the next section (EXECUTING ICMAKE SCRIPTS) πŸ‘‘
  • --tmpdir=directory (-T) β€” by default temporary files are created in the /tmp sub-directory, or in the user's home (${HOME}) directory if /tmp/ can't be used. To specify another directory to write temporary files in, you can specify icmake's option --tmpdir (or -T), followed by the name of an (existing!) directory to use for temporary files. E.g., when compiling an icmake file main.im, the output of icmake's pre-processor is written to a temporary file which is removed after compilation. To write the temporary file to ~/.icmake, icmake can be called as
icmake -T ~/.icmake -c main.im
  • --unassemble (-u) β€” the file specified as first argument is an icmake bim-file, which gets unassembled πŸ”§ (cf. section ICM-UN below for more info about unassembling icmake bim-files).
  • --verbose (-V) β€” icmake child processes and their arguments are written to the standard output stream before they get called πŸ“’. This option may precede "action" options (-c, -d, -e, -s and -u), either as two separate options or by "gluing" both options together, like -Ve πŸ’…
  • --version (-v) β€” displays its version and then icmake ends. Bye bestie πŸ‘‹βœ¨

πŸ¦‹ EXECUTING ICMAKE SCRIPTS πŸ¦‹

The -t option is available primarily for being used in executable icmake scripts. The first line of executable icmake scripts is made up of these components:

  • a shebang (#!) specification followed by icmake's location;
  • the -t option followed by its argument (see below ⬇️);

and optionally:

  • compilation and execution options (specified as described at the --source option);
  • a non-option component (e.g., :) which will be replaced by the location of the executable icmake script;
  • remaining components on the first line are forwarded as-is to the icmake script's main function;

E.g., the following simple icm executable script args could be defined in ~/bin:

#!/usr/bin/icmake -t. -d one : two --dir three
void main(int argc, list argv)
{
    #ifdef one
        printf << "one is defined\n";
    #endif
    printf << argc << " arguments: " << argv << '\n';
}

When it's called as ~/bin/args four five, then the arguments four and five are added to the two --dir three arguments already specified by the script itself πŸŽ€. Called this way the script outputs β€” its 1st argument is the name of a temporary .bim file whose final extension is different at each new call (see also this section's final paragraph):

one is defined
/tmp/args.F04dgh two --dir three four five

The argument of the -t option is used to specify the location of the files used by icmake's -t option (/dir can also be specified as multiple directories, like /dir/sub1/sub2):

  • if it's a single dot (-t.), the compiled (temporary) bim-file is written in icmake's directory used for temporary files (e.g., /tmp or $HOME) 🏠;
  • if it's ~/dir or /dir, then icmake writes temporary files in the specified directory, replacing ~ by the user's $HOME directory;
  • if it's ~/dir/name or /dir/name, then [~]/dir/name specifies the path of the compiled .bim file, writing all other temporary files in the same directory as the .bim file. The .bim file is kept after execution (allowing it to be executed repeatedly using 'icmake -e') πŸ‘‘. The icmake-script is not compiled if the .bim file is younger than the script.

When executing icmake scripts (either by using executable #/bin/icmake scripts or explicitly calling icmake -t) the preprocessed scripts and usually the compiled script are temporary files β€” which get removed after executing the constructed binary file πŸ—‘οΈ. When errors are encountered, the name of the temporary file containing the errors gets reported. Those temporary files are made of three parts: the directory receiving icmake's temporary files; the filename of the icmake script which is passed to icmake -s; and a random 6-character extension. E.g., when executing a script like showfiles (using #!/bin/icmake -t .) and the script contains errors, then the error messages may refer to /tmp/showfiles.2JS47P πŸ˜­πŸ’€

🌸 ICM-DEP 🌸

Okay so Icm-dep is a little support program that icmake --dependencies (or its short lil' alternative -d) calls out to, and its whole personality is figuring out source- and precompiled-header file dependencies. It's giving "backstage crew" energy β€” you don't see it, but nothing works without it. 🫢

Quick vibe check though: when you're using icmbuild(1) and an icmconf file has the #define SPCH directive, then icmake -d is not used β€” instead, the directories inspected when using a SPCH are automatically inspected (and updated when necessary) by icmake -S. So like, don't manually call the girl, she's already on it. πŸ’…

icmake -d's synopsis is

icmake -d [options] argument

Whatever you put after -d gets forwarded straight to icm-dep. Your options, bestie:

  • --classes=filename (-c) β€” By default, icm-dep inspects the dependencies of the directories mentioned in the file CLASSES. But if the icmconf(7) file specifies PARSER_DIR and/or SCANNER_DIR, then those directories are also considered. Use this option to specify the file containing the names of the directories that icm-dep should inspect. Custom guest list, basically. ✨
  • --gch β€” If an icmconf file specifies the (deprecated πŸ‘€) #define PRECOMP directive, then icmake -d checks whether precompiled headers must be refreshed. If an icmconf file does not contain a #define PRECOMP directive, but precompiled headers should nonetheless be inspected, then you can pass option --gch.
  • --help (-h) β€” A summary of icm-dep's usage gets written to the standard output and icmake terminates, returning 0 to the operating system. The "hey bestie here's how I work" option. πŸ’–
  • --icmconf=filename (-i) β€” By default icmake -d inspects the content of icmconf files. Use this option if, instead of icmconf, some other file should be inspected. Swapping the whole vibe.
  • --mainih=mainheader (-m) β€” In the icmconf file the #define IH directive specifies the suffix of class header files that should be precompiled, assuming their filenames are equal to the names of the directories listed in the CLASSES file. But β€” plot twist β€” CLASSES does not specify the name of the program's top-level directory. So this option specifies the name of the top-level header file to precompile. By default main.ih is used. πŸŽ€
  • --no-gch β€” If an icmconf file contains a (deprecated) #define PRECOMP directive, but icmake -d should not check whether precompiled headers must be refreshed, then specify option --no-gch. Respectfully declining, no cap.
  • --no-use-all β€” If this option is specified then the #define USE_ALL "filename" directive in the icmconf file (cf. icmconf(7)) is ignored. Like leaving it on read. πŸ™ˆ
  • --use-all=filename β€” If this option is specified then all files in directories containing the file filename and source files in directories (recursively) depending on the files in those directories are recompiled. Recursive recompile era. πŸ”₯
  • --verbose (-V) β€” This option can be specified multiple times, and the number of times it's specified determines the verbosity of icmake -d's output. Not specified? icmake -d silently performs its duties (quiet queen πŸ‘‘). Specified once (which is the default specification)? Then icmake -d writes to the standard output the actions it performs. Specified twice? It also reports non-default options and automatically included directories. Three times? It also reports class dependencies. More often than that? It reports what files it encountered and what decision it would make when go would be specified. She's telling you everything, fr fr. πŸ’€
  • --version (-v) β€” Icmake -d writes icm-dep's version number to the standard output and terminates, returning 0 to the operating system. Little flex, then dip. ✌️

Following the non-terminating options, argument go must be specified to allow icmake -d to actually perform its actions. Specifying another argument results in a dry run: it analyzes dependencies, but won't remove or touch files. Basically window shopping. πŸ›οΈ

Heads up bestie: it's go or nothing. No go, no action β€” just vibes and analysis.

Icmake -d can be used for software projects which are developed as described in the C++ Annotations, section Header file organization in chapter Classes. For those projects, classes are developed in their own directories, which are direct sub-directories of the project's main program directory. Their class interfaces are provided in class-header files bearing the names of the class-directories, and all headers that are required by the class's sources are declared in a separate internal header files, commonly having extensions .ih. Iconic structure, lowkey. πŸ¦‹


🌈 ICM-MULTICOMP 🌈

Icmake supports multi-threaded source-file compilation, which often significantly reduces the compilation time of the source files of projects. Multitasking main character energy. ⭐

When you're using icmbuild(1), multi-threaded compilation is automatically used when icmconf files contain the #define MULTICOMP directive (cf. icmconf(7)). It can also be called independently from icmconf using icmake's --multicomp (or -m) option. She doesn't need the config file, she just likes it. πŸ’…

Icmake -m's synopsis is

icmake -m [options] arguments

Icmake -m accepts the following options:

  • --help (-h) β€” Icmake -m writes a summary of its usage to the standard output and terminates, returning 0 to the operating system. The classic "what do I do again" button. 🫢
  • --nr (-n) β€” When compiling source files and option --nr is specified, the thread number compiling a source file is written to the standard output stream. So you can see which lil worker bee did what. 🐝
  • --quiet (-q) β€” When this option is not specified then the path names of the compiled object and source files are written to the standard output stream. When it's specified once, only the source files' directories and filenames are written to the standard output stream, and when it's specified more than once, no information about the compiled files is written to the standard output stream. Levels of shyness, we love a range. πŸŽ€
  • --threads=nThreads (-t) β€” By default the computer's number of cores determines the number of threads being used when compiling the source files. A different number of threads can be requested using this option, e.g., --threads 5. Go off, control the chaos. πŸ”₯
  • --version (-v) β€” Icmake -m reports its version number to the standard output and terminates, returning 0 to the operating system.

Icmake -m needs one command-line argument and an optional second argument. Let's break it down:

  • the first argument is the name of the file specifying which files must be compiled. Use icmbuild(1) to write this file. It can also be constructed otherwise: the specified file must contain groups of file specifications where each group starts with a line like : support tmp/o 5 where the 2nd element (here: support) specifies the (sub-)directory of the source files (use . to refer to the project's top-level directory); the 3rd element (here: tmp/o) specifies the destination directory of the compiled files (which is created if not existing); and the 4th element (here: t) specifies the prefix to add in front of the compiled object files. Following this line, the remaining lines of a group specify the names of the source files (located in the specified (sub-)directory) to compile. Once the compilation ends (either because all files were successfully ccompiled, or because a compilation failed) the specification file is removed. Self-destructing manifest, honestly iconic. πŸ’€βœ¨
  • the second argument is optional. By default the following specification is used (all on one line):
g++ -c -o $2 ${ICMAKE_CPPSTD} --Wall -Werror $1

Here $1 is replaced by the location of the source file to compile and $2 is replaced by the location of the compiled object file. If the environment variable ICMAKE_CPPSTD is defined (specifying the C++ standard to use, e.g., ICMAKE_CPPSTD=--std=c++26) then its value replaces ${ICMAKE_CPPSTD} in the specification.

If the default compiler specification cannot be used, the command to compile source files can be provided as icmake -m's second command-line argument, which should be quoted, like

’g++ -c -o $2 ’${ICMAKE_CPPSTD}’ --Wall -Werror $1’

or the second command-line argument can be f:file, where file is the name of a file whose first line contains the specification of the command compiling source files (which must specify $1 and $2 and optionally $ICMAKE_CPPSTD).

Tea time β˜•: the PATH environment variable is used to locate the compiler; the compiler's absolute path can also be specified. Either way, she'll find it. πŸ’–

πŸŽ€ ICM-SPCH πŸŽ€

okay so Single Pre-Compiled Headers (SPCH, yes that's the acronym, slay) are a thing you get with icmake --spch β€” or the short version, -S. πŸ’…

The synopsis for icmake -S is literally:

icmake -S [options] arguments

And here's every single option it takes, no skipping, bestie:

  • --all=file (-a) β€” calls icm -S's options --list, --precompile, and --soft-links in sequence (all three are described further down), where file is written by --list and then used as the option argument for --precompile and --soft-links. icmake -S --all file can optionally be followed by one or two arguments. If you give them, the first one sets the location of the SPCH file, and the second one sets the (file containing the) compiler command used to build the SPCH. Details live at --precompile below.
  • --classes=filename (-c) β€” filename is the name of a file holding a list of directories that the --list option inspects (default is CLASSES). Your project's top directory gets inspected automatically, unless you pass --no-topdir;
  • --help (-h) β€” icmake -S writes a lil summary of its usage to standard output and then peaces out, returning 0 to the operating system;
  • --internal=.ext (-i) β€” .ext is the extension used for the internal headers (dot included, don't forget it). Default is .ih;
  • --list (-l) β€” ignored when --all is specified. Writes the names of the files to process when constructing an SPCH to the file given as icmake -S's first command line argument. That filename can't have an extension or directory specifications (like spch);
  • --no-topdir (-n) β€” ignore the internal header found in the project's top directory. You'd use this when, e.g., you're merely constructing a library instead of a program;
  • --option=opt (-o) β€” an extra option added to the compiler's options when --precompile is requested. The opt option gets inserted before the compiler's option specification -x (peep the next option, --precompile). You can specify multiple --option options;
  • --precompile=file (-p) β€” precompiles file (the name of the file you gave at --list) into the SPCH file specified as icmake -S's first command-line argument. If that argument ends in / then the SPCH 'argument'file.gch is written instead. By default the SPCH is constructed with this command (all on one line, fr):
g++ -c -o $2 ${ICMAKE_CPPSTD} -Wall -Werror -O2 -x c++-header $1

Here $1 gets replaced by 'file', and $2 gets replaced by the name of the SPCH, while $ICMAKE_CPPSTD refers to the value of the ICMAKE_CPPSTD environment variable (which specifies the C++ standard to use, e.g. ICMAKE_CPPSTD=--std=c++26). Alternatively, the command that constructs the SPCH can be handed in as the second command-line argument, and it should be quoted. Like, e.g. (one line):

'g++ -c -o $2 '${ICMAKE_CPPSTD}' -Wall -Werror -O2 -x c++-header $1'

or that second command-line argument can be f:file, where file is the name of a file whose first line specifies the command constructing the SPCH (which must specify $1 and $2 and optionally $ICMAKE_CPPSTD). The PATH environment variable is used to locate the compiler; you can also just use the compiler's absolute path.

  • --quiet (-q) β€” by default the (g++) command constructing the single precompiled header file is echoed to standard output. Specify this option to suppress writing the command to standard output.
  • --soft-links=file (-s) β€” ignored when --all is specified. This option uses the same arguments as --precompile. It creates .gch soft-links from the header files listed in file to the generated SPCH file;
  • --unused=regex (-u) β€” in practice you probably won't need this, but files matching the (POSIX extended) regex are not inspected by icmake -S. When you use it, specs like (...)|(...) let you specify multiple regexes. Alternatively f:file can be used as the option argument to specify a file whose non-empty lines contain regexes;
  • --version (-v) β€” icmake -S writes its version number to standard output and terminates, returning 0 to the operating system;
  • --warn (-w) β€” interactively warn when existing header files are about to be modified, letting you accept or refuse the modifications. Once you refuse, icm-spch ends.

icmake -S needs one argument, and optionally two β€” all described above at --list, --precompile, and --soft-links. 🫢

Pre-compiled headers have been around for quite a while and usually give a significant reduction in compilation time. And using single precompiled headers gives a large reduction in the disk space you need, compared to using precompiled headers for separate directories. ✨

When you use SPCHs, almost-identical precompiled headers for separate directories get avoided: only one precompiled header is constructed, and then every component of a project uses it. Because identical sections are avoided, the sizes (and construction times) of SPCHs are way smaller β€” usually only like 5 to 10 % of the space (and construction time) compared to using separately constructed pre-compiled headers. πŸ”₯

SPCHs are super easy to use together with icmbuild(1). Often a specification in a project's icmconf file like #define SPCH "" is literally all it takes (cf. icmconf(7)). πŸ‘‘


πŸ¦‹ ICM-UN πŸ¦‹

The support program icm-un is called by icmake -u, and it expects one argument: a bim-file. It disassembles that binary file and shows you the assembler instructions plus the structure of the bim-file.

So as an illustration, imagine this script gets compiled by icmake -c demo.im:

void main()
{
    printf << "hello world\n";
}

then the resulting demo.bim file gets disassembled by icmake -u demo.bim, which writes the following to the standard output file (yes, "fle" in the original, we don't gatekeep typos):

icm-un by Frank B. Brokken (f.b.brokken@rug.nl)
icm-un V12.04.00
Copyright (c) GPL 1992-2024. NO WARRANTY.

Binary file statistics:
    strings      at offset  0x0025
    variables    at offset  0x0033
    filename     at offset  0x0033
    code         at offset  0x0014
    first opcode at offset  0x0021

String constants dump:
    [0025 (0000)] ""
    [0026 (0001)] "hello world."

Disassembled code:
    [0014] 06 01 00   push string "hello world."
    [0017] 05 01 00   push int 0001
    [001a] 1b 1d      callrss 1d (printf)
    [001c] 1c 02      add sp, 02
    [001e] 04         push int 0
    [001f] 24         pop reg
    [0020] 23         ret
    [0021] 21 14 00   call [0014]
    [0024] 1d         exit

Offsets are shown in hexadecimal and they're absolute byte offsets in the bim-file. The string constants dump also shows, between parentheses, the offsets of the individual strings relative to the start of the strings section. The output also shows the opcodes of the instructions of the compiled .im source files. If opcodes use arguments, then those argument values show up after their opcodes. Every opcode line ends by showing the opcode's mnemonic plus (if applicable) the nature of its argument. 🧚


🌸 FILES 🌸

The paths mentioned here are the ones used in the source distribution and by the Debian Linux distribution. But ngl they're suggestive only and might have been configured differently:

Binary programs:

  • /usr/bin/icmake: the main icmake program;
  • /usr/bin/icmbuild: the wrapper program around the icmbuild script handling standard program maintenance;
  • /usr/bin/icmodmap: the module mapper which initializes the maintenance of C++ programs using modules;
  • /usr/bin/icmstart: an icmake-script that can be used to create the startup-files of new projects;

Support programs:

  • /usr/libexec/icmake/icm-comp: the compiler called by icmake;
  • /usr/libexec/icmake/icm-dep: the support program handling class-dependencies;
  • /usr/libexec/icmake/icm-exec: the byte-code interpreter;
  • /usr/libexec/icmake/icm-multicomp: the multi-thread source file compiler;
  • /usr/libexec/icmake/icm-pp: the preprocessor called by icmake;
  • /usr/libexec/icmake/icm-spch: the program preparing SPCHs;
  • /usr/libexec/icmake/icm-un: the icmake unassembler.

⭐ EXAMPLES ⭐

The distribution (usually in /usr/share/doc/icmake) contains a directory examples with additional examples of icmake script. The icmstart script is an icmake script, and so is /usr/libexec/icmake/icmbuild, which is called by the /usr/bin/icmbuild program. Also go peek at the EXAMPLE section in the icmscript(7) man-page. πŸ’–


πŸ‘‘ SEE ALSO πŸ‘‘

chmod(1), icmbuild(1), icmconf(7), icmodmap(1), icmscript(7), icmstart(1), icmstart.rc(7), make(1)


πŸ’€ BUGS πŸ’€

None reported. (iconic behaviour, honestly)


This is free software, distributed under the terms of the GNU General Public License (GPL).


πŸ’œ AUTHOR πŸ’œ

Frank B. Brokken (f.b.brokken@rug.nl).


and that's a wrap on the whole page, bestie 🫢 this was icmake.13.07.00, dated 1992-2026 β€” go forth and compile, mwah πŸ’…βœ¨

πŸ“¦ where this page comes from