diff --git a/WORKSPACE b/WORKSPACE
index ac387ff8..f4d6249c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,15 +3,15 @@ workspace(name = "rules_foreign_cc")
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
new_http_archive(
- name = "bazel_skylib",
- urls = [
- "https://github.com/bazelbuild/bazel-skylib/archive/0.5.0.tar.gz",
- ],
- strip_prefix= "bazel-skylib-0.5.0",
- sha256 = "b5f6abe419da897b7901f90cbab08af958b97a8f3575b0d3dd062ac7ce78541f",
- type = "tar.gz",
- build_file_content = all_content,
- )
+ name = "bazel_skylib",
+ build_file_content = all_content,
+ sha256 = "b5f6abe419da897b7901f90cbab08af958b97a8f3575b0d3dd062ac7ce78541f",
+ strip_prefix = "bazel-skylib-0.5.0",
+ type = "tar.gz",
+ urls = [
+ "https://github.com/bazelbuild/bazel-skylib/archive/0.5.0.tar.gz",
+ ],
+)
new_http_archive(
name = "libevent",
@@ -21,21 +21,59 @@ new_http_archive(
)
new_http_archive(
- name = "zlib",
- urls = [
- "https://zlib.net/zlib-1.2.11.tar.xz",
- ],
- strip_prefix= "zlib-1.2.11",
- sha256 = "4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
- build_file_content = all_content,
- )
+ name = "zlib",
+ build_file_content = all_content,
+ sha256 = "4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
+ strip_prefix = "zlib-1.2.11",
+ urls = [
+ "https://zlib.net/zlib-1.2.11.tar.xz",
+ ],
+)
new_http_archive(
- name = "libpng",
- urls = [
- "http://ftp-osl.osuosl.org/pub/libpng/src/libpng16/libpng-1.6.34.tar.xz",
- ],
- strip_prefix= "libpng-1.6.34",
- sha256 = "2f1e960d92ce3b3abd03d06dfec9637dfbd22febf107a536b44f7a47c60659f6",
- build_file_content = all_content,
- )
\ No newline at end of file
+ name = "libpng",
+ build_file_content = all_content,
+ sha256 = "2f1e960d92ce3b3abd03d06dfec9637dfbd22febf107a536b44f7a47c60659f6",
+ strip_prefix = "libpng-1.6.34",
+ urls = [
+ "http://ftp-osl.osuosl.org/pub/libpng/src/libpng16/libpng-1.6.34.tar.xz",
+ ],
+)
+
+new_http_archive(
+ name = "org_linaro_components_toolchain_gcc_5_3_1",
+ build_file = "framework_example/cmake_cross/compilers/linaro_linux_gcc_5.3.1.BUILD",
+ strip_prefix = "gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf",
+ url = "https://bazel-mirror.storage.googleapis.com/releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf.tar.xz",
+)
+
+http_archive(
+ name = "bazel_toolchains",
+ sha256 = "259ec05a457bc93aec2aee7e4e67fb4bc1724a183b67baaf5dd6a08be6d6a84a",
+ strip_prefix = "bazel-toolchains-e76b1031eba14c16d72f5837ae7cb7630a2322e2",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/e76b1031eba14c16d72f5837ae7cb7630a2322e2.tar.gz",
+ "https://github.com/bazelbuild/bazel-toolchains/archive/e76b1031eba14c16d72f5837ae7cb7630a2322e2.tar.gz",
+ ],
+)
+
+android_sdk_repository(
+ name = "androidsdk",
+)
+
+android_ndk_repository(
+ name = "androidndk",
+)
+
+# Google Maven Repository
+GMAVEN_TAG = "20180625-1"
+
+http_archive(
+ name = "gmaven_rules",
+ strip_prefix = "gmaven_rules-%s" % GMAVEN_TAG,
+ url = "https://github.com/bazelbuild/gmaven_rules/archive/%s.tar.gz" % GMAVEN_TAG,
+)
+
+load("@gmaven_rules//:gmaven.bzl", "gmaven_rules")
+
+gmaven_rules()
diff --git a/framework_example/cmake/BUILD b/framework_example/cmake/BUILD
index 5d39168c..fd96a457 100644
--- a/framework_example/cmake/BUILD
+++ b/framework_example/cmake/BUILD
@@ -25,7 +25,7 @@ cc_binary(
)
cc_binary(
- name = "test_zlib",
+ name = "zlib_usage_example",
srcs = ["zlib-example.cpp"],
- deps = ["libz"],
+ deps = [":libz"],
)
diff --git a/framework_example/cmake_android/AndroidManifest.xml b/framework_example/cmake_android/AndroidManifest.xml
new file mode 100644
index 00000000..8af06726
--- /dev/null
+++ b/framework_example/cmake_android/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/BUILD b/framework_example/cmake_android/BUILD
new file mode 100644
index 00000000..148db3a3
--- /dev/null
+++ b/framework_example/cmake_android/BUILD
@@ -0,0 +1,38 @@
+load("//tools/build_defs:cmake.bzl", "cmake_external")
+load("@gmaven_rules//:defs.bzl", "gmaven_artifact")
+
+cmake_external(
+ name = "libhello",
+ additional_tools = [
+ "@androidndk//:files",
+ ],
+ lib_source = "//framework_example/cmake_hello_world_lib:srcs",
+)
+
+cc_library(
+ name = "hello_lib_usage_example",
+ srcs = ["hello_lib-example.cpp"],
+ linkstatic = True,
+ deps = [":libhello"],
+ alwayslink = True,
+)
+
+android_library(
+ name = "lib",
+ srcs = ["java/com/example/android/bazel/MainActivity.java"],
+ custom_package = "com.example.android.bazel",
+ manifest = "LibraryManifest.xml",
+ resource_files = glob(["res/**/*"]),
+ deps = [
+ ":hello_lib_usage_example",
+ gmaven_artifact("com.android.support:appcompat-v7:aar:26.1.0"),
+ gmaven_artifact("com.android.support.constraint:constraint-layout:aar:1.1.2"),
+ ],
+)
+
+android_binary(
+ name = "app",
+ custom_package = "com.example.android.bazel",
+ manifest = "AndroidManifest.xml",
+ deps = [":lib"],
+)
diff --git a/framework_example/cmake_android/LibraryManifest.xml b/framework_example/cmake_android/LibraryManifest.xml
new file mode 100644
index 00000000..f6724fd1
--- /dev/null
+++ b/framework_example/cmake_android/LibraryManifest.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/cpp/native-lib.cpp b/framework_example/cmake_android/cpp/native-lib.cpp
new file mode 100644
index 00000000..b28dfc6c
--- /dev/null
+++ b/framework_example/cmake_android/cpp/native-lib.cpp
@@ -0,0 +1,13 @@
+#include
+#include
+
+extern "C"
+JNIEXPORT jstring
+
+JNICALL
+Java_com_example_android_bazel_MainActivity_stringFromJNI(
+ JNIEnv *env,
+ jobject /* this */) {
+ std::string hello = "Hello from C++";
+ return env->NewStringUTF(hello.c_str());
+}
diff --git a/framework_example/cmake_android/hello_lib-example.cpp b/framework_example/cmake_android/hello_lib-example.cpp
new file mode 100644
index 00000000..c42ed6eb
--- /dev/null
+++ b/framework_example/cmake_android/hello_lib-example.cpp
@@ -0,0 +1,8 @@
+#include
+#include "hello.h"
+
+int main(int argc, char* argv[])
+{
+ hello_func();
+ return 0;
+}
\ No newline at end of file
diff --git a/framework_example/cmake_android/java/com/example/android/bazel/MainActivity.java b/framework_example/cmake_android/java/com/example/android/bazel/MainActivity.java
new file mode 100644
index 00000000..cd79f132
--- /dev/null
+++ b/framework_example/cmake_android/java/com/example/android/bazel/MainActivity.java
@@ -0,0 +1,28 @@
+package framework_example.cmake_android.java.com.example.android.bazel;
+
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class MainActivity extends AppCompatActivity {
+
+ static {
+ System.loadLibrary("app");
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // setContentView(R.layout.activity_main);
+ //
+ // // Example of a call to a native method
+ // TextView tv = (TextView) findViewById(R.id.sample_text);
+ // tv.setText(stringFromJNI());
+ }
+
+ /**
+ * A native method that is implemented by the 'native-lib' native library,
+ * which is packaged with this application.
+ */
+ public native String stringFromJNI();
+}
diff --git a/framework_example/cmake_android/res/drawable-v24/ic_launcher_foreground.xml b/framework_example/cmake_android/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..c7bd21db
--- /dev/null
+++ b/framework_example/cmake_android/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/res/drawable/ic_launcher_background.xml b/framework_example/cmake_android/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..d5fccc53
--- /dev/null
+++ b/framework_example/cmake_android/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/res/layout/activity_main.xml b/framework_example/cmake_android/res/layout/activity_main.xml
new file mode 100644
index 00000000..367bd1ab
--- /dev/null
+++ b/framework_example/cmake_android/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher.xml b/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher_round.xml b/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/framework_example/cmake_android/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher.png b/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..a2f59082
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher_round.png b/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..1b523998
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher.png b/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..ff10afd6
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher_round.png b/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..115a4c76
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher.png b/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..dcd3cd80
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher_round.png b/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..459ca609
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher.png b/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..8ca12fe0
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher_round.png b/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..8e19b410
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher.png b/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..b824ebdd
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher_round.png b/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..4c19a13c
Binary files /dev/null and b/framework_example/cmake_android/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/framework_example/cmake_android/res/values/colors.xml b/framework_example/cmake_android/res/values/colors.xml
new file mode 100644
index 00000000..3ab3e9cb
--- /dev/null
+++ b/framework_example/cmake_android/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/framework_example/cmake_android/res/values/strings.xml b/framework_example/cmake_android/res/values/strings.xml
new file mode 100644
index 00000000..a73177f1
--- /dev/null
+++ b/framework_example/cmake_android/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Built By Bazel
+
diff --git a/framework_example/cmake_android/res/values/styles.xml b/framework_example/cmake_android/res/values/styles.xml
new file mode 100644
index 00000000..5885930d
--- /dev/null
+++ b/framework_example/cmake_android/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/framework_example/cmake_android/zlib-example.cpp b/framework_example/cmake_android/zlib-example.cpp
new file mode 100644
index 00000000..19e7a057
--- /dev/null
+++ b/framework_example/cmake_android/zlib-example.cpp
@@ -0,0 +1,80 @@
+// Copied from https://gist.github.com/arq5x/5315739 for test purposes
+
+#include
+#include // for strlen
+#include
+#include "zlib.h"
+
+// adapted from: http://stackoverflow.com/questions/7540259/deflate-and-inflate-zlib-h-in-c
+int main(int argc, char* argv[])
+{
+ // original string len = 36
+ char a[50] = "Hello Hello Hello Hello Hello Hello!";
+
+ // placeholder for the compressed (deflated) version of "a"
+ char b[50];
+
+ // placeholder for the UNcompressed (inflated) version of "b"
+ char c[50];
+
+
+ printf("Uncompressed size is: %lu\n", strlen(a));
+ printf("Uncompressed string is: %s\n", a);
+
+
+ printf("\n----------\n\n");
+
+ // STEP 1.
+ // deflate a into b. (that is, compress a into b)
+
+ // zlib struct
+ z_stream defstream;
+ defstream.zalloc = Z_NULL;
+ defstream.zfree = Z_NULL;
+ defstream.opaque = Z_NULL;
+ // setup "a" as the input and "b" as the compressed output
+ defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator
+ defstream.next_in = (Bytef *)a; // input char array
+ defstream.avail_out = (uInt)sizeof(b); // size of output
+ defstream.next_out = (Bytef *)b; // output char array
+
+ // the actual compression work.
+ deflateInit(&defstream, Z_BEST_COMPRESSION);
+ deflate(&defstream, Z_FINISH);
+ deflateEnd(&defstream);
+
+ // This is one way of getting the size of the output
+ printf("Compressed size is: %lu\n", strlen(b));
+ printf("Compressed string is: %s\n", b);
+
+
+ printf("\n----------\n\n");
+
+
+ // STEP 2.
+ // inflate b into c
+ // zlib struct
+ z_stream infstream;
+ infstream.zalloc = Z_NULL;
+ infstream.zfree = Z_NULL;
+ infstream.opaque = Z_NULL;
+ // setup "b" as the input and "c" as the compressed output
+ infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input
+ infstream.next_in = (Bytef *)b; // input char array
+ infstream.avail_out = (uInt)sizeof(c); // size of output
+ infstream.next_out = (Bytef *)c; // output char array
+
+ // the actual DE-compression work.
+ inflateInit(&infstream);
+ inflate(&infstream, Z_NO_FLUSH);
+ inflateEnd(&infstream);
+
+ printf("Uncompressed size is: %lu\n", strlen(c));
+ printf("Uncompressed string is: %s\n", c);
+
+
+ // make sure uncompressed is exactly equal to original.
+ assert(strcmp(a,c)==0);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/framework_example/cmake_hello_world_lib/BUILD b/framework_example/cmake_hello_world_lib/BUILD
new file mode 100644
index 00000000..a4b04b80
--- /dev/null
+++ b/framework_example/cmake_hello_world_lib/BUILD
@@ -0,0 +1,8 @@
+# example code is taken from https://github.com/Akagi201/learning-cmake/tree/master/hello-world-lib
+# for test only
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//visibility:public"]
+)
diff --git a/framework_example/cmake_hello_world_lib/CMakeLists.txt b/framework_example/cmake_hello_world_lib/CMakeLists.txt
new file mode 100644
index 00000000..4e1188e9
--- /dev/null
+++ b/framework_example/cmake_hello_world_lib/CMakeLists.txt
@@ -0,0 +1,8 @@
+# taken from https://github.com/Akagi201/learning-cmake/tree/master/hello-world-lib
+# for test only
+
+cmake_minimum_required(VERSION 2.8.4)
+
+project(hellolib)
+
+add_subdirectory(src)
\ No newline at end of file
diff --git a/framework_example/cmake_hello_world_lib/src/CMakeLists.txt b/framework_example/cmake_hello_world_lib/src/CMakeLists.txt
new file mode 100644
index 00000000..d4226ca3
--- /dev/null
+++ b/framework_example/cmake_hello_world_lib/src/CMakeLists.txt
@@ -0,0 +1,24 @@
+# taken from https://github.com/Akagi201/learning-cmake/tree/master/hello-world-lib
+# for test only
+
+cmake_minimum_required(VERSION 2.8.4)
+
+message("CMAKE_CXX_CREATE_STATIC_LIBRARY: " CMAKE_CXX_CREATE_STATIC_LIBRARY)
+
+set(LIBHELLO_SRC hello.c)
+
+add_library(hello_dynamic SHARED ${LIBHELLO_SRC})
+add_library(hello_static STATIC ${LIBHELLO_SRC})
+
+set_target_properties(hello_dynamic PROPERTIES OUTPUT_NAME "hello")
+set_target_properties(hello_dynamic PROPERTIES VERSION 1.2 SOVERSION 1)
+
+set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
+
+set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
+
+install(TARGETS hello_dynamic hello_static
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+
+install(FILES hello.h DESTINATION include)
\ No newline at end of file
diff --git a/framework_example/cmake_hello_world_lib/src/hello.c b/framework_example/cmake_hello_world_lib/src/hello.c
new file mode 100644
index 00000000..740ba68c
--- /dev/null
+++ b/framework_example/cmake_hello_world_lib/src/hello.c
@@ -0,0 +1,7 @@
+#include "hello.h"
+
+void hello_func(void) {
+ printf("Hello World!\n");
+
+ return;
+}
\ No newline at end of file
diff --git a/framework_example/cmake_hello_world_lib/src/hello.h b/framework_example/cmake_hello_world_lib/src/hello.h
new file mode 100644
index 00000000..857e1e24
--- /dev/null
+++ b/framework_example/cmake_hello_world_lib/src/hello.h
@@ -0,0 +1,8 @@
+#ifndef HELLO_H_
+#define HELLO_H_ (1)
+
+#include
+
+void hello_func(void);
+
+#endif
\ No newline at end of file
diff --git a/tools/build_defs/cc_linking_util.bzl b/tools/build_defs/cc_linking_util.bzl
deleted file mode 100644
index c05eb088..00000000
--- a/tools/build_defs/cc_linking_util.bzl
+++ /dev/null
@@ -1,227 +0,0 @@
-""" Defines create_linking_info, which wraps passed libraries into CcLinkingInfo
-"""
-
-load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
-
-LibrariesToLinkInfo = provider(
- doc = "Libraries to be wrapped into CcLinkingInfo",
- fields = dict(
- static_libraries = "Static library files, optional",
- shared_libraries = "Dynamic library files, optional",
- interface_libraries = "Interface library files, optional",
-))
-
-def _to_list(element):
- if element == None:
- return []
- else:
- return [element]
-
-def _to_depset(element):
- if element == None:
- return depset()
- return depset(element)
-
-def _perform_error_checks(
- system_provided,
- shared_library_artifacts,
- interface_library_artifacts,
- targets_windows):
- # If the shared library will be provided by system during runtime, users are not supposed to
- # specify shared_library.
- if system_provided and shared_library_artifacts != None:
- fail("'shared_library' shouldn't be specified when 'system_provided' is true")
-
- # If a shared library won't be provided by system during runtime and we are linking the shared
- # library through interface library, the shared library must be specified.
- if (not system_provided and shared_library_artifacts == None and
- interface_library_artifacts != None):
- fail("'shared_library' should be specified when 'system_provided' is false")
-
- if targets_windows and shared_library_artifacts != None:
- fail("'interface library' must be specified when using cc_import for " +
- "shared library on Windows")
-
-def _build_static_library_to_link(ctx, library):
- if library == None:
- fail("Parameter 'static_library_artifact' cannot be None")
-
- static_library_category = None
- if ctx.attr.alwayslink:
- static_library_category = "alwayslink_static_library"
- else:
- static_library_category = "static_library"
-
- return cc_common.create_library_to_link(
- ctx = ctx,
- library = library,
- artifact_category = static_library_category,
- )
-
-def _build_shared_library_to_link(ctx, library, cc_toolchain, targets_windows):
- if library == None:
- fail("Parameter 'shared_library_artifact' cannot be None")
-
- if targets_windows:
- return cc_common.create_library_to_link(
- ctx = ctx,
- library = library,
- artifact_category = "dynamic_library",
- )
- else:
- return cc_common.create_symlink_library_to_link(
- ctx = ctx,
- cc_toolchain = cc_toolchain,
- library = library,
- )
-
-def _build_interface_library_to_link(ctx, library, cc_toolchain, targets_windows):
- if library == None:
- fail("Parameter 'interface_library_artifact' cannot be None")
-
- if targets_windows:
- return cc_common.create_library_to_link(
- ctx = ctx,
- library = library,
- artifact_category = "interface_library",
- )
- else:
- return cc_common.create_symlink_library_to_link(
- ctx = ctx,
- cc_toolchain = cc_toolchain,
- library = library,
- )
-
-# we could possibly take a decision about linking interface/shared library beased on each library name
-# (usefull for the case when multiple output targets are provided)
-def _build_libraries_to_link_and_runtime_artifact(ctx, files, cc_toolchain, targets_windows):
- static_libraries = [_build_static_library_to_link(ctx, lib) for lib in (files.static_libraries or [])]
-
- shared_libraries = []
- runtime_artifacts = []
- if files.shared_libraries != None:
- for lib in files.shared_libraries:
- shared_library += _build_shared_library_to_link(ctx, lib, cc_toolchain, targets_windows)
- runtime_artifact += shared_library.artifact()
-
- interface_libraries = []
- if files.interface_libraries != None:
- for lib in files.interface_libraries:
- interface_libraries += _build_interface_library_to_link(ctx, lib, cc_toolchain, targets_windows)
-
- dynamic_libraries_for_linking = None
- if len(interface_libraries) > 0:
- dynamic_libraries_for_linking = interface_libraries
- else:
- dynamic_libraries_for_linking = shared_libraries
-
- return {"static_libraries": static_libraries,
- "dynamic_libraries": dynamic_libraries_for_linking,
- "runtime_artifacts": runtime_artifacts}
-
-def _build_cc_link_params(
- ctx,
- user_link_flags,
- static_libraries,
- dynamic_libraries,
- runtime_artifacts):
- static_shared = None
- static_no_shared = None
- if static_libraries != None and len(static_libraries) > 0:
- static_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- user_link_flags = user_link_flags,
- libraries_to_link = _to_depset(static_libraries),
- )
- static_no_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- libraries_to_link = _to_depset(static_libraries),
- )
- else:
- static_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- user_link_flags = user_link_flags,
- libraries_to_link = _to_depset(dynamic_libraries),
- dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
- )
- static_no_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- libraries_to_link = _to_depset(dynamic_libraries),
- dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
- )
-
- no_static_shared = None
- no_static_no_shared = None
- if dynamic_libraries != None and len(dynamic_libraries) > 0:
- no_static_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- user_link_flags = user_link_flags,
- libraries_to_link = _to_depset(dynamic_libraries),
- dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
- )
- no_static_no_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- libraries_to_link = _to_depset(dynamic_libraries),
- dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
- )
- else:
- no_static_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- user_link_flags = user_link_flags,
- libraries_to_link = _to_depset(static_libraries),
- )
- no_static_no_shared = cc_common.create_cc_link_params(
- ctx = ctx,
- libraries_to_link = _to_depset(static_libraries),
- )
-
- return {"static_mode_params_for_dynamic_library": static_shared,
- "static_mode_params_for_executable": static_no_shared,
- "dynamic_mode_params_for_dynamic_library": no_static_shared,
- "dynamic_mode_params_for_executable": no_static_no_shared}
-
-def targets_windows(ctx, cc_toolchain):
- """ Returns true if build is targeting Windows
- Args:
- ctx - rule context
- cc_toolchain - optional - Cc toolchain
- """
- toolchain = cc_toolchain if cc_toolchain else find_cpp_toolchain(ctx)
- feature_configuration = cc_common.configure_features(
- cc_toolchain = toolchain,
- requested_features = ctx.features,
- unsupported_features = ctx.disabled_features,
- )
-
- return cc_common.is_enabled(
- feature_configuration = feature_configuration,
- feature_name = "targets_windows",
- )
-
-def create_linking_info(ctx, user_link_flags, files):
- """ Creates CcLinkingInfo for the passed user link options and libraries.
- Args:
- ctx - rule context
- user_link_flags - (list of strings) link optins, provided by user
- files - (LibrariesToLink) provider with the library files
- """
- cc_toolchain = find_cpp_toolchain(ctx)
- for_windows = targets_windows(ctx, cc_toolchain)
-
- _perform_error_checks(
- False,
- files.shared_libraries,
- files.interface_libraries,
- for_windows,
- )
-
- artifacts = _build_libraries_to_link_and_runtime_artifact(
- ctx,
- files,
- cc_toolchain,
- for_windows,
- )
-
- link_params = _build_cc_link_params(ctx, user_link_flags, **artifacts)
-
- return CcLinkingInfo(**link_params)
diff --git a/tools/build_defs/cc_toolchain_util.bzl b/tools/build_defs/cc_toolchain_util.bzl
new file mode 100644
index 00000000..ba906ffd
--- /dev/null
+++ b/tools/build_defs/cc_toolchain_util.bzl
@@ -0,0 +1,397 @@
+""" Defines create_linking_info, which wraps passed libraries into CcLinkingInfo
+"""
+
+load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load(
+ "@bazel_tools//tools/build_defs/cc:action_names.bzl",
+ "ASSEMBLE_ACTION_NAME",
+ "CPP_COMPILE_ACTION_NAME",
+ "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME",
+ "CPP_LINK_EXECUTABLE_ACTION_NAME",
+ "CPP_LINK_STATIC_LIBRARY_ACTION_NAME",
+ "C_COMPILE_ACTION_NAME",
+)
+
+LibrariesToLinkInfo = provider(
+ doc = "Libraries to be wrapped into CcLinkingInfo",
+ fields = dict(
+ static_libraries = "Static library files, optional",
+ shared_libraries = "Shared library files, optional",
+ interface_libraries = "Interface library files, optional",
+ ),
+)
+
+CxxToolsInfo = provider(
+ doc = "Paths to the C/C++ tools, taken from the toolchain",
+ fields = dict(
+ cc = "C compiler",
+ cxx = "C++ compiler",
+ cxx_linker_static = "C++ linker to link static library",
+ cxx_linker_executable = "C++ linker to link executable",
+ ),
+)
+
+CxxFlagsInfo = provider(
+ doc = "Flags for the C/C++ tools, taken from the toolchain",
+ fields = dict(
+ cc = "C compiler flags",
+ cxx = "C++ compiler flags",
+ cxx_linker_shared = "C++ linker flags when linking shared library",
+ cxx_linker_static = "C++ linker flags when linking static library",
+ cxx_linker_executable = "C++ linker flags when linking executable",
+ assemble = "Assemble flags",
+ ),
+)
+
+def _to_list(element):
+ if element == None:
+ return []
+ else:
+ return [element]
+
+def _to_depset(element):
+ if element == None:
+ return depset()
+ return depset(element)
+
+def _perform_error_checks(
+ system_provided,
+ shared_library_artifacts,
+ interface_library_artifacts,
+ targets_windows):
+ # If the shared library will be provided by system during runtime, users are not supposed to
+ # specify shared_library.
+ if system_provided and shared_library_artifacts != None:
+ fail("'shared_library' shouldn't be specified when 'system_provided' is true")
+
+ # If a shared library won't be provided by system during runtime and we are linking the shared
+ # library through interface library, the shared library must be specified.
+ if (not system_provided and shared_library_artifacts == None and
+ interface_library_artifacts != None):
+ fail("'shared_library' should be specified when 'system_provided' is false")
+
+ if targets_windows and shared_library_artifacts != None:
+ fail("'interface library' must be specified when using cc_import for " +
+ "shared library on Windows")
+
+def _build_static_library_to_link(ctx, library):
+ if library == None:
+ fail("Parameter 'static_library_artifact' cannot be None")
+
+ static_library_category = None
+ if ctx.attr.alwayslink:
+ static_library_category = "alwayslink_static_library"
+ else:
+ static_library_category = "static_library"
+
+ return cc_common.create_library_to_link(
+ ctx = ctx,
+ library = library,
+ artifact_category = static_library_category,
+ )
+
+def _build_shared_library_to_link(ctx, library, cc_toolchain, targets_windows):
+ if library == None:
+ fail("Parameter 'shared_library_artifact' cannot be None")
+
+ if targets_windows:
+ return cc_common.create_library_to_link(
+ ctx = ctx,
+ library = library,
+ artifact_category = "dynamic_library",
+ )
+ else:
+ return cc_common.create_symlink_library_to_link(
+ ctx = ctx,
+ cc_toolchain = cc_toolchain,
+ library = library,
+ )
+
+def _build_interface_library_to_link(ctx, library, cc_toolchain, targets_windows):
+ if library == None:
+ fail("Parameter 'interface_library_artifact' cannot be None")
+
+ if targets_windows:
+ return cc_common.create_library_to_link(
+ ctx = ctx,
+ library = library,
+ artifact_category = "interface_library",
+ )
+ else:
+ return cc_common.create_symlink_library_to_link(
+ ctx = ctx,
+ cc_toolchain = cc_toolchain,
+ library = library,
+ )
+
+# we could possibly take a decision about linking interface/shared library beased on each library name
+# (usefull for the case when multiple output targets are provided)
+def _build_libraries_to_link_and_runtime_artifact(ctx, files, cc_toolchain, targets_windows):
+ static_libraries = [_build_static_library_to_link(ctx, lib) for lib in (files.static_libraries or [])]
+
+ shared_libraries = []
+ runtime_artifacts = []
+ if files.shared_libraries != None:
+ for lib in files.shared_libraries:
+ shared_library += _build_shared_library_to_link(ctx, lib, cc_toolchain, targets_windows)
+ runtime_artifact += shared_library.artifact()
+
+ interface_libraries = []
+ if files.interface_libraries != None:
+ for lib in files.interface_libraries:
+ interface_libraries += _build_interface_library_to_link(ctx, lib, cc_toolchain, targets_windows)
+
+ dynamic_libraries_for_linking = None
+ if len(interface_libraries) > 0:
+ dynamic_libraries_for_linking = interface_libraries
+ else:
+ dynamic_libraries_for_linking = shared_libraries
+
+ return {
+ "static_libraries": static_libraries,
+ "dynamic_libraries": dynamic_libraries_for_linking,
+ "runtime_artifacts": runtime_artifacts,
+ }
+
+def _build_cc_link_params(
+ ctx,
+ user_link_flags,
+ static_libraries,
+ dynamic_libraries,
+ runtime_artifacts):
+ static_shared = None
+ static_no_shared = None
+ if static_libraries != None and len(static_libraries) > 0:
+ static_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ user_link_flags = user_link_flags,
+ libraries_to_link = _to_depset(static_libraries),
+ )
+ static_no_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ libraries_to_link = _to_depset(static_libraries),
+ )
+ else:
+ static_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ user_link_flags = user_link_flags,
+ libraries_to_link = _to_depset(dynamic_libraries),
+ dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
+ )
+ static_no_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ libraries_to_link = _to_depset(dynamic_libraries),
+ dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
+ )
+
+ no_static_shared = None
+ no_static_no_shared = None
+ if dynamic_libraries != None and len(dynamic_libraries) > 0:
+ no_static_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ user_link_flags = user_link_flags,
+ libraries_to_link = _to_depset(dynamic_libraries),
+ dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
+ )
+ no_static_no_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ libraries_to_link = _to_depset(dynamic_libraries),
+ dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
+ )
+ else:
+ no_static_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ user_link_flags = user_link_flags,
+ libraries_to_link = _to_depset(static_libraries),
+ )
+ no_static_no_shared = cc_common.create_cc_link_params(
+ ctx = ctx,
+ libraries_to_link = _to_depset(static_libraries),
+ )
+
+ return {
+ "static_mode_params_for_dynamic_library": static_shared,
+ "static_mode_params_for_executable": static_no_shared,
+ "dynamic_mode_params_for_dynamic_library": no_static_shared,
+ "dynamic_mode_params_for_executable": no_static_no_shared,
+ }
+
+def targets_windows(ctx, cc_toolchain):
+ """ Returns true if build is targeting Windows
+ Args:
+ ctx - rule context
+ cc_toolchain - optional - Cc toolchain
+ """
+ toolchain = cc_toolchain if cc_toolchain else find_cpp_toolchain(ctx)
+ feature_configuration = cc_common.configure_features(
+ cc_toolchain = toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+
+ return cc_common.is_enabled(
+ feature_configuration = feature_configuration,
+ feature_name = "targets_windows",
+ )
+
+def create_linking_info(ctx, user_link_flags, files):
+ """ Creates CcLinkingInfo for the passed user link options and libraries.
+ Args:
+ ctx - rule context
+ user_link_flags - (list of strings) link optins, provided by user
+ files - (LibrariesToLink) provider with the library files
+ """
+ cc_toolchain = find_cpp_toolchain(ctx)
+ for_windows = targets_windows(ctx, cc_toolchain)
+
+ _perform_error_checks(
+ False,
+ files.shared_libraries,
+ files.interface_libraries,
+ for_windows,
+ )
+
+ artifacts = _build_libraries_to_link_and_runtime_artifact(
+ ctx,
+ files,
+ cc_toolchain,
+ for_windows,
+ )
+
+ link_params = _build_cc_link_params(ctx, user_link_flags, **artifacts)
+
+ return CcLinkingInfo(**link_params)
+
+def getToolsInfo(ctx):
+ """ Takes information about tools paths from cc_toolchain, returns CxxToolsInfo
+ Args:
+ ctx - rule context
+ """
+ cc_toolchain = find_cpp_toolchain(ctx)
+ feature_configuration = cc_common.configure_features(
+ cc_toolchain = cc_toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+
+ return CxxToolsInfo(
+ cc = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ ),
+ cxx = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = CPP_COMPILE_ACTION_NAME,
+ ),
+ cxx_linker_static = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
+ ),
+ cxx_linker_executable = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
+ ),
+ )
+
+def getFlagsInfo(ctx):
+ """ Takes information about flags from cc_toolchain, returns CxxFlagsInfo
+ Args:
+ ctx - rule context
+ """
+ cc_toolchain = find_cpp_toolchain(ctx)
+ feature_configuration = cc_common.configure_features(
+ cc_toolchain = cc_toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+ copts = ctx.attr.copts if hasattr(ctx.attr, "copts") else depset()
+
+ return CxxFlagsInfo(
+ cc = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = cc_common.create_compile_variables(
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ user_compile_flags = copts,
+ ),
+ ),
+ cxx = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_COMPILE_ACTION_NAME,
+ variables = cc_common.create_compile_variables(
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ user_compile_flags = copts,
+ add_legacy_cxx_options = True,
+ ),
+ ),
+ cxx_linker_shared = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
+ variables = cc_common.create_link_variables(
+ cc_toolchain = cc_toolchain,
+ feature_configuration = feature_configuration,
+ is_using_linker = True,
+ is_linking_dynamic_library = True,
+ ),
+ ),
+ cxx_linker_static = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
+ variables = cc_common.create_link_variables(
+ cc_toolchain = cc_toolchain,
+ feature_configuration = feature_configuration,
+ is_using_linker = False,
+ is_linking_dynamic_library = False,
+ ),
+ ),
+ cxx_linker_executable = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
+ variables = cc_common.create_link_variables(
+ cc_toolchain = cc_toolchain,
+ feature_configuration = feature_configuration,
+ is_using_linker = True,
+ is_linking_dynamic_library = False,
+ ),
+ ),
+ assemble = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = ASSEMBLE_ACTION_NAME,
+ variables = cc_common.create_compile_variables(
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ user_compile_flags = copts,
+ ),
+ ),
+ )
+
+def absolutize_path_in_str(ctx, text, root_str):
+ """ Replaces relative paths in [the middle of] 'text', prepending them with 'root_str'.
+ If there is nothing to replace, returns the 'text'.
+
+ We only will replace relative paths starting with either 'external/' or '/',
+ because we only want to point with absolute paths to external repositories or inside our
+ current workspace. (And also to limit the possibility of error with such not exact replacing.)
+
+ Args:
+ ctx - rule context (to determine the top package name)
+ text - the text to do replacement in
+ root_str - the text to prepend to the found relative path
+ """
+ package = ctx.label.package
+ if package.find("/") > 0:
+ (package, separator, tail) = package.partition("/")
+
+ new_text = _prefix(text, "external/", root_str)
+ if new_text == text:
+ new_text = _prefix(text, package + "/", root_str)
+
+ return new_text
+
+def _prefix(text, from_str, prefix):
+ (before, middle, after) = text.partition(from_str)
+ if not middle or before.endswith("/"):
+ return text
+ return before + prefix + middle + after
diff --git a/tools/build_defs/cmake.bzl b/tools/build_defs/cmake.bzl
index fcef0b3e..f79c920e 100644
--- a/tools/build_defs/cmake.bzl
+++ b/tools/build_defs/cmake.bzl
@@ -1,24 +1,102 @@
""" Defines the rule for building external library with CMake
"""
-load("//tools/build_defs:framework.bzl", "cc_external_rule_impl", "detect_root",
- "CC_EXTERNAL_RULE_ATTRIBUTES", "create_attrs")
+load(
+ "//tools/build_defs:framework.bzl",
+ "CC_EXTERNAL_RULE_ATTRIBUTES",
+ "cc_external_rule_impl",
+ "create_attrs",
+ "detect_root",
+)
+load("//tools/build_defs:cc_toolchain_util.bzl", "absolutize_path_in_str", "getFlagsInfo", "getToolsInfo")
def _cmake_external(ctx):
- options = " ".join(ctx.attr.cmake_options)
- root = detect_root(ctx.attr.lib_source)
- cmake_string = "cmake -DCMAKE_PREFIX_PATH=\"$EXT_BUILD_ROOT\" -DCMAKE_INSTALL_PREFIX=$INSTALLDIR {} $EXT_BUILD_ROOT/{}".format(options, root)
+ options = " ".join(ctx.attr.cmake_options)
+ root = detect_root(ctx.attr.lib_source)
- attrs = create_attrs(ctx.attr,
- configure_name = 'CMake',
- configure_script = cmake_string)
+ tools = getToolsInfo(ctx)
+ flags = getFlagsInfo(ctx)
- return cc_external_rule_impl(ctx, attrs)
+ cmake_string = " ".join([
+ " ".join(_get_toolchain_variables(ctx, tools, flags)),
+ " cmake",
+ " ".join(_get_toolchain_options(ctx, tools, flags)),
+ "-DCMAKE_PREFIX_PATH=\"$EXT_BUILD_ROOT\"",
+ "-DCMAKE_INSTALL_PREFIX=$INSTALLDIR",
+ options,
+ "$EXT_BUILD_ROOT/" + root,
+ ])
+
+ attrs = create_attrs(
+ ctx.attr,
+ configure_name = "CMake",
+ configure_script = cmake_string,
+ )
+
+ return cc_external_rule_impl(ctx, attrs)
+
+def _get_toolchain_variables(ctx, tools, flags):
+ vars = []
+
+ if tools.cc:
+ vars += _env_var(ctx, "CC", [tools.cc])
+ if tools.cxx:
+ vars += _env_var(ctx, "CXX", [tools.cxx])
+ if flags.cc:
+ vars += _env_var(ctx, "CFLAGS", flags.cc)
+ if flags.cc:
+ vars += _env_var(ctx, "CXXFLAGS", flags.cxx)
+ if flags.assemble:
+ vars += _env_var(ctx, "ASMFLAGS", flags.assemble)
+ return vars
+
+def _get_toolchain_options(ctx, tools, flags):
+ options = []
+ if tools.cxx_linker_static:
+ options += _option(ctx, "CMAKE_AR", [tools.cxx_linker_static])
+
+ # this does not work by some reason
+ # options += _option(ctx, "CMAKE_CXX_CREATE_STATIC_LIBRARY", [" qc "])
+ # options += _option(ctx, "CMAKE_CXX_ARCHIVE_CREATE", [" qc "])
+ # options += _option(ctx, "CMAKE_CXX_ARCHIVE_APPEND", [" qc "])
+ # options += _option(ctx, "CMAKE_CXX_ARCHIVE_FINISH", [" "])
+
+ if tools.cxx_linker_executable:
+ # https://github.com/Kitware/CMake/blob/master/Modules/CMakeCXXInformation.cmake
+ rule_string = " ".join([
+ "{}",
+ "",
+ "",
+ "",
+ "",
+ "-o ",
+ "",
+ ]).format(absolutize_path_in_str(ctx, tools.cxx_linker_executable, "$EXT_BUILD_ROOT/"))
+ options += _option(ctx, "CMAKE_CXX_LINK_EXECUTABLE", [rule_string])
+
+ # commented out for now, because http://cmake.3232098.n2.nabble.com/CMake-incorrectly-passes-linker-flags-to-ar-td7592436.html
+ # if flags.cxx_linker_static:
+ # options += _option(ctx, "CMAKE_STATIC_LINKER_FLAGS", flags.cxx_linker_static)
+ if flags.cxx_linker_shared:
+ options += _option(ctx, "CMAKE_SHARED_LINKER_FLAGS", flags.cxx_linker_shared)
+ if flags.cxx_linker_executable:
+ options += _option(ctx, "CMAKE_EXE_LINKER_FLAGS", flags.cxx_linker_executable)
+
+ return options
+
+def _env_var(ctx, cmake_option, flags):
+ return ["{}=\"{}\"".format(cmake_option, _join_flags_list(ctx, flags))]
+
+def _option(ctx, cmake_option, flags):
+ return ["-D{}=\"{}\"".format(cmake_option, _join_flags_list(ctx, flags))]
+
+def _join_flags_list(ctx, flags):
+ return " ".join([absolutize_path_in_str(ctx, flag, "$EXT_BUILD_ROOT/") for flag in flags])
def _attrs():
- attrs = dict(CC_EXTERNAL_RULE_ATTRIBUTES)
- attrs.update({"cmake_options": attr.string_list(mandatory = False, default = [])})
- return attrs
+ attrs = dict(CC_EXTERNAL_RULE_ATTRIBUTES)
+ attrs.update({"cmake_options": attr.string_list(mandatory = False, default = [])})
+ return attrs
""" Rule for building external library with CMake
Attributes:
@@ -29,5 +107,5 @@ cmake_external = rule(
attrs = _attrs(),
fragments = ["cpp"],
output_to_genfiles = True,
- implementation = _cmake_external
+ implementation = _cmake_external,
)
diff --git a/tools/build_defs/framework.bzl b/tools/build_defs/framework.bzl
index 519c4742..c428d1e8 100644
--- a/tools/build_defs/framework.bzl
+++ b/tools/build_defs/framework.bzl
@@ -3,8 +3,12 @@
"""
load("@bazel_skylib//lib:collections.bzl", "collections")
-load("//tools/build_defs:cc_linking_util.bzl", "create_linking_info", "LibrariesToLinkInfo",
- "targets_windows")
+load(
+ "//tools/build_defs:cc_toolchain_util.bzl",
+ "LibrariesToLinkInfo",
+ "create_linking_info",
+ "targets_windows",
+)
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
Many of the attributes have default values.
@@ -13,242 +17,245 @@ load("//tools/build_defs:cc_linking_util.bzl", "create_linking_info", "Libraries
description dict. See cmake.bzl as an example.
"""
CC_EXTERNAL_RULE_ATTRIBUTES = {
- # Library name. Defines the name of the install directory and the name of the static library,
- # if no output files parameters are defined (any of static_libraries, shared_libraries,
- # interface_libraries, binaries_names)
- # Optional. If not defined, defaults to the target's name.
- "lib_name": attr.string(mandatory = False),
- # Label with source code to build. Typically a filegroup for the source of remote repository.
- # Mandatory.
- "lib_source": attr.label(mandatory = True, allow_files = True),
- # Optional compilation definitions to be passed to the dependencies of this library.
- # They are NOT passed to the compiler, you should duplicate them in the configuration options.
- "defines": attr.string_list(mandatory = False, default = []),
- #
- # Optional additional inputs to be declared as needed for the shell script action.
- # Not used by the shell script part in cc_external_rule_impl.
- "additional_inputs": attr.label_list(mandatory = False, allow_files = True, default = []),
- # Optional additional tools needed for the building.
- # Not used by the shell script part in cc_external_rule_impl.
- "additional_tools": attr.label_list(mandatory = False, allow_files = True, default = []),
- #
- # Optional part of the shell script to be added after the make commands
- "postfix_script": attr.string(mandatory = False),
- # Optinal make commands, defaults to ["make", "make install"]
- "make_commands": attr.string_list(mandatory = False, default = ["make", "make install"]),
- #
- # Optional dependencies to be copied into the directory structure.
- # Typically those directly required for the external building of the library/binaries.
- # (i.e. those that the external buidl system will be looking for and paths to which are
- # provided by the calling rule)
- "deps": attr.label_list(mandatory = False, allow_files = True, default = []),
- # Optional tools to be copied into the directory structure.
- # Similar to deps, those directly required for the external building of the library/binaries.
- "tools_deps": attr.label_list(mandatory = False, allow_files = True, default = []),
- #
- # Optional name of the output subdirectory with the header files, defaults to 'include'.
- "out_include_dir": attr.string(mandatory = False, default = "include"),
- # Optional name of the output subdirectory with the library files, defaults to 'lib'.
- "out_lib_dir": attr.string(mandatory = False, default = "lib"),
- # Optional name of the output subdirectory with the binary files, defaults to 'bin'.
- "out_bin_dir": attr.string(mandatory = False, default = "bin"),
- #
- # Optional. if true, link all the object files from the static library,
- # even if they are not used.
- "alwayslink": attr.bool(mandatory = False, default = False),
- # Optional link options to be passed up to the dependencies of this library
- "linkopts": attr.string_list(mandatory = False, default = []),
- #
- # Output files names parameters. If any of them is defined, only these files are passed to
- # Bazel providers.
- # if no of them is defined, default lib_name.a/lib_name.lib static library is assumed.
- #
- # Optional names of the resulting static libraries.
- "static_libraries": attr.string_list(mandatory = False),
- # Optional names of the resulting shared libraries.
- "shared_libraries": attr.string_list(mandatory = False),
- # Optional names of the resulting interface libraries.
- "interface_libraries": attr.string_list(mandatory = False),
- # Optional names of the resulting binaries.
- "binaries": attr.string_list(mandatory = False),
- #
- # Optional name of the output subdirectory with pkgconfig files.
- "out_pkg_config_dir": attr.string(mandatory = False),
- # link to the shell utilities used by the shell script in cc_external_rule_impl.
- "_utils": attr.label(
- default = Label("//tools/build_defs:utils.sh"),
- allow_single_file = True,
- executable = True,
- cfg = "target"
- ),
- # we need to declare this attribute to access cc_toolchain
- "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
+ # Library name. Defines the name of the install directory and the name of the static library,
+ # if no output files parameters are defined (any of static_libraries, shared_libraries,
+ # interface_libraries, binaries_names)
+ # Optional. If not defined, defaults to the target's name.
+ "lib_name": attr.string(mandatory = False),
+ # Label with source code to build. Typically a filegroup for the source of remote repository.
+ # Mandatory.
+ "lib_source": attr.label(mandatory = True, allow_files = True),
+ # Optional compilation definitions to be passed to the dependencies of this library.
+ # They are NOT passed to the compiler, you should duplicate them in the configuration options.
+ "defines": attr.string_list(mandatory = False, default = []),
+ #
+ # Optional additional inputs to be declared as needed for the shell script action.
+ # Not used by the shell script part in cc_external_rule_impl.
+ "additional_inputs": attr.label_list(mandatory = False, allow_files = True, default = []),
+ # Optional additional tools needed for the building.
+ # Not used by the shell script part in cc_external_rule_impl.
+ "additional_tools": attr.label_list(mandatory = False, allow_files = True, default = []),
+ #
+ # Optional part of the shell script to be added after the make commands
+ "postfix_script": attr.string(mandatory = False),
+ # Optinal make commands, defaults to ["make", "make install"]
+ "make_commands": attr.string_list(mandatory = False, default = ["make", "make install"]),
+ #
+ # Optional dependencies to be copied into the directory structure.
+ # Typically those directly required for the external building of the library/binaries.
+ # (i.e. those that the external buidl system will be looking for and paths to which are
+ # provided by the calling rule)
+ "deps": attr.label_list(mandatory = False, allow_files = True, default = []),
+ # Optional tools to be copied into the directory structure.
+ # Similar to deps, those directly required for the external building of the library/binaries.
+ "tools_deps": attr.label_list(mandatory = False, allow_files = True, default = []),
+ #
+ # Optional name of the output subdirectory with the header files, defaults to 'include'.
+ "out_include_dir": attr.string(mandatory = False, default = "include"),
+ # Optional name of the output subdirectory with the library files, defaults to 'lib'.
+ "out_lib_dir": attr.string(mandatory = False, default = "lib"),
+ # Optional name of the output subdirectory with the binary files, defaults to 'bin'.
+ "out_bin_dir": attr.string(mandatory = False, default = "bin"),
+ #
+ # Optional. if true, link all the object files from the static library,
+ # even if they are not used.
+ "alwayslink": attr.bool(mandatory = False, default = False),
+ # Optional link options to be passed up to the dependencies of this library
+ "linkopts": attr.string_list(mandatory = False, default = []),
+ #
+ # Output files names parameters. If any of them is defined, only these files are passed to
+ # Bazel providers.
+ # if no of them is defined, default lib_name.a/lib_name.lib static library is assumed.
+ #
+ # Optional names of the resulting static libraries.
+ "static_libraries": attr.string_list(mandatory = False),
+ # Optional names of the resulting shared libraries.
+ "shared_libraries": attr.string_list(mandatory = False),
+ # Optional names of the resulting interface libraries.
+ "interface_libraries": attr.string_list(mandatory = False),
+ # Optional names of the resulting binaries.
+ "binaries": attr.string_list(mandatory = False),
+ #
+ # Optional name of the output subdirectory with pkgconfig files.
+ "out_pkg_config_dir": attr.string(mandatory = False),
+ # link to the shell utilities used by the shell script in cc_external_rule_impl.
+ "_utils": attr.label(
+ default = Label("//tools/build_defs:utils.sh"),
+ allow_single_file = True,
+ executable = True,
+ cfg = "target",
+ ),
+ # we need to declare this attribute to access cc_toolchain
+ "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
}
def create_attrs(attr_struct, configure_name, configure_script, **kwargs):
- """ Function for adding/modifying context attributes struct (originally from ctx.attr),
- provided by user, to be passed to the cc_external_rule_impl function as a struct.
+ """ Function for adding/modifying context attributes struct (originally from ctx.attr),
+ provided by user, to be passed to the cc_external_rule_impl function as a struct.
- Copies a struct 'attr_struct' values (with attributes from CC_EXTERNAL_RULE_ATTRIBUTES)
- to the resulting struct, adding or replacing attributes passed in 'configure_name',
- 'configure_script', and '**kwargs' parameters.
- """
- dict = {}
- for key in CC_EXTERNAL_RULE_ATTRIBUTES:
- if not key.startswith("_") and hasattr(attr_struct, key):
- dict[key] = getattr(attr_struct, key)
+ Copies a struct 'attr_struct' values (with attributes from CC_EXTERNAL_RULE_ATTRIBUTES)
+ to the resulting struct, adding or replacing attributes passed in 'configure_name',
+ 'configure_script', and '**kwargs' parameters.
+ """
+ dict = {}
+ for key in CC_EXTERNAL_RULE_ATTRIBUTES:
+ if not key.startswith("_") and hasattr(attr_struct, key):
+ dict[key] = getattr(attr_struct, key)
- dict["configure_name"] = configure_name
- dict["configure_script"] = configure_script
+ dict["configure_name"] = configure_name
+ dict["configure_script"] = configure_script
- for arg in kwargs:
- dict[arg] = kwargs[arg]
- return struct(**dict)
+ for arg in kwargs:
+ dict[arg] = kwargs[arg]
+ return struct(**dict)
def cc_external_rule_impl(ctx, attrs):
- """ Framework function for performing external C/C++ building.
+ """ Framework function for performing external C/C++ building.
- To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
- and use results in Bazel.
- It is possible to use it to build a group of external libraries, that depend on each other or on
- Bazel library, and pass nessesary tools.
+ To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
+ and use results in Bazel.
+ It is possible to use it to build a group of external libraries, that depend on each other or on
+ Bazel library, and pass nessesary tools.
- Accepts the actual commands for build configuration/execution in attrs.
+ Accepts the actual commands for build configuration/execution in attrs.
- Creates and runs a shell script, which:
+ Creates and runs a shell script, which:
- 1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
- of the execroot directory. Adds tools into PATH.
- 2) defines the correct absolute paths in tools with the script paths, see 7
- 3) defines the following environment variables:
- EXT_BUILD_ROOT: execroot directory
- EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:
- include - here the include directories are symlinked
- lib - here the library files are symlinked
- lib/pkgconfig - here the pkgconfig files are symlinked
- bin - here the tools are copied
- INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
- will be installed
+ 1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
+ of the execroot directory. Adds tools into PATH.
+ 2) defines the correct absolute paths in tools with the script paths, see 7
+ 3) defines the following environment variables:
+ EXT_BUILD_ROOT: execroot directory
+ EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:
+ include - here the include directories are symlinked
+ lib - here the library files are symlinked
+ lib/pkgconfig - here the pkgconfig files are symlinked
+ bin - here the tools are copied
+ INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
+ will be installed
- These variables should be used by the calling rule to refer to the created directory structure.
- 4) calls 'attrs.configure_script'
- 5) calls 'attrs.make_commands'
- 6) calls 'attrs.postfix_script'
- 7) replaces absolute paths in possibly created scripts with a placeholder value
+ These variables should be used by the calling rule to refer to the created directory structure.
+ 4) calls 'attrs.configure_script'
+ 5) calls 'attrs.make_commands'
+ 6) calls 'attrs.postfix_script'
+ 7) replaces absolute paths in possibly created scripts with a placeholder value
- Please see cmake.bzl for example usage.
+ Please see cmake.bzl for example usage.
- Args:
- ctx: calling rule context
- attrs: struct with fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there), and
- two mandatory fields:
- configure_name: name of the configuration tool, to be used in action mnemonic
- configure_script: actual configuration script
- All other fields are ignored.
- """
- lib_name = _value(attrs.lib_name, ctx.attr.name)
+ Args:
+ ctx: calling rule context
+ attrs: struct with fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there), and
+ two mandatory fields:
+ configure_name: name of the configuration tool, to be used in action mnemonic
+ configure_script: actual configuration script
+ All other fields are ignored.
+ """
+ lib_name = _value(attrs.lib_name, ctx.attr.name)
- inputs = _define_inputs(attrs)
- outputs = _define_outputs(ctx, attrs, lib_name)
- out_cc_info = _define_out_cc_info(ctx, attrs, inputs, outputs)
+ inputs = _define_inputs(attrs)
+ outputs = _define_outputs(ctx, attrs, lib_name)
+ out_cc_info = _define_out_cc_info(ctx, attrs, inputs, outputs)
- shell_utils = ctx.attr._utils.files.to_list()[0].path
+ shell_utils = ctx.attr._utils.files.to_list()[0].path
- script_lines = [
- "set -e",
- "EXT_BUILD_ROOT=$(pwd)",
- "source " + shell_utils,
- "echo \"Building external library '{}'\"".format(lib_name),
- "TMPDIR=$(mktemp -d)",
- "trap \"{ rm -rf $TMPDIR; }\" EXIT",
- "EXT_BUILD_DEPS=$(mktemp -d --tmpdir=$EXT_BUILD_ROOT)",
- "\n".join(_copy_deps_and_tools(inputs)),
- "define_absolute_paths $EXT_BUILD_ROOT/bin $EXT_BUILD_ROOT/bin",
- "INSTALLDIR=$EXT_BUILD_ROOT/" + outputs.installdir.path,
- "mkdir -p $INSTALLDIR",
- "echo_vars INSTALLDIR EXT_BUILD_DEPS EXT_BUILD_ROOT PATH",
- "pushd $TMPDIR",
- attrs.configure_script,
- "\n".join(attrs.make_commands),
- _value(attrs.postfix_script, ""),
- "replace_absolute_paths $INSTALLDIR $INSTALLDIR",
- "popd",
- ]
+ script_lines = [
+ "set -e",
+ "export EXT_BUILD_ROOT=$(pwd)",
+ "source " + shell_utils,
+ "echo \"Building external library '{}'\"".format(lib_name),
+ "TMPDIR=$(mktemp -d)",
+ "trap \"{ rm -rf $TMPDIR; }\" EXIT",
+ "export EXT_BUILD_DEPS=$(mktemp -d --tmpdir=$EXT_BUILD_ROOT)",
+ "\n".join(_copy_deps_and_tools(inputs)),
+ "define_absolute_paths $EXT_BUILD_ROOT/bin $EXT_BUILD_ROOT/bin",
+ "export INSTALLDIR=$EXT_BUILD_ROOT/" + outputs.installdir.path,
+ "mkdir -p $INSTALLDIR",
+ "echo_vars INSTALLDIR EXT_BUILD_DEPS EXT_BUILD_ROOT PATH",
+ "pushd $TMPDIR",
+ attrs.configure_script,
+ "\n".join(attrs.make_commands),
+ _value(attrs.postfix_script, ""),
+ "replace_absolute_paths $INSTALLDIR $INSTALLDIR",
+ "popd",
+ ]
- script_text = '\n'.join(script_lines)
+ script_text = "\n".join(script_lines)
- ctx.actions.run_shell(
- mnemonic="Cc" + attrs.configure_name.capitalize() + "MakeRule",
- inputs = inputs.declared_inputs,
- outputs = outputs.declared_outputs,
- tools = ctx.attr._utils.files,
- use_default_shell_env=True,
- command = script_text,
- execution_requirements = {"block-network": ""}
- )
+ ctx.actions.run_shell(
+ mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
+ inputs = inputs.declared_inputs,
+ outputs = outputs.declared_outputs,
+ tools = ctx.attr._utils.files,
+ use_default_shell_env = True,
+ command = script_text,
+ execution_requirements = {"block-network": ""},
+ )
- return [DefaultInfo(files = depset(direct = outputs.declared_outputs)),
- OutputGroupInfo(gen_dir = depset([outputs.installdir]),
- bin_dir = depset([outputs.out_bin_dir]),
- out_binary_files = depset(outputs.out_binary_files),
- pkg_config_dir = outputs.out_pkg_dir or []),
- cc_common.create_cc_skylark_info(ctx=ctx),
- out_cc_info.compilation_info,
- out_cc_info.linking_info,
-]
+ return [
+ DefaultInfo(files = depset(direct = outputs.declared_outputs)),
+ OutputGroupInfo(
+ gen_dir = depset([outputs.installdir]),
+ bin_dir = depset([outputs.out_bin_dir]),
+ out_binary_files = depset(outputs.out_binary_files),
+ pkg_config_dir = outputs.out_pkg_dir or [],
+ ),
+ cc_common.create_cc_skylark_info(ctx = ctx),
+ out_cc_info.compilation_info,
+ out_cc_info.linking_info,
+ ]
def _value(value, default_value):
- if (value):
- return value
- return default_value
+ if (value):
+ return value
+ return default_value
def _depset(item):
- if item == None:
- return depset()
- return depset([item])
+ if item == None:
+ return depset()
+ return depset([item])
def _list(item):
- if item:
- return [item]
- return []
+ if item:
+ return [item]
+ return []
def _copy_deps_and_tools(files):
- list = []
- list += _symlink_to_dir("lib", files.libs, False)
- list += _symlink_to_dir("include", files.headers, True)
- list += _symlink_to_dir("lib/pkgconfig", files.pkg_configs, False)
- list += _symlink_to_dir("bin", files.tools_files, False)
+ list = []
+ list += _symlink_to_dir("lib", files.libs, False)
+ list += _symlink_to_dir("include", files.headers, True)
+ list += _symlink_to_dir("lib/pkgconfig", files.pkg_configs, False)
+ list += _symlink_to_dir("bin", files.tools_files, False)
- list += ["if [ -d $EXT_BUILD_DEPS/bin ]; then"]
- list += [" tools=$(find $EXT_BUILD_DEPS/bin -type d,l -maxdepth 1)"]
- list += [" for tool in $tools; do export PATH=$PATH:$tool; done"]
- list += ["fi"]
- list += ["path $EXT_BUILD_DEPS/bin"]
- list += ["export PKG_CONFIG_PATH=$EXT_BUILD_ROOT/lib/pkgconfig"]
+ list += ["if [ -d $EXT_BUILD_DEPS/bin ]; then"]
+ list += [" tools=$(find $EXT_BUILD_DEPS/bin -type d,l -maxdepth 1)"]
+ list += [" for tool in $tools; do export PATH=$PATH:$tool; done"]
+ list += ["fi"]
+ list += ["path $EXT_BUILD_DEPS/bin"]
+ list += ["export PKG_CONFIG_PATH=$EXT_BUILD_ROOT/lib/pkgconfig"]
- return list
+ return list
def _symlink_to_dir(dir_name, files_list, link_children):
- if len(files_list) == 0:
- return []
- list = ["mkdir -p $EXT_BUILD_DEPS/" + dir_name]
+ if len(files_list) == 0:
+ return []
+ list = ["mkdir -p $EXT_BUILD_DEPS/" + dir_name]
- paths_list = []
- for file in files_list:
- paths_list += [file if type(file) == "string" else file.path]
+ paths_list = []
+ for file in files_list:
+ paths_list += [file if type(file) == "string" else file.path]
- link_function = "symlink_dir_contents_to_dir" if link_children else "symlink_to_dir"
- for path in paths_list:
- list += ["{} $EXT_BUILD_ROOT/{} $EXT_BUILD_DEPS/{}".format(link_function, path, dir_name)]
+ link_function = "symlink_dir_contents_to_dir" if link_children else "symlink_to_dir"
+ for path in paths_list:
+ list += ["{} $EXT_BUILD_ROOT/{} $EXT_BUILD_DEPS/{}".format(link_function, path, dir_name)]
- return list
+ return list
def _check_file_name(var, name):
- if (len(var) == 0):
- fail("{} can not be empty string.".format(name.capitalize()))
+ if (len(var) == 0):
+ fail("{} can not be empty string.".format(name.capitalize()))
- if (not var[0:1].isalpha()):
- fail("{} should start with a letter.".format(name.capitalize()))
+ if (not var[0:1].isalpha()):
+ fail("{} should start with a letter.".format(name.capitalize()))
for index in range(1, len(var) - 1):
letter = var[index]
if not letter.isalnum() and letter != '_':
@@ -265,58 +272,58 @@ _Outputs = provider(
out_binary_files = "Binary files, which will be created by the action",
libraries = "Library files, which will be created by the action",
declared_outputs = "All output files and directories of the action",
- )
+ ),
)
def _define_outputs(ctx, attrs, lib_name):
- static_libraries = []
- if (not (hasattr(attrs, "static_libraries") and len(attrs.static_libraries) > 0) and
+ static_libraries = []
+ if (not (hasattr(attrs, "static_libraries") and len(attrs.static_libraries) > 0) and
not (hasattr(attrs, "shared_libraries") and len(attrs.shared_libraries) > 0) and
not (hasattr(attrs, "interface_libraries") and len(attrs.interface_libraries) > 0) and
not (hasattr(attrs, "binaries") and len(attrs.binaries) > 0)):
- static_libraries = [lib_name + (".lib" if targets_windows(ctx, None) else ".a")]
- else:
- static_libraries = attrs.static_libraries
+ static_libraries = [lib_name + (".lib" if targets_windows(ctx, None) else ".a")]
+ else:
+ static_libraries = attrs.static_libraries
- _check_file_name(lib_name, "Library name")
+ _check_file_name(lib_name, "Library name")
- out_binary_files = []
- for file in attrs.binaries:
- out_binary_files += [_declare_out(ctx, lib_name, attrs.out_bin_dir, file)]
+ out_binary_files = []
+ for file in attrs.binaries:
+ out_binary_files += [_declare_out(ctx, lib_name, attrs.out_bin_dir, file)]
- out_pkg_dir = None
- if attrs.out_pkg_config_dir:
- out_pkg_dir = ctx.actions.declare_file("/".join([lib_name, attrs.out_pkg_config_dir]))
+ out_pkg_dir = None
+ if attrs.out_pkg_config_dir:
+ out_pkg_dir = ctx.actions.declare_file("/".join([lib_name, attrs.out_pkg_config_dir]))
- installdir = ctx.actions.declare_directory(lib_name)
- out_include_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_include_dir)
- out_bin_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_bin_dir)
- out_lib_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_lib_dir)
+ installdir = ctx.actions.declare_directory(lib_name)
+ out_include_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_include_dir)
+ out_bin_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_bin_dir)
+ out_lib_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_lib_dir)
- libraries = LibrariesToLinkInfo(
- static_libraries = _declare_out(ctx, lib_name, out_lib_dir, static_libraries),
- shared_libraries = _declare_out(ctx, lib_name, out_lib_dir, attrs.shared_libraries),
- interface_libraries = _declare_out(ctx, lib_name, out_lib_dir, attrs.interface_libraries),
- )
- declared_outputs = [installdir, out_include_dir, out_bin_dir, out_lib_dir] + out_binary_files
- declared_outputs += _list(out_pkg_dir) + libraries.static_libraries
- declared_outputs += libraries.shared_libraries + libraries.interface_libraries
+ libraries = LibrariesToLinkInfo(
+ static_libraries = _declare_out(ctx, lib_name, out_lib_dir, static_libraries),
+ shared_libraries = _declare_out(ctx, lib_name, out_lib_dir, attrs.shared_libraries),
+ interface_libraries = _declare_out(ctx, lib_name, out_lib_dir, attrs.interface_libraries),
+ )
+ declared_outputs = [installdir, out_include_dir, out_bin_dir, out_lib_dir] + out_binary_files
+ declared_outputs += _list(out_pkg_dir) + libraries.static_libraries
+ declared_outputs += libraries.shared_libraries + libraries.interface_libraries
- return _Outputs(
- installdir = installdir,
- out_include_dir = out_include_dir,
- out_bin_dir = out_bin_dir,
- out_lib_dir = out_lib_dir,
- out_pkg_dir = out_pkg_dir,
- out_binary_files = out_binary_files,
- libraries = libraries,
- declared_outputs = declared_outputs,
- )
+ return _Outputs(
+ installdir = installdir,
+ out_include_dir = out_include_dir,
+ out_bin_dir = out_bin_dir,
+ out_lib_dir = out_lib_dir,
+ out_pkg_dir = out_pkg_dir,
+ out_binary_files = out_binary_files,
+ libraries = libraries,
+ declared_outputs = declared_outputs,
+ )
def _declare_out(ctx, lib_name, dir, files):
- if files and len(files) > 0:
- return [ctx.actions.declare_file("/".join([lib_name, dir.basename, file])) for file in files]
- return []
+ if files and len(files) > 0:
+ return [ctx.actions.declare_file("/".join([lib_name, dir.basename, file])) for file in files]
+ return []
_InputFiles = provider(
doc = """Provider to keep different kinds of input files, directories,
@@ -331,45 +338,45 @@ to be copied into the bin folder, which is added to the PATH""",
PKG_CONFIG_PATH is assigned to that folder""",
deps_compilation_info = "Merged CcCompilationInfo from deps attribute",
deps_linking_info = "Merged CcLinkingInfo from deps attribute",
- declared_inputs = "All files and directories that must be declared as action inputs"
- )
+ declared_inputs = "All files and directories that must be declared as action inputs",
+ ),
)
def _define_inputs(attrs):
- pkg_configs = []
- compilation_infos = []
- linking_infos = []
+ pkg_configs = []
+ compilation_infos = []
+ linking_infos = []
- for dep in attrs.deps:
- compilation_infos += [dep[CcCompilationInfo]]
- linking_infos += [dep[CcLinkingInfo]]
+ for dep in attrs.deps:
+ compilation_infos += [dep[CcCompilationInfo]]
+ linking_infos += [dep[CcLinkingInfo]]
- provider = dep[OutputGroupInfo]
- if provider and hasattr(provider, "pkg_config_dir"):
- # or do we want to be able to produce several files?
- pkg_configs += provider.pkg_config_dir.to_list()
+ provider = dep[OutputGroupInfo]
+ if provider and hasattr(provider, "pkg_config_dir"):
+ # or do we want to be able to produce several files?
+ pkg_configs += provider.pkg_config_dir.to_list()
- tools_roots = []
- tools_files = []
- for tool in attrs.tools_deps:
- tool_root = detect_root(tool)
- tools_roots += [tool_root]
- for file_list in tool.files.to_list():
- tools_files += _list(file_list)
+ tools_roots = []
+ tools_files = []
+ for tool in attrs.tools_deps:
+ tool_root = detect_root(tool)
+ tools_roots += [tool_root]
+ for file_list in tool.files.to_list():
+ tools_files += _list(file_list)
- for tool in attrs.additional_tools:
- for file_list in tool.files.to_list():
- tools_files += _list(file_list)
+ for tool in attrs.additional_tools:
+ for file_list in tool.files.to_list():
+ tools_files += _list(file_list)
- deps_compilation = cc_common.merge_cc_compilation_infos(cc_compilation_infos = compilation_infos)
- deps_linking = cc_common.merge_cc_linking_infos(cc_linking_infos = linking_infos)
+ deps_compilation = cc_common.merge_cc_compilation_infos(cc_compilation_infos = compilation_infos)
+ deps_linking = cc_common.merge_cc_linking_infos(cc_linking_infos = linking_infos)
- (libs, linkopts) = _collect_libs_and_flags(deps_linking)
- headers = []
- for cc_info in compilation_infos:
- headers += _get_headers(cc_info)
+ (libs, linkopts) = _collect_libs_and_flags(deps_linking)
+ headers = []
+ for cc_info in compilation_infos:
+ headers += _get_headers(cc_info)
- return _InputFiles(
+ return _InputFiles(
headers = headers,
libs = libs,
deps_linkopts = linkopts,
@@ -378,70 +385,83 @@ def _define_inputs(attrs):
deps_compilation_info = deps_compilation,
deps_linking_info = deps_linking,
declared_inputs = depset(attrs.lib_source.files) + libs + tools_files + pkg_configs +
- attrs.additional_inputs + deps_compilation.headers
-)
+ attrs.additional_inputs + deps_compilation.headers,
+ )
def _get_headers(compilation_info):
- include_dirs = collections.uniq(compilation_info.system_includes.to_list())
- headers = []
- for header in compilation_info.headers:
- path = header.path
- included = False
- for dir in include_dirs:
- if path.startswith(dir):
- included = True
- break
- if not included:
- headers += [header]
- return headers + include_dirs
+ include_dirs = collections.uniq(compilation_info.system_includes.to_list())
+ headers = []
+ for header in compilation_info.headers:
+ path = header.path
+ included = False
+ for dir in include_dirs:
+ if path.startswith(dir):
+ included = True
+ break
+ if not included:
+ headers += [header]
+ return headers + include_dirs
def _define_out_cc_info(ctx, attrs, inputs, outputs):
- compilation_info = CcCompilationInfo(headers = depset([outputs.out_include_dir]),
- system_includes = depset([outputs.out_include_dir.path]),
- defines = depset(attrs.defines))
- out_compilation_info = cc_common.merge_cc_compilation_infos(
- cc_compilation_infos = [inputs.deps_compilation_info, compilation_info])
+ compilation_info = CcCompilationInfo(
+ headers = depset([outputs.out_include_dir]),
+ system_includes = depset([outputs.out_include_dir.path]),
+ defines = depset(attrs.defines),
+ )
+ out_compilation_info = cc_common.merge_cc_compilation_infos(
+ cc_compilation_infos = [inputs.deps_compilation_info, compilation_info],
+ )
- linkopts = depset(direct = attrs.linkopts, transitive = [depset(inputs.deps_linkopts)])
- linking_info = create_linking_info(ctx, linkopts, outputs.libraries)
- out_linking_info = cc_common.merge_cc_linking_infos(
- cc_linking_infos = [inputs.deps_linking_info, linking_info])
+ linkopts = depset(direct = attrs.linkopts, transitive = [depset(inputs.deps_linkopts)])
+ linking_info = create_linking_info(ctx, linkopts, outputs.libraries)
+ out_linking_info = cc_common.merge_cc_linking_infos(
+ cc_linking_infos = [inputs.deps_linking_info, linking_info],
+ )
- return struct(
- compilation_info = out_compilation_info,
- linking_info = out_linking_info
- )
+ return struct(
+ compilation_info = out_compilation_info,
+ linking_info = out_linking_info,
+ )
def _collect_libs_and_flags(cc_linking):
- libs = []
- linkopts = []
+ libs = []
+ linkopts = []
- for params in [cc_linking.static_mode_params_for_dynamic_library,
- cc_linking.static_mode_params_for_executable,
- cc_linking.dynamic_mode_params_for_dynamic_library,
- cc_linking.dynamic_mode_params_for_executable]:
- libs += [lib.artifact() for lib in params.libraries_to_link.to_list()]
- libs += params.dynamic_libraries_for_runtime.to_list()
- linkopts = params.linkopts.to_list()
+ for params in [
+ cc_linking.static_mode_params_for_dynamic_library,
+ cc_linking.static_mode_params_for_executable,
+ cc_linking.dynamic_mode_params_for_dynamic_library,
+ cc_linking.dynamic_mode_params_for_executable,
+ ]:
+ libs += [lib.artifact() for lib in params.libraries_to_link.to_list()]
+ libs += params.dynamic_libraries_for_runtime.to_list()
+ linkopts = params.linkopts.to_list()
- return (collections.uniq(libs), collections.uniq(linkopts))
+ return (collections.uniq(libs), collections.uniq(linkopts))
def detect_root(source):
- """Detects the path to the topmost directory of the 'source' outputs.
- To be used with external build systems to point to the source code/tools directories.
+ """Detects the path to the topmost directory of the 'source' outputs.
+ To be used with external build systems to point to the source code/tools directories.
- If the target groups the sources of the external dependency, the workspace root is used,
- and no other checks are performed (i.e. it is assumed that the whole contents of the external
- dependency is used).
- Otherwise, for the "usual" targets, target's files are iterated and the path with the least length
- is selected.
- """
- root = source.label.workspace_root
- sources = source.files
- if (not root or len(root) == 0) and len(sources) > 0:
- root = ""
- # find topmost directory
- for file in sources:
- if len(root) == 0 or len(root) > len(file.path):
- root = file.path
- return root
\ No newline at end of file
+ If the target groups the sources of the external dependency, the workspace root is used,
+ and no other checks are performed (i.e. it is assumed that the whole contents of the external
+ dependency is used).
+ Otherwise, for the "usual" targets, target's files are iterated and the path with the least length
+ is selected.
+ """
+ root = source.label.workspace_root
+ sources = source.files
+ if (not root or len(root) == 0) and len(sources) > 0:
+ root = ""
+
+ # find topmost directory
+ for file in sources:
+ if len(root) == 0 or len(root) > len(file.path):
+ root = file.path
+ else:
+ return root
+
+ (before, sep, after) = root.rpartition("/")
+ if before and sep and after:
+ return before
+ return root