Skip to content

Commit 5c8fa84

Browse files
authored
Merge pull request github#10786 from github/alexdenisov/xcode-autobuilder
Swift: introduce Xcode autobuilder
2 parents 6208071 + 0c3fd9f commit 5c8fa84

14 files changed

+605
-4
lines changed

swift/BUILD.bazel

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ pkg_files(
2424
)
2525

2626
pkg_files(
27-
name = "qltest",
28-
srcs = ["tools/qltest.sh"],
27+
name = "scripts",
28+
srcs = ["tools/qltest.sh", "tools/autobuild.sh"],
2929
attributes = pkg_attributes(mode = "0755"),
3030
prefix = "tools",
3131
)
@@ -46,8 +46,8 @@ pkg_filegroup(
4646
srcs = [
4747
":dbscheme_files",
4848
":manifest",
49-
":qltest",
5049
":tracing-config",
50+
":scripts",
5151
],
5252
visibility = ["//visibility:public"],
5353
)
@@ -58,6 +58,12 @@ pkg_runfiles(
5858
prefix = "tools/" + codeql_platform,
5959
)
6060

61+
pkg_runfiles(
62+
name = "xcode-autobuilder",
63+
srcs = ["//swift/xcode-autobuilder"],
64+
prefix = "tools/" + codeql_platform,
65+
)
66+
6167
pkg_files(
6268
name = "swift-test-sdk-arch",
6369
srcs = ["//swift/tools/prebuilt:swift-test-sdk"],
@@ -70,7 +76,12 @@ pkg_filegroup(
7076
srcs = [
7177
":extractor",
7278
":swift-test-sdk-arch",
73-
],
79+
] + select({
80+
"@platforms//os:linux": [],
81+
"@platforms//os:macos": [
82+
":xcode-autobuilder"
83+
],
84+
}),
7485
visibility = ["//visibility:public"],
7586
)
7687

swift/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ project(codeql)
1414
include(../misc/bazel/cmake/setup.cmake)
1515

