use tools paths and flags from the toolchain (#7)

* take tools paths and flags from the toolchain

* correct toolchain data extraction, correct cmake flags and environment

* framework script: export variables intended to be used in config script

config script can create child processes which could use this variables

* cmake: prepend relative [to the execroot] paths with "$EXT_BUILD_ROOT/"

unfortunately, CMake does not understand relative paths
(sometimes it runs tests for the passed compiler and for that
concatenates the passed relative path to some tmp directory created for test)

we replace only paths starting with external/ and <top-package-name>/,
so we are quite fine to not make a mistake with replacing some not related to paths text;
the targets for replacement take very different form (judging by examining
toolchain definitions), for instance "-Lexternal/something"

* test data for cross compilation for android and with --crosstool_top

data files taken from bazel examples and bazel test data;

NB one of the interesting things is that we need to specify tools dependency on android sdk and ndk, so that cmake_external shell script have access to these tools

* remove cross compilation example with CROSSTOOL for now

* add very simple CMake library (test data)

* rename target to indicate it is not a test, but example

* adjust android example:

rename the target to indicate it is not a test but example,
add android ndk sources as additional tool for cmake target,
(otherwise it is not available in sandbox)
use more simple cmake-built library

* corrections to the framework & cmake:

- correct search for the root directory of the filegroup (when it is not under external)
- it was a mistake to specify shared library linker, specify CMAKE_AR instead
- unfortunately, I have not discovered how to modify CMake behaviour to pass the custom static flags (rcsD) before "-qc <target>" to the ar linker; option from documentation does not work. To be investigated. For now, do not pass the static cxx linker options, taken from Bazel toolchain.
This commit is contained in:
irengrig 2018-08-06 15:23:18 +02:00 committed by GitHub
parent 44c0c97846
commit 067d4be22e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 1398 additions and 587 deletions

View File

@ -4,14 +4,14 @@ all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//v
new_http_archive( new_http_archive(
name = "bazel_skylib", name = "bazel_skylib",
build_file_content = all_content,
sha256 = "b5f6abe419da897b7901f90cbab08af958b97a8f3575b0d3dd062ac7ce78541f",
strip_prefix = "bazel-skylib-0.5.0",
type = "tar.gz",
urls = [ urls = [
"https://github.com/bazelbuild/bazel-skylib/archive/0.5.0.tar.gz", "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,
)
new_http_archive( new_http_archive(
name = "libevent", name = "libevent",
@ -22,20 +22,58 @@ new_http_archive(
new_http_archive( new_http_archive(
name = "zlib", name = "zlib",
build_file_content = all_content,
sha256 = "4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
strip_prefix = "zlib-1.2.11",
urls = [ urls = [
"https://zlib.net/zlib-1.2.11.tar.xz", "https://zlib.net/zlib-1.2.11.tar.xz",
], ],
strip_prefix= "zlib-1.2.11", )
sha256 = "4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066",
build_file_content = all_content,
)
new_http_archive( new_http_archive(
name = "libpng", name = "libpng",
build_file_content = all_content,
sha256 = "2f1e960d92ce3b3abd03d06dfec9637dfbd22febf107a536b44f7a47c60659f6",
strip_prefix = "libpng-1.6.34",
urls = [ urls = [
"http://ftp-osl.osuosl.org/pub/libpng/src/libpng16/libpng-1.6.34.tar.xz", "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, 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()

View File

@ -25,7 +25,7 @@ cc_binary(
) )
cc_binary( cc_binary(
name = "test_zlib", name = "zlib_usage_example",
srcs = ["zlib-example.cpp"], srcs = ["zlib-example.cpp"],
deps = ["libz"], deps = [":libz"],
) )

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.bazel">
<uses-sdk android:minSdkVersion="14" />
</manifest>

View File

@ -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"],
)

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.bazel">
<uses-sdk android:minSdkVersion="14" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,13 @@
#include <jni.h>
#include <string>
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());
}

View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include "hello.h"
int main(int argc, char* argv[])
{
hello_func();
return 0;
}

View File

@ -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();
}

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF"
android:strokeWidth="0.8" />
</vector>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.bazel.MainActivity">
<TextView
android:id="@+id/sample_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@ -0,0 +1,3 @@
<resources>
<string name="app_name">Built By Bazel</string>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -0,0 +1,80 @@
// Copied from https://gist.github.com/arq5x/5315739 for test purposes
#include <stdio.h>
#include <string.h> // for strlen
#include <assert.h>
#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;
}

View File

@ -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"]
)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,7 @@
#include "hello.h"
void hello_func(void) {
printf("Hello World!\n");
return;
}

View File

@ -0,0 +1,8 @@
#ifndef HELLO_H_
#define HELLO_H_ (1)
#include <stdio.h>
void hello_func(void);
#endif

View File

@ -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)

View File

@ -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 '<top-package-name>/',
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

View File

@ -1,20 +1,98 @@
""" Defines the rule for building external library with CMake """ Defines the rule for building external library with CMake
""" """
load("//tools/build_defs:framework.bzl", "cc_external_rule_impl", "detect_root", load(
"CC_EXTERNAL_RULE_ATTRIBUTES", "create_attrs") "//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): def _cmake_external(ctx):
options = " ".join(ctx.attr.cmake_options) options = " ".join(ctx.attr.cmake_options)
root = detect_root(ctx.attr.lib_source) 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)
attrs = create_attrs(ctx.attr, tools = getToolsInfo(ctx)
configure_name = 'CMake', flags = getFlagsInfo(ctx)
configure_script = cmake_string)
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) 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", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_CREATE", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_APPEND", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_FINISH", ["<CMAKE_RANLIB> <TARGET>"])
if tools.cxx_linker_executable:
# https://github.com/Kitware/CMake/blob/master/Modules/CMakeCXXInformation.cmake
rule_string = " ".join([
"{}",
"<FLAGS>",
"<CMAKE_CXX_LINK_FLAGS>",
"<LINK_FLAGS>",
"<OBJECTS>",
"-o <TARGET>",
"<LINK_LIBRARIES>",
]).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(): def _attrs():
attrs = dict(CC_EXTERNAL_RULE_ATTRIBUTES) attrs = dict(CC_EXTERNAL_RULE_ATTRIBUTES)
attrs.update({"cmake_options": attr.string_list(mandatory = False, default = [])}) attrs.update({"cmake_options": attr.string_list(mandatory = False, default = [])})
@ -29,5 +107,5 @@ cmake_external = rule(
attrs = _attrs(), attrs = _attrs(),
fragments = ["cpp"], fragments = ["cpp"],
output_to_genfiles = True, output_to_genfiles = True,
implementation = _cmake_external implementation = _cmake_external,
) )

