Xcode/GCC predefined macro for target name? - xcode

I was wondering if there is an Xcode or GCC preprocessor symbol for the target name of the application.
For example if I'm building an application called "MonkeyChicken", is there a preprocessor symbol such that
printf( __TARGET_NAME__ )
outputs:
MonkeyChicken

I don't believe there is any built-in (gcc has no idea what you're building when you compile a file), but you can always create one using GCC_PREPROCESSOR_DEFINITIONS in an xcconfig file (you are using xcconfig, right?) Something like this should work as you indicate above:
GCC_PREPROCESSOR_DEFINITIONS = __TARGET_NAME__=\"$(PRODUCT_NAME)\"

Related

How to add compile flags in cmake on windows?

I wrote a project using CMake (with ninja and Visual Studio 2017 C++ compiler), with two modules lib_A and lib_B
lib_B depends one lib_A.
Both lib_B and lib_A define std::vector < size_t >.
Finally, the compiler told me: LNK2005 lib_A: std::vector < size_t > already defined in lib_B
I searched answers, and they gave the solution to add link flag /FORCE:MULTIPLE, page1 and page2.
I tried all these, but none of them work.
Use target_link_libraries
with target_link_libraries(lib_B lib_A INTERFACE "/FORCE:MULTIPLE")
compiler tells me The INTERFACE, PUBLIC or PRIVATE option must appear as the second argument, just after the target name.
with target_link_libraries(lib_B INTERFACE "/FORCE:MULTIPLE" lib_A )
compiler tells me ninja: error: '/FORCE:MULTIPLE', needed by 'lib_B', missing and no known rule to make it
Use CMAKE_EXE_LINKER_FLAGS
withset(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "/FORCE:MULTIPLE")
compile tells me LINK : warning LNK4012: value “x64;/FORCE:MULTIPLE” is invalid, must be one of "ARM, EBC, HYBRID_X86_ARM64X64, or X86" omit this option"
Use set_target_properties
with CMake code
get_target_property(TEMP lib_B COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
SET(TEMP "") # Set to empty string
else()
SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP} /FORCE:MULTIPLE" )
set_target_properties(lib_B PROPERTIES COMPILE_FLAGS ${TEMP} )
The compiler tells me cl: command line error D8021 : invalid parameter "/FORCE:MULTIPLE"
If I change /FORCE:MULTIPLE to -Wl,--allow-multiple-definition, compiler tells me similar result.
Could anyone help me?
Does add link flag with any error?
You can use target_link_options in CMake ≥ 3.13 or set_target_properties with the LINK_FLAGS property before.
i.e. target_link_options(${PROJECT_NAME} PUBLIC $<$<CXX_COMPILER_ID:MSVC>:/FORCE:MULTIPLE>)
This also uses generator expressions to only apply the flag for MSVC.
But it seems like both your libraries are shared (DLL), but you are statically linking the runtime to both.
I don’t think that that’s a good idea.
Try either linking to the runtime dynamically for both libs if you want to dynamically link to them, or use the static runtime but build both libraries as static library too.
Adding the following line worked for me:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE")

Compile a third-party library also using SCons from SCons build script

I'm using SCons to build my project.
A third-party library I've integrated also uses SCons, but it can be updated from Git at any time and I've got no control over the contents of its SConstruct file.
When compiled on its own, the library's SConstruct file accepts the parameters bits=32/64 and target=debug/release
I tried building it with env.SConscript(), but this doesn't pass the parameters in a form that the target SConstruct file accepts (without using SCons' Import() function):
# Compile Godot-CPP, a wrapper library we depend on
if nuclex._is_debug_build(environment):
compile_godot_cpp = environment.SConscript(
'addons/godot-cpp/SConstruct', export='bits=64 target=debug'
)
else:
compile_godot_cpp = environment.SConscript(
'addons/godot-cpp/SConstruct', export='bits=64 target=release'
)
Can I compile another SConstruct file and pass parameters to it as if SCons had been invoked from the command line on its own?
I'm aware that I could just use env.Command() to start another SCons process, but then SCons couldn't parallelize the build (i.e. scons -j16) like it does in the case of env.SConscript().
There's not a good way to do this beyond Command().
You might ask the godot project if they could move the bulk of their logic into a SConscript at the top level which you could then import and somehow pass the needed parameters to.

Necessity of include_directories command in cmake project

