intellij icon indicating copy to clipboard operation
intellij copied to clipboard

CLion `strip_include_prefix` isn't honored within a `cc_library` target

Open sfc-gh-abalik opened this issue 2 years ago • 3 comments

Description of the bug:

If a cc_library target uses strip_include_prefix and files within that library #include headers using paths relative to the strip_include_prefix folder, CLion will not find the headers. Bazel is able to build these just fine.

What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

.
├── BUILD
├── main.cc
├── mylib
│   ├── BUILD
│   ├── lib1
│   │   └── lib1.h
│   └── lib2
│       └── lib2.h
├── repro.bazelproject
└── WORKSPACE
##### BUILD #####

load("@rules_cc//cc:defs.bzl", "cc_binary")

cc_binary(
    name = "main",
    srcs = ["main.cc"],
    deps = ["//mylib"],
)

##### main.cc #####

#include <iostream>

#include "lib2/lib2.h"

int main() {
  std::cout << LIB2_HELLO << std::endl;
  return 0;
}

##### mylib/BUILD #####

load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
    name = "mylib",
    hdrs = glob(["**/*.h"]),
    strip_include_prefix = "//mylib/",
    visibility = ["//visibility:public"],
)

##### mylib/lib1/lib1.h #####

#include <string>

const std::string LIB1_HELLO = "Hello";

##### mylib/lib2/lib2.h #####

#include <iostream>

#include "lib1/lib1.h"

const std::string LIB2_HELLO = LIB1_HELLO;

CLion can't find the header include in lib2.h

image

image

Which Intellij IDE are you using? Please provide the specific version.

CLion 2023.2.2

What programming languages and tools are you using? Please provide specific versions.

C++

What Bazel plugin version are you using?

2023.09.26.0.1-api-version-232

Have you found anything relevant by searching the web?

No response

Any other information, logs, or outputs that you want to share?

Side note - I had to add a trailing '/' to the strip_include_prefix:

strip_include_prefix = "//mylib/",

Without that, the #include in main.cc isn't found:

image

CLion logs an error though when I include this trailing '/':

Failed to resolve virtual includes for ExecutionRootPath{path='bazel-out/aarch64-fastbuild/bin/mylib/_virtual_includes/mylib'}
  
  java.lang.IllegalArgumentException: Invalid workspace path 'mylib///mylib/': Workspace path may not end with '/': mylib///mylib/
at com.google.idea.blaze.base.model.primitives.WorkspacePath.<init>(WorkspacePath.java:59)
at com.google.idea.blaze.base.model.primitives.WorkspacePath.<init>(WorkspacePath.java:69)
at com.google.idea.blaze.base.sync.workspace.VirtualIncludesHandler.resolveVirtualInclude(VirtualIncludesHandler.java:107)
at com.google.idea.blaze.base.sync.workspace.ExecutionRootPathResolver.resolveToIncludeDirectories(ExecutionRootPathResolver.java:124)
at com.google.idea.blaze.cpp.HeaderRootTrimmer.lambda$doCollectHeaderRoots$1(HeaderRootTrimmer.java:105)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:131)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:74)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:82)
at com.intellij.util.concurrency.BoundedTaskExecutor.doRun(BoundedTaskExecutor.java:249)
at com.intellij.util.concurrency.BoundedTaskExecutor.access$200(BoundedTaskExecutor.java:31)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.executeFirstTaskAndHelpQueue(BoundedTaskExecutor.java:227)
at com.intellij.util.ConcurrencyUtil.runUnderThreadName(ConcurrencyUtil.java:218)
at com.intellij.util.concurrency.BoundedTaskExecutor$1.run(BoundedTaskExecutor.java:215)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:702)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:699)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:699)
at java.base/java.lang.Thread.run(Thread.java:833)

There's a probably a simple fix for this to handle the trailing '/'. I can open a separate issue for this if needed.

sfc-gh-abalik avatar Oct 20 '23 18:10 sfc-gh-abalik

cc @ujohnny who's been working on strip_include_prefix recently.

sfc-gh-abalik avatar Oct 20 '23 18:10 sfc-gh-abalik

Same issue here.

burnpanck avatar Jan 03 '24 09:01 burnpanck

Ok I found the bug and was able to fix it in https://github.com/bazelbuild/intellij/pull/5969. The current code is written assuming the strip_include_prefix is a package-relative path, but strip_include_prefix can also be specified as a repository-relative path (e.g. strip_include_prefix = "//some/prefix". When a repository-relative path is used, it gets concatenated to the package path, which creates header paths that don't exist.

To fix it we just need to skip that concatenation when a repository-relative path is used.

I also fixed the trailing '/' I mentioned at the bottom of the summary. I just needed to trip the trailing '/' before creating the WorkspacePath object.

ptal @ujohnny / @tpasternak

sfc-gh-abalik avatar Jan 19 '24 19:01 sfc-gh-abalik

ok, it's fixed iiuc

tpasternak avatar Mar 01 '24 10:03 tpasternak