cmake: define order of link flags - linker

I am new to cmake. I need to link some additional libraries so I used
CMAKE_EXE_LINKER_FLAGS:STRING=-lmymalloc -Wl,--wrap,malloc
The problem is that -lmymalloc is listed as the first argument of the linker flags in the generated Makefile, then several others follow (which seem to be defined in another way by cmake). I need to move it to the end of the listed flags, otherwise it will not link. How can I do that?

Related

M1 mac using clion with cmake and homebrew to use sdl2_gfx error [duplicate]

Looking around on the net I have seen a lot of code like this:
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(app ${SDL2_LIBRARIES})
However that seems to be the wrong way about doing it, as it only uses the include directories and libraries, but ignored defines, library paths and other flags that might be returned by pkg-config.
What would be the correct way to do this and ensure that all compile and link flags returned by pkg-config are used by the compiled app? And is there a single command to accomplish this, i.e. something like target_use(app SDL2)?
ref:
include()
FindPkgConfig
First of, the call:
include(FindPkgConfig)
should be replaced with:
find_package(PkgConfig)
The find_package() call is more flexible and allows options such as REQUIRED, that do things automatically that one would have to do manually with include().
Secondly, manually calling pkg-config should be avoid when possible. CMake comes with a rich set of package definitions, found in Linux under /usr/share/cmake-3.0/Modules/Find*cmake. These provide more options and choice for the user than a raw call to pkg_search_module().
As for the mentioned hypothetical target_use() command, CMake already has that built-in in a way with PUBLIC|PRIVATE|INTERFACE. A call like target_include_directories(mytarget PUBLIC ...) will cause the include directories to be automatically used in every target that uses mytarget, e.g. target_link_libraries(myapp mytarget). However this mechanism seems to be only for libraries created within the CMakeLists.txt file and does not work for libraries acquired with pkg_search_module(). The call add_library(bar SHARED IMPORTED) might be used for that, but I haven't yet looked into that.
As for the main question, this here works in most cases:
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
...
target_link_libraries(testapp ${SDL2_LIBRARIES})
target_include_directories(testapp PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(testapp PUBLIC ${SDL2_CFLAGS_OTHER})
The SDL2_CFLAGS_OTHER contains defines and other flags necessary for a successful compile. The flags SDL2_LIBRARY_DIRS and SDL2_LDFLAGS_OTHER are however still ignored, no idea how often that would become a problem.
More documentation here http://www.cmake.org/cmake/help/latest/module/FindPkgConfig.html
If you're using cmake and pkg-config in a pretty normal way, this solution works.
If, however, you have a library that exists in some development directory (such as /home/me/hack/lib), then using other methods seen here fail to configure the linker paths. Libraries that are not found under the typical install locations would result in linker errors, like /usr/bin/ld: cannot find -lmy-hacking-library-1.0. This solution fixes the linker error for that case.
Another issue could be that the pkg-config files are not installed in the normal place, and the pkg-config paths for the project need to be added using the PKG_CONFIG_PATH environment variable while cmake is running (see other Stack Overflow questions regarding this). This solution also works well when you use the correct pkg-config path.
Using IMPORTED_TARGET is key to solving the issues above. This solution is an improvement on this earlier answer and boils down to this final version of a working CMakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(ya-project C)
# the `pkg_check_modules` function is created with this call
find_package(PkgConfig REQUIRED)
# these calls create special `PkgConfig::<MODULE>` variables
pkg_check_modules(MY_PKG REQUIRED IMPORTED_TARGET any-package)
pkg_check_modules(YOUR_PKG REQUIRED IMPORTED_TARGET ya-package)
add_executable(program-name file.c ya.c)
target_link_libraries(program-name PUBLIC
PkgConfig::MY_PKG
PkgConfig::YOUR_PKG)
Note that target_link_libraries does more than change the linker commands. It also propagates other PUBLIC properties of specified targets like compiler flags, compiler defines, include paths, etc., so, use the PUBLIC keyword with caution.
It's rare that one would only need to link with SDL2. The currently popular answer uses pkg_search_module() which checks for given modules and uses the first working one.
It is more likely that you want to link with SDL2 and SDL2_Mixer and SDL2_TTF, etc... pkg_check_modules() checks for all the given modules.
# sdl2 linking variables
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2 SDL2_ttf SDL2_mixer SDL2_image)
# your app
file(GLOB SRC "my_app/*.c")
add_executable(my_app ${SRC})
target_link_libraries(my_app ${SDL2_LIBRARIES})
target_include_directories(my_app PUBLIC ${SDL2_INCLUDE_DIRS})
target_compile_options(my_app PUBLIC ${SDL2_CFLAGS_OTHER})
Disclaimer: I would have simply commented on Grumbel's self answer if I had enough street creds with stackoverflow.
Most of the available answers fail to configure the headers for the pkg-config library. After meditating on the Documentation for FindPkgConfig I came up with a solution that provides those also:
include(FindPkgConfig)
if(NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "pkg-config not found!" )
endif()
pkg_check_modules(<some-lib> REQUIRED IMPORTED_TARGET <some-lib>)
target_link_libraries(<my-target> PkgConfig::<some-lib>)
(Substitute your target in place of <my-target> and whatever library in place of <some-lib>, accordingly.)
The IMPORTED_TARGET option seems to be key and makes everything then available under the PkgConfig:: namespace. This was all that was required and also all that should be required.
There is no such command as target_use. But I know several projects that have written such a command for their internal use. But every project want to pass additional flags or defines, thus it does not make sense to have it in general CMake. Another reason not to have it are C++ templated libraries like Eigen, there is no library but you only have a bunch of include files.
The described way is often correct. It might differ for some libraries, then you'll have to add _LDFLAGS or _CFLAGS. One more reason for not having target_use. If it does not work for you, ask a new question specific about SDL2 or whatever library you want use.
If you are looking to add definitions from the library as well, the add_definitions instruction is there for that. Documentation can be found here, along with more ways to add compiler flags.
The following code snippet uses this instruction to add GTKGL to the project:
pkg_check_modules(GTKGL REQUIRED gtkglext-1.0)
include_directories(${GTKGL_INCLUDE_DIRS})
link_directories(${GTKGL_LIBRARY_DIRS})
add_definitions(${GTKGL_CFLAGS_OTHER})
set(LIBS ${LIBS} ${GTKGL_LIBRARIES})
target_link_libraries([insert name of program] ${LIBS})

