diff mbox series

[v4] sanity: test for c toolchain

Message ID 20250120194636.22297-1-gavrosc@yahoo.com
State New
Headers show
Series [v4] sanity: test for c toolchain | expand

Commit Message

Christos Gavros Jan. 20, 2025, 7:46 p.m. UTC
Users reported issues caused by missing the right libstdc++-version-dev.
A new function 'check_c_toolchain' added in sanity.bbclass to test linking libstdc++
Fixes [YOCTO #15712]

Signed-off-by: Christos Gavros <gavrosc@yahoo.com>
Reviewed-by: Yoann Congal <yoann.congal@smile.fr>
---
v3->v4
* move new function call in 'check_sanity_version_change()'
---
 meta/classes-global/sanity.bbclass | 40 ++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

Comments

Ross Burton Jan. 21, 2025, 3:29 p.m. UTC | #1
Hi,

Some more comments:

The shortlog says “C toolchain” but the test is for the C++ toolchain not C, correct?

> +def check_c_toolchain(d):

> +    try:
> +        with NamedTemporaryFile(delete=False, suffix=".c") as c_file:

Why delete=False and then manual cleanup later?  You can move the compiler invocation to inside the with and use c_file.flush() to write the dummy code to disk, or just pass the source to the compiler through stdin with subprocess.run(…, input=c_code).

> +            c_code = """
> +            #include <stdio.h>
> +            int main() {
> +                printf(\"Hello, World!\\n\");

No need to escape the “ inside a “””.

As we’re explicitly testing the C++ linkage to libstdc++, would it be safer to actually call something from libstdc++ and call BUILD_CXX instead of BUILD_CC?

> +                return 0;
> +            }
> +            """
> +            c_file.write(c_code.encode('utf-8'))

Set the mode when you open the file to text and you won’t need to encode manually.

> +            c_file_name = c_file.name
> +
> +        build_cc = d.getVar('BUILD_CC').strip()

BUILD_CC could include whitespace, so you should use shlex.split() to turn the command into a list of tokens if you want to pass a list to run().

> +        output_binary = c_file_name + ".out"
> +        compile_command = [build_cc, c_file_name, '-o', output_binary,'-lstdc++']
> +        result = subprocess.run(compile_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
> +
> +        if result.returncode == 0:
> +            return None
> +        else:
> +            return f"C toolchain check failed to link against libstdc++. Please ensure libstdc++ and headers are installed. Error:\n{result.stderr.decode()}"
> +    except Exception as e:
> +        return f"An unexpected issue occurred during the C toolchain check: {str(e)}"
> +    finally:
> +        if c_file_name and os.path.exists(c_file_name):
> +            os.remove(c_file_name)
> +        if output_binary and os.path.exists(output_binary):
> +            os.remove(output_binary)

There’s a neater way of doing this by reading source code from stdin and writing to /dev/null, so there’s no cleanup to do. Something like this entirely untested code:

c_code = “…”
cmd = shlex.split(d.getVar(“BUILD_CXX”)) + [“-“, “-o”, “/dev/null”, “-lstdc++”])
try:
  subprocess.run(cmd, input=c_code, capture_output=True, text=True, check=True)
  return None
except subprocess.CalledProcessError:
  return f"An unexpected issue occurred during the C toolchain check: {str(e)}”

Cheers,
Ross
Christos Gavros Jan. 21, 2025, 3:41 p.m. UTC | #2
hi

actually patch v1 used g++ and was compiling a "hello world" .cpp program but on of the comments was to change to gcc and c program.
You can see a bit more about that here https://bugzilla.yoctoproject.org/show_bug.cgi?id=15712
What is your opinion ?

Regarding the rest of the comments , I will try to change the code and submit v5 :)

Thenx
Christos
diff mbox series

Patch

diff --git a/meta/classes-global/sanity.bbclass b/meta/classes-global/sanity.bbclass
index 7b8a497d5a..26ce5fbc09 100644
--- a/meta/classes-global/sanity.bbclass
+++ b/meta/classes-global/sanity.bbclass
@@ -602,6 +602,43 @@  def drop_v14_cross_builds(d):
                 bb.utils.remove(stamp + "*")
                 bb.utils.remove(workdir, recurse = True)
 
+def check_c_toolchain(d):
+    """
+    it checks if the c compiling and linking to libstdc++ works properly in the native system
+    """
+    import os
+    import subprocess
+    from tempfile import NamedTemporaryFile
+
+    try:
+        with NamedTemporaryFile(delete=False, suffix=".c") as c_file:
+            c_code = """
+            #include <stdio.h>
+            int main() {
+                printf(\"Hello, World!\\n\");
+                return 0;
+            }
+            """
+            c_file.write(c_code.encode('utf-8'))
+            c_file_name = c_file.name
+
+        build_cc = d.getVar('BUILD_CC').strip()
+        output_binary = c_file_name + ".out"
+        compile_command = [build_cc, c_file_name, '-o', output_binary,'-lstdc++']
+        result = subprocess.run(compile_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+        if result.returncode == 0:
+            return None
+        else:
+            return f"C toolchain check failed to link against libstdc++. Please ensure libstdc++ and headers are installed. Error:\n{result.stderr.decode()}"
+    except Exception as e:
+        return f"An unexpected issue occurred during the C toolchain check: {str(e)}"
+    finally:
+        if c_file_name and os.path.exists(c_file_name):
+            os.remove(c_file_name)
+        if output_binary and os.path.exists(output_binary):
+            os.remove(output_binary)
+
 def sanity_handle_abichanges(status, d):
     #
     # Check the 'ABI' of TMPDIR
@@ -770,6 +807,9 @@  def check_sanity_version_change(status, d):
     # macOS with default HFS+ file system)
     status.addresult(check_case_sensitive(tmpdir, "TMPDIR"))
 
+    # Check if linking with lstdc++ is failing
+    status.addresult(check_c_toolchain(d))
+
 def sanity_check_locale(d):
     """
     Currently bitbake switches locale to en_US.UTF-8 so check that this locale actually exists.