1616
include_generated(//swift/extractor:cmake)
17+
include_generated(//swift/xcode-autobuilder:cmake)

swift/tools/autobuild.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
if [[ "$OSTYPE" == "darwin"* ]]; then
4+
exec "${CODEQL_EXTRACTOR_SWIFT_ROOT}/tools/${CODEQL_PLATFORM}/xcode-autobuilder"
5+
else
6+
echo "Not implemented yet"
7+
exit 1
8+
fi

swift/xcode-autobuilder/BUILD.bazel

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
load("//swift:rules.bzl", "swift_cc_binary")
2+
load("//misc/bazel/cmake:cmake.bzl", "generate_cmake")
3+
4+
swift_cc_binary(
5+
name = "xcode-autobuilder",
6+
srcs = glob([
7+
"*.cpp",
8+
"*.h",
9+
]),
10+
visibility = ["//swift:__pkg__"],
11+
linkopts = [
12+
"-lxml2",
13+
"-framework CoreFoundation",
14+
],
15+
target_compatible_with = ["@platforms//os:macos"],
16+
)
17+
18+
generate_cmake(
19+
name = "cmake",
20+
targets = [":xcode-autobuilder"],
21+
visibility = ["//visibility:public"],
22+
)

swift/xcode-autobuilder/CFHelpers.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "swift/xcode-autobuilder/CFHelpers.h"
2+
3+
#include <iostream>
4+
5+
typedef CFTypeID (*cf_get_type_id)();
6+
7+
template <typename CFType, cf_get_type_id get_type_id>
8+
CFType cf_cast(const void* ptr) {
9+
if (!ptr) {
10+
return nullptr;
11+
}
12+
if (CFGetTypeID(ptr) != get_type_id()) {
13+
std::cerr << "Unexpected type: ";
14+
CFShow(ptr);
15+
abort();
16+
}
17+
return static_cast<CFType>(ptr);
18+
}
19+
20+
CFStringRef cf_string_ref(const void* ptr) {
21+
return cf_cast<CFStringRef, CFStringGetTypeID>(ptr);
22+
}
23+
24+
CFArrayRef cf_array_ref(const void* ptr) {
25+
return cf_cast<CFArrayRef, CFArrayGetTypeID>(ptr);
26+
}
27+
CFDictionaryRef cf_dictionary_ref(const void* ptr) {
28+
return cf_cast<CFDictionaryRef, CFDictionaryGetTypeID>(ptr);
29+
}
30+
31+
std::string stringValueForKey(CFDictionaryRef dict, CFStringRef key) {
32+
auto cfValue = cf_string_ref(CFDictionaryGetValue(dict, key));
33+
if (cfValue) {
34+
const int bufferSize = 256;
35+
char buf[bufferSize];
36+
if (CFStringGetCString(cfValue, buf, bufferSize, kCFStringEncodingUTF8)) {
37+
return {buf};
38+
}
39+
}
40+
return {};
41+
}

swift/xcode-autobuilder/CFHelpers.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <CoreFoundation/CoreFoundation.h>
4+
#include <string>
5+
#include <vector>
6+
7+
CFStringRef cf_string_ref(const void* ptr);
8+
CFArrayRef cf_array_ref(const void* ptr);
9+
CFDictionaryRef cf_dictionary_ref(const void* ptr);
10+
11+
std::string stringValueForKey(CFDictionaryRef dict, CFStringRef key);
12+
13+
struct CFKeyValues {
14+
static CFKeyValues fromDictionary(CFDictionaryRef dict) {
15+
auto size = CFDictionaryGetCount(dict);
16+
CFKeyValues ret(size);
17+
CFDictionaryGetKeysAndValues(dict, ret.keys.data(), ret.values.data());
18+
return ret;
19+
}
20+
explicit CFKeyValues(size_t size) : size(size), keys(size), values(size) {}
21+
size_t size;
22+
std::vector<const void*> keys;
23+
std::vector<const void*> values;
24+
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "swift/xcode-autobuilder/XcodeBuildRunner.h"
2+
3+
#include <vector>
4+
#include <iostream>
5+
#include <spawn.h>
6+
7+
static int waitpid_status(pid_t child) {
8+
int status;
9+
while (waitpid(child, &status, 0) == -1) {
10+
if (errno != EINTR) break;
11+
}
12+
return status;
13+
}
14+
15+
extern char** environ;
16+
17+
static bool exec(const std::vector<std::string>& argv) {
18+
const char** c_argv = (const char**)calloc(argv.size() + 1, sizeof(char*));
19+
for (size_t i = 0; i < argv.size(); i++) {
20+
c_argv[i] = argv[i].c_str();
21+
}
22+
c_argv[argv.size()] = nullptr;
23+
24+
pid_t pid = 0;
25+
if (posix_spawn(&pid, argv.front().c_str(), nullptr, nullptr, (char* const*)c_argv, environ) !=
26+
0) {
27+
std::cerr << "[xcode autobuilder] posix_spawn failed: " << strerror(errno) << "\n";
28+
free(c_argv);
29+
return false;
30+
}
31+
free(c_argv);
32+
int status = waitpid_status(pid);
33+
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
34+
return false;
35+
}
36+
return true;
37+
}
38+
39+
void buildTarget(Target& target, bool dryRun) {
40+
std::vector<std::string> argv({"/usr/bin/xcodebuild", "build"});
41+
if (!target.workspace.empty()) {
42+
argv.push_back("-workspace");
43+
argv.push_back(target.workspace);
44+
argv.push_back("-scheme");
45+
} else {
46+
argv.push_back("-project");
47+
argv.push_back(target.project);
48+
argv.push_back("-target");
49+
}
50+
argv.push_back(target.name);
51+
argv.push_back("CODE_SIGNING_REQUIRED=NO");
52+
argv.push_back("CODE_SIGNING_ALLOWED=NO");
53+
54+
if (dryRun) {
55+
for (auto& arg : argv) {
56+
std::cout << arg + " ";
57+
}
58+
std::cout << "\n";
59+
} else {
60+
if (!exec(argv)) {
61+
std::cerr << "Build failed\n";
62+
exit(1);
63+
}
64+
}
65+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include "swift/xcode-autobuilder/XcodeTarget.h"
4+
5+
void buildTarget(Target& target, bool dryRun);

0 commit comments

Comments
 (0)