Change the order of compiler flags - c++

To prevent "undefined reference to..." boost errors, I need to append the boost libraries at the very end of the compiler flags. Therefore, in CMakeLists.txt I set:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem")
However, verbose output of cmake shows me that additional flags are appended behind the ones I defined:
g++ -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem CMakeFiles/My_Project.dir/main.cpp.o -o My_Project -L/usr/local/boost_1_60_0/lib
Is it possible to change the order?
The complete CMakeLists.txt:
cmake_minimum_required(VERSION 3.4)
project(My_Project)
set(CMAKE_VERBOSE_MAKEFILE ON)
# This is bad but I currently don't have another working solution.
set(BOOSTROOT "/usr/local/boost_1_60_0/")
set(BOOST_ROOT "/usr/local/boost_1_60_0/")
find_package(Boost 1.60.0 COMPONENTS system filesystem REQUIRED)
if(Boost_FOUND)
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "Boost_VERSION: ${Boost_VERSION}")
link_directories(${Boost_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
endif()
add_executable(BoostTest main.cpp)
if(Boost_FOUND)
target_link_libraries(BoostTest ${Boost_LIBRARIES})
endif()
# Boost libraries appended at the end. However, cmake generates flags like this:
# c++ -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem CMakeFiles/My_Project.dir/main.cpp.o -o My_Project -L/usr/local/boost_1_60_0/lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -O0 -Wall -DBOOST_SYSTEM_NO_DEPRECATED -lboost_system -lboost_filesystem")
set(SOURCE_FILES main.cpp)
add_executable(My_Project ${SOURCE_FILES})
Thanks

You should use target_link_libraries instead of manually appending -lboost directives into your compiler flags.
TARGET_LINK_LIBRARIES(My_Project boost)
It should also be mentioned that it's possible the linker might be invoked as a separate invocation after the compilation of object files

Related

How to print out debug info to terminal when running c++ with CMake?

I am reading a C++ project and want to print out the #ifdef _DEBUG message when running the program at a Linux terminal. For example:
#ifdef _DEBUG
cout << s1 << endl;
#endif
Currently, it doesn't print out the debug info above, but only prints out logger info as below:
logger_(MY_MODULE_LOG_ERROR, "config is null ");
The project is made through cmake. It has a top level CMakeLists.txt file, in addition to each CZMakeLists.txt under src/ and its subdirectories. The content of the top-level CMakelists.txt is below:
cmake_minimum_required (VERSION 3.12)
project (TAGS_NEW )
set(CMAKE_VERBOSE_MAKEFILE true)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -w")
# gdb debug : -g
add_compile_options(
-Wall
-Wextra
-Wstrict-aliasing
-Wno-unused-parameter
-Wno-missing-field-initializers
-Wchar-subscripts
-Wpointer-arith
-Wformat
-Wformat-security
-Werror=format-security
-fstack-protector-all
-fPIE
-fpie
-fPIC
-fpic
-pipe
-fdata-sections
-ffunction-sections
)
option(DEBUG_OUTPUT "option for debug out" OFF)
if (DEBUG_OUTPUT)
add_definitions(-D_DEBUG)
endif()
# option(DEBUG_GDB "option for gdb debug" OFF)
# if (DEBUG_GDB)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ggdb")
# endif()
# set(CMAKE_BUILD_TYPE "Debug")
option(CMAKE_BUILD_TYPE "option for gdb debug" DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
option(COMPILE_DLL "option for generate dynamic library" OFF)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${TAGS_NEW_SOURCE_DIR}/output)
add_definitions(-D_Python_CALL -D_ChaiScriptON)
include_directories(${TAGS_NEW_SOURCE_DIR}/third-party/include ${TAGS_MINING_NEW_SOURCE_DIR}/include )
# $(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())")
find_package( PythonLibs 2.7 REQUIRED )
include_directories( ${PYTHON_INCLUDE_DIRS} )
link_directories(${TAGS_NEW_SOURCE_DIR}/third-party/lib)
add_subdirectory (src)
execute_process(COMMAND sh genGlobal.sh ${TAGS_NEW_SOURCE_DIR} WORKING_DIRECTORY ${TAGS_NEW_SOURCE_DIR})
I tried to change the OFF to ON in the line below, but it doesn't help:
option(DEBUG_OUTPUT "option for debug out" OFF)
I am new to CMake. How to print out all the debug info?
Options are meant to be provided from outside not to be modified in the CMake file. In fact you can't change an option with the option command once it is set in the cache (after the first CMake run). So run your cmake like this: cmake -DDEBUG_OUTPUT=ON .. and you will get your macro defined.

How to build with OpenCM3 + FreeRTOS + CMake to ARM CM4?

I am trying to program an ARM STM32F407 on an STM32F4Discovery board. First, I built a project with OpenCM3 + CMakeLists.txt. It worked! The LED flashed. ;-) Now, I'm trying to make the same project with OpenCM3 + FreeRTOS + CMakeLists.txt. Is not working! :-( It is not able to link xTaskCreate and vTaskDelay.
Please can anyone see where I'm going wrong?
I got my FreeRTOSConfig.h from here.
Below I show the error messages and my CMakeLists.txt file.
[100%] Linking C executable TesteRTOS.elf
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/TesteRTOS.dir/src/Teste.c.o: in function `GreenLEDTask':
Teste.c:(.text.GreenLEDTask+0x16): undefined reference to `vTaskDelay'
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/TesteRTOS.dir/src/Teste.c.o: in function `main':
Teste.c:(.text.main+0x20): undefined reference to `xTaskCreate'
/usr/local/Cellar/arm-none-eabi-gcc/10.3-2021.07/gcc/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld: Teste.c:(.text.main+0x24): undefined reference to `vTaskStartScheduler'
collect2: error: ld returned 1 exit status
make[2]: *** [TesteRTOS.elf] Error 1
make[1]: *** [CMakeFiles/TesteRTOS.dir/all] Error 2
make: *** [all] Error 2
cmake_minimum_required(VERSION 3.13)
set(HAVE_FLAG_SEARCH_PATHS_FIRST 0)
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(TesteRTOS C CXX ASM)
set(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(MCU_LINKER_SCRIPT ${PROJECT_DIR}/linkerscript.ld)
set(MCU_ROM_ADDRESS 0x08000000)
set(CPU_PARAMETERS
-mcpu=cortex-m4
-mthumb
-mfpu=fpv4-sp-d16
-mfloat-abi=hard
)
set(OPENCM3_COMPILER_FLAGS -DSTM32F4)
set(OPENCM3_MCU_LIB opencm3_stm32f4)
set(RTOS_PATH ~/Documents/STM32/FreeRTOS-Kernel)
set(RTOS_PORTABLE ARM_CM4F)
enable_language(C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
# Specify the cross compiler
SET(CMAKE_C_COMPILER /usr/local/bin/arm-none-eabi-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/bin/arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER /usr/local/bin/arm-none-eabi-gcc)
set(CMAKE_AR /usr/local/bin/arm-none-eabi-ar)
SET(CMAKE_OBJCOPY /usr/local/bin/arm-none-eabi-objcopy)
SET(CMAKE_SIZE /usr/local/bin/arm-none-eabi-size)
file(GLOB_RECURSE PROJECT_SOURCES FOLLOW_SYMLINKS
${PROJECT_DIR}/*.cpp
${PROJECT_DIR}/*.c
)
add_executable(${CMAKE_PROJECT_NAME}
${PROJECT_SOURCES}
)
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
SUFFIX ".elf"
)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
$ENV{OPENCM3_PATH}/include
${PROJECT_DIR}
${RTOS_PATH}/include
)
FILE(GLOB FreeRTOS_src ${RTOS_PATH}/*.c)
add_library(FreeRTOS STATIC
${FreeRTOS_src}
${RTOS_PATH}/portable/GCC/${RTOS_PORTABLE}/port.c
${RTOS_PATH}/portable/MemMang/heap_4.c
)
target_include_directories(FreeRTOS PUBLIC
${RTOS_PATH}/include
${RTOS_PATH}/portable/GCC/${RTOS_PORTABLE}/
${PROJECT_DIR}
)
target_compile_options(FreeRTOS PRIVATE
${CPU_PARAMETERS}
${OPENCM3_COMPILER_FLAGS}
-Wall -Wextra -Wundef -Wshadow -Wredundant-decls
-fno-common -ffunction-sections -fdata-sections -MD
$<$<CONFIG:Debug>:-Og -g3 -ggdb>
$<$<CONFIG:Release>:-Og -g0>
)
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE
${CPU_PARAMETERS}
${OPENCM3_COMPILER_FLAGS}
-Wall -Wextra -Wundef -Wshadow -Wredundant-decls
-fno-common -ffunction-sections -fdata-sections -MD
$<$<CONFIG:Debug>:-Og -g3 -ggdb>
$<$<CONFIG:Release>:-Og -g0>
)
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
--static -nostartfiles
--specs=nosys.specs
-T${MCU_LINKER_SCRIPT} -L$ENV{OPENCM3_PATH}/lib
${CPU_PARAMETERS}
-ggdb3 -Wl,-Map=${CMAKE_PROJECT_NAME}.map
-Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
-Wl,--cref -Wl,--gc-sections
)
target_link_libraries(${CMAKE_PROJECT_NAME} ${OPENCM3_MCU_LIB} FreeRTOS)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${CMAKE_PROJECT_NAME}>)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
${CMAKE_PROJECT_NAME}.hex
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
${CMAKE_PROJECT_NAME}.bin
COMMENT "Creating ${PROJECT_NAME}.bin and ${PROJECT_NAME}.hex."
)
add_custom_target(FLASH
st-flash --reset write ${PROJECT_NAME}.bin ${MCU_ROM_ADDRESS}
DEPENDS ${CMAKE_PROJECT_NAME}
COMMENT "Flashing ${PROJECT_NAME}"
)

How to create a CMAKE Script to build a C++ app with embedded Python?

To Compile a C app with embedded Python, for s simple project the following works great:
gcc -std=c99 -ggdb3 -O0 -pedantic-errors -Wall -Wextra \
-fpie $(/opt/python/38/bin/python3-config --cflags --embed) -o 'app' \
'main.c' $(/opt/python/38/bin/python3-config --embed --ldflags)
To compile and run this code:
#define PY_SSIZE_T_CLEAN
#include <python3.8/Python.h>
int main(int argc, char *argv[]) {
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
Py_SetProgramName(program);
Py_Initialize();
PyRun_SimpleString("print(list(range(0,5)))");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
How would you you build that with CMAKE?
Tried:
cmake_minimum_required(VERSION 3.17)
project(app C)
set(CMAKE_C_STANDARD 99)
add_executable(app main.c)
execute_process(COMMAND python3-config --cflags --embed OUTPUT_VARIABLE PY_CFLAGS)
execute_process(COMMAND python3-config --ldflags --embed OUTPUT_VARIABLE PY_LDFLAGS)
SET(PY_CFLAGS "-std=c99 -ggdb3 -O0 -pedantic-errors -Wall -Wextra -fpie ${PY_CFLAGS}")
SET(GCC_COVERAGE_LINK_FLAGS "${PY_LDFLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PY_CFLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PY_LDFLAGS}")
But doesn't work, and ends up with: undefined reference to `main'.
Any Advice
Here's a working CMAKE Script, that successfully compiles a C program that embeds Python (Via #include <Python.h>)
cmake_minimum_required(VERSION 3.17)
project(myapp C)
set(CMAKE_C_STANDARD 99)
add_executable(myapp main.c)
include_directories(/opt/python/38/include/python3.8)
link_directories(/opt/python/38/lib)
target_link_libraries(myapp python3.8 crypt pthread dl util m)

error: no type named 'invoke_result_t' in namespace 'std' gcc-7

My cmake file:
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_COMPILER "gcc-7")
project(invertedindex)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -O0")
set(SOURCE_FILES main.cpp inverted_index.hpp params.hpp)
add_executable(invertedindex ${SOURCE_FILES})
Fortunately I looked at the generated compiler command
/usr/local/bin/gcc-7 -Wall -Wextra -Wconversion -O0 -std=gnu++1z -o CMakeFiles/invertedindex.dir/main.cpp.o -c /Users/adam/school/cpp/invertedindex/main.cpp
and saw -std=gnu++1z. I have no interest in studying long hours what the f*ck that is and why it is there when I have
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
It suspect that -std=gnu++1z is not a stable, finished library, or sth. But gcc 7 supports most of the features of c++17 standard.
when I chickened out of knowing that it should work, I replaced manually the generated command parameter to -std=gnu++17 and it worked. What's wrong? How do I make it work in cmake?
See how to specify compiler in cmake
I was using the third method which is marked with avoid.
First method, that is setting CXX env var didn't work (compiler was some Mac g++).
So I tried the second method - specifying compiler in cmake args -D CMAKE_C_COMPILER=gcc-7, which worked. Even though generating again c++1z param. I don't understand it, but until I breaks I'm good.
/usr/local/bin/gcc-7 -Wall -Wextra -Wconversion -O0 -g -std=gnu++1z -o CMakeFiles/invertedindex.dir/main.cpp.o -c /Users/adam/school/cpp/invertedindex/main.cpp

