Fix cmake build: use target_link_libraries instead of LINK_FLAGS#26
Fix cmake build: use target_link_libraries instead of LINK_FLAGS#26rljacobuc wants to merge 2 commits intoSEATStandards:mainfrom
Conversation
LINK_FLAGS places library flags before object files in the linker command, causing undefined reference errors with GNU ld which requires libraries to appear after the object files that use them. Replace LINK_FLAGS with target_link_options (for rpath) and target_link_libraries (for wxWidgets and NetCDF libraries) so that the link order is correct. Co-Authored-By: Oz <[email protected]>
There was a problem hiding this comment.
Pull request overview
Fixes GNU ld undefined-reference link errors by ensuring libraries are emitted after objects in the final link command.
Changes:
- Removes
LINK_FLAGSusage fromset_target_properties. - Adds
target_link_optionsfor rpath andtarget_link_librariesfor wxWidgets/NetCDF linkage. - Parses wx/NetCDF link flags into CMake lists via
separate_arguments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/CMakeLists.txt
Outdated
| ) | ||
|
|
||
| # Link libraries after object files (required for GNU ld) | ||
| target_link_options(ncvis PRIVATE -Wl,-rpath,${WXCONFIG_RPATH}/lib) |
There was a problem hiding this comment.
Using a raw -Wl,-rpath,... linker flag is toolchain-specific and bypasses CMake’s dedicated RPATH handling. Prefer setting BUILD_RPATH / INSTALL_RPATH (or CMAKE_INSTALL_RPATH) via target properties for better portability and clearer intent, while still achieving correct runtime search paths.
| ) | |
| # Link libraries after object files (required for GNU ld) | |
| target_link_options(ncvis PRIVATE -Wl,-rpath,${WXCONFIG_RPATH}/lib) | |
| BUILD_RPATH "${WXCONFIG_RPATH}/lib" | |
| INSTALL_RPATH "${WXCONFIG_RPATH}/lib" | |
| ) | |
| # Link libraries after object files (required for GNU ld) |
src/CMakeLists.txt
Outdated
| # Link libraries after object files (required for GNU ld) | ||
| target_link_options(ncvis PRIVATE -Wl,-rpath,${WXCONFIG_RPATH}/lib) | ||
| separate_arguments(WX_LINK_LIBS UNIX_COMMAND "${WX_LINK_FLAGS}") | ||
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") |
There was a problem hiding this comment.
Passing -L… search-path flags via target_link_libraries works but is not idiomatic CMake and can be harder to reason about across generators. Prefer expressing the library directory via target_link_directories(ncvis PRIVATE ${NC_LIB_DIR}) (or linking to an imported target like NetCDF::NetCDF if available) and keep target_link_libraries focused on actual libraries (e.g., netcdf).
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") | |
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-lnetcdf ${NC_LINK_FLAGS}") | |
| target_link_directories(ncvis PRIVATE ${NC_LIB_DIR}) |
src/CMakeLists.txt
Outdated
| separate_arguments(WX_LINK_LIBS UNIX_COMMAND "${WX_LINK_FLAGS}") | ||
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") | ||
| target_link_libraries(ncvis PRIVATE ${WX_LINK_LIBS} ${NC_LINK_LIBS}) | ||
|
|
There was a problem hiding this comment.
${WX_LINK_FLAGS} / ${NC_LINK_FLAGS} typically contain a mix of true libraries (-l...) and non-library linker options (e.g., -pthread, -Wl,...). Feeding the whole parsed list into target_link_libraries makes the intent unclear and can complicate future changes. Consider splitting the parsed values into (1) libraries for target_link_libraries and (2) flags for target_link_options, so each API is used for its intended purpose.
| separate_arguments(WX_LINK_LIBS UNIX_COMMAND "${WX_LINK_FLAGS}") | |
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") | |
| target_link_libraries(ncvis PRIVATE ${WX_LINK_LIBS} ${NC_LINK_LIBS}) | |
| separate_arguments(WX_LINK_ITEMS UNIX_COMMAND "${WX_LINK_FLAGS}") | |
| separate_arguments(NC_LINK_ITEMS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") | |
| # Split wxWidgets link items into libraries (-l...) and other linker options | |
| set(WX_LIBRARIES "") | |
| set(WX_OPTIONS "") | |
| foreach(item IN LISTS WX_LINK_ITEMS) | |
| if(item MATCHES "^-l.+") | |
| list(APPEND WX_LIBRARIES "${item}") | |
| else() | |
| list(APPEND WX_OPTIONS "${item}") | |
| endif() | |
| endforeach() | |
| # Split NetCDF link items into libraries (-l...) and other linker options | |
| set(NC_LIBRARIES "") | |
| set(NC_OPTIONS "") | |
| foreach(item IN LISTS NC_LINK_ITEMS) | |
| if(item MATCHES "^-l.+") | |
| list(APPEND NC_LIBRARIES "${item}") | |
| else() | |
| list(APPEND NC_OPTIONS "${item}") | |
| endif() | |
| endforeach() | |
| # Link true libraries | |
| target_link_libraries(ncvis PRIVATE ${WX_LIBRARIES} ${NC_LIBRARIES}) | |
| # Apply non-library linker options | |
| target_link_options(ncvis PRIVATE ${WX_OPTIONS} ${NC_OPTIONS}) |
src/CMakeLists.txt
Outdated
| separate_arguments(WX_LINK_LIBS UNIX_COMMAND "${WX_LINK_FLAGS}") | ||
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") |
There was a problem hiding this comment.
separate_arguments(... UNIX_COMMAND ...) hard-codes UNIX-style parsing. If this project is ever generated on non-UNIX platforms, this can mis-parse arguments. Using NATIVE_COMMAND (or guarding with if(UNIX) and providing an alternative) makes the behavior more robust.
| separate_arguments(WX_LINK_LIBS UNIX_COMMAND "${WX_LINK_FLAGS}") | |
| separate_arguments(NC_LINK_LIBS UNIX_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") | |
| separate_arguments(WX_LINK_LIBS NATIVE_COMMAND "${WX_LINK_FLAGS}") | |
| separate_arguments(NC_LINK_LIBS NATIVE_COMMAND "-L${NC_LIB_DIR} -lnetcdf ${NC_LINK_FLAGS}") |
|
@copilot make a PR to apply changes based on the comments in this thread |
- Use BUILD_RPATH/INSTALL_RPATH properties instead of raw -Wl,-rpath flag - Use target_link_directories instead of -L flag in separate_arguments - Split link items into libraries (target_link_libraries) and flags (target_link_options) - Use NATIVE_COMMAND instead of UNIX_COMMAND in separate_arguments Co-Authored-By: Oz <[email protected]>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| separate_arguments(WX_LINK_ITEMS NATIVE_COMMAND "${WX_LINK_FLAGS}") | ||
| separate_arguments(NC_LINK_ITEMS NATIVE_COMMAND "-lnetcdf ${NC_LINK_FLAGS}") | ||
| target_link_directories(ncvis PRIVATE ${NC_LIB_DIR}) | ||
|
|
||
| # Split wxWidgets link items into libraries (-l...) and other linker options | ||
| set(WX_LIBRARIES "") | ||
| set(WX_OPTIONS "") | ||
| foreach(item IN LISTS WX_LINK_ITEMS) | ||
| if(item MATCHES "^-l.+") | ||
| list(APPEND WX_LIBRARIES "${item}") | ||
| else() | ||
| list(APPEND WX_OPTIONS "${item}") | ||
| endif() | ||
| endforeach() | ||
|
|
||
| # Split NetCDF link items into libraries (-l...) and other linker options | ||
| set(NC_LIBRARIES "") | ||
| set(NC_OPTIONS "") | ||
| foreach(item IN LISTS NC_LINK_ITEMS) | ||
| if(item MATCHES "^-l.+") | ||
| list(APPEND NC_LIBRARIES "${item}") | ||
| else() | ||
| list(APPEND NC_OPTIONS "${item}") | ||
| endif() | ||
| endforeach() | ||
|
|
||
| # Link true libraries | ||
| target_link_libraries(ncvis PRIVATE ${WX_LIBRARIES} ${NC_LIBRARIES}) | ||
|
|
||
| # Apply non-library linker options | ||
| target_link_options(ncvis PRIVATE ${WX_OPTIONS} ${NC_OPTIONS}) |
There was a problem hiding this comment.
target_link_directories() and target_link_options() are used here, but the project’s top-level cmake_minimum_required(VERSION 3.1) is lower than the CMake versions that provide these commands. As-is, configuring with older CMake will fail. Either bump the minimum required CMake version accordingly, or rewrite this logic using commands/properties available in the current minimum version (while still keeping libraries in target_link_libraries).
LINK_FLAGS places library flags before object files in the linker command, causing undefined reference errors with GNU ld which requires libraries to appear after the object files that use them.
Replace LINK_FLAGS with target_link_options (for rpath) and target_link_libraries (for wxWidgets and NetCDF libraries) so that the link order is correct.