@@ -24,12 +24,6 @@ constexpr codeql::SwiftDiagnostic noSwiftTarget{
2424 .action = " To analyze a custom set of source files, set up a [manual build "
2525 " command][1].\n\n [1]: " MANUAL_BUILD_COMMAND_HELP_LINK};
2626
27- constexpr codeql::SwiftDiagnostic spmNotSupported{
28- .id = " spm-not-supported" ,
29- .name = " Swift Package Manager is not supported" ,
30- .action = " Swift Package Manager builds are not currently supported by `autobuild`. Set up a "
31- " [manual build command][1].\n\n [1]: " MANUAL_BUILD_COMMAND_HELP_LINK};
32-
3327static codeql::Logger& logger () {
3428 static codeql::Logger ret{" main" };
3529 return ret;
@@ -44,38 +38,63 @@ static bool endsWith(std::string_view s, std::string_view suffix) {
4438 return s.size () >= suffix.size () && s.substr (s.size () - suffix.size ()) == suffix;
4539}
4640
47- static bool isNonSwiftOrTestTarget (const Target & t) {
41+ static bool isNonSwiftOrTestTarget (const XcodeTarget & t) {
4842 return t.fileCount == 0 || t.type == uiTest || t.type == unitTest ||
4943 // unknown target types can be legitimate, let's do a name-based heuristic then
5044 (t.type == unknownType && (endsWith (t.name , " Tests" ) || endsWith (t.name , " Test" )));
5145}
5246
53- static void autobuild (const CLIArgs& args) {
54- auto collected = collectTargets (args.workingDir );
55- auto & targets = collected.targets ;
56- for (const auto & t : targets) {
47+ static void buildSwiftPackages (const std::vector<std::filesystem::path>& swiftPackages,
48+ bool dryRun) {
49+ auto any_successful =
50+ std::any_of (std::begin (swiftPackages), std::end (swiftPackages), [&](auto & packageFile) {
51+ LOG_INFO (" Building Swift package: {}" , packageFile);
52+ return buildSwiftPackage (packageFile, dryRun);
53+ });
54+ if (!any_successful) {
55+ codeql::Log::flush ();
56+ exit (1 );
57+ }
58+ }
59+
60+ static bool autobuild (const CLIArgs& args) {
61+ auto structure = scanProjectStructure (args.workingDir );
62+ auto & xcodeTargets = structure.xcodeTargets ;
63+ auto & swiftPackages = structure.swiftPackages ;
64+ for (const auto & t : xcodeTargets) {
5765 LOG_INFO (" {}" , t);
5866 }
5967 // Filter out targets that are tests or have no swift source files
60- targets.erase (std::remove_if (std::begin (targets), std::end (targets), isNonSwiftOrTestTarget),
61- std::end (targets));
68+ xcodeTargets.erase (
69+ std::remove_if (std::begin (xcodeTargets), std::end (xcodeTargets), isNonSwiftOrTestTarget),
70+ std::end (xcodeTargets));
6271
6372 // Sort targets by the amount of files in each
64- std::sort (std::begin (targets), std::end (targets),
65- [](Target& lhs, Target& rhs) { return lhs.fileCount > rhs.fileCount ; });
66- if ((!collected.xcodeEncountered || targets.empty ()) && collected.swiftPackageEncountered ) {
67- DIAGNOSE_ERROR (spmNotSupported,
68- " A Swift package was detected, but no viable Xcode target was found." );
69- } else if (!collected.xcodeEncountered ) {
70- DIAGNOSE_ERROR (noProjectFound, " `autobuild` could not detect an Xcode project or workspace." );
71- } else if (targets.empty ()) {
73+ std::sort (std::begin (xcodeTargets), std::end (xcodeTargets),
74+ [](XcodeTarget& lhs, XcodeTarget& rhs) { return lhs.fileCount > rhs.fileCount ; });
75+
76+ if (structure.xcodeEncountered && xcodeTargets.empty () && swiftPackages.empty ()) {
77+ // Report error only when there are no Xcode targets and no Swift packages
7278 DIAGNOSE_ERROR (noSwiftTarget, " All targets found within Xcode projects or workspaces either "
7379 " contain no Swift source files, or are tests." );
74- } else {
75- LOG_INFO (" Selected {}" , targets.front ());
76- buildTarget (targets.front (), args.dryRun );
77- return ;
80+ return false ;
81+ } else if (!structure.xcodeEncountered && swiftPackages.empty ()) {
82+ DIAGNOSE_ERROR (noProjectFound,
83+ " `autobuild` could not detect an Xcode project or workspace or Swift package" );
84+ return false ;
85+ } else if (!xcodeTargets.empty ()) {
86+ LOG_INFO (" Building Xcode target: {}" , xcodeTargets.front ());
87+ installDependencies (structure, args.dryRun );
88+ auto buildSucceeded = buildXcodeTarget (xcodeTargets.front (), args.dryRun );
89+ // If build failed, try to build Swift packages
90+ if (!buildSucceeded && !swiftPackages.empty ()) {
91+ buildSwiftPackages (swiftPackages, args.dryRun );
92+ }
93+ return buildSucceeded;
94+ } else if (!swiftPackages.empty ()) {
95+ buildSwiftPackages (swiftPackages, args.dryRun );
7896 }
97+ return true ;
7998}
8099
81100static CLIArgs parseCLIArgs (int argc, char ** argv) {
@@ -96,7 +115,10 @@ static CLIArgs parseCLIArgs(int argc, char** argv) {
96115
97116int main (int argc, char ** argv) {
98117 auto args = parseCLIArgs (argc, argv);
99- autobuild (args);
118+ auto success = autobuild (args);
100119 codeql::Log::flush ();
120+ if (!success) {
121+ return 1 ;
122+ }
101123 return 0 ;
102124}
0 commit comments