Replace -fPIC with -fpic

When using Qt CMake automatically adds the -fPIC flag to compile options. I want to use -fpic, so I went through all Cmake variables and replaced -fPIC with -fpic.
cmake_minimum_required(VERSION 3.5)
project(sss)
find_package(Qt5 REQUIRED COMPONENTS Core Sql)
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if (NOT "${${_variableName}}" STREQUAL "")
string(REPLACE "-fPIC" "-fpic" ${_variableName} ${${_variableName}})
string(REPLACE "-fPIE" "-fpie" ${_variableName} ${${_variableName}})
endif()
#message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
set(CMAKE_CXX_FLAGS "-fpie")
set(CMAKE_EXE_LINKER_FLAGS "-fpie -pie")
add_executable(sss main.cpp)
target_link_libraries(sss Qt5::Core Qt5::Sql)
main.cpp contains
#include <QSqlDatabase>
int main(){
QSqlDatabase::addDatabase("QPSQL");
}
Unfortunately CMake still adds the -fPIC flag, althoguh the listed variables does not contain it:
Building CXX object CMakeFiles/sss.dir/main.cpp.o
/usr/bin/c++ -DQT_CORE_LIB -DQT_NO_DEBUG -DQT_SQL_LIB -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++-64 -isystem /usr/include/x86_64-linux-gnu/qt5/QtSql -fPIC -o CMakeFiles/sss.dir/main.cpp.o -c src/main.cpp
How can I replace -fPIC with -fpic?
Turning my comment into an answer
Your code overwrites CMake global variables like CMAKE_CXX_COMPILE_OPTIONS_PIC or CMAKE_CXX_COMPILE_OPTIONS_PIE.
But Qt brings its own -fPIC option through target properties. The Qt5::Core target does have INTERFACE_COMPILE_OPTIONS set to -fPIC (see e.g. here).
Try overwriting the target properties by adding
set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_OPTIONS "-fpic")
after your find_package(Qt5 ...) call.