//-------------------------------------------------------------------------------------------------- static void BuildExecutables ( legato::App& app, const legato::BuildParams_t& buildParams ) //-------------------------------------------------------------------------------------------------- { // Create an Executable Builder object. ExecutableBuilder_t exeBuilder(buildParams); // For each executable, auto& exeList = app.Executables(); for (auto i = exeList.begin(); i != exeList.end(); i++) { legato::Executable& exe = i->second; // Put the intermediate build output files under a directory named after the executable. std::string objOutputDir = legato::CombinePath(buildParams.ObjOutputDir(), exe.CName()); // Auto-generate the source code file containing main() and add it to the default component. exeBuilder.GenerateMain(exe, objOutputDir); // Build the executable. exeBuilder.Build(exe, objOutputDir); } }
//-------------------------------------------------------------------------------------------------- static void BuildStandAlone ( void ) //-------------------------------------------------------------------------------------------------- { // Create an Interface Builder object. InterfaceBuilder_t interfaceBuilder(BuildParams); // Build the IPC API libs. for (auto& mapEntry : Component.ProvidedApis()) { auto& interface = mapEntry.second; // We want the generated code and other intermediate output files to go into a separate // interface-specific directory to avoid confusion. interfaceBuilder.Build(interface, legato::CombinePath(BuildParams.ObjOutputDir(), interface.InternalName())); // Add the interface instance library to the list of libraries to link the component // library with. Component.AddRequiredLib(interface.Lib().ShortName()); } for (auto& mapEntry : Component.RequiredApis()) { auto& interface = mapEntry.second; if (!interface.TypesOnly()) // If only using types, don't need a library. { // We want the generated code and other intermediate output files to go into a separate // interface-specific directory to avoid confusion. interfaceBuilder.Build(interface, legato::CombinePath(BuildParams.ObjOutputDir(), interface.InternalName())); // Add the interface instance library to the list of libraries to link the component // library with. Component.AddRequiredLib(interface.Lib().ShortName()); } } // Build the component library. Build(); }
//-------------------------------------------------------------------------------------------------- static void Build ( void ) //-------------------------------------------------------------------------------------------------- { // Create a Component Builder object and use it to build the component library. ComponentBuilder_t componentBuilder(BuildParams); componentBuilder.Build(Component, BuildParams.ObjOutputDir()); }
//-------------------------------------------------------------------------------------------------- static void GetCommandLineArgs ( int argc, const char** argv ) //-------------------------------------------------------------------------------------------------- { // The target device (e.g., "ar7"). std::string target = "localhost"; // Non-zero = say what we are doing on stdout. bool isVerbose = false; // Full path of the library file to be generated. "" = use default file name. std::string buildOutputPath = ""; // Path to the directory where generated runtime libs should be put. std::string libOutputDir = "."; // Path to the directory where intermediate build output files (such as generated // source code and object code files) should be put. std::string objOutputDir = "."; std::string cFlags; // C compiler flags. std::string cxxFlags; // C++ compiler flags. std::string ldFlags; // Linker flags. // Lambda function that gets called once for each occurence of the --cflags (or -C) // argument on the command line. auto cFlagsPush = [&](const char* arg) { cFlags += " "; cFlags += arg; }; // Lambda function that gets called for each occurence of the --cxxflags, (or -X) argument on // the command line. auto cxxFlagsPush = [&](const char* arg) { cxxFlags += " "; cxxFlags += arg; }; // Lambda function that gets called once for each occurence of the --ldflags (or -L) // argument on the command line. auto ldFlagsPush = [&](const char* arg) { ldFlags += " "; ldFlags += arg; }; // Lambda functions for handling arguments that can appear more than once on the // command line. auto interfaceDirPush = [&](const char* path) { BuildParams.AddInterfaceDir(path); }; auto sourceDirPush = [&](const char* path) { BuildParams.AddSourceDir(path); }; // Lambda function that gets called once for each occurence of a component path on the // command line. auto componentPathSet = [&](const char* param) { static bool matched = false; if (matched) { throw legato::Exception("Only one component allowed. First is '" + Component.Path() + "'. Second is '" + param + "'."); } matched = true; Component.Path(param); }; // Register all our arguments with the argument parser. le_arg_AddOptionalString(&buildOutputPath, "", 'o', "output-path", "Specify the complete path name of the component library to be built."); le_arg_AddOptionalString(&libOutputDir, ".", 'l', "lib-output-dir", "Specify the directory into which any generated runtime libraries" " should be put. (This option ignored if -o specified.)"); le_arg_AddOptionalString(&objOutputDir, "./_build", 'w', "object-dir", "Specify the directory into which any intermediate build artifacts" " (such as .o files and generated source code files) should be put."); le_arg_AddOptionalString(&target, "localhost", 't', "target", "Specify the target device to build for (localhost | ar7)."); le_arg_AddMultipleString('i', "interface-search", "Add a directory to the interface search path.", interfaceDirPush); le_arg_AddMultipleString('c', "component-search", "(DEPRECATED) Add a directory to the source search path (same as -s).", sourceDirPush); le_arg_AddMultipleString('s', "source-search", "Add a directory to the source search path.", sourceDirPush); le_arg_AddOptionalFlag(&isVerbose, 'v', "verbose", "Set into verbose mode for extra diagnostic information."); le_arg_AddMultipleString('C', "cflags", "Specify extra flags to be passed to the C compiler.", cFlagsPush); le_arg_AddMultipleString('X', "cxxflags", "Specify extra flags to be passed to the C++ compiler.", cxxFlagsPush); le_arg_AddMultipleString('L', "ldflags", "Specify extra flags to be passed to the linker when linking " "executables.", ldFlagsPush); le_arg_AddOptionalFlag(&IsStandAlone, 'a', "stand-alone", "Create IPC interface instance libraries for APIs required by" " the component and link the component library with those interface" " libraries, so that the component library can be loaded and run" " without the help of mkexe or mkapp. This is useful when integrating" " with third-party code that uses some other build system." ); // Any remaining parameters on the command-line are treated as a component path. // Note: there should only be one. le_arg_SetLooseParamHandler(componentPathSet); // Scan the arguments now. le_arg_Scan(argc, argv); // Were we given a component? if (Component.Name() == "") { throw std::runtime_error("A component must be supplied on the command line."); } // Add the current working directory to the list of source search directories and the // list of interface search directories. BuildParams.AddSourceDir("."); BuildParams.AddInterfaceDir("."); // Store other build params specified on the command-line. if (isVerbose) { BuildParams.SetVerbose(); } BuildParams.SetTarget(target); BuildParams.LibOutputDir(libOutputDir); BuildParams.ObjOutputDir(objOutputDir); BuildParams.CCompilerFlags(cFlags); BuildParams.CxxCompilerFlags(cxxFlags); BuildParams.LinkerFlags(ldFlags); if (buildOutputPath != "") { Component.Lib().BuildOutputPath(buildOutputPath); } }
//-------------------------------------------------------------------------------------------------- static void GetCommandLineArgs ( int argc, const char** argv ) //-------------------------------------------------------------------------------------------------- { std::string target; bool isVerbose = false; // Path to the directory where intermediate build output files (such as generated // source code and object code files) should be put. std::string objectFilesDir; std::string cFlags; // C compiler flags. std::string ldFlags; // Linker flags. // Lambda function that gets called once for each occurence of the --cflags (or -C) // argument on the command line. auto cFlagsPush = [&](const char* arg) { cFlags += " "; cFlags += arg; }; // Lambda function that gets called once for each occurence of the --ldflags (or -L) // argument on the command line. auto ldFlagsPush = [&](const char* arg) { ldFlags += " "; ldFlags += arg; }; // Lambda function that gets called once for each occurence of the interface search path // argument on the command line. auto ifPathPush = [&](const char* path) { BuildParams.AddInterfaceDir(legato::DoEnvVarSubstitution(path)); }; // Lambda function that gets called once for each occurence of the source search path // argument on the command line. auto sourcePathPush = [&](const char* path) { BuildParams.AddSourceDir(legato::DoEnvVarSubstitution(path)); }; // Lambda function that gets called once for each occurence of a .sdef file name on the // command line. auto sdefFileNameSet = [&](const char* param) { static bool matched = false; if (matched) { throw legato::Exception("Only one system definition (.sdef) file allowed."); } matched = true; System.DefFilePath(legato::DoEnvVarSubstitution(param)); }; le_arg_AddOptionalString(&OutputDir, ".", 'o', "output-dir", "Specify the directory into which the final, built system file" "(ready to be installed on the target) should be put."); le_arg_AddOptionalString(&objectFilesDir, "", 'w', "object-dir", "Specify the directory into which any intermediate build artifacts" " (such as .o files and generated source code files) should be put."); le_arg_AddMultipleString('i', "interface-search", "Add a directory to the interface search path.", ifPathPush); le_arg_AddMultipleString('s', "source-search", "Add a directory to the source search path.", sourcePathPush); le_arg_AddOptionalString(&target, "localhost", 't', "target", "Set the compile target (localhost|ar7)."); le_arg_AddOptionalFlag(&isVerbose, 'v', "verbose", "Set into verbose mode for extra diagnostic information."); le_arg_AddMultipleString('C', "cflags", "Specify extra flags to be passed to the C compiler.", cFlagsPush); le_arg_AddMultipleString('L', "ldflags", "Specify extra flags to be passed to the linker when linking " "executables.", ldFlagsPush); // Any remaining parameters on the command-line are treated as the .sdef file path. // Note: there should only be one parameter not prefixed by an argument identifier. le_arg_SetLooseParamHandler(sdefFileNameSet); le_arg_Scan(argc, argv); // Were we given an system definition? if (System.DefFilePath() == "") { throw std::runtime_error("A system definition must be supplied."); } // If we were not given an object file directory (intermediate build output directory) path, // use a subdirectory of the current working directory. if (objectFilesDir == "") { objectFilesDir = "./_build_" + System.Name() + "/" + target; } BuildParams.ObjOutputDir(objectFilesDir); // Add the directory containing the .sdef file to the list of source search directories // and the list of interface search directories. std::string systemDefFileDir = legato::GetContainingDir(System.DefFilePath()); BuildParams.AddSourceDir(systemDefFileDir); BuildParams.AddInterfaceDir(systemDefFileDir); // Store other build params specified on the command-line. if (isVerbose) { BuildParams.SetVerbose(); } BuildParams.SetTarget(target); BuildParams.CCompilerFlags(cFlags); BuildParams.LinkerFlags(ldFlags); }
//-------------------------------------------------------------------------------------------------- static void Build ( void ) //-------------------------------------------------------------------------------------------------- { // Construct the working directory structure, which consists of an "obj" directory and // a "staging" directory. Application bundles will be put inside the "staging" directory. // The "staging" directory will get tarred to become the actual system bundle. // The "obj" directory is for intermediate build output, like generated .c // files and .o files. Under the "obj" directory each app has its own subdirectory to work in. if (BuildParams.IsVerbose()) { std::cout << "Creating working directories under '" << BuildParams.ObjOutputDir() << "'." << std::endl; } std::string objDirPath = BuildParams.ObjOutputDir() + "/obj"; std::string stagingDirPath = BuildParams.ObjOutputDir() + "/staging"; // Clean the staging area. legato::CleanDir(stagingDirPath); // Create the staging and working directories. legato::MakeDir(objDirPath); legato::MakeDir(stagingDirPath); // For each app in the system, for (auto& mapEntry : System.Apps()) { auto& app = mapEntry.second; // Create an Application Builder object to use to build this app. // Give it the appropriate build parameters. legato::BuildParams_t appBuildParams(BuildParams); appBuildParams.ObjOutputDir(legato::CombinePath(objDirPath, app.Name())); appBuildParams.StagingDir(legato::CombinePath(appBuildParams.ObjOutputDir(), "staging")); ApplicationBuilder_t appBuilder(appBuildParams); // Build the app. This should result in an application bundle appearing in the // staging directory. appBuilder.Build(app, stagingDirPath); } // TODO: Copy in metadata for use by Developer Studio. // Generate a configuration data file containing user-to-app and user-to-user bindings. GenerateSystemConfig(stagingDirPath); // Create the tarball file name. std::string outputPath = legato::CombinePath(OutputDir, System.Name()); outputPath += "." + BuildParams.Target() + "_sys"; // Add the file name extension. if (!legato::IsAbsolutePath(outputPath)) { outputPath = legato::GetWorkingDir() + "/" + outputPath; } // Create the tarball. std::string tarCommandLine = "tar cf \"" + outputPath + "\" -C \"" + stagingDirPath + "\" ."; if (BuildParams.IsVerbose()) { std::cout << "Packaging system into '" << outputPath << "'." << std::endl; std::cout << std::endl << "$ "<< tarCommandLine << std::endl << std::endl; } mk::ExecuteCommandLine(tarCommandLine); }
//-------------------------------------------------------------------------------------------------- static void GetCommandLineArgs ( int argc, const char** argv ) //-------------------------------------------------------------------------------------------------- { // The target device (e.g., "ar7"). std::string target = "localhost"; // Non-zero = say what we are doing on stdout. int isVerbose = 0; // Path to the directory where generated runtime libs should be put. std::string libOutputDir = "."; // Path to the directory where intermediate build output files (such as generated // source code and object code files) should be put. std::string objOutputDir = "."; std::string cFlags; // C compiler flags. std::string ldFlags; // Linker flags. // Lambda functions for handling arguments that can appear more than once on the // command line. auto interfaceDirPush = [&](const char* path) { BuildParams.AddInterfaceDir(path); }; auto componentDirPush = [&](const char* path) { BuildParams.AddComponentDir(path); }; auto contentPush = [&](const char* param) { ContentNames.push_back(param); }; // Register all our arguments with the argument parser. le_arg_AddString(&ExePath, 'o', "output", "The path of the executable file to generate."); le_arg_AddOptionalString(&libOutputDir, ".", 'l', "lib-output-dir", "Specify the directory into which any generated runtime libraries" " should be put."); le_arg_AddOptionalString(&objOutputDir, "./_build", 'w', "object-dir", "Specify the directory into which any intermediate build artifacts" " (such as .o files and generated source code files) should be put."); le_arg_AddOptionalString(&target, "localhost", 't', "target", "Specify the target device to build for (localhost | ar7)."); le_arg_AddMultipleString('i', "interface-search", "Add a directory to the interface search path.", interfaceDirPush); le_arg_AddMultipleString('c', "component-search", "Add a directory to the component search path.", componentDirPush); le_arg_AddOptionalFlag(&isVerbose, 'v', "verbose", "Set into verbose mode for extra diagnostic information."); le_arg_AddOptionalString(&cFlags, "", 'C', "cflags", "Specify extra flags to be passed to the C compiler."); le_arg_AddOptionalString(&ldFlags, "", 'L', "ldflags", "Specify extra flags to be passed to the linker when linking " "executables and libraries."); // Any remaining parameters on the command-line are treated as content items to be included // in the executable. le_arg_SetLooseParamHandler(contentPush); // Scan the arguments now. le_arg_Scan(argc, argv); // Add the current working directory to the list of component search directories and the // list of interface search directories. BuildParams.AddComponentDir("."); BuildParams.AddInterfaceDir("."); // Add the Legato framework include directory to the include path so people don't have // to keep doing it themselves. BuildParams.AddInterfaceDir("$LEGATO_ROOT/framework/c/inc"); // Store other build params specified on the command-line. if (isVerbose) { BuildParams.SetVerbose(); } BuildParams.SetTarget(target); BuildParams.LibOutputDir(libOutputDir); BuildParams.ObjOutputDir(objOutputDir); BuildParams.CCompilerFlags(cFlags); BuildParams.LinkerFlags(ldFlags); }