Skip to content

Commit

Permalink
cmake: add a proper test to determine if -lc is required
Browse files Browse the repository at this point in the history
Issue <#187> indicates that
OpenBSD requires an explicit specification of -lc on the linker
line when -Wl,--no-undefined is used.

Unfortunately, unconditionally adding -lc is not possible, as that
breaks MinGW builds.

This commit adds a proper CMake test to check whether -lc is
required when using -Wl,--no-undefined. If and only if it is
required, -lc will be added to the linker flags.

This now fixes <#233>.
  • Loading branch information
Christian Seiler committed Feb 8, 2024
1 parent 2145b1e commit 301e51b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
36 changes: 36 additions & 0 deletions cmake/compilerOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,39 @@ if(NOT MSVC)
endif()
endif()
endif()

set(REQUIRE_EXPLICIT_LIBC_LINK 0)
if(USE_GNU_LINK_FLAGS)
# OpenBSD apparently requires an explicit -lc if -Wl,--no-undefined
# is used, but that is NOT required on other platforms, and on even
# other platforms (e.g. MinGW) -lc might not even exist at all.
# Therefore detect if -lc works and if it is required, and omit it
# if it doesn't.
# Just running check_linker_flag() doesn't help here, because we
# actually need to reference a symbol from libc to cause an error.
# Use -shared in CMAKE_REQUIRED_LINK_OPTIONS because how symbols
# (esp. undefined ones) are resolved during linking can differ
# between shared libraries and executables.
set(TEST_LINK_NO_UNDEFINED_EXIMPLICIT_LIBC "
#include <stdlib.h>
int main() { int* foo = (int*) malloc(sizeof(int)); free(foo); return 0; }
")
message(STATUS "Checking if -lc is explicitly needed in conjunction with -Wl,--no-undefined")
set(CMAKE_REQUIRED_FLAGS "-fPIC")
set(CMAKE_REQUIRED_LINK_OPTIONS "-shared;-Wl,--no-undefined")
check_c_source_compiles("${TEST_LINK_NO_UNDEFINED_EXIMPLICIT_LIBC}" HAVE_LINK_NO_UNDEFINED_IMPLICIT_LIBC)
set(CMAKE_REQUIRED_LINK_OPTIONS "-shared;-Wl,--no-undefined;-lc")
check_c_source_compiles("${TEST_LINK_NO_UNDEFINED_EXIMPLICIT_LIBC}" HAVE_LINK_NO_UNDEFINED_EXPLICIT_LIBC)
set(CMAKE_REQUIRED_LINK_OPTIONS "")
set(CMAKE_REQUIRED_FLAGS "")

if(NOT HAVE_LINK_NO_UNDEFINED_IMPLICIT_LIBC AND NOT HAVE_LINK_NO_UNDEFINED_EXPLICIT_LIBC)
message(FATAL_ERROR "Could not compile a simple test program either with -lc or without -lc with the current set of options")
elseif(NOT HAVE_LINK_NO_UNDEFINED_IMPLICIT_LIBC AND HAVE_LINK_NO_UNDEFINED_EXPLICIT_LIBC)
message(STATUS "Checking if -lc is explicitly needed in conjunction with -Wl,--no-undefined - yes")
set(REQUIRE_EXPLICIT_LIBC_LINK 1)
else()
message(STATUS "Checking if -lc is explicitly needed in conjunction with -Wl,--no-undefined - no")
set(REQUIRE_EXPLICIT_LIBC_LINK 0)
endif()
endif()
6 changes: 5 additions & 1 deletion cmake/src.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ if(STDINT_MSVC)
endif()

if(HAVE_LIBM)
target_link_libraries(${PROJECT_NAME} PUBLIC m c)
target_link_libraries(${PROJECT_NAME} PUBLIC m)
endif()

if(MSVC)
Expand All @@ -84,6 +84,10 @@ if(ZLIB_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC MATIO::ZLIB)
endif()

if(REQUIRE_EXPLICIT_LIBC_LINK)
target_link_libraries(${PROJECT_NAME} PUBLIC c)
endif()

set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ${MATIO_PIC})
# Convert matio_LIB_VERSIONINFO libtool version format into SOVERSION
# Convert from ":" separated into CMake list format using ";"
Expand Down

0 comments on commit 301e51b

Please sign in to comment.