The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

CBUILD

From Allegro Wiki
Revision as of 05:37, December 23, 2006 by Awikiadmin (talk | contribs) (twiki import)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
This article is a stub. Please help Allegro by expanding it.


Cbuild Image:wip.gif

Introduction

A multiplatform build system using (mostly) standard ANSI C aimed at organizing and creating projects with ease.

Image:help.gif add more information


Usage

CBuild comes with a single source file cbuild.c and it's default script file default.cbd. The file cbuild.c is self-compiling under Linux and theoretically should be under Windows with a BASH shell (such as MSys).

So issuing:

myshell $ ./cbuild.c

will get it started and read in the default.cbd file and do whatever it is instructed to do within that file.


Example

Lets take a look at the provided default.cbd and explan it's usage: <highlightSyntax language="cbuild"># Example cbuild script file, which can be used to build itself with GCC.

  1. Note: This is a comparitively simple example, and in no way showcases
  2. CBuild's extensive capabilities. For more in-depth information, please see
  3. the AWiki entry at <http://awiki.tomasu.org/bin/view/Main/CBUILD>
  1. Everything past the first '#' character in a line is ignored. To put a '#'
  2. character in a line, escape it like '\#', or put it in quotes.
  3. Use ${var} to dereference the environment variable 'var', and $(cmd otps) to
  4. replace text using sub-command 'cmd'.
  5. &#xxxx; will give you the character the given number value represents, in
  6. UTF-8 (ie. © or &#0xA9; will give you the copyright symbol on a UTF-8
  7. compatible console). In addition, the standard HTML entity names are also
  8. valid (ie. © will also give you the copyright symbol).
  1. All whitespace between a command and its option(s) are eaten by the parser.


  1. You can use 'echo' to print a line to the console. Use 'put' to print a
  2. line without a trailing newline

echo "CBuild © 2006" echo ""

  1. 'ifopt' checks the command line for the specified option. The rest of the
  2. line will only be processed if it was passed. Whitespace between the option
  3. name and next command is ignored. If the command line opt has a =, it will
  4. be treated as an opt=val pair and only the portion before the = needs to
  5. match.
  6. 'verbose' causes cbuild to display the commands being run for a number of
  7. commands, in place of the cleaner, more readable output.

ifopt verbose verbose 1


  1. To keep the main directory clean, it's usually best to put the temporary
  2. object and dependancy files into subdirectories. Changing the variables
  3. OBJ_DIR and DEP_DIR will do just this.

OBJ_DIR = obj DEP_DIR = dep


  1. The 'do' command allows cbuild to execute a block if the following if-type
  2. check passes. End the block with 'done' or use 'else' (which can also be
  3. followed by an if-type command) to make another block to run if the initial
  4. check failed. Indentation is unimportant.

do ifopt help echo " CBuild - a platform-independant build system using (mostly) ANSI C.

Available options:

   verbose        - Enable more verbose command printing
   clean          - Clean a previously compiled build
   --install path - Installs the optimized executable to the specified path
   help           - Display this help message

For advanced scripting information, please see CBuild's AWiki entry at <http://awiki.tomasu.org/bin/view/Main/CBUILD> To report bugs, please email me at <kcat@strangesoft.net> or <chris.kcat@gmail.com>. "

# 'exit' returns from the script, and cbuild will return with the specified # number as the exit code exit 0 done


  1. 'goto' jumps to the specified label (prepended with ':') which can be ahead
  2. of or behind the current line.

ifopt clean goto clean


  1. Here we set some standard optimizing C flags. This only persists until
  2. another line is encountered that sets them differently. You can use ?=
  3. instead of = to set a variable only if its not already set. If you wish
  4. to start with spaces, encapsulate the value in s or ""s, or escape
  5. the first whitespace character with \

CFLAGS ?= "-O2 -W -Wall"


  1. Create the object and dependancy file directories. 'ifnexist' will run the
  2. following command if the specified file or directory doesn't exist.

ifnexist ${OBJ_DIR} mkdir ${OBJ_DIR} ifnexist ${DEP_DIR} mkdir ${DEP_DIR}


echo "" echo "- Building optimized version -"

  1. This compiles a list of source files, one at a time. Files with the '.c'
  2. extension are compiled using the program specified in 'CC' (default: 'gcc').
  3. The source files will have their extension changed to 'OBJ_EXT' (default
  4. value: '.o') when compiled, and be placed in 'OBJ_DIR'. 'CFLAGS' and
  5. 'CPPFLAGS' will be applied to the command line for C files.

compile cbuild.c


  1. linkexec will link the previously-compiled objects into the named file with
  2. the command named in 'LD' (default: 'gcc'). LDFLAGS will be applied to the
  3. end of the command line. The specified output file will have 'EXE_EXT'
  4. (default: '.exe' in Win32, nothing elsewhere) appended.

