Tutorial

Why Would You Want To Use WhyTools?

WhyTools Build Environment Setup

  1. Create a subdirectory for the build environment files somewhere. I recommend creating it as ~/WhyTools.
  2. Stick SystemDefinitions, Packages, BasicMakefile and the template makefile into the just created directory.
  3. Go over the SystemDefinitions file and edit it to fit your environment. Set up the correct operating system type, machine architecture, your preferred compiler type, etc. If you are using Linux or Mac OS X and GNU gcc/g++, you can probably just go with the defaults. The following settings should be checked:
    GNUC_BASEDIR
    Root directory of the "GNU compiler collection (gcc)." This is used to construct the names of compilers and such. You can find out yours by typing "which gcc" and taking everything up to, but not including, the /bin/gcc.
  4. Go over the Packages file and adapt the packages' base directories according to your directory structure. If there are packages you never use, or that don't exist on your system, just remove them. Or leave them be.
  5. Create an environment variable BUILDROOT and point it to the new directory. For example, type "setenv BUILDROOT ~/WhyTools." I recommend adding this to your .cshrc script.
  6. While you're at it, add ./exe (or ./exe/64 on 64-bit Linuxes) to your path, preferrably at the beginning: "setenv PATH ./exe:${PATH}," or "setenv PATH ./exe/64:${PATH}," respectively.

Starting A New Project

  1. Create a project directory, say "~/Project."
  2. Create a few C/C++ source files, headers, etc.
  3. Copy the template makefile from the build environment directory.
  4. Edit the copied makefile:
    1. Set default optimization level and debugging level for this project.
    2. Set any special compiler/linker flags your project requires.
    3. List the software packages your project depends on in the PACKAGES variable. For example, a project that requires Fltk and OpenGL would use a package line like this:
      PACKAGES = FLTK GL
      
      This list of packages will be applied to all targets; you can augment or redefine the package list on a per-target basis if required.
    4. Edit the makefile to contain a rule to build your executable.
      ...
      ########################################################################
      # Specify build rules for executables
      ########################################################################
      
      # These are all the source files that need to be *linked* into
      # the "Main" executable:
      MAIN_SOURCES = Source1.cpp \
                     Source2.cpp \
                     Source3.cpp \
                     ... \
                     SourceN.cpp
      
      # ... or, to just use *all* sources found in the project directory
      # and all its subdirectories:
      MAIN_SOURCES = $(shell find --follow . -name "*.cpp")
      
      # Set up a target for the "Main" executable with a list of
      # object files it depends on:
      $(EXEDIR)/Main: $(MAIN_SOURCES:%.cpp=$(OBJDIR)/%.o)
      # Note: No actual linker command line required!
      
      # Set up a phony target to allow typing "make Main" for building
      # the "Main" executable:
      .PHONY: Main
      Main: $(EXEDIR)/Main
      ...
      
    5. Now add the $(EXEDIR)/Main target to the list of all targets at the top of the makefile:
      ...
      ALL = $(EXEDIR)/Main
      ...
      
      (Use the full $(EXEDIR)/Main target to ensure that it will be deleted on a "make clean".)

      Of course, this is the simplest possible setup. A project directory can contain any number of executable targets, libraries, shared libraries, etc. Parameters and flags can be overriden on a per-target basis, this includes per-executable-target override and per-objectfile-target override. Say that the Main executable uses the pthreads library. You can tell the compiler and linker where to find the library by adding a per-target parameter (before the other lines regarding target Main):

      $(EXEDIR)/Main: PACKAGES += PTHREADS
      
  5. Now, just typing "make" or "make Main" will build the executable with default debug and optimization options. The build will create three subdirectories under the project directory:
    1. A directory "d" containing the automatically generated dependency files.
    2. A directory "o" containing subdirectories (generated from compiler options) containing all generated object files.
    3. A directory "exe" containing generated executable files.
  6. To specify different options temporarily, say to build a quick debug version, specify values for OPTLEVEL and/or DEBUGLEVEL on the make commandline: "make OPTLEVEL=0 DEBUGLEVEL=2," or use the default debugging flags by running "make DEBUG=1." Object files generated with different compiler options will not clobber object files from other builds.
  7. Typing "make clean" will delete all object files generated from the default compiler options and all executable targets contained in the ALL list. Other actions to be performed on a make clean can be listed under the extraclean target in the makefile.
  8. To completely remove all subdirectories created by the build process, type "make squeakyclean." This will recursively delete all files under the dependency, object and executable subdirectories. Other actions to be performed on a make squeakyclean can be listed under the extrasqueakyclean target in the makefile.