diff --git a/.arcconfig b/.arcconfig --- a/.arcconfig +++ b/.arcconfig @@ -6,5 +6,6 @@ "git:arc.feature.start.default" : "origin/master", "arc.feature.start.default" : "master", "history.immutable" : false, - "load" : ["arcanist"] + "load" : ["arcanist"], + "build_directory": "build-cmake" } diff --git a/arcanist/.phutil_module_cache b/arcanist/.phutil_module_cache --- a/arcanist/.phutil_module_cache +++ b/arcanist/.phutil_module_cache @@ -1 +1 @@ -{"__symbol_cache_version__":11,"d60c8224f471e0ecddc2a6f3c6839cd1":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"id":1317},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1324,"Filesystem":1168,"ArcanistLinter":1431,"ArcanistLintSeverity":1509}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"213c3145da34ed6dfc0d70d628a2a086":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":323,"id":1868},"class":{"ArcanistExternalLinter":129,"ArcanistLintMessage":1875,"Filesystem":737,"ArcanistLinter":1923,"ArcanistLintSeverity":2009}},"xmap":{"CheckDocLinter":["ArcanistExternalLinter"]}},"7bab1f879b8a86dd9977b8c0d075935f":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":787,"id":1664},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":1671,"Filesystem":1515,"ArcanistLinter":1778,"ArcanistLintSeverity":1856}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"ea2beb1668dfbdd87488f18fbb20178f":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2676},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2683,"Filesystem":791,"ArcanistLinter":2731,"ArcanistLintSeverity":2839}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"d8eaa2e7c86750dc3ee35036b5fd8bfc":{"have":{"class":{"LocaleDependenceLinter":137}},"need":{"function":{"pht":375,"id":2052},"class":{"ArcanistExternalLinter":168,"ArcanistLintMessage":2059,"Filesystem":816,"ArcanistLinter":2107,"ArcanistLintSeverity":2227}},"xmap":{"LocaleDependenceLinter":["ArcanistExternalLinter"]}},"e3132d407656d565ce80d359f4f0fe5f":{"have":{"class":{"PythonFormatLinter":124}},"need":{"function":{"pht":354,"id":1845},"class":{"ArcanistExternalLinter":151,"ArcanistLintMessage":1852,"Filesystem":777,"ArcanistLinter":1977,"ArcanistLintSeverity":2060}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}}} \ No newline at end of file +{"__symbol_cache_version__":11,"90a8b110dc475955f15bb81d37268cb5":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"execx":769,"id":1903},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1910,"Filesystem":1754,"ArcanistLinter":2017,"ArcanistLintSeverity":2095}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"bf0805c02029a7226e8c0d7dee039b3c":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":323,"id":1847},"class":{"ArcanistExternalLinter":129,"ArcanistLintMessage":1854,"Filesystem":731,"ArcanistLinter":1902,"ArcanistLintSeverity":1988}},"xmap":{"CheckDocLinter":["ArcanistExternalLinter"]}},"6af7410cfea496ff1d4dcc2624b6b8ea":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":781,"id":1653},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":1660,"Filesystem":1504,"ArcanistLinter":1767,"ArcanistLintSeverity":1845}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"c8d28781ae8aa129cc38d505095f7f45":{"have":{"class":{"LocaleDependenceLinter":155}},"need":{"function":{"pht":579,"id":3348},"class":{"ArcanistExternalLinter":186,"ArcanistLintMessage":3355,"Filesystem":1035,"ArcanistLinter":3405,"ArcanistLintSeverity":3564}},"xmap":{"LocaleDependenceLinter":["ArcanistExternalLinter"]}},"6f2f22dd0f259fb2eaa284b4fab3bc29":{"have":{"class":{"PythonFormatLinter":123}},"need":{"function":{"pht":353,"id":1838},"class":{"ArcanistExternalLinter":150,"ArcanistLintMessage":1845,"Filesystem":776,"ArcanistLinter":1970,"ArcanistLintSeverity":2053}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}},"25781df78f6eebfb223296b8265e9d19":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2629},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2636,"Filesystem":776,"ArcanistLinter":2684,"ArcanistLintSeverity":2792}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"74ec116ee9ddb8d1b9e1ac3568d523ab":{"have":{"class":{"ArcanistBuildWorkflow":48}},"need":{"function":{"phutil_console_format":320,"pht":775},"class":{"ArcanistWorkflow":78,"ExecFuture":3740,"PhutilConsole":1585,"Filesystem":2718},"class\/interface":{"FilesystemException":2876}},"xmap":{"ArcanistBuildWorkflow":["ArcanistWorkflow"]}}} \ No newline at end of file diff --git a/arcanist/__phutil_library_map__.php b/arcanist/__phutil_library_map__.php --- a/arcanist/__phutil_library_map__.php +++ b/arcanist/__phutil_library_map__.php @@ -9,6 +9,7 @@ phutil_register_library_map(array( '__library_version__' => 2, 'class' => array( + 'ArcanistBuildWorkflow' => 'workflow/ArcanistBuildWorkflow.php', 'AutoPEP8FormatLinter' => 'linter/AutoPEP8Linter.php', 'CheckDocLinter' => 'linter/CheckDocLinter.php', 'ClangFormatLinter' => 'linter/ClangFormatLinter.php', @@ -18,6 +19,7 @@ ), 'function' => array(), 'xmap' => array( + 'ArcanistBuildWorkflow' => 'ArcanistWorkflow', 'AutoPEP8FormatLinter' => 'ArcanistExternalLinter', 'CheckDocLinter' => 'ArcanistExternalLinter', 'ClangFormatLinter' => 'ArcanistExternalLinter', diff --git a/arcanist/workflow/ArcanistBuildWorkflow.php b/arcanist/workflow/ArcanistBuildWorkflow.php new file mode 100644 --- /dev/null +++ b/arcanist/workflow/ArcanistBuildWorkflow.php @@ -0,0 +1,171 @@ + array( + 'help' => pht('Clear the CMake cache before running the build.'), + ), + 'dir' => array( + 'param' => 'build directory', + 'help' => pht('Set the build directory. It will be created if it does '. + 'not exist. It defaults to the build directory configured using the '. + '`build_directory` option in your configuration file.'), + ), + 'post-clean' => array( + 'help' => pht('Delete all files and the build directory if the build '. + 'is successful.'), + ), + '*' => 'targets', + ); + } + + public function requiresWorkingCopy() { + return true; + } + + private function setSuccess($duration) { + $out = phutil_console_format( + "** %s ** %s (%.3f s)\n", + pht('OKAY'), + pht('Build is successful'), + $duration); + + PhutilConsole::getConsole()->writeOut($out); + + return self::RESULT_OKAY; + } + + private function setFailure($failureReason) { + $out = phutil_console_format( + "** %s ** %s\n", + pht('FAILED'), + pht($failureReason)); + + PhutilConsole::getConsole()->writeOut($out); + + return self::RESULT_ERRORS; + } + + public function run() { + $root = $this->getWorkingCopy()->getProjectRoot(); + + /* + * Create the build directory if it doesn't exist. + * The build directory can be specified on the command line using the --dir + * option. If not specified, the build directory is read from the + * configuration option `build_directory`. + */ + $buildDir = $this->getArgument('dir', + $this->getConfigurationManager()->getConfigFromAnySource( + 'build_directory')); + if (!$buildDir) { + return $this->setFailure( + 'No build directory is configured. Set the `build_directory` option '. + 'in you configuration file and run `arc build` again, or select the '. + 'build directory by using the `--dir` argument on the command line.'); + } + $buildDir = Filesystem::resolvePath($buildDir, $root); + + try { + $buildDir = Filesystem::createDirectory($buildDir, 0755, + $recursive = true); + } catch (FilesystemException $e) { + var_dump($e); + return $this->setFailure( + 'Unable to create the build directory: '.$buildDir.'. '. + 'Check the permissions and run `arc build` again.'); + } + + /* Clear the CMake cache if requested */ + if ($this->getArgument('clear-cache')) { + /* Delete the CMakeCache.txt file */ + $cacheFile = Filesystem::resolvePath('CMakeCache.txt', $buildDir); + if (file_exists($cacheFile)) { + try { + Filesystem::remove($cacheFile); + } catch (FilesystemException $e) { + return $this->setFailure( + 'Unable to remove the '.$buildDir.'/CMakeCache.txt file. '. + 'Check the permissions and run `arc build --clear-cache` again.'); + } + } + } + + $timeStart = microtime(true); + + /* Run CMake from the build repository */ + $future = new ExecFuture('cmake -GNinja '.$root); + $future->setCWD($buildDir); + list($ret) = $future->resolve(); + + if ($ret != 0) { + return $this->setFailure( + 'CMake failed with error '.strval($ret)); + } + + /* + * Run Ninja from the build directory. + * If "targets" arguments are specified, pass them to Ninja, otherwise do + * not speficy any target and let Ninja build the default. + */ + $targets = $this->getArgument('targets'); + $cmd = 'ninja'; + foreach ($targets as $_) { + $cmd .= ' %s'; + } + + $future = new ExecFuture($cmd, ...$targets); + $future->setCWD($buildDir); + list($ret) = $future->resolve(); + + $timeEnd = microtime(true); + + if ($ret != 0) { + return $this->setFailure( + 'Ninja failed with error '.strval($ret)); + } + + /* Remove the build directory if requested. */ + if ($this->getArgument('post-clean')) { + try { + Filesystem::remove($buildDir); + } catch (FilesystemException $e) { + return $this->setFailure( + 'Unable to delete the build directory: '.$buildDir.'. '. + 'Check the permissions and run `arc build --post-clean` again.'); + } + } + + return $this->setSuccess($timeEnd - $timeStart); + } +}