linkexec cbuild


echo "" echo "- Building debug version -"

  1. This sets some debug cflags and sets the object extension to '-dbg.o', causing
  2. the source file to compile as 'cbuild-dbg.o'

CFLAGS = "-MMD -g3" OBJ_EXT = "-dbg.o" compile cbuild.c linkexec cbuild-dbg

echo ""

  1. The getoptval directive gives the value of an option passed to the command line
  2. in the form of 'option=value' or 'option value'

INSTALL_PATH = $('getoptval' --install)

  1. 'if' will run the following command(s) if the two values (in the form x=y)
  2. are equal.

do if "${INSTALL_PATH}"="" put "Do you wish to install CBuild? [y/N] "

# 'read' will read user keyboard input until enter/return is pressed read INPUT

ifnot $(tolower ${'INPUT'})='y' ifnot $(tolower ${'INPUT'})='yes' exit 0

do ifplat win32 INSTALL_PATH = ${'WINDIR'} else ifplat dos INSTALL_PATH = C:/DOS else INSTALL_PATH = /usr/local/bin done

# 'fixpath' converts \ directory seperators to / in the specified var. This # is required for CBuild to behave properly with directories fixpath INSTALL_PATH

echo "" echo "CBuild will install to '"${'INSTALL_PATH'}"'." echo "If you wish to use a different location, please specify it below (press enter" echo "for the default, type 'abort' to abort installation)" put "-> "

get_path

read INPUT

# 'fixpath' converts \ directory seperators to / in the specified var. This # is required for CBuild to behave properly with directories fixpath INPUT

do ifnot ${'INPUT'}= if $('tolower' ${'INPUT'})='abort' exit 0 do ifnexist ${'INPUT'}/. echo "" echo "The directory '"${'INPUT'}"/' doesn't appear to exist." echo "Please specify a valid path, or 'abort' to abort installation." put "-> " goto get_path done INSTALL_PATH = ${'INPUT'} done done

copyexec cbuild ${'INSTALL_PATH'}/ echo ""

exit 0

clean
  1. Here's the cleanup area, accessible if you pass "clean" to cbuild. "rmexec"
  2. deletes the specified executable (prepending 'EXE_EXT' to the filename), and
  3. "rmobj" deletes the object and dependancy file that would be generated by
  4. compiling the specified file. Prepending a command with "-" will cause cbuild
  5. to continue even if the command fails, while prepending with '!' will cause
  6. cbuild to continue without any error messages.

-rmexec cbuild cbuild-dbg

-rmobj cbuild OBJ_EXT = "-dbg.o" -rmobj cbuild

-rm "${OBJ_DIR}" "${DEP_DIR}"

exit 0

</highlightSyntax>

Image:wip.gif incomplete

Here's another, even simpler, example: CBUILD_Example2


Advanced


Syntax

To read variables, use the syntax ${VARIABLE}. Using ${'VARIABLE'} will encapsulate the given variable's value within 'hard quotes'. To set a variable, use VARIABLE = value.

Internally Recognized Variables
VARIABLE DEFAULT DESCRIPTION
* N/A All of the cmd-line arguments
@ N/A All of the cmd-line arguments, individually encapsulated in 'hard quotes' (caveat: using ${'@'} will behave like ${'*')!)
0... N/A The given cmd-line argument (0 is the executing command, 1 is the first argument, 2 is the second, etc). Out-of-bounds arguments (i.e. anything greater than or equal to argc) will give nothing
CC gcc C compiler to use
CXX =g++= C++ compiler to use
LD gcc Linker to use
OUT_OPT -o  compiler flag to specify the output file (the object file name will immediately follow this)
SRC_OPT -c  compiler flag to specify source-to-object compilation (the source file name will immediately follow this)
DEP_OPT -MMD -MF  compiler flag to generate a dependancy file (the dependancy file name will immediately follow this). If this is blank, dependancy files aren't generated and the other DEP_* vars are ignored
OBJ_EXT .o extension to use for objects
OBJ_DIR . directory for object files (. means current directory)
DEP_EXT .d extension to use for dependency files
DEP_DIR . directory for dependency files (. means current directory)
EXE_EXT .exe in dos/windows Executable file extension
AR ar Archiver to use (to create static libraries)
AR_OPT archiver flags
LIB_PRE lib library prefix
LIB_EXT .a library file extension
CPPFLAGS additional preprocessor flags
CFLAGS additional C compiler flags
CXXFLAGS additional C++ compiler flags
LDFLAGS additional linker flags
EXTRA_SRC_DEPS additional dependancies to check when compiling source files
EXTRA_LD_DEPS additional dependancies to check when linking (commands that use LD only)

The commands below are provided for your use.