I'm following a tutorial on CMake and I have problems understanding the necessity of using the 'include_directories' command at one point.
Let me explain the project first:
In my working directory I have:
- a main.cpp function, a CMakeLists.txt(the main one), a configuration file, a 'MathFunction' directory and a 'build' directory
In the MathFunction directory I have:
- a CMakeLists.txt file that will be invoked by the main one
- A file 'mysqrt.cxx' that contains the implementation of a function which will be used in 'main.cpp' application
- A 'MathFunctions.h' header file that contains the prototype of that function
In the CMakeLists from 'MathFunction' directory I'm creating a library using code from 'mysqrt.cxx' like this:
add_library(MathFunctions mysqrt.cxx)
This snippet is a part of my main CMake code:
# add the MathFunctions library?
#
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions") # WHY DO WE NEED THIS
add_subdirectory (MathFunctions)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
add_executable(Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)
Now I do not understand why I need too add that 'include_directories' command in order to use the library? Shouldn't it be enough that the last command 'target_link_libraries' links the already created executable and libraries togheter so there would be no need to also include_directories?
Thank you for reading and I'm sorry if I have not explained it very well but I hope you will understand what I mean :D
Command include_directories sets directories for header files (.h) to be searched. Linking (target_link_libraries) with a library basically specifies only a library file (.so, .dll or other type). As you see, these are different things.
When linking executable with a library target, CMake propagates (more precisely, "consumes") some properties of that library target to the executable. Among these properties there is INTERFACE_INCLUDE_DIRECTORIES property, which adds include directories to the executable.
So, when a library target has INTERFACE_INCLUDE_DIRECTORIES property correctly being set, you don't need to explicitly specify include directories for executable:
MathFunctions/CMakeLists.txt:
add_library(MathFunctions mysqrt.cxx)
# Among other things, this call sets INTERFACE_INCLUDE_DIRECTORIES property.
target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
CMakeLsits.txt:
add_executable(Tutorial tutorial.cxx)
# This also propagates include directories from the library to executable
target_link_libraries (Tutorial MathFunctions)
Note, that using simple
# This *doesn't* set INTERFACE_INCLUDE_DIRECTORIES property.
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
in MathFunctions/CMakeLists.txt doesn't imply propagating include directories to the linked executable.

Compiling Bzip2 with C++11

I'm trying to compile the MultiBoost Library with C++11 but I can't make it work. The problem seems to be with the BZip2 Library that is used internally. More specificly there is a wrapper called Bzip2Wrapper to provide a c++ interface to the C library. All the files of the C library are included in the same folder. When using the default make file everything works but when I change
project(multiboost)
to
project(multiboost CXX)
I get the following errors:
libMultiBoostLib.a(Serialization.cpp.o): In function `Bzip2WrapperReader::open(char const*)':
Serialization.cpp:(.text._ZN18Bzip2WrapperReader4openEPKc[_ZN18Bzip2WrapperReader4openEPKc]+0x97): undefined reference to `BZ2_bzReadOpen'
Serialization.cpp:(.text._ZN18Bzip2WrapperReader4openEPKc[_ZN18Bzip2WrapperReader4openEPKc]+0xc5): undefined reference to `BZ2_bzReadClose'
libMultiBoostLib.a(Serialization.cpp.o): In function `Bzip2WrapperReader::close()': ...
The CMakeList file looks like this
# Bzip2
file(GLOB bzip2_SRCS "${BASEPATH}/Bzip2/*.cpp" "${BASEPATH}/Bzip2/*.c" "${BASEPATH}/Bzip2/*.h")
add_library(Bzip2Lib STATIC ${bzip2_SRCS})
#add_library(bzip2 SHARED ${bzip2_lib_SRCS})
...
# adding library to the exec
target_link_libraries(multiboost MultiBoostLib Bzip2Lib)
Any ideas what could go wrong? I don't even know what the problem is.
Thanks!
This does not look like a C++11 error but an error in the Build system.
I have not looked at the Code, but from the output you added something like this
target_link_libraries(MultiBoostLib PUBLIC Bzip2Lib)
should add the missing dependency from libMultiBoostLib on libBzip2Lib.
I found the problem. I was adding "CXX" to my project description which disabled the use of C. Therefore the libraries (in C) could not be compiled. Changing it to "project(name C CXX)" solved this issue. I then also needed to include the line "set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")" to enable C++11 support. Now everything is working.
Thanks a lot!

cmake: add_custom_command only invoked first time

