Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG]: module being stripped if no build type selected (2.10.2 regression) #4454

Open
3 tasks done
tttapa opened this issue Jan 13, 2023 · 4 comments
Open
3 tasks done
Assignees

Comments

@tttapa
Copy link
Contributor

tttapa commented Jan 13, 2023

Required prerequisites

What version (or hash if on master) of pybind11 are you using?

2.10.3

Problem description

If no CMAKE_BUILD_TYPE is specified, the seemingly innocuous quotes that were added in 88b019a cause the pybind11_add_module function to strip the module, even for debug builds.

By relying on CMAKE_BUILD_TYPE at configure time rather than on $<CONFIG> at generation time, multi-configuration generators like Ninja Multi-Config cannot work correctly. It might be better to use a generator expression (e.g. https://stackoverflow.com/questions/45455350/cmake-how-to-add-a-custom-command-that-is-only-executed-for-one-configuration).

Reproducible example code

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(test-project)

# Use case-insensitive comparison to match the result of $<CONFIG:cfgs>
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
if(NOT MSVC AND NOT ${uppercase_CMAKE_BUILD_TYPE} MATCHES DEBUG|RELWITHDEBINFO)
    # Strip unnecessary sections of the binary on Linux/macOS
    message(STATUS "Without quotes: strip")
else()
    message(STATUS "Without quotes: no strip")
endif()

# Use case-insensitive comparison to match the result of $<CONFIG:cfgs>
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
if(NOT MSVC AND NOT "${uppercase_CMAKE_BUILD_TYPE}" MATCHES DEBUG|RELWITHDEBINFO)
    # Strip unnecessary sections of the binary on Linux/macOS
    message(STATUS "With quotes:    strip")
else()
    message(STATUS "With quotes:    no strip")
endif()

Run CMake without build type

cmake -Bbuild -S.
-- Without quotes: no strip
-- With quotes:    strip

Is this a regression? Put the last known working version here if it is.

1f04cc7

@tttapa tttapa added the triage New bug, unverified label Jan 13, 2023
@tttapa tttapa changed the title [BUG]: module being stripped if no build type set (2.10.2 regression) [BUG]: module being stripped if no build type selected (2.10.2 regression) Jan 13, 2023
@Skylion007
Copy link
Collaborator

FYI @henryiii , is this a regression or something we forgot to mention in the changelog?

@Skylion007 Skylion007 added build system and removed triage New bug, unverified labels Feb 4, 2023
@henryiii
Copy link
Collaborator

henryiii commented Feb 5, 2023

How would you propose using a generator expression? You can't run a configure-time function based on a generator expression. I need to check to see if generator expressions can be used inside pybind11_strip. To fix the bug back to 2.10.0 behavior, I expect you could check to see if it's defined? I'm guessing the quotes cause it to "not match" (empty string) rather then being skipped.

@tttapa
Copy link
Contributor Author

tttapa commented Aug 6, 2023

How would you propose using a generator expression? You can't run a configure-time function based on a generator expression.

Indeed, what I meant is changing the add_custom_command command itself.
For instance:

diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake
index cc87ced5..fa7170cb 100644
--- a/tools/pybind11Common.cmake
+++ b/tools/pybind11Common.cmake
@@ -397,9 +397,21 @@ function(pybind11_strip target_name)
       set(x_opt -x)
     endif()
 
-    add_custom_command(
-      TARGET ${target_name}
-      POST_BUILD
-      COMMAND ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>)
+    if(CMAKE_VERSION VERSION_LESS 3.8)
+      message(WARNING "CMake 3.8+ required for correct strip behavior when using multi-config "
+                      "generators")
+      add_custom_command(
+        TARGET ${target_name}
+        POST_BUILD
+        COMMAND ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>)
+    else()
+      set(no_debug_info $<NOT:$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>>)
+      set(strip_cmd ${CMAKE_STRIP} ${x_opt} $<TARGET_FILE:${target_name}>)
+      add_custom_command(
+        TARGET ${target_name}
+        POST_BUILD
+        COMMAND "$<${no_debug_info}:${strip_cmd}>"
+        COMMAND_EXPAND_LISTS)
+    endif()
   endif()
 endfunction()

This would need some refactoring, though, because now pybind11_strip is a bit of a confusing name for the function, as it always strips, except when using a multi-config generator, then it strips conditionally.
Perhaps you could keep pybind11_strip as is for backwards compatibility, and add a new pybind11_strip_if_not_debug function that includes both the configure-time check from pybind11(New)Tools.cmake and the generator expressions from the patch above?

I would definitely be in favor of adding the if (DEFINED CMAKE_BUILD_TYPE) check in the meantime. I'll submit a PR.

@jasjuang
Copy link

Recently got bitten by this. The modification @tttapa did to the add_custom_command is required in order for the Xcode debugger to jump into the break points that is set in the source files that creates the python bindings when running debug on an application that uses the embedded interpreter to import the python bindings. Without @tttapa's patch, the debug symbols got stripped away in Xcode debug mode which causes the Xcode lldb debugger to unable to jump into the break points.

Looking forward to seeing @tttapa's fix making into the master branch in the near future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants