Cross-Compiling C and C++ with CMake

Embedded development, especially in SOA (Service Oriented Architecture), often encounters a scenario where part of the business functionality is developed in C and is relatively mature, and there is a desire to reuse it directly. However, the underlying services obtained by the business layer are written in C++. If both need to be placed in a single process, the corresponding source code of C and C++ needs to be cross-compiled to generate an executable file. This article discusses cross-compiling C and C++.

1. Differences Between C and C++

First, we know that C is a procedure-oriented (PO) programming language, while C++ is an object-oriented (OO) programming language. C++ can be seen as a superset of C, incorporating more features.

(1) Differences Between PO and OO

  • Advantages of PO: Higher efficiency, as PO languages (e.g., C) do not require object instantiation, consuming fewer resources;

  • Disadvantages of PO: Poor portability and high maintenance costs.

  • Advantages of OO: High reusability and low maintenance costs;

  • Disadvantages of OO: Lower efficiency, as an object must be instantiated before use.

2. Compilation Principles

Regardless of whether it is C or C++, these high-level languages, which are easy for humans to read, ultimately need to be compiled into machine-readable binary language.

The compilation process generally consists of four steps: Preprocessing -> Compilation -> Assembly -> Linking.
(1) Preprocessing

The preprocessing is handled by the preprocessor, which removes comments, includes header files or packages, and replaces macro definitions in the source files (*.c, *.cpp, etc.).

(2) Compilation

In the assembly stage, the compiler translates the preprocessed high-level language into machine-readable assembly language.

(3) Assembly

The assembler converts the assembly language into machine language (binary file) and performs relocation. The loader then places the relocated instructions and data into specified memory locations.

(4) Linking

Finally, the linker combines multiple relocatable machine code files (including library files) to create an executable file.

The compilation process is illustrated as follows:

Cross-Compiling C and C++ with CMake

3. Cross-Compiling C and C++ Using CMake

Note: The main function (main.cpp) is written in C++ and calls the C-written add() interface in main(). The file structure is as follows:

Cross-Compiling C and C++ with CMake

Tip: To obtain the file structure of a folder under Windows, you can use the command: Get-ChildItem . -recurse
(1) File Content
1. Cal.h File
#ifndef _CAL_H_#define _CAL_H_
    typedef int(*calOpt)(int, int);
    #ifdef __cplusplus    extern "C"    {    #endif
        extern int add(int x,int y);
    #ifdef __cplusplus    }    #endif
#endif
As shown above, to achieve mixed programming in C and C++, the header file must use extern “C”. extern “C” is a linkage specification provided by C++ to inform the compiler that this is a function written in C. Functions declared after extern “C” will not use C++’s name mangling. This is because C++ adds extra modifiers to function names after compilation, while C does not, leading to different names for the same function after compilation, which prevents C++ from directly calling C functions.
2. Cal.c File
#include "Cal.h"
int add(int x,int y){    return (x + y);}
The content of the CMakeLists.txt file in the same folder as Cal.c is as follows:
# Find all source files in the current directory and save the names to the CUR_DIR_SRCS variable
aux_source_directory(. CUR_DIR_SRCS)
# Generate the library
add_library (Cal ${CUR_DIR_SRCS})
target_include_directories(Cal PUBLIC "../include/")
3. main.cpp File
#include <iostream>
#include "Cal.h"
int main(){
    int result;    calOpt optFunc = add;    /* Call add function through function pointer */    result = optFunc(0x10, 0x20);
    std::cout << "result = " << result << std::endl;    return 0;}
The content of the CMakeLists.txt file in the same folder as main.cpp is as follows:
# Minimum required version of cmake
cmake_minimum_required(VERSION 3.10)
# Set project name and version
project(CMake_Pro)
# Set C++ standard version
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(ENV{myEnvVar} "80")
MESSAGE(STATUS "myEnvVar: $ENV{myEnvVar}")
# Add src subdirectory
add_subdirectory(src)
# Compile source code to generate target
add_executable(CMake_Pro main.cpp)
# Include header file path
target_include_directories(CMake_Pro PUBLIC "./include/")
# Add library link
target_link_libraries(CMake_Pro Cal)
4. Running the Compilation Batch Script (*.bat)
@echo off
set buildDir=build
@REM Create the build folder if it does not exist
if not exist %buildDir% md %buildDir%
if exist %buildDir% cd %buildDir%
echo "***************: Execute cmake ***************"
cmake -G"Unix Makefiles" ../
echo "***************: Execute make ***************"
make 
pause
(2) Compilation
Run the CMake_Build.bat script, and the compilation process is as follows:

Cross-Compiling C and C++ with CMake

As can be seen, during the compilation process, the Cal.c file is first compiled into a static library file (libCal.a), and finally, during linking, the linker combines it into a complete executable file. The advantage of this approach is that it retains the efficiency of the original C file.
Run Result:

Cross-Compiling C and C++ with CMake

Previous Highlights

Summary of previous exciting articles on Autosar: 1~70
Summary of previous exciting articles on Autosar: 71~100
Summary of previous exciting articles on Autosar: 101~150

Summary of previous exciting articles on Autosar: 151~200

Overview of DDS and DCPS ModelTRACE32: Multi-core Debugging Configuration

Autosar EcuM: Analysis of APP from RUN to POST_RUN

Autosar Network Management: Can CAN FD Frame Wake Up the Network?

Embedded Development: WWD of TLF35584 External Dog

Embedded Development: Understanding ECU Wake-up, Sleep, and Reset?

Basics of C Language: The Use of do{…}while(0), Quite Elegant

Autosar EcuM: ECU Startup and Shutdown Process

Ethernet Notes: Fast Ethernet 100Base-TX Interface and Encoding

Click below to follow, let’s discuss Autosar/embedded systems together. If needed, contact the author to join the group for more professional answers.

Leave a Comment