I'm running into a problem with add_custom_command for a custom target (created using add_custom_target).
My general idea is to incorporate a static code analysis tool into the cmake tool-chain. My solution is based on the one described here: https://github.com/rpavlik/cmake-modules/blob/master/CppcheckTargets.cmake
In a nutshell, each project that I want to run static code analysis for has the following two lines of code:
include(cppcheck)
add_cppcheck(${le_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
The module has this at the top of the file:
if (NOT TARGET ANALYZE_CODE)
add_custom_target(ANALYZE_CODE WORKING_DIRECTORY ${LE_LITEN_ROOT})
set_target_properties(ANALYZE_CODE PROPERTIES EXCLUDE_FROM_ALL TRUE)
endif ()
and later on in the function the custom command is added:
add_custom_command(TARGET
ANALYZE_CODE
PRE_BUILD
COMMAND
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT
"${_name}_cppcheck: Running cppcheck on target ${_name}..."
VERBATIM)
The problem I'm seeing is that the command is only added for the project that included the file first. I'm not sure why and what is going on. I verified the following using message() commands:
The target is only created once
The add_custom_command is run for every project that calls the function, with proper arguments
But when I actually look at the target in visual studio, only the first include / function call command is added.
If the file is only included without calling the function, no custom commands are added at all.
Desired behavior:
I would like ONE target named "ANALYZE_CODE" to run all commands added by calls to the function.
I.e. if 3 projects include the two lines from above, the target ANALYZE_CODE is created once but 3 custom commands are added to it, one for each project.
It turns out you're somewhat stuck between a rock and a hard place here. The issue I think boils down to a couple of factors.
Firstly, although the docs don't make it clear, add_custom_command(TARGET ...) only works for targets created in the same directory. So the first subproject to call include(cppcheck) is the only one which can effectively add custom commands to the target ANALYZE_CODE.
A workaround for this might seem to be to move all calls to add_cppcheck from their respective subdirectories up to the top-level CMakeLists file.
include(cppcheck)
add_cppcheck(${le_first_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
add_cppcheck(${le_second_project} STYLE POSSIBLE_ERROR FAIL_ON_WARNINGS)
...
This isn't a great solution, since these really belong inside their own subdirs. But a bigger issue is that properties on source files only persist in the scope of the CMakeLists.txt in which they are added. This isn't obvious at all, but from the docs for set_source_files_properties:
Source file properties are visible only to targets added in the same directory (CMakeLists.txt).
The innards of the add_cppcheck have the following block of code:
foreach(_source ${_cppcheck_sources})
get_source_file_property(_cppcheck_lang "${_source}" LANGUAGE)
get_source_file_property(_cppcheck_loc "${_source}" LOCATION)
if("${_cppcheck_lang}" MATCHES "CXX")
list(APPEND _files "${_cppcheck_loc}")
endif()
endforeach()
So this is checking that each source file for the given target is designated as a C++ file before adding it to the list of files to be given to cppcheck. If this function is invoked from within the CMakeLists.txt where the target is defined (i.e. the subdir) then the files all have the appropriate property and are correctly added.
However, if the function is called from the parent CMakeLists.txt, the files have lost their properties, and so none are added and cppcheck is passed an empty list!
Now for the possible fixes. There are probably few ways to get out of this hole - I can point to a couple.
You could continue with the option to always call add_cppcheck from the top-level CMake file and avoid using the source files' properties. So the problem codeblock above could be changed to something more like:
set(CxxExtensions .cpp .CPP .cc .CC .cxx .CXX)
foreach(_source ${_cppcheck_sources})
get_filename_component(Extension "${_source}" EXT)
list(FIND CxxExtensions "${Extension}" IsCxxFile)
if(IsCxxFile GREATER -1)
list(APPEND _files "${_source}")
endif()
endforeach()
You could even enforce that the function is only called from the top-level CMakeLists.txt by adding something like this at the start of the function:
if(NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
message(FATAL_ERROR "This can only be called from the top-level CMakeLists.txt")
endif()
The second fix (which I'd personally favour) is to leave the add_cppcheck calls inside the subdirs and have the function add a custom target rather than command. These targets can successfully be applied as dependencies of the top-level target ANALYZE_CODE. So for example, change the add_custom_command to something like:
add_custom_target(ANALYZE_${_name}
${CPPCHECK_EXECUTABLE}
${CPPCHECK_QUIET_ARG}
${CPPCHECK_TEMPLATE_ARG}
${_cppcheck_args}
${_files}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "ANALYZE_${_name}: Running cppcheck on target ${_name}..."
VERBATIM)
add_dependencies(ANALYZE_CODE ANALYZE_${_name})
set_target_properties(ANALYZE_${_name} PROPERTIES FOLDER "Code Analysis")
This should cause building ANALYZE_CODE to trigger building each of the subordinate ANALYZE_... targets.
It has the downside of "polluting" the solution with a lot of extra targets, but an upside is that you could use these targets in the add_test calls (although this may be a step too far):
# CMake 2.8.0 and newer
add_test(NAME ${_name}_cppcheck_test
COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}
--target ANALYZE_${_name})

Resources