Correctly setting linker flags using CMake - c

I have a project with C and ASM (AT&T) source files that needs a linker script. My CMakeLists.txt looks something like this:
cmake_minimum_required(VERSION 2.8.4)
project(proj C ASM-ATT)
file(GLOB SOURCE_FILES *.c *.S)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -Wall -g -fno-stack-protector -pedantic")
add_executable(proj ${SOURCE_FILES})
set_target_properties(proj PROPERTIES LINK_FLAGS "-T${proj_SOURCE_DIR}/link.ld -melf_i386")
Strangely enough, building with make VERBOSE=1 reveals the following:
[ 14%] Linking C executable proj
(...)
/usr/bin/cc -m32 -Wall -g -fno-stack-protector -pedantic -T/path/to/link.ld -melf_i386 (all object files)
cc: error: unrecognized command line option '-melf_i386'
It seems that CMake is trying to use /usr/bin/cc as a C linker. I have played around with this and tried several different options (including setting CMAKE_LINKER and CMAKE_EXE_LINK_OPTIONS).
Also note that CMakeCache.txt contains a line saying
CMAKE_LINKER:FILEPATH=/usr/bin/ld
so it obviously is aware of ld and is simply using the C compiler to link the executable.
Any help would be greatly appreciated!

CMake by default invokes the linker indirectly through the compiler executable. The template command for linking executables is set up in the variable CMAKE_LANG_LINK_EXECUTABLE.
To have the compiler pass the flags on to the linker, use -Wl upon setting LINK_FLAGS, i.e.:
set_target_properties(
proj PROPERTIES LINK_FLAGS "-Wl,-T${proj_SOURCE_DIR}/link.ld,-melf_i386")

Related

CMake compile NASM and C and link everything together

I'm trying to compile assembly files with NASM and C files with GCC and link all object files together. Moreover, I'd like the C preprocessor to process the assembly files as well. This is normally no problem from the command line or a simple makefile, but I've had some trouble in replicating this functionality in CMake.
The exact process, assuming three files (boot.S, kernel.c, link.ld) would look something like this:
gcc -E -P boot.S -D <...> -o boot.s
nasm -f elf32 boot.s -o boot.o
gcc -c kernel.c -o kernel.o -ffreestanding -O2 -Wall -Wextra
Now its time to link. I want to do this like this (maybe with a few extra flags):
gcc -T link.ld -o out.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
The problems with CMake are the following:
Cmake support for NASM is weird at best. When adding .S files as sources to targets they don't get recognized as assembly files and I get hit with 'cannot determine linker language for target'. I have tried adding 's S' to CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS but it still doesn't work unless I manually set the languages with set_source_files_properties(). Moreover, as is pointed out here, CMAKE_ASM_NASM_LINK_EXECUTABLE is broken.
As far as I understand, after compiling source files to objects, CMake attempts to link them automatically. Which linker will it use to link all .o files? Will it use the linker for C? Will it use the linker for NASM? The answer is relevant, because I need to configure it with the flags I mentioned above.
What would an example CMakeLists.txt would look like that replicates the previously mentioned process? Also do I need a create_custom_command() in order to invoke just the preprocessor? Thank you.

Configuring Cmake file for library dependency [duplicate]

