# Writing Umakefil/*.pcf Files

## Targets and global functions

UmakefileVersion(major, minor)
arguments: major(int), minor(int)
returns: none
All umake files should start with a call to UmakefileVersion(), this will tell the build system how to interpret the contents of the umake file in a way that is backwards compatible. When creating a new umake file, you should use the version of the build system you are currently using. This documentation was written for build 2.2 which means that you should use `UmakefileVersion(2,2)` in order to get the build system to behave as described here.

MultiTargetMake(umakefil1_path, umakefil2_path, ...)
arguments: umakefil1_path(string)
returns: none
See full documentation here.

ProgramWithResourceTarget(target, rtarget, rfile, includes)
arguments: target(string), rtarget(string), rfile(string), includes(string or list of strings)
returns: none
On the Macintosh OS9, this builds a program and Windows .xrs DLL. On all other platforms, ProgramWithResourceTarget simply calls ProgramTarget with the target argument.

DLLWithResourceTarget(target, rtarget, rfile, includes)
arguments: target(string), rtarget(string), rfile(string), includes(string or list of strings)
returns: none
On the Macintosh OS9, this builds a DLL and Windows .xrs DLL. On all other platforms, DLLWithResourceTarget simply calls DLLTarget with the target argument.

ProgramTarget(target)
arguments: target(string)
returns: none
Specifies a executable should be built from the project data, with name name target. Umake may add a platform-appropriate extension to the output name. There are also several other methods of changing the output name of the executable.

LibraryTarget(target)
arguments: target(string)
returns: none
Specifies a static library should be built from the project data, with name name target. Umake may add a platform-appropriate extension to the output name. There are no other ways of changing the output name for a static library, because project.AddModuleLibraries allows linking to static libraries by adding only their module name. Because of this, the only way for those other modules to find the library is to assume its name was created the standard way by umake. Also, target must be the same as the CVS module name.

DLLTarget(target, [ libtarget ])
arguments: target(string), libtarget(string)
returns: none
Specifies a dynamic library should be built from the project data, with name name target. Umake may add a platform-appropriate extension to the output name, and change the name to include versioning information. There are also several other methods of changing the output name of the DLL.

If the optional argument libtarget is specified, the *.lib file generated by some platforms will use this name instead of target.

EmptyTarget()
arguments: none
returns: none
Creates a empty Makefile.

GetSDKPath(sdk_name)
arguments: sdk_name(string)
returns: path(string)
This function allows you to access the path to an third party library or SDK. These paths should be defined in your buildrc file, or using environment variables. For more information on sdk:s, see the SDK BIF tag. GetSDKPath will always return an absolute path.

SetSDKPath(sdk_name, path)
arguments: sdk_name(string), path(string)
returns: none
This function tells the build system where to find an SDK. It is required in order for the build system to be able to find directx and other third party libraries. These paths can later be used in your umake files and should also be declared in your BIF files.

## Global Variables

ALL GLOBAL VARIABLES ARE DEPRECATED. Yes, that's right. The entire Umakefil should be written with methods of the project object described below.

common_defines = "define1 define2 ..."
Specifies a space-separated list of defines to be added to the project. This has been replaced with project.AddDefines().

common_libraries = "module1 module2 ..."
Specifies a space-separated list of static libraries built in CVS modules named module1, module2, etc., should be added to the project. This has been replaced with project.AddModuleLibraries().

common_includes = "path1 path2 ..."
Specifies a space-separated list of include search paths to be added to the project. This has been replaced with project.AddIncludes().

common_srcs = "source1_path source2_path ..."
Specifies a space-separated list of source files to be added to the project. This has been replaced with project.AddSources().

sub_umakes = "umake1 umake2 ..."
sub_platform_name_pcfs = "name1 name2 ..."
sub_platform_type_pcfs = "type1 type2 .."
Specifies a space-separated list of umake files for a multi-target module. This entire method of writing multi-target makefiles has been deprecated because it is fundamentally broken.

## Methods of project

project.SetDLLTypePlugin()
project.SetDLLTypeCodec()
project.SetDLLTypeCommon()
arguments: none
returns: none
Specifies the DLL being built is a G2 plug-in, codec, or common(normal). This is used in when building in a mode which statically links the plug-ins into the player.

