idf_main.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright 2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at",
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License
  14. #include <windows.h>
  15. #include <shlwapi.h>
  16. #include <strsafe.h>
  17. #include <stdarg.h>
  18. #define LINESIZE 1024
  19. static void fail(LPCSTR message, ...) __attribute__((noreturn));
  20. static void fail(LPCSTR message, ...)
  21. {
  22. DWORD written;
  23. char msg[LINESIZE];
  24. va_list args = NULL;
  25. va_start(args, message);
  26. StringCchVPrintfA(msg, sizeof(msg), message, args);
  27. WriteFile(GetStdHandle(STD_ERROR_HANDLE), message, lstrlen(msg), &written, NULL);
  28. ExitProcess(1);
  29. }
  30. int main(int argc, LPTSTR argv[])
  31. {
  32. /* Print the version of this wrapper tool, but only if invoked as "idf.exe".
  33. * "idf -v" will invoke idf.py as expected.
  34. */
  35. LPCTSTR cmdname = PathFindFileName(argv[0]);
  36. int cmdname_length = strlen(cmdname);
  37. if (argc == 2 &&
  38. cmdname_length > 4 &&
  39. StrCmp(cmdname + cmdname_length - 4, TEXT(".exe")) == 0 &&
  40. (StrCmp(argv[1], TEXT("--version")) == 0 ||
  41. StrCmp(argv[1], TEXT("-v")) == 0)) {
  42. LPCSTR msg = VERSION "\n";
  43. DWORD written;
  44. WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, lstrlen(msg), &written, NULL);
  45. return 0;
  46. }
  47. LPCTSTR idfpy_script_name = TEXT("idf.py");
  48. /* Get IDF_PATH */
  49. TCHAR idf_path[LINESIZE] = {};
  50. if (GetEnvironmentVariable(TEXT("IDF_PATH"), idf_path, sizeof(idf_path)) == 0) {
  51. DWORD err = GetLastError();
  52. if (err == ERROR_ENVVAR_NOT_FOUND) {
  53. fail("IDF_PATH environment variable needs to be set to use this tool\n");
  54. } else {
  55. fail("Unknown error (%u)\n", err);
  56. }
  57. }
  58. /* Prepare the command line: python.exe %IDF_PATH%\\tools\idf.py <rest of the args> */
  59. TCHAR cmdline[LINESIZE] = {};
  60. StringCchCat(cmdline, sizeof(cmdline), TEXT("python.exe "));
  61. StringCchCat(cmdline, sizeof(cmdline), idf_path);
  62. StringCchCat(cmdline, sizeof(cmdline), TEXT("\\tools\\"));
  63. StringCchCat(cmdline, sizeof(cmdline), idfpy_script_name);
  64. StringCchCat(cmdline, sizeof(cmdline), TEXT(" "));
  65. for (int i = 1; i < argc; ++i) {
  66. StringCchCat(cmdline, sizeof(cmdline), argv[i]);
  67. StringCchCat(cmdline, sizeof(cmdline), TEXT(" "));
  68. }
  69. SetEnvironmentVariable(TEXT("IDF_PY_PROGRAM_NAME"), idfpy_script_name);
  70. /* Reuse the standard streams of this process */
  71. STARTUPINFO start_info = {
  72. .cb = sizeof(STARTUPINFO),
  73. .hStdError = GetStdHandle(STD_ERROR_HANDLE),
  74. .hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE),
  75. .hStdInput = GetStdHandle(STD_INPUT_HANDLE),
  76. .dwFlags = STARTF_USESTDHANDLES
  77. };
  78. /* Run the child process */
  79. PROCESS_INFORMATION child_process;
  80. if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &start_info, &child_process)) {
  81. DWORD err = GetLastError();
  82. if (err == ERROR_FILE_NOT_FOUND) {
  83. fail("Can not find Python\n");
  84. } else {
  85. fail("Unknown error (%u)\n", err);
  86. }
  87. }
  88. /* Wait for it to complete */
  89. WaitForSingleObject(child_process.hProcess, INFINITE);
  90. /* Return with the exit code of the child process */
  91. DWORD exitcode;
  92. if (!GetExitCodeProcess(child_process.hProcess, &exitcode)) {
  93. fail("Couldn't get the exit code (%u)\n", GetLastError());
  94. }
  95. return exitcode;
  96. }