Git Product home page Git Product logo

cc-rules's Introduction

C and C++ rules for Please

This repo defines a Please plugin for building C and C++ code.

C and C++ build actions are very similar and can be intermingled freely (following the usual language rules); the main reason for separating them is to allow defining different tools and compiler flags for the two.

Basic usage

# Add this to plugins/BUILD 
plugin_repo(
    name = "cc",
    revision = "v1.0.0",
)

# Subinclude from the plugin
subinclude("///plugins/cc//build_defs:cc")

# Compile some C code
cc_library(
    name = "foo",
    srcs = ["foo.c"],
    # Headers are specified separately so they can be exposed to other rules
    hdrs = ["foo.h"],
)

cc_binary(
   name = "main",
   srcs = ["main.c"],
   deps = [":foo"],
)

Build definitions

There are several different targets available providing different rules:

//build_defs:cc

Contains the following C++ rules that use cpp_tool, default_opt_cppflags, default_dbg_cppflags and test_main.

  • cc_library()
  • cc_binary()
  • cc_test()
  • cc_object()
  • cc_static_library()
  • cc_shared_object()
  • cc_module() (N.B. this is still experimental)

And the following C rules that use cc_tool, default_opt_cflags and default_dbg_cflags:

  • c_library()
  • c_binary()
  • c_test()
  • c_object()
  • c_static_library()
  • c_shared_object()

See the docstring for each rule for more specific detail on what they each do.

//build_defs:cc_embed_binary

Contains rules for embedding files into an object file that can be linked into a binary and loaded at runtime. There are both C and C++ variants that work similarly to the other build actions for each language.

These have the extra config value default_namespace to set the default namespace to generate; it can also be overridden per target.

When building on OSX, the config value asm_tool is also used (by default this is nasm). On other platforms this is not required.

  • c_embed_binary()
  • cc_embed_binary()

Configuration

This plugin can be configured by adding fields to the [Plugin "cc"] section in your .plzconfig. The available configuration settings are documented here.

CCTool

The tool used by c_xxx() build definitions to compile C code. Defaults to gcc.

[Plugin "cc"]
CCTool = clang

CPPTool

The tool used by cc_xxx() build definitions to compile C++ code. Defaults to g++.

[Plugin "cc"]
CPPTool = clang++

LDTool

The tool used to link C and C++ binaries and shared objects. Defaults to ld.

[Plugin "cc"]
LDTool = ld

ARTool

The tool used to manipulate .a archives. Defaults to ar.

[Plugin "cc"]
ARTool = ar

DefaultOptCFlags

Default flags used to compile C code. Defaults to --std=c99 -O3 -pipe -DNDEBUG -Wall -Werror.

[Plugin "cc"]
DefaultOptCFlags = --std=c99 -O4

DefaultDbgCFlags

Default flags used to compile C code for debugging. Defaults to --std=c99 -g3 -pipe -DDEBUG -Wall -Werror.

[Plugin "cc"]
DefaultDbgCFlags = --std=c99 -O4

DefaultOptCppFlags

Default flags used to compile C++ code. Defaults to --std=c++11 -O3 -pipe -DNDEBUG -Wall -Werror.

[Plugin "cc"]
DefaultOptCFlags = --std=c99 -O4

DefaultDbgCppFlags

Default flags used to compile C++ code for debugging. Defaults to --std=c++11 -g3 -pipe -DDEBUG -Wall -Werror.

[Plugin "cc"]
DefaultDbgCFlags = --std=c99 -O4

DefaultLDFlags

Default flags to pass when linking C and C++ code. Defaults to -lpthread -ldl.

[Plugin "cc"]
DefaultLDFlags = -ldl

PkgConfigPath

Controls the PKG_CONFIG_PATH environment variable used by pkg_config. Not set by default.

[Plugin "cc"]
PackageConfigPath = /opt/toolchain/pkg_configs

TestMain

