CMake toolchain: Linker fails with 'no input files' error - cmake

Ouch! I inadvertently updated CMake to 3.9.1 (long story, and I don't know the old version), which is not terribly new, but is what Ubuntu/PopOS! 17.10 seem to support, and now my project failed to find my tools. Okay, I said, my original toolchain file used the obsolete/deprecated "force toolchain" thing, which was given to me several years ago. Having recently learned the correct way, I updated my toolchain file, and all works fine - until it is time to link. Now, the link fails with no input files; in other words, the command looks like this:
ld
There were no changes to my CMakeLists.txt file, and I am stumped! What could cause the link command to change so drastically?
Here is the new toolchain file:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(XILINX_ROOT /home/bgrimes/osu/tools/opt/pkg/petalinux)
set(XILINX_TOOLS ${XILINX_ROOT}/tools/linux-i386/gcc-arm-linux-gnueabi)
set(CMAKE_C_COMPILER "${XILINX_TOOLS}/bin/arm-linux-gnueabihf-gcc")
set(CMAKE_CXX_COMPILER "${XILINX_TOOLS}/bin/arm-linux-gnueabihf-g++")
set(CMAKE_CXX_LINK_EXECUTABLE "${XILINX_TOOLS}/bin/arm-linux-gnueabihf-ld")
#set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-a9" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfpv3" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXILINX" )
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions")
Here is the old toolchain file:
INCLUDE(CMakeForceCompiler)
SET(CMAKE_SYSTEM_NAME "Linux")
CMAKE_FORCE_C_COMPILER(arm-linux-gnueabihf-gcc GNU)
CMAKE_FORCE_CXX_COMPILER(arm-linux-gnueabihf-g++ GNU)
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-a9" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=hard" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfpv3" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXILINX" )
set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions" )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" FORCE )
set( CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" FORCE )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "" FORCE )

Variable CMAKE_CXX_LINK_EXECUTABLE denotes the rule for link, not just a linker.
So setting it with
set(CMAKE_CXX_LINK_EXECUTABLE "${XILINX_TOOLS}/bin/arm-linux-gnueabihf-ld")
effectively makes the linker to be called without any arguments.
Common way to set this variable is:
set(CMAKE_LINKER "${XILINX_TOOLS}/bin/arm-linux-gnueabihf-ld")
set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_LINKER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
See also that answer: CMake: use a custom linker.
Note, that CMAKE_LINKER variable is not a special variable by itself: CMake knows nothing about it. In the example above this variable is referred via <CMAKE_LINKER> construction in the rule.

Related

Disable compiler warnings when using FetchContent with CMake [duplicate]

I have a C/C++ project in which I want to use CppUTest.
So I include the dependency of CppUTest with:
include(FetchContent)
FetchContent_Declare(
CppUTest
GIT_REPOSITORY https://github.com/cpputest/cpputest.git
GIT_TAG latest-passing-build
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
)
set(TESTS OFF CACHE BOOL "Switch off CppUTest Test build")
FetchContent_MakeAvailable(CppUTest)
This works fine.
In my (automotive) project, I use the C++20 standard and I need to enable all/most warnings. But when I do, CppUTest brings me a lot of warnings. So, I would like to compile CppUTest with different compiler options than the project's code.
How can I configure that in CMake?
I googled a lot but didn't find anything that works.
Thanks,
Stefan
PS: My simplified CMake file is:
cmake_minimum_required(VERSION 3.5)
project(projectName LANGUAGES CXX C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
MESSAGE("Setting Clang flags:")
SET(COMPILE_FLAGS_WARNINGS "-Weverything")
SET(COMPILE_FLAGS_DEBUG "-Og")
SET(COMPILE_FLAGS_RELEASE "-O2")
SET(COMPILE_FLAGS_COVERAGE "--coverage")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
#more options here
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
#more options here
endif()
MESSAGE("Debug: ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS_WARNINGS} ${COMPILE_FLAGS_DEBUG}")
MESSAGE("Release: ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS_WARNINGS} ${COMPILE_FLAGS_RELEASE}")
MESSAGE("Coverage: ${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS_WARNINGS} ${COMPILE_FLAGS_DEBUG} ${COMPILE_FLAGS_COVERAGE}")
### Dependencies:
include(FetchContent)
FetchContent_Declare(
CppUTest
GIT_REPOSITORY https://github.com/cpputest/cpputest.git
GIT_TAG latest-passing-build
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
)
set(TESTS OFF CACHE BOOL "Switch off CppUTest Test build")
FetchContent_MakeAvailable(CppUTest)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS_WARNINGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${COMPILE_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "${COMPILE_FLAGS_RELEASE}")
enable_testing()
### add tests
add_subdirectory(path/to/my/tests)
Do not use set(CMAKE_<LANG>*. Use *target* interfaces. If you do not want all stuff to be compiled with a specific option, do not set them globally. Instead:
set_target_properties(mytests PROPERTY
CXX_STANDARD 11
etc.
)
target_compile_options(mytests PUBLIC -option1 -option2 ...)
Anyway, SET(CMAKE_<LANG>_* affect targets declared after it. So move set(CMAKE_* after FetchContent_MakeAvailable(CppUTest)

CMake question: Two same output obj generated by VS IDE and CMake command line cause LNK4006

I am new for CMake, and I'm adding NASM files into projects by CMakelists.
With this version, IDE and project have two output folders to generate same obj, so that cause warning lnk4006 already defined second definition ignored.
One output folder and it is like build\encoder\x86.
Another is like build\encoder\x86\xxxenc_x86_asm.dir\Debug\ or build\encoder\x86\xxxenc_x86_asm.dir\Release.
I have trid to update the second output path to be same with the first, but it can't work.
CMakelists like following:
add_library(${ENCODER_X86_ASM_LIB_NAME} OBJECT "")
if ((LINUX OR MACOSX OR WIN32) AND ${ENABLE_ASM})
set(ASM_EXECUTABLE "${NASM_EXE}")
if(CMAKE_GENERATOR STREQUAL "Xcode")
add_library(${ENCODER_NATIVE_ASM_LIB_NAME} INTERFACE)
endif()
set(X86_ASM_SRCS
asm/avx2/average_avx2.asm)
if (WIN32)
set(ASM_FLAGS ...)
elseif(MACOSX)
set(ASM_FLAGS -I${PROJECT_SOURCE_DIR}/ -f macho64 -O2 -DARCH_X86_64=1 -DPREFIX -DOS_MAC=1 -DPIC -Worphan-labels -DSTACK_ALIGNMENT=16)
elseif(LINUX)
set(ASM_FLAGS -I${PROJECT_SOURCE_DIR}/ -f elf64 -O2 -DARCH_X86_64=1 -DOS_MAC=0 -DPIC -Worphan-labels -DSTACK_ALIGNMENT=16)
endif()
#generate objects when building CMake
if(CMAKE_GENERATOR STREQUAL "Xcode")
asm_compile_to_target(${ENCODER_NATIVE_ASM_LIB_NAME} ${X86_ASM_SRCS})
else()
asm_compile_to_target(${ENCODER_X86_ASM_LIB_NAME} ${X86_ASM_SRCS})
endif()
if ((MACOSX AND (CMAKE_GENERATOR STREQUAL "Xcode")) OR WIN32)
foreach(asm_file ${X86_ASM_SRCS})
set(ASM_SRC ${CMAKE_CURRENT_LIST_DIR}/${asm_file})
get_filename_component(filename "${asm_file}" NAME_WE)
set(ASM_OBJ "${CMAKE_CURRENT_BINARY_DIR}/${filename}${CMAKE_C_OUTPUT_EXTENSION}")
list(APPEND ASM_SRCS ${ASM_SRC})
list(APPEND ASM_OBJS ${ASM_OBJ})
add_custom_command(
OUTPUT ${ASM_OBJ}
COMMAND ${ASM_EXECUTABLE}
ARGS ${ASM_FLAGS} ${ASM_SRC} -o ${ASM_OBJ}
DEPENDS ${ASM_SRC}
)
endforeach()
foreach(OBJ ${ASM_OBJS})
list(APPEND ASM_PRIMITIVES ${OBJ})
endforeach()
foreach(SRC ${X86_ASM_SRCS})
list(APPEND ASM_PRIMITIVES ${CMAKE_CURRENT_LIST_DIR}/${SRC})
endforeach()
source_group(Assembly FILES ${ASM_PRIMITIVES})
if(CMAKE_GENERATOR STREQUAL "Xcode")
target_sources(${ENCODER_NATIVE_ASM_LIB_NAME} INTERFACE ${ASM_PRIMITIVES})
else()
target_sources(${ENCODER_X86_ASM_LIB_NAME} PRIVATE ${ASM_PRIMITIVES})
endif()
if (MACOSX)
add_custom_target(${ENCODER_X86_ASM_LIB_NAME}-asm ALL DEPENDS ${ASM_PRIMITIVES})
target_sources(${ENCODER_X86_ASM_LIB_NAME} INTERFACE ${ASM_PRIMITIVES})
add_dependencies(${ENCODER_X86_ASM_LIB_NAME} ${ENCODER_X86_ASM_LIB_NAME}-asm)
else()
target_sources(${ENCODER_X86_ASM_LIB_NAME} PRIVATE ${ASM_PRIMITIVES})
endif()
endif() ## if ((MACOSX) AND (CMAKE_GENERATOR STREQUAL "Xcode") OR WIN32)
endif() ## if ((LINUX OR MACOSX OR WIN32) AND ${ENABLE_AVX2})
target_compile_definitions(${ENCODER_X86_ASM_LIB_NAME} PUBLIC)
Here, CMAKE_CURRENT_BINARY_DIR is one output folder and it is build\encoder\x86.
how to deal with this issue?
Background is this: we need to support incremental compiling in IDE, also need to support building by cmake command line.
I have tried to update output path(or directory) as:
set_target_properties(${ENCODER_X86_ASM_LIB_NAME} PROPERTIES LIBRARY_OUTPUT_PATH ${PATH} )
set_target_properties(${ENCODER_X86_ASM_LIB_NAME} PROPERTIES BUILD_RPATH ${PATH} )
set_target_properties(${ENCODER_X86_ASM_LIB_NAME} PROPERTIES INSTALL_RPATH ${PATH} )
set_target_properties(${ENCODER_X86_ASM_LIB_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PATH} )
It just can't work.
Thanks!

How to set CMAKE_TOOLCHAIN_FILE for when the project is created on windows only

I am trying to use vcpkg for Windows build when the CMake is also used for Linux build. The Linux build doesn't use vcpkg.
This is part of CMake that works on windows:
cmake_minimum_required(VERSION 3.5)
file(TO_CMAKE_PATH $ENV{LOCAL_ROOT} LOCAL_ROOT)
set(VCPKG_ROOT "${LOCAL_ROOT}/vcpkg-master")
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
OPTION(USE_BOOST "use BOOST library" ON)
OPTION(CREATE_DLL "Create DLL or .so library" OFF)
OPTION(READ_GIT_HASH "read git sha1 hash for versioning" OFF)
project(ExtractOnctData)
if(MSVC)
add_definitions (-D_USE_MATH_DEFINES)
add_definitions (-DNOMINMAX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP ")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" )
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ot /openmp /MT" )
else(MSVC)
#Use C++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#Find and use standard libraries
find_package(Threads REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif(MSVC)
but it breaks Linux build as the three vcpkg settings which not used in Linux build added to CMake.
If I do this:
cmake_minimum_required(VERSION 3.5)
if(MSVC)
file(TO_CMAKE_PATH $ENV{LOCAL_ROOT} LOCAL_ROOT)
set(VCPKG_ROOT "${LOCAL_ROOT}/vcpkg-master")
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
endif(MSVC)
OPTION(USE_BOOST "use BOOST library" ON)
OPTION(CREATE_DLL "Create DLL or .so library" OFF)
OPTION(READ_GIT_HASH "read git sha1 hash for versioning" OFF)
project(ExtractOnctData)
if(MSVC)
add_definitions (-D_USE_MATH_DEFINES)
add_definitions (-DNOMINMAX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP ")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" )
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ot /openmp /MT" )
else(MSVC)
#Use C++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#Find and use standard libraries
find_package(Threads REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif(MSVC)
Then it doesn't work in Windows.
If I do this:
cmake_minimum_required(VERSION 3.5)
OPTION(USE_BOOST "use BOOST library" ON)
OPTION(CREATE_DLL "Create DLL or .so library" OFF)
OPTION(READ_GIT_HASH "read git sha1 hash for versioning" OFF)
project(ExtractOnctData)
if(MSVC)
file(TO_CMAKE_PATH $ENV{LOCAL_ROOT} LOCAL_ROOT)
set(VCPKG_ROOT "${LOCAL_ROOT}/vcpkg-master")
set(CMAKE_TOOLCHAIN_FILE "${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
endif(MSVC)
if(MSVC)
add_definitions (-D_USE_MATH_DEFINES)
add_definitions (-DNOMINMAX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP ")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" )
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ot /openmp /MT" )
else(MSVC)
#Use C++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#Find and use standard libraries
find_package(Threads REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif(MSVC)
It doesn't work in windows.
How Can I fix this problem?
A few things:
you want to define CMAKE_TOOLCHAIN_FILE and VCPKG_TARGET_TRIPLET before your project(ExtractOnctData)call (so the third example will never work)
You want to use if(WIN32) (target system) or if(CMAKE_HOST_WIN32) instead of if(MSVC). if(MSVC) is a compiler check and not a host/target system check.
Remove OPTION(CREATE_DLL "Create DLL or .so library" OFF). This should be controlled by BUILD_SHARED_LIBS (https://cmake.org/cmake/help/v3.17/variable/BUILD_SHARED_LIBS.html). Make sure you export your functions correctly on Windows if you allow a DLL build
find_package(Threads REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread"). Link target Threads::Threads instead and you can move it out of the if.
Please don't add /MT(d) to CMAKE_CXX_FLAGS_(DEBUG|RELEASE) on Windows.
Don't add -std=c++11 use target_compile_features instead (https://cmake.org/cmake/help/v3.17/manual/cmake-compile-features.7.html#compile-feature-requirements). Maybe add a compiler_(flag|requirements) interface target which you use to setup all those flags

How to write my CMakeLists.txt in a less boilerplate form?

In the example below I find the pattern set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} xxx") very boilerplate. Same case for include_directories("${CMAKE_CURRENT_SOURCE_DIR}/...").
Is it possible to simplify the writing?
cmake_minimum_required(VERSION 3.6)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CROSS_COMPILE arm-none-eabi- )
set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc.exe)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++.exe)
set(CMAKE_ASM_COMPILER ${CROSS_COMPILE}as.exe)
set(CMAKR_C_FLAGS "${CMAKR_C_FLAGS} -mlittle-endian")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-m4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfpv4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mabi=aapcs")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsigned-char")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=nosys.specs")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mthumb")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mcpu=cortex-m4")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g" CACHE INTERNAL "")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
project("project" C)
add_definitions(-DBLE_STACK_SUPPORT_REQD)
add_definitions(-DS132)
add_definitions(-DNRF_LOG_USES_RTT=1)
add_definitions(-DSWI_DISABLE0)
add_definitions(-DSOFTDEVICE_PRESENT)
add_definitions(-DNRF52)
add_definitions(-DAC_ACC_RAW_SAMPLING_FREQUENCY_25Hz)
add_definitions(-DDEBUG)
add_definitions(-DENABLE_DEBUG_LOG_SUPPORT)
add_definitions(-DNRF_LOG_USES_COLORS=0)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/foo")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/bar")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/baz")
list(
APPEND src
${CMAKE_CURRENT_SOURCE_DIR}/foo/foo.c
${CMAKE_CURRENT_SOURCE_DIR}/bar/bar.c
${CMAKE_CURRENT_SOURCE_DIR}/baz/baz.c
)
add_executable(
project
${src}
)
First of all, most of your CMakeLists.txt is more suitable for a toolchain file.
Regarding your questions:
Compile Flags
Compile flags can be added via add_compile_options():
add_compile_options(
-mlittle-endian
-mcpu=cortex-m4
-mthumb
...
)
Alternatively, you could do what Akira suggested:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
-mlittle-endian \
-mcpu=cortex-m4 \
-mthumb \
... \
")
Unfortunately, you cannot do list(APPEND...), because CMAKE_C_FLAGS is a string rather than a list.
If you need to pass compound options, e.g. --section .text=FOO, please use the latter approach. For details please refer to this question: Pass compound compiler options using cmake.
Include Directories
include_directories() can have multiple arguments, e.g.:
include_directories(
foo
bar
baz
)
Note, you do not need to explicitly specify ${CMAKE_CURRENT_SOURCE_DIR}, because:
Relative paths are interpreted as relative to the current source directory.
For more complicated projects, please consider target_include_directories() as an alternative.
Miscellaneous
You do not need to put everything in quotation marks.
You do not need to explicitly specify ${CMAKE_CURRENT_SOURCE_DIR}. Most of the commands interpret relative paths as relative to the current source directory.
add_definitions() also accepts multiple arguments.
All values in cmake are stored as strings, so you can set your CMAKE_C_FLAGS flags much easier as follows:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
-mlittle-endian \
-mcpu=cortex-m4 \
-mthumb \
-mfpu=vfpv4 \
-g3 \
-Wall \
-Werror \
-mabi=aapcs \
-O2 \
-std=c99 \
-fsigned-char \
-ffunction-sections \
-fdata-sections \
-fmessage-length=0 \
")
The code above will replace the value of CMAKE_C_FLAGS variable with the new string defined above. To check your results, you always can use the message command.
Note: the \ characters at the end of all lines above are used for line continuation. You can read more about it in the CMake documentation.
The same can be applied to the include_directories command but with lists:
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}/foo"
"${CMAKE_CURRENT_SOURCE_DIR}/bar"
"${CMAKE_CURRENT_SOURCE_DIR}/baz"
)
The lists in cmake are strings too but their elements are separated by ; characters. When you specify multiple arguments, they will be joined as a list.

Make References like Visual Studio in CMake

I start to use CMake recently and I starting to get used to the program. I managed to generate two Visual Studio solutions/projects: a shared library (core.dll) and a static library (zlib.lib). Now I still have a problem, my core.dll library makes references to the zlib library in Visual Studio. (In Properties -> Common Properties -> References). How can I reproduce this?
Here is how my files are located:
project
---core
------src
------CMakeLists.txt
---external
------zlib
------CMakeLists.txt
---------zlib-1.2.8
And here my two CMakeLists :
For core.dll
cmake_minimum_required(VERSION 2.8)
#Configuration project
project(core CXX)
#add definitions
#set(LIBRARY_OUTPUT_PATH_DEBUG vc2013_x64/bin/)
set(BIN_PATH "../vc2013_x64d")
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
add_definitions(-D_UNICODE -D_USRDLL -DCORE_EXPORTS)
add_definitions("/Gm")#"/GL" "/Gy"
#remove_definitions
add_definitions(-UCMAKE_INTDIR="Release")
#Configuration Library
add_library(
core
SHARED
... .h and .cpp
)
For zlib.lib
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#Configuration de ZLib
PROJECT(zlib C)
SET(BIN_PATH "../core/vc2013_x64d")
SET_TARGET_PROPERTIES(PROPERTIES LINKER_LANGUAGE C)
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /W3")
ADD_DEFINITIONS("/Gm" -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_UNICODE)
ADD_LIBRARY(
zlib
STATIC
... .h and .c
)
EDIT :
It's work like this :
cmake_minimum_required(VERSION 2.8)
#Configuration de Zlib.lib
PROJECT(zlib C)
SET(BIN_PATH "../cmakex64d")
#SET_TARGET_PROPERTIES(PROPERTIES LINKER_LANGUAGE C)
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/lib/" )
SET(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /W3")
ADD_DEFINITIONS("/Gm" -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -D_UNICODE)
ADD_LIBRARY(
zlib
STATIC
external/zlib/zlib-1.2.8/adler32.c
external/zlib/zlib-1.2.8/compress.c
external/zlib/zlib-1.2.8/crc32.c
external/zlib/zlib-1.2.8/deflate.c
external/zlib/zlib-1.2.8/gzclose.c
external/zlib/zlib-1.2.8/gzlib.c
external/zlib/zlib-1.2.8/gzread.c
external/zlib/zlib-1.2.8/gzwrite.c
external/zlib/zlib-1.2.8/infback.c
external/zlib/zlib-1.2.8/inffast.c
external/zlib/zlib-1.2.8/inflate.c
external/zlib/zlib-1.2.8/inftrees.c
external/zlib/zlib-1.2.8/trees.c
external/zlib/zlib-1.2.8/uncompr.c
external/zlib/zlib-1.2.8/zutil.c
external/zlib/zlib-1.2.8/crc32.h
external/zlib/zlib-1.2.8/deflate.h
external/zlib/zlib-1.2.8/gzguts.h
external/zlib/zlib-1.2.8/inffast.h
external/zlib/zlib-1.2.8/inffixed.h
external/zlib/zlib-1.2.8/inflate.h
external/zlib/zlib-1.2.8/inftrees.h
external/zlib/zlib-1.2.8/trees.h
external/zlib/zlib-1.2.8/zlib.h
external/zlib/zlib-1.2.8/zutil.h
)
project(core CXX)
set(BIN_PATH "../cmakex64d")
set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BIN_PATH}/bin/" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
set_property(GLOBAL PROPERTY LINK_LIBRARY_DEPENDENCIES "yes")
add_definitions(-D_UNICODE -D_USRDLL -DCORE_EXPORTS)
add_definitions("/Gm")
#Configuration de core.dll
add_library(
core
SHARED
core/src/asserts.h
core/src/errors.h
core/src/filepath.h
core/src/memory.h
core/src/resources.h
core/src/stdafx.h
core/src/streams.h
core/src/string.h
core/src/system.h
core/src/variants.h
core/src/filepath.cpp
core/src/main.cpp
core/src/memory.cpp
core/src/resources.cpp
core/src/stdafx.cpp
core/src/streams.cpp
core/src/string.cpp
core/src/system.cpp
)
link_directories("/build/lib/")
target_link_libraries(core zlib)
But when i "configure" in CMake i've this warning now :
CMake Warning (dev) at C:/Program Files
(x86)/CMake/share/cmake-3.1/Modules/CMakeDetermineCXXCompiler.cmake:106
(if): Policy CMP0054 is not set: Only interpret if() arguments as
variables or keywords when unquoted. Run "cmake --help-policy
CMP0054" for policy details. Use the cmake_policy command to set
the policy and suppress this warning.
Quoted variables like "MSVC" will no longer be dereferenced when the
policy is set to NEW. Since the policy is not set the OLD behavior
will be used. Call Stack (most recent call first): CMakeLists.txt:51
(project) This warning is for project developers. Use -Wno-dev to
suppress it.
CMake Warning (dev) at C:/Program Files
(x86)/CMake/share/cmake-3.1/Modules/CMakeFindBinUtils.cmake:33 (if):
Policy CMP0054 is not set: Only interpret if() arguments as variables
or keywords when unquoted. Run "cmake --help-policy CMP0054" for
policy details. Use the cmake_policy command to set the policy and
suppress this warning.
Quoted variables like "MSVC" will no longer be dereferenced when the
policy is set to NEW. Since the policy is not set the OLD behavior
will be used. Call Stack (most recent call first): C:/Program Files
(x86)/CMake/share/cmake-3.1/Modules/CMakeDetermineCXXCompiler.cmake:162
(include) CMakeLists.txt:51 (project) This warning is for project
developers. Use -Wno-dev to suppress it.
Why ? I've not that before ?