Command Chart
COMMAND USAGE DESCRIPTION
do
do command
starts a multi line command
else
else
lets you specify an alternate action for if* commands
done
done
ends a multi line command
if
if "foo"="bar" command
runs command if "foo" and "bar" are equal
ifnot
ifnot "foo"="bar" command
runs command if "foo" and "bar" are not equal
ifret
ifret NUMBER command
runs command if the last command's result is equal to NUMBER. Note that not all commands will (re)set the return value!
ifnret
ifnret NUMBER command
runs command if the last command's result is not equal to NUMBER
ifplat
ifplat PLATFORM command
runs command if the current platform is PLATFORM. Available platforms include win32, linux, macosx, msdos, unix, i386, and more (see below for full list).
ifnplat
ifnplat PLATFORM command
runs command if the current platform isn't PLATFORM
ifopt
ifopt OPTION command
runs command if OPTION was passed at the command line
ifnopt
ifnopt OPTION command
runs command if OPTION wasn't passed at the command line
ifexist
ifexist FILE command
runs command if FILE exists
ifnexist
ifnexist FILE command
runs command if FILE doesn't exist
ifwrite
ifwrite FILE command
runs command if FILE has write permissions (this will be false if the file doesn't exist)
ifnwrite
ifnwrite FILE command
runs command if FILE doesn't have write permissions
call
call command
runs command via the system shell
fixpath
fixpath VARNAME
modifies the given variable to use / as path seperators instead of \. This is required for DOS/Windows-style paths as CBuild will not recognize \-seperators as directories (note: the variable name is given as VARNAME, not ${VARNAME}!)
reinvoke
reinvoke args
reinvokes the current cbuild file with the given optional arguments
invoke
invoke file
invokes a new cbuild file within the current context
define
define NAME COMMAND
creates a command with the given NAME, which will act like the given COMMAND. Commands defined here will not override existing commands. Using ${num} in the COMMAND (within 'quotes' or with the $ escaped, so it doesn't expand when first processed) will be replaced with the arguments passed to the command later (${0} will be the command name, ${1} the first word after, etc). Be aware, the arguments passed to a defined command will be parsed twice, once when read, and again when used, so take this into account
compile
compile file_list
compiles a list of files, and stores them in a list to be linked later
compileadd
compileadd file_list
same as above, and adds them to the same list as the last compile command
linkexec
linkexec file
Links an executable file, using the previously-compiled source files. The executable will have EXE_EXT appended.
linklib
linklib file
Links a standard archive library, using the previously-compiled source files. The file will have LIB_PRE prepended, and is sub-directory-aware, as well as have LIB_EXT appended.
loadlist
loadlist LIST
Loads a list of words into a buffer, to later execute an action on them
execlist
execlist command
Executes a command on each of the words in the previously loaded list. Use the macro <@> to specify the word being used
echo
echo TEXT
Prints a string to the console
put
put TEXT
Prints a string to the console without a newline
read
read VARNAME
Reads user-input from stdin until a new-line is encountered, and stores it in the variable VARNAME. The trailing new-line is stripped
setinput
setinput FILE
Opens FILE for subsequent read calls, in place of stdin. Pass nothing for FILE to revert to stdin
writefile
writefile FILE TEXT
Creates/truncates a file and writes a string to it
appendfile
appendfile FILE TEXT
Appends a string to a file
goto
goto LABEL
Jumps to the specified label. A label is denoted by a '#:' combo prepended to it at the beginning of a line
src_paths
src_paths DIRLIST
Stores a list of paths to look for source files in. Passing only '.' clears the list.
rmexec
rmexec LIST
Deletes the specified executables, appending EXE_EXT to the names as needed
rmlib
rmlib LIST
Deletes the specified libraries, prepending LIB_PRE to the filename portions and appending with LIB_EXT
rmobj
rmobj LIST
Removes a list of object files and their associated dependancy files, replacing the extension of the named file as necesarry
rm
rm LIST
Removes a list of files or empty directories.
mkdir
mkdir DIR
Creates a directory (with mode 700 in Unix)
verbose
verbose NUM
Enables/disables command verboseness.
uninvoke
uninvoke NUM
Leaves the current script, falling back to the previous if the current was started with the invoke command. Otherwise, it behaves like exit.
copy
copy file1 file2
Copies a file.
copylib
copylib name1 name2
Copies a library file, prepending and appending the names as necesarry.
copyexec
copyexec name1 name2
Copies an executable file, appending the names as necesarry.
popfront
popfront VARNAME
Removes the first word and trailing whitespace from the variable VARMNAME
associate
associate ext command
Sets a command to compile files with the specified ext with (the command can use the macros <@>, <!>, and <*> to get the object name, source name, and unadorned file name (as passed to the compile or compileadd command, without the extension)
exit
exit NUM
Exits the script with the specified exitcode.
ADD MORE STUFF

Using a compiler's pre-defined macro set, CBuild can currently detect the following platforms: aix, amigaos, beos, unicos, dgux, dynix, freebsd, gnuhurd, hpux, irix, linux, macosx, mpeix, msdos, netbsd, openbsd, os2, pyramiddc, qnx4, qnx6, reliantunix, scoopensever, solaris, sunos, solaris, symbian, osf1 (aka tru64), ultrix, unixware, vms, and win32. As well, it detects the following general environments: bsd, svr4, unix, uwin, and windu. As well as the architectures: i386, ia64, powerpc, and sparc.

Note that these are detected when CBuild is compiled, so if you want run-time detection you'll need to do some of your own checking in a script.

When defining your own commands, be aware that there are internal commands not listed here which may take precedance. These commands are prefixed with at least one underscore (_). As well, defining a command that begins with atexit_ will cause that command to be executed when the script exits, in the opposite order in which they were defined. If another exit is triggered, the script will immediately abort.


When used, the following sub-commands will be replaced with the described text. They use the syntax $(command options). Some sub-commands have strict formatting rules regarding the , character and may abort the script if this isn't met. Prefixing the command name with * will cause the returned value to be encapsulated in 'hard quotes' (important when dealing with user input).

Sub-command Chart
COMMAND USAGE DESCRIPTION
getoptval
$(getoptval variable)
gets the value of command line arguments in the form --foo=blah or --foo blah
word
$(word n,list-of-words)
gives the n th word from the given list (1-based)
libname
$(libname name)
builds the name of a library, ie: $(libname name) may give: libname.a
findsrc
$(findsrc list-of-files)
looks for the given source files, by searching the paths given to src_paths, and returns the files with the proper path
ifeq
$(ifeq A,B,YES,NO)
returns YES if A and B are the same, NO if not.
add
$(add A,B)
returns the result of A+B
sub
$(sub A,B)
returns the result of A-B
mult
$(mult A,B)
returns the result of A*B
div
$(div A,B)
returns the result of A/B (warning: if B evaluates to 0, the script will abort with a divide-by-0 error)
lsa
$(lsa list-of-files)
for directories, returns a listing of all files and directories inside it, including . and ... For files, returns the given name if it exists
ls
$(ls list-of-files)
same as lsa except it disregards files starting with .
tolower
$(tolower string)
returns string with all uppercase characters converted to lowercase
toupper
$(toupper string)
returns string with all lowercase characters converted to uppercase
which
$(which program)
returns the full location of program by searching the path. Note for DOS and Windows, you need to specify the .exe extension (${EXE_EXT} may be used)
suffix
$(suffix list-of-files)
strips out the path and base filename of the given list, returning only the file extensions
basename
$(basename list-of-files)
strips out the suffixes of the given file list
addprefix
$(addprefix pre,list-of-words)
prefixes the given list of words with pre
addsuffix
$(addsuffix suf,list-of-words)
appends suf to the given list of words
dir
$(dir list-of-files)
removes the filename portions, leaving only the paths (note: only / is seen valid path seperator)
notdir
$(notdir list-of-files)
removes the paths, leaving only the filenames

Note: lsa, ls, suffix, basename, addprefix, addsuffix, join, dir, and notdir will only leave one space between returned words.


Bash Autocompletion Code:

Add this to your ~/.bashrc and see a miracle ;) <highlightSyntax language="bash"> alias cbuild="./cbuild.c"

_cbuild_opts () {

  FILES=( default.cbd )
  COMPREPLY=()
  k=${#FILES[@]}
  for (( i=0; i < $k; i++ )); do
     for j in `grep -s -E 'invoke .*.cbd' ${FILES[i]} | cut -d' ' -f2`; do
        FILES[$k]="$j";
        let k+=1
     done
  done
  rm -fr tmp
  touch tmp
  k=0
  for i in ${FILES[@]} ; do
     echo $i >> tmp
  done
  tmp=`sort -u tmp`
  rm -fr tmp
  touch tmp
  for i in $tmp; do
     if [ -f $i ] ; then
        for j in `cat $i | sed -n -e 's/.*ifn\?opt\s\+\([^ \t]\+\).*/\1/p' -e 's/\$(getoptval\s\+\(\[^)]+\))/\1/p'`; do
           echo $j >> tmp
        done
     fi
  done
  k=0
  for i in `sort -u tmp`; do
     COMPREPLY[$k]=$i
     let k+=1
  done
  rm -fr tmp

} complete -F _cbuild_opts ./cbuild cbuild

</highlightSyntax>

Credits

Files: Latest Cbuild

Written by KittyCat

  • File:Cbuild.xml: Kate syntax file
    • Place into ~/.kde/share/apps/katepart/syntax/ and kate will highlight cbuild files

Requests

  • $(backticks program) or
  • capture VAR program
    • $VAR now contains the output of "program"