/*++ Copyright (c) 2017 Minoca Corp. This file is licensed under the terms of the GNU General Public License version 3. Alternative licensing terms are available. Contact info@minocacorp.com for details. See the LICENSE file at the root of this project for complete licensing information. Module Name: env.ck Abstract: This build module contains the environment and functions used throughout the Minoca OS build. Author: Evan Green 1-Feb-2017 Environment: Build --*/ // // -------------------------------------------------------------------- Imports // from mingen import config; from os import getenv, basename; // // -------------------------------------------------------------------- Globals // var mconfig; // // ------------------------------------------------------------------ Functions // function initListFromEnvironment ( name, default ) /*++ Routine Description: This routine gets an environment variable. It either returns that environment variable wrapped in a list, or the given default. Arguments: name - Supplies the name of the environment variable. default - Supplies the default value to return if not set. Return Value: Returns eithe the provided default or has the contents of the environment variable wrapped in a list. --*/ { var value = getenv(name); if (value != null) { return [value]; } return default; } function getTools ( ) /*++ Routine Description: This routine is called as part of setupEnv, at the end. It returns the basic set of tools used by the environment. Arguments: None. Return Value: Returns a list of the basic tools used in the environment. --*/ { var buildCflagsLine = "$BUILD_BASE_CPPFLAGS $CPPFLAGS " + "$BUILD_BASE_CFLAGS $CFLAGS -MMD -MF $OUT.d "; var buildAsflagsLine = buildCflagsLine + "$BUILD_BASE_ASFLAGS $ASFLAGS "; var buildLdflagsLine = "$BUILD_BASE_LDFLAGS $LDFLAGS "; var cflagsLine = "$BASE_CPPFLAGS $CPPFLAGS $BASE_CFLAGS $CFLAGS " "-MMD -MF $OUT.d "; var asflagsLine = cflagsLine + "$BASE_ASFLAGS $ASFLAGS "; var entries; var ldflagsLine = "-Wl,-Map=$OUT.map $BASE_LDFLAGS $LDFLAGS "; var symlinkCommand = "ln -sf $SYMLINK_IN $OUT"; var buildLdLine = "$BUILD_CC " + buildLdflagsLine + "-o $OUT $IN -Bdynamic $DYNLIBS"; var tools; if (mconfig.build_os == "Windows") { symlinkCommand = "cp $IN $OUT"; } // // On Mac OS there shouldn't be a -Bdynamic flag to indicate the start of // the dynamic libraries section. // if (mconfig.build_os == "Darwin") { buildLdLine = "$BUILD_CC " + buildLdflagsLine + "-o $OUT $IN $DYNLIBS"; // // Create a .map file (except on Mac, which doesn't support it). // } else { buildLdflagsLine = "-Wl,-Map=$OUT.map " + buildLdflagsLine; } // // Define the tools used. // tools = [ // // C compiler for target binaries. // { "type": "tool", "name": "cc", "command": "$CC " + cflagsLine + "-c -o $OUT $IN", "description": "Compiling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // C++ compiler for target binaries. // { "type": "tool", "name": "cxx", "command": "$CXX " + cflagsLine + "-c -o $OUT $IN", "description": "Compiling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // Linker for target binaries. // { "type": "tool", "name": "ld", "command": "$CC " + ldflagsLine + "-o $OUT $IN -Bdynamic $DYNLIBS", "description": "Linking - $OUT", }, // // Static archiver for target binaries. // { "type": "tool", "name": "ar", "command": "$AR rcs $OUT $IN", "description": "Building Library - $OUT", }, // // Assembler for target binaries. // { "type": "tool", "name": "as", "command": "$CC " + asflagsLine + "-c -o $OUT $IN", "description": "Assembling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // Objcopy for target binaries. // { "type": "tool", "name": "objcopy", "command": "$SHELL -c \"cd `dirname $IN` && " "$OBJCOPY $OBJCOPY_FLAGS `basename $IN` $OUT\"", "description": "Objectifying - $IN" }, // // Strip for target binaries. // { "type": "tool", "name": "strip", "command": "$STRIP $STRIP_FLAGS -o $OUT $IN", "description": "Stripping - $OUT", }, // // C compiler for the build machine. // { "type": "tool", "name": "build_cc", "command": "$BUILD_CC " + buildCflagsLine + "-c -o $OUT $IN", "description": "Compiling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // C++ compiler for the build machine. // { "type": "tool", "name": "build_cxx", "command": "$BUILD_CXX " + buildCflagsLine + "-c -o $OUT $IN", "description": "Compiling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // Linker for the build machine. // { "type": "tool", "name": "build_ld", "command": "$BUILD_CC " + buildLdflagsLine + "-o $OUT $IN -Bdynamic $DYNLIBS", "description": "Linking - $OUT", }, // // Static archiver for the build machine. // { "type": "tool", "name": "build_ar", "command": "$BUILD_AR rcs $OUT $IN", "description": "Building Library - $OUT", }, // // Assembler for the build machine. // { "type": "tool", "name": "build_as", "command": "$BUILD_CC " + buildAsflagsLine + "-c -o $OUT $IN", "description": "Assembling - $IN", "depsformat": "gcc", "depfile": "$OUT.d" }, // // Strip for the build machine. // { "type": "tool", "name": "build_strip", "command": "$BUILD_STRIP $STRIP_FLAGS -o $OUT $IN", "description": "Stripping - $OUT", }, // // Windows resource compiler for the build machine. // { "type": "tool", "name": "build_rcc", "command": "$RCC -o $OUT $IN", "description": "Compiling Resource - $IN", }, // // ACPI assembler used to build firmware images. // { "type": "tool", "name": "iasl", "command": "$SHELL -c \"$IASL $IASL_FLAGS -p $OUT $IN > $OUT.stdout\"", "description": "Compiling ASL - $IN" }, // // Copy files from one location to another. // { "type": "tool", "name": "copy", "command": "$SHELL -c \"cp $CPFLAGS $IN $OUT && [ -z $CHMOD_FLAGS ] || " "chmod $CHMOD_FLAGS $OUT\"", "description": "Copying - $IN -> $OUT" }, // // Create symbolic links (or just copy on Windows). // { "type": "tool", "name": "symlink", "command": symlinkCommand, "description": "Symlinking - $OUT" }, // // Touch a file with the date. // { "type": "tool", "name": "stamp", "command": "$SHELL -c \"date > $OUT\"", "description": "Stamp - $OUT" }, // // Touch to create a timestamped empty file. // { "type": "tool", "name": "touch", "command": "touch $OUT", "description": "Touch - $OUT" }, // // Create a directory. // { "type": "tool", "name": "mkdir", "command": "mkdir -p $OUT", "description": "mkdir $OUT" }, // // Generate a version.h. // { "type": "tool", "name": "gen_version", "command": "$SHELL $S/tasks/build/print_version.sh $OUT $FORM " "$MAJOR $MINOR $REVISION $RELEASE $SERIAL $BUILD_STRING", "description": "Versioning - $OUT" }]; return tools; } function setupEnv ( ) /*++ Routine Description: This routine is called once to set up the build environment. Arguments: None. Return Value: Returns the basic set of tools used by the environment. --*/ { var archVariant; // // Prefer Ninja files. // config.format ?= "ninja"; // // Set up the Minoca config dictionary. // mconfig = {}; mconfig.build_os = config.build_os; mconfig.build_machine = config.build_machine; mconfig.build_variant = ""; if (mconfig.build_machine == "i686") { mconfig.build_arch = "x86"; } else if (mconfig.build_machine == "i586") { mconfig.build_arch = "x86"; mconfig.build_variant = "q"; } else if ((mconfig.build_machine == "armv7") || (mconfig.build_machine == "armv6")) { mconfig.build_arch = mconfig.build_machine; } else if (mconfig.build_machine == "x86_64") { mconfig.build_arch = "x64"; } mconfig.arch = getenv("ARCH"); mconfig.arch ?= mconfig.build_arch; mconfig.arch ?= "x86"; mconfig.debug = getenv("DEBUG"); mconfig.debug ?= "dbg"; mconfig.variant = getenv("VARIANT"); mconfig.variant ?= mconfig.build_variant; mconfig.release_level = "SystemReleaseDevelopment"; mconfig.cflags = initListFromEnvironment("CFLAGS", ["-O2", "-Wall", "-Werror"]); mconfig.kernelCflags = []; mconfig.cppflags = initListFromEnvironment("CPPFLAGS", []); mconfig.ldflags = initListFromEnvironment("LDFLAGS", []); mconfig.asflags = initListFromEnvironment("ASFLAGS", []); mconfig.stripflags = initListFromEnvironment("STRIP_FLAGS", []); mconfig.build_cc = getenv("BUILD_CC"); mconfig.build_cc ?= "gcc"; mconfig.build_ar = getenv("BUILD_AR"); mconfig.build_ar ?= "ar"; mconfig.build_strip = getenv("BUILD_STRIP"); mconfig.build_strip ?= "strip"; config.output ?= "$S/../" + mconfig.arch + mconfig.variant + mconfig.debug + "/obj/os"; mconfig.outroot = "$O/../.."; mconfig.binroot = mconfig.outroot + "/bin"; mconfig.stripped = mconfig.binroot + "/stripped"; mconfig.cc = getenv("CC"); mconfig.ar = getenv("AR"); mconfig.objcopy = getenv("OBJCOPY"); mconfig.strip = getenv("STRIP"); mconfig.rcc = getenv("RCC"); mconfig.rcc ?= "windres"; mconfig.iasl = getenv("IASL"); mconfig.iasl ?= "iasl"; mconfig.shell = getenv("SHELL"); mconfig.shell ?= "sh"; mconfig.target = null; // // Add in the command line variables, then define the derived variables. // for (key in config.cmdvars) { mconfig[key] = config.cmdvars[key]; } archVariant = mconfig.arch + mconfig.variant; if (!mconfig.target) { if (archVariant == "x86") { mconfig.target = "i686-pc-minoca"; } else if (archVariant == "x86q") { mconfig.target = "i586-pc-minoca"; } else if ((mconfig.arch == "armv7") || (mconfig.arch == "armv6")) { mconfig.target = "arm-none-minoca"; } else if (mconfig.arch == "x64") { mconfig.target = "x86_64-pc-minoca"; } else { Core.raise(ValueError("Unknown architecture" + mconfig.arch)); } } mconfig.native = false; if ((mconfig.build_os == "Minoca") && (mconfig.arch == mconfig.build_arch)) { mconfig.native = true; } if (mconfig.native) { mconfig.cc ?= mconfig.build_cc; mconfig.ar ?= mconfig.build_ar; mconfig.strip ?= mconfig.build_strip; mconfig.objcopy ?= "objcopy"; } else { mconfig.cc ?= mconfig.target + "-gcc"; mconfig.ar ?= mconfig.target + "-ar"; mconfig.strip ?= mconfig.target + "-strip"; mconfig.objcopy ?= mconfig.target + "-objcopy"; } if (mconfig.debug == "dbg") { mconfig.cflags += ["-DDEBUG=1"]; } else { mconfig.cflags += ["-Wno-unused-but-set-variable", "-DNDEBUG"]; } mconfig.cflags += ["-fno-builtin", "-g", "-save-temps=obj", "-ffunction-sections", "-fdata-sections", "-fvisibility=hidden"]; mconfig.cppflags += ["-I$S/include"]; mconfig.build_cflags = [] + mconfig.cflags; mconfig.build_cppflags = [] + mconfig.cppflags; mconfig.cflags += ["-fpic"]; // // Windows cannot handle -fpic, but everyone else can. // if (mconfig.build_os == "Windows") { mconfig.build_cflags += ["-mno-ms-bitfields"]; } else { mconfig.build_cflags += ["-fpic"]; } if (mconfig.build_os == "Darwin") { mconfig.build_cflags += ["-Wno-tautological-compare", "-Wno-parentheses-equality"]; } // // Add some architecture variant flags. // if (archVariant == "x86q") { mconfig.cppflags += ["-Wa,-momit-lock-prefix=yes", "-march=i586"]; } else if (archVariant == "x64") { mconfig.kernelCflags = ["-mno-sse", "-mno-red-zone"]; } else if (archVariant == "armv6") { mconfig.cflags += ["-march=armv6zk", "-marm", "-mfpu=vfp"]; } mconfig.build_asflags = []; mconfig.asflags += ["-Wa,-g"]; mconfig.build_ldflags = initListFromEnvironment("BUILD_LDFLAGS", [] + mconfig.ldflags); mconfig.ldflags += ["-Wl,--gc-sections"]; // // Mac OS cannot handle --gc-sections or strip -p. // if (mconfig.build_os != "Darwin") { mconfig.build_ldflags += ["-Wl,--gc-sections"]; mconfig.stripflags += ["-p"]; } // // Define the set of variables that get passed all the way through to the // final Make/ninja file. Passing these on as variables rather than // substituting during the mingen build process allows for a smaller // build file, and easier manual tweaking by the user. // config.vars = { "BUILD_CC": mconfig.build_cc, "BUILD_AR": mconfig.build_ar, "BUILD_STRIP": mconfig.build_strip, "CC": mconfig.cc, "AR": mconfig.ar, "STRIP": mconfig.strip, "OBJCOPY": mconfig.objcopy, "RCC": mconfig.rcc, "IASL": mconfig.iasl, "SHELL": mconfig.shell, "BASE_CFLAGS": mconfig.cflags, "KERNEL_CFLAGS": mconfig.kernelCflags, "BASE_CPPFLAGS": mconfig.cppflags, "BASE_LDFLAGS": mconfig.ldflags, "BASE_ASFLAGS": mconfig.asflags, "BUILD_BASE_CFLAGS": mconfig.build_cflags, "BUILD_BASE_CPPFLAGS": mconfig.build_cppflags, "BUILD_BASE_LDFLAGS": mconfig.build_ldflags, "BUILD_BASE_ASFLAGS": mconfig.build_asflags, "STRIP_FLAGS": mconfig.stripflags, "IASL_FLAGS": ["-we"], "CPFLAGS": "-p", }; if (config.verbose) { Core.print("Minoca Build Configuration:"); for (key in mconfig) { Core.print("\t%s: %s" % [key, mconfig[key].__str()]); } } return getTools(); } function addConfig ( entry, name, value ) /*++ Routine Description: This routine adds a configure option to a list, ensuring that both the config dictionary and option already exist. Arguments: entry - Supplies the entry to add the configure option to. name - Supplies the name of the option to add. value - Supplies the new value to add to the list of options. Return Value: None. --*/ { if (!entry.get("config")) { entry.config = {}; } if (!entry.config.get(name)) { entry.config[name] = []; } entry.config[name] += [value]; return; } function group ( name, entries ) /*++ Routine Description: This routine creates a phony target that groups a bunch of different targets together under a common name. Arguments: name - Supplies the name of the new group target. entries - Supplies the list of entries. Return Value: Returns a list containing the entry for the group target. --*/ { var entry = { "label": name, "type": "target", "tool": "phony", "inputs": entries, "config": {} }; return [entry]; } function touch ( destination, destinationLabel, mode ) /*++ Routine Description: This routine creates an empty file target. Arguments: destination - Supplies the copy destination. destinationLabel - Supplies a label naming the target. mode - Supplies the chmod mode of the destination. Return Value: Returns a list containing the copy entry. --*/ { var config = {}; if (mode) { config["CHMOD_FLAGS"] = mode; } destinationLabel ?= destination; var entry = { "type": "target", "tool": "touch", "label": destinationLabel, "output": destination, "config": config }; return [entry]; } function makedir ( destination, destinationLabel ) /*++ Routine Description: This routine creates an empty directory target. Arguments: destination - Supplies the copy destination. destinationLabel - Supplies a label naming the target. Return Value: Returns a list containing the copy entry. --*/ { destinationLabel ?= destination; var entry = { "type": "target", "tool": "mkdir", "label": destinationLabel, "output": destination, }; return [entry]; } function copy ( source, destination, destinationLabel, flags, mode ) /*++ Routine Description: This routine creates a target that copies a file from one place to another. Arguments: source - Supplies the source to copy. destination - Supplies the copy destination. destinationLabel - Supplies a label naming the copy target. flags - Supplies the flags to include in the copy. mode - Supplies the chmod mode of the destination. Return Value: Returns a list containing the copy entry. --*/ { var config = {}; if (flags) { config["CPFLAGS"] = flags; } if (mode) { config["CHMOD_FLAGS"] = mode; } var entry = { "type": "target", "tool": "copy", "label": destinationLabel, "inputs": [source], "output": destination, "config": config }; if (!destinationLabel) { entry["label"] = destination; } return [entry]; } function strip ( params ) /*++ Routine Description: This routine converts an entry to a strip entry, where the target will be stripped. Arguments: params - Supplies the existing entry. Return Value: Returns a list containing the strip entry. --*/ { params.type = "target"; params.tool = "strip"; if (params.get("build")) { params.tool = "build_strip"; } return [params]; } function binplace ( params ) /*++ Routine Description: This routine replaces the current target with a copied version in the final bin directory. This will also create a stripped version in the stripped directory unless told not to. Arguments: params - Supplies the existing entry. Return Value: Returns a list containing the strip entry. --*/ { var build = params.get("build"); var copiedEntry; var cpflags = params.get("cpflags");; var destination; var destinationLabel; var destinationPath; var element; var entries = []; var extraCopy; var fileName; var label = params.get("label"); var mode = params.get("mode"); var newOriginalLabel; var originalTarget; var source = params.get("output"); var strippedEntry; var strippedOutput; label ?= source; source ?= label; if ((!label) || (!source)) { Core.raise(ValueError("Label or output must be defined")); } // // Set the output since the label is going to be renamed and create the // copy target. // params.output = source; params.type = "target"; fileName = basename(source); destination = params.get("binplace"); newOriginalLabel = label + "_orig"; originalTarget = ":" + newOriginalLabel; // // Create the first or only one with the genuine label. // element = destination; if (element is List) { element = element[0]; } if (!element) { element = "bin"; } destinationPath = mconfig.outroot + "/" + element + "/" + fileName; copiedEntry = copy(originalTarget, destinationPath, label, cpflags, mode)[0]; entries.append(copiedEntry); // // Handle binplacing into several areas. // if (destination is List) { for (index in 1..destination.length()) { element = destination[index]; if (!element) { element = "bin"; } destinationPath = mconfig.outroot + "/" + element + "/" + fileName; destinationLabel = "%s_%d" % [label, index]; extraCopy = copy(originalTarget, destinationPath, destinationLabel, cpflags, mode)[0]; copiedEntry.implicit = [":" + destinationLabel]; entries.append(extraCopy); } } // // The original label was given to the copied destination, so tack an _orig // on the source label. // params.label = newOriginalLabel; // // Unless asked not to, create a stripped entry as well. // if (!params.get("nostrip")) { if (build) { strippedOutput = mconfig.stripped + "/build/" + fileName; } else { strippedOutput = mconfig.stripped + "/" + fileName; } strippedEntry = { "label": label + "_stripped", "inputs": [originalTarget], "output": strippedOutput, "build": build, }; // // Make the binplaced copy depend on the stripped version. // copiedEntry.implicit = [":" + strippedEntry["label"]]; entries += strip(strippedEntry); } entries.append(params); return entries; } function compiledSources ( params ) /*++ Routine Description: This routine compiles a group of object file targets from source files. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list containing a list of object names, and a list of object targets. --*/ { var build = params.get("build"); var entries = []; var ext; var includes = params.get("includes"); var inputParts; var inputs = params.inputs; var objName; var obj; var objs = []; var sourcesConfig = params.get("sources_config"); var prefix = params.get("prefix"); var suffix; var tool; if (includes) { sourcesConfig ?= {}; if (!sourcesConfig.get("CPPFLAGS")) { sourcesConfig.CPPFLAGS = []; } for (include in includes) { sourcesConfig["CPPFLAGS"] += ["-I" + include]; } } if (inputs.length() == 0) { Core.raise(ValueError("Compilation must have inputs")); } for (input in inputs) { inputParts = input.rsplit(".", 1); try { ext = inputParts[1]; } except IndexError { ext = ""; } suffix = ".o"; if (ext == "c") { tool = "cc"; } else if (ext == "cc") { tool = "cxx"; } else if (ext == "S") { tool = "as"; } else if (ext == "rc") { tool = "rcc"; suffix = ".rsc"; } else { objs += [input]; continue; } if (build) { tool = "build_" + tool; } objName = inputParts[0] + suffix; if (objName[0] == ":") { objName = objName[1...-1]; } if (prefix) { objName = prefix + "/" + objName; } obj = { "type": "target", "label": objName, "output": objName, "inputs": [input], "tool": tool, "config": sourcesConfig, }; entries += [obj]; objs += [":" + objName]; } if (prefix) { if (!params.get("output")) { params.output = params.label; } params.output = prefix + "/" + params.output; } return [objs, entries]; } function executable ( params ) /*++ Routine Description: This routine links a set of sources into some sort of executable or shared object. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the linked entry. --*/ { var build = params.get("build"); var entry = params.get("entry"); var compilation = compiledSources(params); var linkerScript = params.get("linker_script"); var objs = compilation[0]; var entries = compilation[1]; var textAddress = params.get("text_address");; params.type = "target"; params.inputs = objs; params.tool = "ld"; if (build) { params.tool = "build_ld"; } // // Convert options for text_address, linker_script, and entry to actual // LDFLAGS. // if (textAddress) { addConfig(params, "LDFLAGS", "-Wl,-Ttext-segment=" + textAddress); addConfig(params, "LDFLAGS", "-Wl,--section-start,.init=" + textAddress); } if (linkerScript) { addConfig(params, "LDFLAGS", "-Wl,-T" + linkerScript); } if (entry != null) { addConfig(params, "LDFLAGS", "-Wl,-e" + entry); addConfig(params, "LDFLAGS", "-Wl,-u" + entry); } if (params.get("binplace")) { entries += binplace(params); } else { entries += [params]; } return entries; } function application ( params ) /*++ Routine Description: This routine creates a position independent application. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the application entry. --*/ { var build = params.get("build"); var exename = params.get("output"); exename ?= params.get("label"); if (!exename) { Core.raise(ValueError("Missing output or label")); } if (build && (mconfig.build_os == "Windows")) { params.output = exename + ".exe"; } if (build && (mconfig.build_os == "Darwin")) { addConfig(params, "LDFLAGS", "-Wl,-pie"); } else { addConfig(params, "LDFLAGS", "-pie"); } if ((!build) && (params.get("binplace") == null)) { params.binplace = "bin"; } return executable(params); } function staticApplication ( params ) /*++ Routine Description: This routine creates a static application suitable for kernel or firmware environments. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the application entry. --*/ { if (!(params.get("sources_config") is Dict)) { params.sources_config = {}; } if (!(params.sources_config.get("CFLAGS") is List)) { params.sources_config.CFLAGS = []; } params.sources_config.CFLAGS += ["$KERNEL_CFLAGS"]; addConfig(params, "LDFLAGS", "-static"); addConfig(params, "LDFLAGS", "-nostdlib"); return executable(params); } function sharedLibrary ( params ) /*++ Routine Description: This routine creates a shared library or DLL. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the application entry. --*/ { var build = params.get("build"); var majorVersion = params.get("major_version"); var minorVersion = params.get("minor_version"); var soname = params.get("soname"); soname ?= params.get("output"); soname ?= params.get("label"); if (!soname) { Core.raise(ValueError( "One of output, label, or soname must be defined.")); } // // Darwin shared libraries build with a whole different ballgame of options. // if (build && (mconfig.build_os == "Darwin")) { majorVersion ?= "0"; minorVersion ?= "0"; soname += ".%s.dylib" % majorVersion; addConfig(params, "LDFLAGS", "-undefined dynamic_lookup -dynamiclib"); addConfig(params, "LDFLAGS", "-current_version %s.%s" % [majorVersion, minorVersion]); addConfig(params, "LDFLAGS", "-compatibility_version %s.%d" % [majorVersion, 0]); } else { addConfig(params, "LDFLAGS", "-shared"); if ((!build) || (mconfig.build_os != "Windows")) { soname += ".so"; if (majorVersion != null) { soname += "." + majorVersion; } addConfig(params, "LDFLAGS", "-Wl,-soname=" + soname); } else { soname += ".dll"; } } params.output = soname; if ((!build) && (params.get("binplace") == null)) { params.binplace = "bin"; } return executable(params); } function staticLibrary ( params ) /*++ Routine Description: This routine creates a static library. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the application entry. --*/ { var build = params.get("build"); var compilation = compiledSources(params); var objs = compilation[0]; var output; var entries = compilation[1]; params.type = "target"; output = params.get("output"); output ?= params.get("label"); if (!output) { Core.raise(ValueError("output or label must be defined")); } params.output = output + ".a"; params.inputs = objs; params.tool = "ar"; if (build) { params.tool = "build_ar"; } if (params.get("binplace")) { entries += binplace(params); } else { entries += [params]; } return entries; } function kernelLibrary ( params ) /*++ Routine Description: This routine creates a static library compiled suitably for running within the kernel. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns the list of the application entry. --*/ { if (!(params.get("sources_config") is Dict)) { params.sources_config = {}; } if (!(params.sources_config.get("CFLAGS") is List)) { params.sources_config.CFLAGS = []; } params.sources_config.CFLAGS += ["$KERNEL_CFLAGS"]; return staticLibrary(params); } function compiledAsl ( inputs ) /*++ Routine Description: This routine creates a list of compiled .aml files from a list of .asl files. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list where the first element is a list of all the resulting target names, and the second element is a list of the target entries. --*/ { var entries = []; var ext; var inputParts; var objName; var obj; var objs = []; if (inputs.length() == 0) { Core.raise(ValueError("Compilation must have inputs")); } for (input in inputs) { inputParts = input.rsplit(".", 1); ext = inputParts[1]; objName = inputParts[0] + ".aml"; obj = { "type": "target", "label": objName, "output": objName, "inputs": [input], "tool": "iasl" }; entries += [obj]; objs += [":" + objName]; } return [objs, entries]; } function objectifiedBinaries ( params ) /*++ Routine Description: This routine creates a group of object file targets from binary files. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of object names in the first element and the object file target entries in the second element. --*/ { var build = params.get("build"); var entries = []; var inputs = params.inputs; var obj; var objcopyConfig = params.get("config"); var objName; var objs = []; var prefix = params.get("prefix"); var tool; if (inputs.length() == 0) { Core.raise(ValueError("Compilation must have inputs")); } for (input in inputs) { tool = "objcopy"; if (build) { tool = "build_objcopy";; } objName = input + ".o"; if (prefix) { objName = prefix + "/" + objName; } obj = { "type": "target", "label": objName, "output": objName, "inputs": [input], "tool": tool, "config": objcopyConfig, }; entries += [obj]; objs += [":" + objName]; } if (prefix) { params.output ?= params.label; params.output = prefix + "/" + params.output; } return [objs, entries]; } function objectifiedBinary ( params ) /*++ Routine Description: This routine creates a single object file from a binary file. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of the object file. --*/ { return objectifiedBinaries(params)[1]; } function objectifiedLibrary ( params ) /*++ Routine Description: This routine creates a library from a set of objectified files. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of the object file. --*/ { var build = params.get("build"); var compilation = objectifiedBinaries(params); var objs = compilation[0]; var entries = compilation[1]; var output = params.get("output"); params.type = "target"; output ?= params.label; params.output = output + ".a"; params.inputs = objs; params.tool = "ar"; if (build) { params.tool = "build_ar"; } entries += [params]; return entries; } // // Create a flat binary from an executable image. // function flattenedBinary ( params ) /*++ Routine Description: This routine creates a flat binary from an executable image. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of the flat binary. --*/ { var entries; params.type = "target"; params.tool = "objcopy"; addConfig(params, "OBJCOPY_FLAGS", "-O binary"); if (params.get("binplace")) { params.nostrip = true; entries = binplace(params); } else { entries = [params]; } return entries; } function driver ( params ) /*++ Routine Description: This routine creates a Minoca kernel driver. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of the driver entry. --*/ { var soname = params.get("output"); if (!params.get("entry")) { params.entry = "DriverEntry"; } if (!(params.get("sources_config") is Dict)) { params.sources_config = {}; } if (!(params.sources_config.get("CFLAGS") is List)) { params.sources_config.CFLAGS = []; } params.sources_config.CFLAGS += ["$KERNEL_CFLAGS"]; params.binplace = "bin"; soname ?= params.get("label"); if (soname != "kernel") { soname += ".drv"; params.output = soname; params.inputs += ["kernel:kernel"]; } addConfig(params, "LDFLAGS", "-shared"); addConfig(params, "LDFLAGS", "-Wl,-soname=" + soname); addConfig(params, "LDFLAGS", "-nostdlib"); return executable(params); } function uefiRuntimeFfs ( name ) /*++ Routine Description: This routine creates a runtime driver .FFS file from an ELF file. Arguments: params - Supplies the entry with inputs filled out. Return Value: Returns a list of the .FFS entry. --*/ { var elfconvConfig; var ffs; var pe; elfconvConfig = { "ELFCONV_FLAGS": "-t efiruntimedriver" }; pe = { "type": "target", "label": name, "inputs": [":" + name + ".elf"], "implicit": ["uefi/tools/elfconv:elfconv"], "tool": "elfconv", "config": elfconvConfig }; ffs = { "type": "target", "label": name + ".ffs", "inputs": [":" + name], "implicit": ["uefi/tools/genffs:genffs"], "tool": "genffs_runtime" }; return [pe, ffs]; } function uefiFwvol ( path, name, ffs ) /*++ Routine Description: This routine creates a UEFI firmware volume object file based on a platform name and a list of FFS inputs. Arguments: path - Supplies the path to the source. The object directory version of this path will be added to the include path. name - Supplies the name of the firmware volume. ffs - Supplies the FFS inputs. Return Value: Returns a list of the firmware volume entry. --*/ { var fwv; var fwvO; var fwvName = name + "fwv"; var fwvS; fwv = { "type": "target", "label": fwvName, "inputs": ffs, "implicit": ["uefi/tools/genfv:genfv"], "tool": "genfv" }; fwvS = { "inputs": [fwvName + ".S"], "includes": ["$O/" + path] }; fwvO = compiledSources(fwvS); fwvO = fwvO[1][0]; fwvO["implicit"] = [":" + fwvName]; return [fwv, fwvO]; } // // Define a function that creates a version.h file target. // function createVersionHeader ( major, minor, revision ) /*++ Routine Description: This routine creates a version.h header that includes aspects of the build environment. Arguments: major - Supplies the major number. minor - Supplies the minor number. revision - Supplies the revision. Return Value: Returns a list of the firmware volume entry. --*/ { var versionConfig; var versionH; versionConfig = { "FORM": "header", "MAJOR": major, "MINOR": minor, "REVISION": revision, "RELEASE": mconfig.release_level }; versionH = { "type": "target", "output": "version.h", "inputs": ["$S/.git/HEAD"], "tool": "gen_version", "config": versionConfig }; return [versionH]; }