I need to compile a static library composed by c files and one asm file using CMake. In the lib dir I have a CMakeLists.txt similar to the following:
I have moved the
set(CMAKE_ASM_COMPILER nasm)
in an upper cmake list and modified de inner
enable_language(C ASM)
include(sourcelist)
add_library(myLib ${sources} foo.asm)
set_property( SOURCE ${sources} APPEND PROPERTY
COMPILE_DEFINITIONS "MYDEF1" ;"MYDEF2")
set_source_files_properties(${sources} PROPERTIES COMPILE_FLAGS -fPIC)
set_property(
foo.asm
APPEND
PROPERTY COMPILE_DEFINITIONS
"QNXNTO")
set_source_files_properties(${sources_asm} PROPERTIES COMPILE_FLAGS "-f elf ")
target_include_directories(myLib PRIVATE ../}
where ${sources} are my c files that are compiled correctly, but
when I try to compile the asm file I got
/usr/bin/nasm -DQNXNTO -f elf -o CMakeFiles/mylib.dir/foo.asm.o -c foo.asm
nasm: error: unrecognised option `-c'
So I have the problem with -c option, it should be -s
How can I remove the unwanted "-c" ?
I have solved the issue:
in the outer cmake list set
.....
set(CMAKE_ASM_NASM_COMPILER /usr/bin/nasm)
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS asm)
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf)
.....
the inner one will be modified in the folowing way:
enable_language(C ASM_NASM)
include(sourcelist)
add_library(myLib ${sources} foo.asm)
set_property( SOURCE ${sources} APPEND PROPERTY
COMPILE_DEFINITIONS "MYDEF1" ;"MYDEF2")
set_source_files_properties(${sources} PROPERTIES COMPILE_FLAGS -fPIC)
set_property(
foo.asm
APPEND
PROPERTY COMPILE_DEFINITIONS
"QNXNTO")
target_include_directories(myLib PRIVATE ../}
The output:
/usr/bin/nasm -DQNXNTO -f elf -o CMakeFiles/mylib.dir/foo.asm.o -c foo.asm
Related
I have a CMake script where the final executable is linked with my own linker script:
cmake_minimum_required(VERSION 3.1)
project(test_app)
set(LINKER_SCRIPT "linker.ld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT}")
add_executable(${PROJECT_NAME}.elf
main.cpp
startup.cpp
)
How do I make an executable dependent also on the linker script file (trigger linking if linker.ld was changed)?
You can add a LINK_DEPENDS property to your executable target, using set_target_properties. Add the following line after your add_executable command:
set_target_properties(${TARGET_NAME} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
The first argument to set_target_properties is the target name, i.e. the first argument you passed to add_executable.
I found this mail which described three possible ways for forcing an executable to be dependent on a linker script. Its author prefers this way:
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(LINKERSCRIPT C)
FILE(WRITE main.c "void main(){}")
# dummy.c must exist:
ADD_EXECUTABLE(EXE main.c dummy.c)
# linkerscript must exist:
SET_SOURCE_FILES_PROPERTIES(
dummy.c PROPERTIES OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/linkerscript
)
Here dummy.c is an empty file, which is listed for the add_executable() command only for make resulted executable dependent on the linker script via the OBJECT_DEPENDS property.
I have a C application which is running on Raspberry Pi 3 and currently, I have to build it on PI with Cmake. I am trying to build it on Ubuntu machine. I have added a CMAKE_TOOLCHAIN_FILE as described here.
I could run cmake. -DCMAKE_TOOLCHAIN_FILE without any problem but the "make" command is not successful and it can not find a header file inside one of the external library: "mirsdrapi-rsp". The error message is:
fatal error: mirsdrapi-rsp.h: No such file or directory
#include "mirsdrapi-rsp.h"
^
compilation terminated.
I have created a folder named "lib" and have put the "libmirsdrapi-rsp.so" file inside it.
my CMakeLists.txt is as below:
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic -Wextra -v -g -D_XOPEN_SOURCE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Wextra -v ")
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "-v")
set (SDR_API_PATH ${CMAKE_SOURCE_DIR}/lib)
include_directories (include ${SDR_API_PATH})
include_directories("${CMAKE_SOURCE_DIR}/lib")
find_library(mirslocation NAMES mirsdrapi-rsp HINTS ${SDR_API_PATH} NO_CMAKE_FIND_ROOT_PATH)
message(STATUS ${mirslocation})
add_library(mirs STATIC IMPORTED)
set_target_properties(mirs PROPERTIES IMPORTED_LOCATION ${mirslocation})
target_link_libraries (raspberryPiDaemon mirs)
target_link_libraries(raspberryPiDaemon m)
Cmake is printing the right path of the library mirsdrapi-rsp while running "find_library" and as I mentioned I am getting the error message just while running "make" command and not "cmake" command.
My content of CMAKE_TOOLCHAIN_FILE is as below:
# Define our host system
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Define the cross compiler locations
SET(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc)
# Define the sysroot path for the RaspberryPi distribution in our tools folder
SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR}/../tools-master/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot/SET)
# Use our definitions for compiler tools
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Search for libraries and headers in the target directories only
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
add_definitions(-Wall -std=c11)
Anybody knows how I can add the header file from mirsdrapi-rsp library to include path?
I guess that you're setting include_directories to the wrong path (it is set 2 times to ${CMAKE_SOURCE_DIR}/lib which must be the folder of libraries not the header files). Check again the correct location of the missing header file.
More precisely: you need to find the path of mirsdrapi-rsp.h and let CMake know it just like for find_library:
find_path(MIRSDRAPI_INCLUDE_DIRS NAMES mirsdrapi-rsp.h PATHS {proper-location})
if (MIRSDRAPI_INCLUDE_DIRS)
target_include_directories(raspberryPiDaemon PRIVATE ${MIRSDRAPI_INCLUDE_DIRS})
endif()
In addition, you can set the INTERFACE_INCLUDE_DIRECTORIES property to the library like this:
set_property(TARGET mirsdrapi-rsp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MIRSDRAPI_INCLUDE_DIRS})
This way, target_include_directories might be unnecessary and target_link_directories should be enough.
With Cmake, I would like to apply some general flags to both executable and libraries.
Well, I thought I could use target_compile_options by using PUBLIC keyword. I tested on a small example with an executable and a static library, both having only one file (main.c & mylib.c), but that does not work as expected.
The root CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.0)
# Add the library
add_subdirectory(mylib)
# Create the executable
add_executable(mytest main.c)
# Link the library
target_link_libraries(mytest mylib)
# Add public flags
target_compile_options(mytest PUBLIC -Wall)
And the library's CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
add_library(mylib STATIC mylib.c)
The flag -Wall is applied only on the main.c and not on the library file (mylib.c):
[ 25%] Building C object mylib/CMakeFiles/mylib.dir/mylib.c.o
cd /patsux/Programmation/Repositories/test-cmake-public/build/mylib && /usr/lib/hardening-wrapper/bin/cc -o CMakeFiles/mylib.dir/mylib.c.o -c /patsux/Programmation/Repositories/test-cmake-public/mylib/mylib.c
[ 50%] Linking C static library libmylib.a
[ 25%] Building C object CMakeFiles/mytest.dir/main.c.o
/usr/lib/hardening-wrapper/bin/cc -Wall -o CMakeFiles/mytest.dir/main.c.o -c /patsux/Programmation/Repositories/test-cmake-public/main.c
Now, If flags are applied on the library instead of the executable, that work.
# Add public flags on the library
target_compile_options(mylib PUBLIC -Wall)
I get:
[ 25%] Building C object mylib/CMakeFiles/mylib.dir/mylib.c.o
cd /patsux/Programmation/Repositories/test-cmake-public/build/mylib && /usr/lib/hardening-wrapper/bin/cc -Wall -o CMakeFiles/mylib.dir/mylib.c.o -c /patsux/Programmation/Repositories/test-cmake-public/mylib/mylib.c
[ 50%] Linking C static library libmylib.a
[ 75%] Building C object CMakeFiles/mytest.dir/main.c.o
/usr/lib/hardening-wrapper/bin/cc -Wall -o CMakeFiles/mytest.dir/main.c.o -c /patsux/Programmation/Repositories/test-cmake-public/main.c
[100%] Linking C executable mytest
That makes no sense to set general flags such as the type of target on a library.
How can I share general flags properly ? I know I can use add_definitions(). Is it the right way ?
I also tested:
set_target_properties(mytest PROPERTIES COMPILE_FLAGS -Wall)
But flags are not public.
You can add the flag like this in your root file:
add_compile_options(-Wall)
Or, if you were using a cmake version prior to 3.0:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
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")
I would like to create a static library that depends on another library, in this case ZLIB, for which I already have a static build (libz.a).
I have the following:
...
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
set (BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set (CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) # to find the .a instead of the .so
...
find_package(ZLIB REQUIRED)
if (ZLIB_FOUND)
message(STATUS "ZLIB library: ${ZLIB_LIBRARIES}") # ZLIB library: /usr/lib64/libz.a
include_directories(${ZLIB_INCLUDE_DIRS})
set (EXT_LIBS ${EXT_LIBS} ${ZLIB_LIBRARIES})
endif()
...
add_library (libTest ${MCCORE_SOURCES_CC})
target_link_libraries(libTest ${EXT_LIBS}) #EXT_LIBS = /usr/lib64/libz.a
However, the final step of the build is creating the static library but without any reference to /usr/lib64/libz.a
ex:
/usr/bin/ar cr libTest.a object1.o object2.o ... objectN.o
I would expect:
/usr/bin/ar cr libTest.a object1.o object2.o ... objectN.o /usr/lib64/libz.a
It seems the final archive creation doesn't care for libraries set with target_link_libraries.
Any ideas?
What can I do to force this?
Under Windows (with Visual Studio) the following would do the trick:
add_library(fooStatic1 STATIC fooStatic.cpp)
set(LIBS_TO_COMBINE "${CMAKE_BINARY_DIR}/libfooStatic1.lib ${ZLIB_LIBRARIES}")
add_library(combined STATIC ${LIBS_TO_COMBINE} dummy.cpp) #dummy.cpp being empty
add_dependencies(combined fooStatic1)
set_source_files_properties(${LIBS_TO_COMBINE} PROPERTIES EXTERNAL_OBJECT TRUE GENERATED TRUE)
set_target_properties(combined PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(combined PROPERTIES STATIC_LIBRARY_FLAGS "${LIBS_TO_COMBINE}")
Unfortunately, it won't work under linux, as ar will just combine the archive files without unpacking them - creating something that is not really usable. In order to achieve your goal you need to extract the .o files and recombine them:
ar -x /usr/lib64/libz.a
ar -x libfooStatic1.a
ar -rc libcombined.a *.o
I am not aware of a CMake macro that would help in the process. You could probably run ar -x in execute_process(...), glob the output, and then run ar -rc.