GCC - Adding Libraries

I want to use functions in the header files gmp.h and mpfr.h, which are in the file /opt/local/include.
But when I run gcc with -v, all of the search paths are something like /Application/Xcode.app/Contents/etc.
I have tried adding LD_LIBRARY_PATH="/opt/local/include" to .bash_profile but it doesn't work. The compiler either tells me that 'gmp.h' file not found, or Undefined symbols for architecture x86_64.
What should I do?
Converting comments into an answer.
You need to add -I/opt/local/include to compile commands (to specify where the headers are) and -L/opt/local/lib and -lgmp and -lmpfr (possibly in the reverse order — MPFR before GMP) to link commands.
That works! Would you mind explaining a little bit the logic behind this? For example if I had another header file header.h I need, how should I include it?
You include it with #include "header.h". You compile the code with -I/directory/containing/header to find the header. You specify where the library (libheader.a or libheader.dylib, since you seem to be on macOS) is too, with -L/directory/containing/lib and -lheader — or whatever is appropriate.
The -I tells the preprocessor to look in the named directory for header files, so it looks for /directory/containing/header/header.h, for example.
The -L tells the linker where to find libraries (so it looks for /directory/containing/lib/libheader.dylib etc).
The -lheader tells the linker to look for libheader.a or libheader.dylib (or local equivalents) for the libraries.
Except for the use of .dylib vs .so vs .dll vs … (and .a vs .lib vs …), the same principles apply to other systems too.
This is probably a duplicate.

GCC header search path deprecated

I have found an unusual C makefile setup that relies upon a deprecated feature of GCC that appears to have no modern replacement.
This system needs to preprocess or 'cook' the local header files before including them. The makefiles take care of this and put the cooked versions in local './prepared/' directories. The header files are included as normal in the c using their normal names eg #include "name.h". The system simply needs './prepared/' to occur in the GCC header file search path before '.'.
Gcc used to offer the -I- option to remove the default '.' and allow the addition of header search path entries before it, but this option is deprecated.
From the gcc docs:
GCC looks for headers requested with #include "file" first in
the directory containing the current file, then in the directories
as specified by -iquote options, then in the same places it would
have looked for a header requested with angle brackets. For example,
if /usr/include/sys/stat.h contains #include "types.h", GCC looks
for types.h first in /usr/include/sys, then in its usual search path.
Is there no way to control the C header search path properly in gcc any more? Or is there another sensible way forward? I don't want to use a deprecated feature that may disappear. Right now I am sadly filtering the gcc deprecated feature warning messages to hide them. I didn't create the build environment, and it would be unpopular to solve the problem in a way that breaks the 'cookery'.
As far as I can tell, GCC provides no other means than the one you've described to avoid having each source file's directory first in the include search path used when compiling that file.
The best solution is probably to fix the headers and build system to get rid of header cooking. Such a scheme is very unusual -- pretty much everybody else gets by without.
If you must continue to rely on header cooking, then you probably should move the original headers to a directory that is not in the include search path. For example, create an "include" subdirectory of the main source directory, and put them there.
Edited to add:
Another alternative is to switch from the quoted include style to the angle-bracketed include style, and rely on -I options to set up the needed internal include directories however you want.

