main.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. 
  2. // Because it would be slow to check if the build system needs to be recompiled every time something uses it,
  3. // you must manually delete the build system's binary and try to build a project using it after making changes to the builder's source code.
  4. // Otherwise buildProject.sh will just see that an old version exists and use it.
  5. // TODO:
  6. // * Optimize compilation of multiple projects by only generating code for compiling objects that have not already been compiled of the same version for another project.
  7. // * Implement more features for the machine, such as:
  8. // * else and elseif cases.
  9. // * Temporarily letting the theoretical path go into another folder within a scope, similar to if statements but only affecting the path.
  10. // Like writing (cd path; stmt;) in Bash but with fast parsed Basic-like syntax.
  11. // The same stack used to store theoretical paths might be useful for else if cases to remember when the scope has already passed a case when not jumping with gotos.
  12. // * Create portable scripted events for pre-build and post-build, translated into both Batch and Bash.
  13. // Pre-build can be used to generate and transpile code before compiling.
  14. // Post-build should be used to execute the resulting program.
  15. // Optionally with variables from the build script as input arguments.
  16. /*
  17. Project files:
  18. Syntax:
  19. * Assign "10" to variable x:
  20. x = 10
  21. * Assign "1" to variable myVariable:
  22. myVariable
  23. * Assign b plus c to a:
  24. a = b + c
  25. * Assign b minus c to a:
  26. a = b - c
  27. * Assign b times c to a:
  28. a = b * c
  29. * Assign b divided by c to a:
  30. a = b / c
  31. * Concatenate "hello" and " world" into "hello world" in message:
  32. message = "hello" & " world"
  33. * If a is less than b or c equals 3 then assign y to z:
  34. if (a < b) or (c == 3)
  35. z = y
  36. end if
  37. * x is assigned a boolean value telling if the content of a matches "abc". (case sensitive comparison)
  38. x = a matches "abc"
  39. Commands:
  40. * Build all projects in myFolder with the SkipIfBinaryExists flag in arbitrary order before continuing with compilation
  41. Build "../myFolder" SkipIfBinaryExists
  42. * Add file.cpp and other implementations found through includes into the list of source code to compile and link.
  43. Crawl "folder/file.cpp"
  44. Systems:
  45. * Linux
  46. Set to non-zero on Linux or similar operating systems.
  47. * Windows
  48. Set to non-zero on MS-Windows.
  49. Variables:
  50. * SkipIfBinaryExists, skips building if the binary already exists.
  51. * Supressed, prevents a compiled program from running after building, which is usually given as an extra argument to Build to avoid launching all programs in a row.
  52. * ProgramPath, a path to the application to create.
  53. * Compiler, a path or global alias to the compiler.
  54. * CompileFrom, from which path should the compiler be executed? Leave empty to use the current directory.
  55. * Debug, 0 for release, anything else (usually 1) for debug.
  56. * StaticRuntime, 0 for dynamic runtime linking, anything else (usually 1) for static runtime.
  57. * Optimization, a natural integer specifying the amount of optimization to apply.
  58. */
  59. #include "../../DFPSR/api/fileAPI.h"
  60. #include "Machine.h"
  61. #include "expression.h"
  62. using namespace dsr;
  63. static ScriptLanguage identifyLanguage(const ReadableString filename) {
  64. String scriptExtension = string_upperCase(file_getExtension(filename));
  65. if (string_match(scriptExtension, U"BAT")) {
  66. return ScriptLanguage::Batch;
  67. } else if (string_match(scriptExtension, U"SH")) {
  68. return ScriptLanguage::Bash;
  69. } else {
  70. throwError(U"Could not identify the scripting language of ", filename, U". Use *.bat or *.sh.\n");
  71. return ScriptLanguage::Unknown;
  72. }
  73. }
  74. // List dependencies for main.cpp on Linux: ./builder main.cpp --depend
  75. DSR_MAIN_CALLER(dsrMain)
  76. void dsrMain(List<String> args) {
  77. if (args.length() <= 1) {
  78. printText(U"No arguments given to Builder. Starting regression test.\n");
  79. expression_runRegressionTests();
  80. } else if (args.length() == 2) {
  81. printText(U"To use the DFPSR build system, pass a path to a project file or folder containing multiple projects, and the flags you want assigned before building.\n");
  82. printText(U"To run regression tests, don't pass any argument to the program.\n");
  83. } else {
  84. // Get the script's destination path for all projects built during the session as the first argument.
  85. String outputScriptPath = args[1];
  86. String tempFolder = file_getAbsoluteParentFolder(outputScriptPath);
  87. // Get the first project file's path, which can then build other projects using the same generated script.
  88. String projectFilePath = args[2];
  89. // Read the reas after the project's path, as named integers assigned to ones.
  90. // Calling builder with the extra arguments will interpret them as variables and mark them as inherited, so that they are passed on to any other projects build from the project file.
  91. // Other values can be assigned using an equality sign.
  92. // Avoid spaces around the equality sign, because quotes are already used for string arguments in assignments.
  93. Machine settings;
  94. argumentsToSettings(settings, args, 3);
  95. // Generate a script.
  96. ScriptTarget scriptTarget = ScriptTarget(identifyLanguage(outputScriptPath), tempFolder);
  97. if (scriptTarget.language == ScriptLanguage::Batch) {
  98. string_append(scriptTarget.generatedCode, U"@echo off\n\n");
  99. } else if (scriptTarget.language == ScriptLanguage::Bash) {
  100. string_append(scriptTarget.generatedCode, U"#!/bin/bash\n\n");
  101. }
  102. build(scriptTarget, projectFilePath, settings);
  103. // Save the script.
  104. if (scriptTarget.language == ScriptLanguage::Batch) {
  105. string_save(outputScriptPath, scriptTarget.generatedCode);
  106. } else if (scriptTarget.language == ScriptLanguage::Bash) {
  107. string_save(outputScriptPath, scriptTarget.generatedCode, CharacterEncoding::BOM_UTF8, LineEncoding::Lf);
  108. }
  109. }
  110. }