A cc_library(), c_library(), or otherwise compatible rule containing the entry point to run tests. Defaults to //unitest-pp:main in this plugin.

[Plugin "cc"]
TestMain = //third_party/cc:gtest_main

DsymTool

On macOS, the tool used to create debug symbols. Defaults to dsymutil.

[Plugin "cc"]
DsymTool = dsymutil

AsmTool

The tool to use to compile asm sources. Defaults to nasm.

[Plugin "cc"]
AsmTool = nasm

DefaultNamespace

The default C++ namespace to use. By default, no namespace is used.

[Plugin "cc"]
DefaultNamespace = foo

General notes

These are very much based on GCC and Clang; while it would be theoretically possible to support MSVC the flag structure would need to change fairly dramatically (and hence it may be easier to support them as a totally parallel set of rules or even a different plugin). In practice this would also require Windows support for Please generally.

cc-rules's People

Contributors

chrisnovakovic avatar peterebden avatar samwestmoreland avatar sfirmery avatar tatskaari avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cc-rules's Issues

Shared libraries with binaries

So usually if I build a binary that needs a shared library (which is not installed in the system) I can do something like add a directory structure:

bin
  |-- my_ _bin
lib
  |-- shared_lib.so

And then when linking in the shared lib set the rpath as $ORIGIN/../lib/ which helps discover the shared libs.
How do I do this with the cc_rules? I can see that the shared lib never makes it to the plz-out/bin so setting something relative seems hard.

Even if I add an additional lib to the output directory using the optional_outs it still does not make it to the plz-out/bin directory which makes running things which need a shared library hard with plz run //path/to/executable. Any suggestions/help with this would be nice.

Currently I have something like:

linker_flags = ["--rpath=$ORIGIN/../../gen/path/to/mylib/"]

Which is pretty nasty (and not very scalable sadly)
Ideally this should be just --rpath=$ORIGIN/../path/to/mylib/

`compile_commands.json` generated by `compdb` has wrong `command`.

Hey! Here is a minimal reproducible example, where the compile_commands.json file generated by the tool compdb looks like:

[
    {
        "command": "/usr/bin/g++ -c -I . main.cc --std=c++11 -g3 -pipe -DDEBUG -Wall -Werror -fPIC",
        "directory": "<project_dir>/plz-out/gen",
        "file": "<project_dir>/main.cc"
    }
]

There are currently two issues:

Issue 1

In command, the path to the cc file is a relative one (main.cc in this case). This path, however, expands to <project_dir>/plz-out/gen/main.cc, which does not exist. If you run Clang tools such as clang-tidy against the source file, you'll get an error like:

clang-tidy main.cc               
Error while processing <project_dir>/main.cc.
error: no input files [clang-diagnostic-error]
error: no such file or directory: 'main.cc' [clang-diagnostic-error]
error: unable to handle compilation, expected exactly one compiler job in '' [clang-diagnostic-error]
Found compiler error(s).

IIUC this is due to please by design compiling each translation unit in a temporary directory plz-out/tmp/... using the source file copied into it, instead of the one in the source tree.

Issue 2

This command string is missing include paths. I would expect it to contain -isystem lib/include. Without it Clang tools won't work.

What I also noticed was that the query result from plz query graph (see attached file) is already missing include paths.
plz_query_graph.json

Is there already any workaround to mitigate this issue? If not, I would be happy to contribute.

`-fmodules-ts` is deprecated since clang16

I got the error when running test for the main please repo:

$ plz test --profile=alpine --exclude=py3 --exclude=python3 --exclude=no-musl --exclude=x86 --exclude=gold --exclude=py2 --exclude=java --exclude=e2e --log_file plz-out/log/test_build.log --log_file_level 4 --trace_file plz-out/log/trace.json

Build stopped after 150ms. 1 target failed:
    //test/cc_rules/clang/modules:_f1#interface
Error building target //test/cc_rules/clang/modules:_f1#interface: exit status 1
clang-16: error: the '-fmodules-ts' flag is deprecated and it will be removed in Clang 17; use '-std=c++20' or higher to use standard C++ modules instead [-Werror,-Wdeprecated-module-ts]