How to avoid library finding CMakeLists feature

I'm trying to adjust 3rd person code to my needs. This code is provided with CMake config files used to build and install it. There is possibility to choose one of libraries. And in code is often used #ifdef USE_FTD2XX directive. I saw that this is defined in CMamkeFiles.txt file like here:
option(USE_FTD2XX "Use FTDI libFTD2XX instead of free libftdi" ON)
if(USE_FTD2XX)
find_package(libFTD2XX)
endif(USE_FTD2XX)
if(LIBFTD2XX_FOUND)
include_directories(${LIBFTD2XX_INCLUDE_DIR})
add_definitions( -DUSE_FTD2XX )
else(LIBFTD2XX_FOUND)
set(LIBFTD2XX_LIBRARIES "")
endif(LIBFTD2XX_FOUND)
But if I simply use *.c and *.cpp files and I analyse and run it simply from IDE (Codeblocks), how could I set using this library in C++ code instead of in CMake? I'm also sure that I want use always this one so it can be fixed.
Should I simply #define USE_FTD2XX in main file?
You cannot simply #define USE_FTD2XX because you also need specific linker options for this to work (i.e. the library to link with). If the option is OFF in cmake, the specific link options won't be present in the Makefile and most likely you'll have linker errors.
So CMake takes care of everything automatically for you, but you need to re-generate your makefiles each time you want to toggle options on/off.
If only headers were involved and no library to link with (like some parts of the Boost framework), then yeah, defining USE_FTD2XX in your should be enough.

Order of linked libraries in ocamlbuild

I'm having an issue with the order in which the libraries are added to the linker. Previously built libraries by ocamlbuild are linked in after the list of libraries I included by the flag rule. And, I don't see any way to define this type of dependency in myocamlbuild.ml either.
Specifically, the issue comes in linking with a previously built library (gzcaml) that requires a library itself (z). Because of the added strictness in newer versions of gcc the argument -lz must appear after libgzcaml.a.
I am including all these libraries with,
flag ["ocaml"; "link"]
(S (process "-cclib" clibs))
where process creates a list alternating the library and A"-cclib", appropriately.
Also, additional libraries are appended (from the verbose output, -lm and -ldl) but I have no idea how I can modify/append these? (this would instantly solve my problem).
My myocamlbuild.ml is quite long else I would have included it here. I have tried moving the above code around to the bottom of the After_rules, to the top. And it does change the order, but never after the built libraries (c and otherwise) that ocamlbuild created previously.
EDIT
Below are code snippets I've used in my configure script and ocamlbuild to solve the issue above. Cheers!
in configure.ac
oCFLAGS="$CFLAGS"
CFLAGS="$FLAGS -Wl,--no-as-needed"
AC_MSG_CHECKING([whether we need to add --no-as-needed linking option])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],
[[
int main(){ return 0; }
]])],
[AC_MSG_RESULT([yes]); CC_NOASNEEDED="true"],
[AC_MSG_RESULT([no]); CC_NOASNEEDED="false"])
CFLAGS=$oCFLAGS
in myocamlbuild.ml.in
if #CC_NOASNEEDED# then
flag ["ocaml"; "link"]
(S [A"-cclib";A"-Wl,--no-as-needed"]);
This is not an answer, but a workaround - disable this new linker behaviour with -cclib -Wl,--no-as-needed.
I guess this should be reported as a bug to mantis. Specifically, ocamlbuild should guarantee that options from flags are inserted into command-line in the same order as they are encountered in the source (this is the case now afair), and ocamlopt should preserve the order of -cclib and -ccopt arguments wrt other entries on the command-line (this is NOT the case now).

Resources