View File

@ -3,8 +3,12 @@
""" """
load("@bazel_skylib//lib:collections.bzl", "collections") load("@bazel_skylib//lib:collections.bzl", "collections")
load("//tools/build_defs:cc_linking_util.bzl", "create_linking_info", "LibrariesToLinkInfo", load(
"targets_windows") "//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. """ Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
Many of the attributes have default values. Many of the attributes have default values.
@ -79,7 +83,7 @@ CC_EXTERNAL_RULE_ATTRIBUTES = {
default = Label("//tools/build_defs:utils.sh"), default = Label("//tools/build_defs:utils.sh"),
allow_single_file = True, allow_single_file = True,
executable = True, executable = True,
cfg = "target" cfg = "target",
), ),
# we need to declare this attribute to access cc_toolchain # we need to declare this attribute to access cc_toolchain
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
@ -156,15 +160,15 @@ def cc_external_rule_impl(ctx, attrs):
script_lines = [ script_lines = [
"set -e", "set -e",
"EXT_BUILD_ROOT=$(pwd)", "export EXT_BUILD_ROOT=$(pwd)",
"source " + shell_utils, "source " + shell_utils,
"echo \"Building external library '{}'\"".format(lib_name), "echo \"Building external library '{}'\"".format(lib_name),
"TMPDIR=$(mktemp -d)", "TMPDIR=$(mktemp -d)",
"trap \"{ rm -rf $TMPDIR; }\" EXIT", "trap \"{ rm -rf $TMPDIR; }\" EXIT",
"EXT_BUILD_DEPS=$(mktemp -d --tmpdir=$EXT_BUILD_ROOT)", "export EXT_BUILD_DEPS=$(mktemp -d --tmpdir=$EXT_BUILD_ROOT)",
"\n".join(_copy_deps_and_tools(inputs)), "\n".join(_copy_deps_and_tools(inputs)),
"define_absolute_paths $EXT_BUILD_ROOT/bin $EXT_BUILD_ROOT/bin", "define_absolute_paths $EXT_BUILD_ROOT/bin $EXT_BUILD_ROOT/bin",
"INSTALLDIR=$EXT_BUILD_ROOT/" + outputs.installdir.path, "export INSTALLDIR=$EXT_BUILD_ROOT/" + outputs.installdir.path,
"mkdir -p $INSTALLDIR", "mkdir -p $INSTALLDIR",
"echo_vars INSTALLDIR EXT_BUILD_DEPS EXT_BUILD_ROOT PATH", "echo_vars INSTALLDIR EXT_BUILD_DEPS EXT_BUILD_ROOT PATH",
"pushd $TMPDIR", "pushd $TMPDIR",
@ -175,27 +179,30 @@ def cc_external_rule_impl(ctx, attrs):
"popd", "popd",
] ]
script_text = '\n'.join(script_lines) script_text = "\n".join(script_lines)
ctx.actions.run_shell( ctx.actions.run_shell(
mnemonic="Cc" + attrs.configure_name.capitalize() + "MakeRule", mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
inputs = inputs.declared_inputs, inputs = inputs.declared_inputs,
outputs = outputs.declared_outputs, outputs = outputs.declared_outputs,
tools = ctx.attr._utils.files, tools = ctx.attr._utils.files,
use_default_shell_env=True, use_default_shell_env = True,
command = script_text, command = script_text,
execution_requirements = {"block-network": ""} execution_requirements = {"block-network": ""},
) )
return [DefaultInfo(files = depset(direct = outputs.declared_outputs)), return [
OutputGroupInfo(gen_dir = depset([outputs.installdir]), DefaultInfo(files = depset(direct = outputs.declared_outputs)),
OutputGroupInfo(
gen_dir = depset([outputs.installdir]),
bin_dir = depset([outputs.out_bin_dir]), bin_dir = depset([outputs.out_bin_dir]),
out_binary_files = depset(outputs.out_binary_files), out_binary_files = depset(outputs.out_binary_files),
pkg_config_dir = outputs.out_pkg_dir or []), pkg_config_dir = outputs.out_pkg_dir or [],
cc_common.create_cc_skylark_info(ctx=ctx), ),
cc_common.create_cc_skylark_info(ctx = ctx),
out_cc_info.compilation_info, out_cc_info.compilation_info,
out_cc_info.linking_info, out_cc_info.linking_info,
] ]
def _value(value, default_value): def _value(value, default_value):
if (value): if (value):
@ -265,7 +272,7 @@ _Outputs = provider(
out_binary_files = "Binary files, which will be created by the action", out_binary_files = "Binary files, which will be created by the action",
libraries = "Library 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", declared_outputs = "All output files and directories of the action",
) ),
) )
def _define_outputs(ctx, attrs, lib_name): def _define_outputs(ctx, attrs, lib_name):
@ -331,8 +338,8 @@ to be copied into the bin folder, which is added to the PATH""",
PKG_CONFIG_PATH is assigned to that folder""", PKG_CONFIG_PATH is assigned to that folder""",
deps_compilation_info = "Merged CcCompilationInfo from deps attribute", deps_compilation_info = "Merged CcCompilationInfo from deps attribute",
deps_linking_info = "Merged CcLinkingInfo 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): def _define_inputs(attrs):
@ -378,8 +385,8 @@ def _define_inputs(attrs):
deps_compilation_info = deps_compilation, deps_compilation_info = deps_compilation,
deps_linking_info = deps_linking, deps_linking_info = deps_linking,
declared_inputs = depset(attrs.lib_source.files) + libs + tools_files + pkg_configs + 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): def _get_headers(compilation_info):
include_dirs = collections.uniq(compilation_info.system_includes.to_list()) include_dirs = collections.uniq(compilation_info.system_includes.to_list())
@ -396,30 +403,36 @@ def _get_headers(compilation_info):
return headers + include_dirs return headers + include_dirs
def _define_out_cc_info(ctx, attrs, inputs, outputs): def _define_out_cc_info(ctx, attrs, inputs, outputs):
compilation_info = CcCompilationInfo(headers = depset([outputs.out_include_dir]), compilation_info = CcCompilationInfo(
headers = depset([outputs.out_include_dir]),
system_includes = depset([outputs.out_include_dir.path]), system_includes = depset([outputs.out_include_dir.path]),
defines = depset(attrs.defines)) defines = depset(attrs.defines),
)
out_compilation_info = cc_common.merge_cc_compilation_infos( out_compilation_info = cc_common.merge_cc_compilation_infos(
cc_compilation_infos = [inputs.deps_compilation_info, compilation_info]) cc_compilation_infos = [inputs.deps_compilation_info, compilation_info],
)
linkopts = depset(direct = attrs.linkopts, transitive = [depset(inputs.deps_linkopts)]) linkopts = depset(direct = attrs.linkopts, transitive = [depset(inputs.deps_linkopts)])
linking_info = create_linking_info(ctx, linkopts, outputs.libraries) linking_info = create_linking_info(ctx, linkopts, outputs.libraries)
out_linking_info = cc_common.merge_cc_linking_infos( out_linking_info = cc_common.merge_cc_linking_infos(
cc_linking_infos = [inputs.deps_linking_info, linking_info]) cc_linking_infos = [inputs.deps_linking_info, linking_info],
)
return struct( return struct(
compilation_info = out_compilation_info, compilation_info = out_compilation_info,
linking_info = out_linking_info linking_info = out_linking_info,
) )
def _collect_libs_and_flags(cc_linking): def _collect_libs_and_flags(cc_linking):
libs = [] libs = []
linkopts = [] linkopts = []
for params in [cc_linking.static_mode_params_for_dynamic_library, for params in [
cc_linking.static_mode_params_for_dynamic_library,
cc_linking.static_mode_params_for_executable, cc_linking.static_mode_params_for_executable,
cc_linking.dynamic_mode_params_for_dynamic_library, cc_linking.dynamic_mode_params_for_dynamic_library,
cc_linking.dynamic_mode_params_for_executable]: cc_linking.dynamic_mode_params_for_executable,
]:
libs += [lib.artifact() for lib in params.libraries_to_link.to_list()] libs += [lib.artifact() for lib in params.libraries_to_link.to_list()]
libs += params.dynamic_libraries_for_runtime.to_list() libs += params.dynamic_libraries_for_runtime.to_list()
linkopts = params.linkopts.to_list() linkopts = params.linkopts.to_list()
@ -440,8 +453,15 @@ def detect_root(source):
sources = source.files sources = source.files
if (not root or len(root) == 0) and len(sources) > 0: if (not root or len(root) == 0) and len(sources) > 0:
root = "" root = ""
# find topmost directory # find topmost directory
for file in sources: for file in sources:
if len(root) == 0 or len(root) > len(file.path): if len(root) == 0 or len(root) > len(file.path):
root = file.path root = file.path
else:
return root
(before, sep, after) = root.rpartition("/")
if before and sep and after:
return before
return root return root