diff --git a/libs/core/config/CMakeLists.txt b/libs/core/config/CMakeLists.txt index 1373f6631388..32c3f6ab9fc8 100644 --- a/libs/core/config/CMakeLists.txt +++ b/libs/core/config/CMakeLists.txt @@ -27,6 +27,7 @@ set(config_macro_headers hpx/config/forward.hpp hpx/config/manual_profiling.hpp hpx/config/move.hpp + hpx/config/static_linker_check.hpp hpx/config/threads_stack.hpp hpx/config/warnings_prefix.hpp hpx/config/warnings_suffix.hpp diff --git a/libs/core/config/include/hpx/config/static_linker_check.hpp b/libs/core/config/include/hpx/config/static_linker_check.hpp new file mode 100644 index 000000000000..e4e336de3ca7 --- /dev/null +++ b/libs/core/config/include/hpx/config/static_linker_check.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2026 The STE||AR-Group +// +// SPDX-License-Identifier: BSL-1.0 +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include + +// Emit a compile-time diagnostic when the user includes hpx/hpx_main.hpp +// while building a statically-linked HPX application on Linux or macOS. +// +// Root cause: the '--wrap=main' linker flag, which redirects user 'main' to +// the HPX runtime entry-point, is only applied automatically when the user +// links against 'HPX::wrap_main'. Without it, the resulting binary will call +// the raw 'main' symbol, bypassing HPX initialisation and producing a +// hard-to-diagnose runtime crash or silent hang. +// +// Actionable remedies (pick one): +// CMake -- add target_link_libraries( PRIVATE HPX::wrap_main) +// Manual -- pass -Wl,--wrap=main to the linker explicitly +// +// This check is intentionally limited to Linux/macOS static builds because: +// * On Windows the wrap mechanism is not used (MSVC uses a different ABI). +// * Dynamic (shared-library) builds already embed the wrap stub inside +// libhpx.so/dylib, so no extra linker flag is needed. + +#if defined(HPX_HAVE_DYNAMIC_HPX_MAIN) +#if (defined(__linux) || defined(__linux__) || defined(linux) || \ + defined(__APPLE__)) && \ + defined(HPX_HAVE_STATIC_LINKING) && \ + !defined(HPX_HAVE_WRAP_MAIN_CONFIGURED) +#warning \ + "HPX static-link wrap-main check: you included hpx/hpx_main.hpp but the " \ + "--wrap=main linker flag has not been applied. Add " \ + "target_link_libraries( PRIVATE HPX::wrap_main) to your " \ + "CMakeLists.txt, or pass -Wl,--wrap=main to the linker manually. " \ + "Without this flag the HPX runtime will not be initialised correctly." +#endif +#endif diff --git a/wrap/CMakeLists.txt b/wrap/CMakeLists.txt index 143952466006..d2d9bf230103 100644 --- a/wrap/CMakeLists.txt +++ b/wrap/CMakeLists.txt @@ -134,7 +134,11 @@ endif() if(HPX_WITH_DYNAMIC_HPX_MAIN) if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") target_link_libraries(hpx_wrap INTERFACE "-Wl,-wrap=main") + target_compile_definitions(hpx_wrap INTERFACE HPX_HAVE_WRAP_MAIN_CONFIGURED) target_link_libraries(hpx_auto_wrap INTERFACE "-Wl,-wrap=main") + target_compile_definitions( + hpx_auto_wrap INTERFACE HPX_HAVE_WRAP_MAIN_CONFIGURED + ) elseif(APPLE) target_link_libraries(hpx_wrap INTERFACE "-Wl,-e,_initialize_main") target_link_libraries(hpx_auto_wrap INTERFACE "-Wl,-e,_initialize_main") diff --git a/wrap/include/hpx/hpx_main.hpp b/wrap/include/hpx/hpx_main.hpp index 9b4077bba341..155f217fef9d 100644 --- a/wrap/include/hpx/hpx_main.hpp +++ b/wrap/include/hpx/hpx_main.hpp @@ -7,6 +7,7 @@ #pragma once +#include #include #if defined(HPX_HAVE_RUN_MAIN_EVERYWHERE)