project.AddBuildOption(option)
arguments: option(string)
returns: none
Sets the same type of build option as the -t option does on the command line. Results may be mixed, because a particular option may have to be processed before the Umakefil is executed.

project.RemoveBuildOption(option)
arguments: option(string)
returns: none
Removes a build option if it was previously set. Results may be mixed, because a particular option may have already been processed before the Umakefil is executed.

project.BuildOption(option)
arguments: option(string)
returns: true/false
Checks if a build option was set.

project.AddSources(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Adds sources to the project. This method takes a comma-separated list of strings. It is best to use UNIX-style (/ path separators) in deep paths, because Umake can convert those paths to the platform-specific paths automatically.

project.AddModuleSources(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Similar to AddSources, but each source is relative to the source root rather than the current directory.

project.RemoveSources(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Removes sources already added to the project, while not blocking those sources from being included later in the Umakefil. The paths must match the string they were added with exactly.

project.AddSourceObjects(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Adds pre-compiled object files to the project. This feature is used in the codes for hand-optimized assembly from Intel.

project.RemoveSourceObjects(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Removes pre-compiled object files from the project.

project.AddIncludes(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Adds header file include paths to the project.

project.RemoveIncludes(source1_path, source2_path, ...)
arguments: variable number of paths(strings)
returns: none
Removes header file include paths from the project.

project.AddModuleIncludes(module1, module2, module3/dir...)
arguments: variable number of paths(strings)
returns: none
Similar to AddIncludes, but paths should be relative to the build root and always use "/" as path separators. So, instead of doing `project.AddIncludes("../gemctl/pub")` you can do `project.AddModuleIncludes("gemctl/pub")`.

project.RemoveModuleIncludes(module1, module2, module3/dir...)
arguments: variable number of paths(strings)
returns: none
Removes header file include paths from the project, syntax is same as project.AddModuleIncludes.

project.AddDefines(define1, define2, ...)
arguments: variable number of defines(strings)
returns: none
Adds C/C++ defines to the project. A define string without a string assignment will default to true, otherwise a value can be set by including the assignment in the string with a = sign. For example: "DEBUG=2" would define the symbol DEBUG to be the value 2.

project.RemoveDefines(define1, define2, ...)
arguments: variable number of defines(strings)
returns: none
Removes C/C++ defines from the project. They must appear exactly as they were added.

project.IsDefined(define)
arguments: a define(string)
returns: bool
Returns true if define is defined, false otherwise.

project.AddLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.RemoveLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.AddSystemLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.RemoveSystemLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.AddDynamicLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.RemoveDynamicLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.AddModuleLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none
This method links against a library created by the build system. Each argument should the name of the module containing that library. If the module is in a subdirectory, / can be used to specify the name. If the name of the library is not the same as the directory it is in, you can append [libname] to specify the name of the library.

> Examples: (where "release" is sometimes replaced with "debug")
> `project.AddModuleLibrary("pnmisc") # Link against pnmisc/release/pnmisc.lib
> project.AddModuleLibrary("foo/bar") # Link against foo/bar/release/bar.lib
> project.AddModuleLibrary("foo/bar[gazonk]") # Link against foo/bar/release/gazonk.lib
> `

When executing AddModuleLibraries, umake will also look for a file called module/libraryname_linkhook.cf and execute it if present. This allows the module to add include paths and other magic so that the library users don't have to think about it.

> Examples: `project.AddModuleLibrary("pnmisc") # Execute pnmisc/pnmisc_linkhook.cf project.AddModuleLibrary("foo/bar") # Execute foo/bar/bar_linkhook.cf project.AddModuleLibrary("foo/bar[gazonk]") # Execute foo/bar/gazonk_linkhook.cf`

project.RemoveModuleLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.AddLocalLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.RemoveLocalLibraries(lib1_path, lib2_path, ...)
arguments: variable number of libraries(strings)
returns: none

project.AddSystemPaths(path1, path2, ...)
arguments: variable number of paths(strings)
returns: none

project.RemoveSystemPaths(path1, path2, ...)
arguments: variable number of paths(strings)
returns: none

project.ExportFunction(func, proto [, includedir, includefile ])
arguments: func(string), proto(string
returns: none
This function should be used in DLLs to export functions which needs to be accessed from outside the DLL. The proto should be a list of arguments accepted by this function. The proto will be used to build prototypes for this function in global header files. If the includeddir and includefile parameters are present, the includefile will be added to the generated header file, and includedir is the directory which contains that include file. Includefile should be relative to the source root as it will be sent to project.AddModuleIncludes in the project which use this header file.

project.AddExportedFunctions(func1, func2, ...) - deprecated
arguments: variable number of functions(strings)
returns: none

project.RemoveExportedFunctions(func1, func2, ...)
arguments: variable number of functions(strings)
returns: none

project.AddCopyTargets(path1, path2, ...)
arguments: variable number of paths(strings)
returns: none

project.RemoveCopyTargets(path1, path2, ...)
arguments: variable number of paths(strings)
returns: none

project.SetModuleDepth(depth)
arguments: depth(int)
returns: none
This function tells the build system how many directory levels below the build root this module is. The default value is 1.

project.EnableFeature(feature)
arguments: feature(string)
returns: none
This function allows you to do what UmakefileVersion does manually. This is the list of features you can turn on using this function:

submodules
  This will enable multi-target umake files to cd into the directory where a submodule is located instead of trying to execute it from the current working directory.

versioning_off
  This will turn off name mangling for DLLs on most platforms. Normally *.ver files are used to create a versioned filename for DLLs, but with this feature. (Which is on by default if you use `UmakeFileVersion(2,1)` or greater)

  project.SetBuildVersion(date) - deprecated
  arguments: date(int)
  returns: none
  This function tells the build system to try to be compatible with the build system on date date. Date should be a 8-digit number on the form `YYYYMMDD`. Please note that the default is 20020101, which means that some newer functionality will be turned off unless you incorporate this function in your umake file.

  project.SetBuild2002Version(date) - deprecated
  arguments: date(int)
  returns: none
  This function does the same as SetBuildVersion, but tells the build system to try to be compatible with the build2002 repository on the given date.

  project.AddDebugOutput(env_var, rel_path )
  arguments: env_var(string), rel_path(string)
  returns: none
  This function takes an environment variable and a relative path as arguments. If the environment variable exists, a link to/alias to/copy of the output will be placed in that directory. Example: `project.AddDebugOutput("RP_DEBUG_BASEDIR","plugins/rv/")` This will copy the output into $RP_DEBUG_BASEDIR/plugins/rv/ Since the paths are often platform specific, this functions should normally only be used in pcf files.
  NOTA BENE: The rel_path arguments *must* end with a slash if it is a directory.

  project.AddFileDepenency(file, depend [, depend, depend ... ] )
  arguments: file(string), depend(string)
  returns: none
  This will add a dependency to the generated makefile so that make knows that file depends on depend.

  project.SetDistLocation( [release = location ], [ debug = location ], [ any = location ] )
  arguments: location(string)
  returns: none

  This will tell umake to check in the library/dll/program generated by this umakefile into the location given by 'location'. The location is relative to the source root and must be a directory which has a <checkin_dependlist> from this module.

  The location should be given using one of the named parameters `release`, `debug` or `any`. If you use the `release` parameter, then the checkin will only be performed if this is a release build.

  The location can use brackets to specify the location and name of the library, a few examples to illustrate. For simplicity, I will assume that project.SetDistLocation was used in a LibraryTarget umakefile.

  `project.SetDistLocation(release="foo/bar[../gazonk]")`
    This will check in the library as 'gazonk'. It will be checked in at the top level so that the distribution will be shared by both debug and release builds using this dist. If this is a debug build, then nothing will happen.
  `project.SetDistLocation(debug="foo/bar[./gazonk]")`
    This will check in the library as 'gazonk'. It will be checked in into the debug directory of the foo/bar module, but only if this is a debug build, otherwise nothing will happen.
  `project.SetDistLocation(any="foo/bar[./gazonk]")`
    This will check in the library as 'gazonk'. It will be checked in into the release/debug directory depending on what kind of build this is.
  `project.SetDistLocation("foo/bar")`
    This will check in the library as 'foo'. It will search the foo/bar directory to see if the library already exists, and if it does check it into the same place. If it does not exist, it will be checked in into the debug/release directory as approperiate. However, no checkin will take place if this is a debug build.