cc_test fails with stricter compiler flags

When running cc_test on a project that specifies stricter compiler arguments such as -Werror=suggest-override, cc_test will fail as it uses unittest-pp which fails to compile with that flag.

Consider restructuring the various cflag options

Right now we have four; dbg/opt and c/c++. The only way to override them is in their entirety which often means you have to repeat two (or all four) of them in order to change one thing (e.g. say you use --std=c++17 globally but you have one package with some third-party code that needs --std=c++03).

I wonder if this should get broken out to different areas, e.g. release/debug specific (-O3 vs. -g3 etc), the language standard, and additional flags (mostly warnings/errors usually). We'd need two of the first (dbg/opt) and of the second (c/c++) and just one of the latter, so it doesn't actually increase the number of options much, but would make it quite a bit more flexible and less repetitive.

Make `-fPIC` optional.

I am using please to handle the building of STM32 projects and most of the required flags and tools are possible to implement by defining them within a .plzconfig file.
However, it looks like please always adds the -fPIC flag to the compiler flags.
It is possible to override this by defining -fno-pic in the compiler_flags section of the c/cc build rules, however this is no longer a project-wide solution as defining all the flags in .plzconfig.

The code is being compiled by arm-none-eabi-g++ instead of the default tool and the inclusion of the -fPIC flag forces the definition of a global offset table in the STM provided linker scripts, as well as potentially adding some extra overhead that isn't necessary.

I realize embedded is not necessarily the goal of the cc-rules, but I have grown to really like please and would like to use it to build all my projects, including embedded code. It's certainly versatile enough to do so!

Fail to build/run gtest cc_test on macOS due to unknown options for ld.

Hello, I've been trying to get a minimal C++ project working with please.

I want to be able to run googletest tests and hit the following build error when using cc_test

❯ plz build
Build stopped after 10.26s. 1 target failed:
    //src:my_test
Error building target //src:my_test: exit status 1
ld: unknown options: -noall_load 
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I made a fork of this repository, changed the flag -all_load to -force_load and removed the -noall_load flags from build_defs/cc.build_defs. I can build and run the test with that change.

However, the GitHub actions for this repository are failing.
I'm not convinced they are failing due to this change, though, as other pull requests have them failing in the same way.

I'm opening this issue as a means of communication.
I'd be happy to help address this however I can.


Here is a minimal set of files to reproduce this issue:

contents of .plzconfig

[please]
version = 17.7.0

[parse]
preloadsubincludes = ///cc//build_defs:cc

[Plugin "cc"]
Target = //plugins:cc

contents of plugins/cc/BUILD

plugin_repo(
  name = "cc",
  revision = "v0.4.0",
  plugin = "cc-rules",
  owner = "please-build",
)

contents of third_party/cc/BUILD

github_repo(
    name = "gtest",
    bazel_compat = True,
    repo = "google/googletest",
    revision = "release-1.8.1",
)

cc_library(
    name = "main",
    deps = [
        "///third_party/cc/gtest//:gtest_main",
    ],
    visibility = ["PUBLIC"],
)

contents of src/BUILD

subinclude("///cc//build_defs:c")
package(cc = {
    "test_main": "//third_party/cc:main",
})

cc_test(
    name = "my_test",
    srcs = ["test.cc"],
)

contents of src/test.cc

#include "gtest/gtest.h"

TEST(GTest, Number1) {
  int a = 5;
  int b = 7;
  EXPECT_EQ(12, a + b);
}

GCC 10 not available on `macos-latest` GHA runner image

macos-latest is now an alias for macos-13, which includes GCC 11 and 12. GitHub actions on macOS will fail until .plzconfig.gcc is updated. We should make sure GCC 11 and/or 12 are also available on ubuntu-latest before choosing one, because Ubuntu and macOS share the same configuration (or we could split them).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.