Work on Ubuntu 16
I used g++ main.cpp -lpq command for compiler my small project. Now I use Clion and wanna do same what I do with g++. But I can't add compiler flags in cmake file and get compile error.
cmake_minimum_required(VERSION 3.5.1)
project(day_g)
set(CMAKE_CXX_FLAGS "-lpq")
add_definitions(-lpq)
message("CMAKE_CXX_FLAGS is ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(day_g ${SOURCE_FILES})
Also I run only cmake file and get CMAKE_CXX_FLAGS with -lpq flag.
CMAKE_CXX_FLAGS is -lpq
-- Configuring done
-- Generating done
How properly add compiler flags to cmake file?
Flag -l is for linker, not for compiler. This flag is used for link with libraries. CMake has special command target_link_libraries for that purpose:
target_link_libraries(day_g pq)
-lq is not a compiler flag (CFLAGS) but a linker flag.
To pass a library in a CMake project you should use:
target_link_libraries(target_name libraries...)
Note that if you specify 'q' as library the project will link with libq.a or, if you are on windows q.dll.
... in your CMakeLists.txt the correct line to add is:
target_link_libraries(day_g pq)
Note also that when you add a CFLAG you should also "remember" the previous ones that may be added by libraries or by your platform, ie:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
To check the exact flags cmake is passing to compiler or linker you can always run, from the build directory, the following command:
make VERBOSE=1

Using a static library in C

I found a useful library on github for my project, after building this later I tried to use some predefined function on it. I couldn't compile my project because there is some header file missing like this one :
In file included from main.c:2:0:
ptask.h:11:19: fatal error: ptime.h: No such file or directory
I compiled my project using this command :
gcc main.c -L. -lptask
This is all the files in project folder :
libptask.a main.c ptask.h
This is the library content:
$ ar -t libptask.a
pbarrier.c.o
pmutex.c.o
ptask.c.o
ptime.c.o
rtmode.c.o
tstat.c.o
libdl.c.o
dle_timer.c.o
calibrate.c.o
Do I need to add all the headers of this files or just link the lib when compiling ?
Your main.c #include-s ptask.h which in turn #include-s ptime.h. Having compiled static libs alone is not enough (that's the linker's job), you still need to have all used header files (which is the compiler's job), both the ones you use and their dependencies, recursively applicable.
Normally you need to be sure that the header files are in your "include path", something that a lot of compilers define with -I as a command-line option. You'll need to include the source directory of that library, or if it has a make install option, then the place where they got installed.
regarding:
gcc main.c -L. -lptask
this is performing the compile step and the link step in one command.
It is also not enabling the warnings, which should always be enabled during the compile step.
Suggest something similar to the following to compile
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -g -c main.c -o main.o -I.
and when you have fixed all the warnings, then use something similar to the following to link
gcc main.o -o main -L. -lptask

Compiling a C program and linking

Do I understand it correctly on how to use cmake for linking
cmake_minimum_required(VERSION 3.2)
project(Sdltest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -lmingw32 -lSDL2main -lSDL2")
set(SOURCE_FILES main.c)
add_executable(Sdltest ${SOURCE_FILES})
I'm trying to link the sdl2 to my project but I get a lot of errors.
like /src/mingw-org-wsl/4.0-dev/src/libcrt/crt/main.c:91: undefined reference to `WinMain#16'
When I use gcc on cmd, it compiles perfectly
gcc main.c -o test -Wall -Werror -lmingw32 -lSDL2main -lSDL2
By the way I use clion 1.0.5
The problem is the flags, you mix compiler and linker flags. First of all this is problematic because the compiler flags aren't used when linking, and secondly because the GNU linker needs the libraries to come after the main source (or object) file on the command line, just like when you build manually.
You set the libraries by using the target_link_libraries command in your CMakeLists.txt file:
target_link_libraries(Sdltest mingw32 SDL2main SDL2)
Also, you're not building a C++ project, you're building a C project, so the flags variable should be CMAKE_C_FLAGS.
Finally, if you're wondering about the command and arguments that CMake uses when building, try making with VERBOSE set to non-zero, e.g.
make VERBOSE=1
I'm sure it's possible to add that argument to CLion.
PS.
If you want to enable more warnings, there are even more flags you could add, like -Wextra and -pedantic. Yes it might sometime give false positives, especially when including header files from external libraries, but I think it's better to have to many warnings when developing than to few.

What am I missing in compiler options for linking with JSON-C static library?

I am trying to compile the json-c-0.9 test binaries, while statically linking to libjson.a, which I have built and is sitting in /path/to/json-c-0.9/lib:
$ gcc -g -v -Wall -std=gnu99 -static -L/path/to/json-c-0.9/lib -ljson test1.c -o test1
I get numerous errors of the form:
/path/to/json-c-0.9/test1.c:17: undefined reference to `json_object_new_string'
/path/to/json-c-0.9/test1.c:18: undefined reference to `json_object_get_string'
/path/to/json-c-0.9/test1.c:19: undefined reference to `json_object_to_json_string'
/path/to/json-c-0.9/test1.c:20: undefined reference to `json_object_put'
/path/to/json-c-0.9/test1.c:22: undefined reference to `json_object_new_string'
etc.
What I am missing in trying to compile the test binaries? Thanks for your advice.
With static linking, gcc only tries to bring in the symbols it needs based on what it has encountered already. In your case, you pass -ljson before your source files, so gcc brings in the static library and doesn't need anything from it, then tries to build your code.
Put the libraries to link against after your code.
$ gcc -g -v -Wall -std=gnu99 -static -L/path/to/json-c-0.9/lib test1.c -o test1 -ljson
Here's mine Cmakelist.txt. untitled3,4 are the folder names. Remember to put header file in the same folder or direct to it correctly.
cmake_minimum_required(VERSION 3.15)
project(untitled3 C )
#find_package( OpenCV REQUIRED )
ADD_LIBRARY(LibsModule
main.c
json.h
libjson.c
)
target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule libjson-c.a)
target_link_libraries(LibsModule libjson-c.4.dylib)
target_link_libraries(LibsModule -L/usr/local/Cellar/json-c/0.13.1/lib)
include_directories(/usr/local/lib/pkgconfig)
include_directories(untitled3)
set(CMAKE_C_STANDARD 99)
set(SOURCES json.h main.c )
configure_file (
"${PROJECT_SOURCE_DIR}/json.h"
"${PROJECT_BINARY_DIR}/json.h"
)
add_executable( untitled4 ${SOURCES} )
target_link_libraries(untitled4 LibsModule)

Resources