Background

I am not a C/C++ developer.

I need to set up a C/C++ development environment on Windows because I evaluated Codeium (AI-powered Visual Studio Code Extension) recently and I need to run some GoogleTest UT generated by Codeium. I must compile C/C++ code, create executable files, and run UT.

Meanwhile, I want to use the CMake extension to make the code compiling and testing more automatic and convenient.

I did a lot of searches on Google and spent a lot of time on VsCode documentation.

None
Photo by Darwin Vegher on Unsplash

Finally, it works. 😅

The diagram below shows all the main steps to set up the final workable C/C++ development environment with VsCode and MYSY2 on Windows.

In this article, I will cover each step. In addition, I will share the problems I encountered and the corresponding solutions.

The use case in the article is simple:

  • define fibonacci function in the header file — fibonacci.h in src/include
  • implement fibonacci function in c source file — fibonacci.c
  • test fibonacci function in cpp source file with googletest — fibonacci_test.cpp

Install and Configure MSYS2

Installation of MSYS2 is simple — follow the guide on the MSYS2 installation page. After downloading the installer file, remember to verify the integrity.

By default, MSYS2 is installed under the root directory of the C drive. E.g. C:\\msys64 .

After installation, I configured it in the Windows Terminal profile as below. Then, I can start a new MSYS2 session with a new tab in Windows Terminal.

{
    "commandline": "C:/msys64/msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell zsh",
    "guid": "{be9452ef-a866-5d5c-a34e-3e2438321f2d}",
    "name": "MSYS",
    "tabTitle": "MSYS"
}

Meanwhile, I configured it in VsCode in settings.json as below and then I can start it from VsCode Terminal.

"terminal.integrated.profiles.windows": {
    "MSYS2 UCRT": {
        "path": "cmd.exe",
        "args": [
            "/c",
            "C:\\msys64\\msys2_shell.cmd -defterm -here -no-start -ucrt64 -shell zsh"
        ]
    }
}

📓 zsh is not available by default, need to install the zsh package.

Install the MinGW-w64 ucrt toolchain package and the ucrt cmake package

MSYS2 provides a package management service — developers can run pacman command to install the supported packages on the MSYS2 Packages website. (The command pacman should be familiar to Linux Arch users)

However, not all supported packages can be searched from the search page. For example, I tried to search mingw-w64-ucrt-x86_64-toolchain on the search page, but it returned nothing.

None
Cannot Search "mingw-w64-ucrt-x86_64-toolchain"

When I go to "Groups", and use Ctrl+F to search mingw-w64-ucrt-x86_64-toolchain , then I found it.

None
Found "mingw-w64-ucrt-x86_64-toolchain" in Groups

💁 Therefore, mingw-w64-ucrt-x86_64-toolchain is not a package but a group of packages. I clicked the name and got to the below page which shows all packages included in the group mingw-w64-ucrt-x86_64-toolchain.

None
Packages included in the group "mingw-w64-ucrt-x86_64-toolchain"

📓 I got the group package's full name mingw-w64-ucrt-x86_64-toolchain from the VsCode guide.

To use cmake with gcc and g++ from the ucrt toolchain packages group, I must install the ucrt cmake package. It won't work (check the Failures Section below) if I use the cmake installed by other packages such as the cmake package. I paid lots of time to be aware of that. I don't know if it's caused by the specific version.

Search ucrt on the search page, then find the ucrt cmake package — mingw-w64-ucrt-x86_64-cmake.

None
Found ucrt cmake package

Click the package name, and go to the details page. Then, copy the command pacman -S mingw-w64-ucrt-x86_64-cmake in the MSYS2 session terminal to install the package.

Set the Environment Variables

To run gcc or g++ in Windows command interpreter or PowerShell, the path C:\msys64\ucrt64\bin need to be added to the environment variable PATH .

Two ways to edit the environment variables:

  • (1) UI: Windows key + s -> "Environment Variable" -> "Edit environment variables for the account", then edit in the popup window.
  • (2) CLI: Run command setx PATH "${env:PATH};C:\msys64\ucrt64\bin" in PowerShell or setx PATH "%PATH%;C:\msys64\ucrt64\bin" in Windows command interpreter.

After that, start a new PowerShell or Windows command interpreter, the command gcc sample.c -o sample will work.

#include <stdio.h>

int main(){
 printf("Hello, World");
}
> gcc sample.c -o sample  && .\sample
Hello, World
> gcc sample.cpp -o sample  && .\sample
Hello, World

To use cmake , I added the path C:\msys64\usr\bin to the environment variable PATH . The reason is that the command make is located under the path C:\msys64\usr\bin and cmake rely on make which supports Unix Makefile.

To use gcc and g++ to compile C/C++ source code files by cmake, I need to configure another 2 environment variables for cmake :

CMAKE_C_COMPILER=gcc.exe
CMAKE_CXX_COMPILER=g++.exe

or

C=gcc.exe
CXX=g++.exe

Otherwise, cmake might use the default compilers cc and c++ as compilers, even though they might also work.

The environment variables used by VsCode CMake Tools extension could be configured in VsCode settings.json file or cmake-kits.jsonfile. I will explain that part in the section VsCode Extension Configuration.

Install Python

Because cmake depends on Python, I need to install Python and add the path to python.exe in the environment variable PATH .

Not many words in this section, download the installer for Windows and do the installation.

Install C/C++ VsCode Extension and CMake Tools Extension

The C/C++ VsCode extensions can be installed with the C/C++ Extension Pack (@id:ms-vscode.cpptools-extension-pack) which includes: C/C++, C/C++ Themes, CMake, and CMake Tools.

None
C/C++ Extension Pack

Note: CMake Tools is included in C/C++ Extension Pack, however, I often need to install CMake Tools separately. I don't know why.

Configure C/C++ VsCode Extension

C/C++ VsCode Extension contains 2 parts: editing (IntelliSense) and debugging. It doesn't contain a compiler, so I need to pre-install compilers and do configuration accordingly as aforementioned.

Note: VsCode Settings or settings.json file could be in different levels or scopes: User, Workspace, and Folder. In Windows, User Settings settings.json file located under $env:USERPROFILE/AppData/Roaming/Code/User/ or $env:USERPROFILE/AppData/Roaming/Code/User/profiles/[profile id]/, Workspace Settings settings.json file's content is included in the workspace file, Folder Settings settings.json file located under workspace folder/.vscode/. Workspace folder is the top level folder of the project added into the workspace.

Intelli Sense Mode

Different OS use different compilers. The compiler to be used is reflected by the available IntelliSense modes. The default mode on Windows is msvc-x64 using Microsoft Visual C++. In my case, I use gcc and g++ provided by the package mingw-w64-ucrt-x86_64-toolchain of MSYS2. Therefore, I should use linux-gcc-x64 . If you are not sure which one to use, don't set it and leave it as ${default} by the extension.

Search the Intelli Sense Mode by id C_Cpp.default.intelliSenseMode

None
Intelli Sense Mode

Compiler Path

It's a good idea to set the compiler path specially. If not, then the compiler in PATH will be used. Sometimes, it might result in tricky errors if PATH is not configured as expected.

In VsCode, click Ctrl+, to open Settings. In the Search Settings text field, type C_Cpp.default.compilerPath and then click the link Edit in settings.json to set the default compiler path.

"C_Cpp.default.compilerPath": "C:\\msys64\\ucrt64\\bin\\gcc.exe"

The configured compiler path will impact the Intelli Sense Mode. So, if the Intelli Sense Mode was configured wrongly, it will be changed according to the compiler path.

The compiler path can also be configured in c_cpp_properties.json file which has higher priority than the configuration in settings.json file.

"compilerPath": "C:\\msys64\\ucrt64\\bin\\g++.exe"

Include Path

To compile C/C++ source files, the header files in the workspace or the libraries should be known for compilers. The include path could be configured in settings by searching C_Cpp.default.includePath or in c_cpp_properties.json used for Intelli Sense or in tasks.jsonfile which is used for specific tasks.

The include path configured by C_Cpp.default.includePath in settings won't be used by tasks.json file. Instead, it's used by Intelli Sense — in the editor, when I type #include the headers files can be displayed in the auto-suggestion list.

None
fibonacci.h is from ${workspaceFolder}\\src\\include folder

Note: one tricky thing here. includePath in c_cpp_properties.json has higher priority than C_Cpp.default.includePath in settings.json. If C_Cpp.default.includePath is configured, than includePath in c_cpp_properties.json can be removed — remove the whole key/value pair rather than keep includePath with empty list. If I keep includePath with empty list in c_cpp_properties.json , then C_Cpp.default.includePath in settings.json won't be used still and compiling error will occurr in the editor.

I only need to configure ${workspaceFolder/**} as value of includePath in c_cpp_properties.jsonor C_Cpp.default.includePath in settings.json which means recursively searching header files in the whole workspace. I don't need to configure system include paths since I configured the compiler path by compilerPath in c_cpp_properties.json or C_Cpp.default.compilerPath in settings.json.

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.22621.0",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "linux-gcc-x64",
            "compilerPath": "C:\\msys64\\ucrt64\\bin\\g++.exe"
        }
    ],
    "version": 4
}

If I remove ${workspaceFolder/**} , then it will complain that the header file is not found.

None
#include errors detected

Configure tasks.json

The file tasks.json file is used to define different tasks including build and run the active file. For example, to compile and run the current file opened in the editor, I defined the task as follows:

{
  "type": "cppbuild",
  "label": "Build Active File",
  "command": "C:\\msys64\\ucrt64\\bin\\g++.exe",
  "args": [
    "-fdiagnostics-color=always",
    "-g",
    "-I${workspaceFolder}\\src\\include",
    "${file}",
    "-o",
    "${fileDirname}\\${fileBasenameNoExtension}.exe"
  ],
  "options": {
    "cwd": "C:\\msys64\\ucrt64\\bin"
  },
  "problemMatcher": [
    "$gcc"
  ],
  "group": {
    "kind": "build",
    "isDefault": true
  }
}

"cppbuild" is the task type defined by the extension C/C++. Label is use to identify the task. command, args and options are the main part to perform the task by the external command. problemMatcher is optional. To use the task as default task, set isDefault as true in the group .

📗Note: -I[PATH] should be before ${file} . To add multiple include paths, it's allowed to use multiple -I[PATH](As a newbie to C/C++, I didn't know that)

"-IC:\\msys64\\usr\\local\\include",
"-I${workspaceFolder}\\src\\include",
None
Default task to be executed by click the triangle icon

Because tasks.json is to call external process (compiler) separately from Intelli Sense, when I removed ${workspaceFolder/**} from c_cpp_properties.json , the task can run still.

Refer to the below articles for more details:

Configure CMake Tools Extension

cmake version to use

The first thing I want to emphasize is the cmake path(cmake.cmakePath).

None
Cmake Path in Settings

After installing the cmake package, the cmake.exe file located at c:\msys64\usr\bin\cmake.exe — it will fail as follows.

None

It might be caused by some bug in old version of cmake . By installing and using cmakefrom ucrt package can solve it.

> pacman -S mingw-w64-ucrt-x86_64-cmake
> C:\msys64\usr\bin\cmake.exe --version
cmake version 3.27.6
> C:\msys64\ucrt64\bin\cmake.exe --version
cmake version 3.27.7

When cmake works well, the below content should be printed in the output console of CMake/Build :

[cmake] — The C compiler identification is GNU 13.2.0 [cmake] — The CXX compiler identification is GNU 13.2.0 [cmake] — Detecting C compiler ABI info [cmake] — Detecting C compiler ABI info — done [cmake] — Check for working C compiler: C:/msys64/ucrt64/bin/cc.exe — skipped [cmake] — Detecting C compile features [cmake] — Detecting C compile features — done [cmake] — Detecting CXX compiler ABI info [cmake] — Detecting CXX compiler ABI info — done [cmake] — Check for working CXX compiler: C:/msys64/ucrt64/bin/g++.exe — skipped [cmake] — Detecting CXX compile features [cmake] — Detecting CXX compile features — done

…… [cmake] — Found Python: C:/Users/wenijinew/dj/venv_rensa/Scripts/python.exe (found version "3.11.0") found components: Interpreter [cmake] — Configuring done (24.9s) [cmake] — Generating done (1.5s) [cmake] — Build files have been written to: C:/Users/wenijinew/dj/gitlab/ecb/ecb-c/build

Refer to:

CMake Kits

CMake kits is a JSON file to configure compilers, toolchain files, and visual studio installation information. In my case, I only use it for compiler configuration.

CMake kits JSON file could be in the default path or the project's .vscode folder.

In Windows, the default path for CMake kits is %USERPROFILE%/AppData/Local/CMakeTools and the file name is cmake-tools-kits.json . The content is automatically generated by CMake Tools itself.

The default CMake kits might not work well. Then, it's a good idea to configure the user local kits file — cmake-kits.json under .vscode of the workspace folder.

In my case, I made the below configuration:

[
    {
        "name": "ECB - GCC 13.2.0 x86_64-w64-mingw32 (ucrt64)",
        "compilers": {
            "C": "C:\\msys64\\usr\\bin\\gcc.exe",
            "CXX": "C:\\msys64\\ucrt64\\bin\\g++.exe"
        },
        "isTrusted": true,
        "environmentVariables": {
            "CMT_MINGW_PATH": "C:\\msys64\\ucrt64\\bin"
        },
        "preferredGenerator": {
            "name": "Unix Makefiles"
        }
    }
]

The content is copied from the default cmake kits file and made little changes:

  • Compiler for C is changed from ucrt64 to usr . The reason is that ucrt\bin\gcc.exe caused system include files not loaded successfully which caused header files not found.
  • Add ECB - as one prefix to the name which is automatically generated by CMake Tools, to make the name more distinguishable.

Refer to:

Add make in PATH

CMake Tools relies on the underlying build tools through generators. In my case, it's make which is supported by the generator Unix Makefiles as I configured in cmake-kits.json by preferredGenerator :

"preferredGenerator": {
     "name": "Unix Makefiles"
}

To know all supported generators, run the command cmake --help and all available generators are printed at the bottom of the output.

In case make is not included in PATH , CMake build process will fail as follows:

[cmake] -- Configuring incomplete, errors occurred!
[cmake] CMake Error: CMake was unable to find a build program corresponding to "Unix Makefiles".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.

There are several ways to solve it:

  • Add the path to make to the environment variable PATH in the Windows system.
  • Add the path to make to the environment variable PATH in settings.json file: (make is under C:/msys64/usr/bin)
"cmake.environment": {
    "PATH": "C:/msys64/ucrt64/bin;C:/msys64/usr/bin"
 }
  • Set CMAKE_MAKE_PROGRAM property for CMake Tools in settings.json file
"cmake.configureSettings": {
    "CMAKE_MAKE_PROGRAM": "C:/msys64/usr/bin/make.exe"
 }

📓Note: it's good to use the first 2 solutions to configure PATH environment variable since if the directory of make is not in PATH then it still not working due to other problems. Therefore, adding "C:/msys64/usr/bin" in PATH is not only for make but also for other relevant issues.

After fixing, run CMake: Delete Cache and Reconfigure All Projects to reconfigure CMake projects.

Refer to:

CMake Tools Configuration FAQ

CMake configure is automatically triggered when save the change of CMakeLists.txt file. How to disable the automatic triggering?

It's controlled by the parameter cmake.configureOnEdit — default value is true which means "Automatically configure CMake project directories when the path in the cmake.sourceDirectory setting is updated or when CMakeLists.txt or *.cmake files are saved". To turn off it, set the value as false .

How to Change c/c++ logging level

None

Refer to

CMakeLists.txt Configuration

To understand well how CMakeLists.txt is used, it's a good idea to learn the CMake Tutorial. However, when I fixed my case, I didn't go through that tutorial. I got some help from Google and Stackoverflow posts. After that, I started learning the details of CMake and got to know how CMakeLists.txt is configured and worked.

Here is my final configuration for the CMakeList.txt to build my source files and run GoogleTest.

cmake_minimum_required (VERSION 3.5)

project (fibonacci_test VERSION 0.1.0 LANGUAGES C CXX)

include(CTest)
enable_testing()

# https://cmake.org/cmake/help/latest/policy/CMP0135.html
# To remove the warning: The DOWNLOAD_EXTRACT_TIMESTAMP option was not given and policy CMP0135 is not set
cmake_policy(SET CMP0135 NEW)

include(FetchContent)
FetchContent_Declare(
  googletest
  # Specify the commit you depend on and update it regularly.
  URL https://github.com/google/googletest/archive/5376968f6948923e2411081fd9372e71a59d8e77.zip
)

# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

include_directories(src/include)

# the below line is to fix the error: undefined reference to `testing::Test::Test()'
set_source_files_properties(src/ecb/code_generation/codeium/c/fibonacci.c PROPERTIES LANGUAGE CXX )
set_source_files_properties(src/test/unit_test_generation/codeium/fibonacci_test.cpp PROPERTIES LANGUAGE CXX )
 
# Now simply link against gtest or gtest_main as needed.
# See https://cmake.org/cmake/help/latest/command/add_library.html#object-libraries
add_library(fibonacci_objs OBJECT src/ecb/code_generation/codeium/c/fibonacci.c  src/test/unit_test_generation/codeium/fibonacci_test.cpp)     
add_executable(fibonacci_test $<TARGET_OBJECTS:fibonacci_objs>)
target_link_libraries(fibonacci_objs gtest_main)
target_link_libraries(fibonacci_test gtest_main)

# test
add_test(NAME fibonacci_test COMMAND fibonacci_test.exe)

CMakeLists.txt consists of commands such as cmake_minimum_required. Each command handles one small task. The command is to run CMake code from a file or module(e.g. CTest). Some command is implicitly called by another command internally. For example, cmake_minimum_required implicitly calls cmake_policy(VERSION) and include(CTest) implicitly calls enable_testing() . Therefore, enable_testing in my CMakeLists.txt is redundant.

The module FetchContent is very important to use Google Test as test framework. (Refer to FetchContent) The command FetchContent_Declare is to tell where and how to populate the dependencies. The command FetchContent_MakeAvailable is to make the dependencies available and the libraries (e.g. gtest_main) defined in the dependencies are ready to use in the targets of the project under building. (Refer to googletest Build with CMake)

Note: without the CMake module FetchContent , developers need to build and configure googletest by themselves. It's not an easy job, especially for a newbie.

The command include_directories is to include the relative directories in the build process. Those directories should be relative to the directory where the CMakeLists.txt file is located.

The command set_source_files_properties is used to tell the build tool the properties of the source files. E.g. which LANGUAGE should be used to compile the source files.

In my case, I need to link the libraries compiled from c source file with gtest_main library and executable file compiled from cpp source file which is unit test cases. Therefore, I need to use CXX as LANGUAGE property for the c source file. Otherwise, the function defined in c source file is not visible for unit test cases cpp file and result in error like error:undefined reference to `testing::Test::Test()'.

None
Built and Link Relationship

To build the executable fibonacci_test , it needs both the source file fibonacci.c and the test source file fibonacci_test.cpp . That's why built the library fibonacci_objs first. The test source file depends on googletest library, so the library fibonacci_objs needs to link to gtest_main . Otherwise, the compiling of fibonacci_test.cpp will fail due to not found the header file gtest/gtest.h.

[build] C:/Users/wenijinew/dj/gitlab/ecb/ecb-c/src/test/unit_test_generation/codeium/fibonacci_test.cpp:1:10: fatal error: gtest/gtest.h: No such file or directory
[build]     1 | #include <gtest/gtest.h>
[build]       |          ^~~~~~~~~~~~~~~
[build] compilation terminated.
[build] make[2]: *** [CMakeFiles/fibonacci_objs.dir/build.make:92: CMakeFiles/fibonacci_objs.dir/src/test/unit_test_generation/codeium/fibonacci_test.cpp.obj] Error 1

However, even the fibonacci_objs already linked to gtest_main , it's still required to link fibonacci_test executable to gtest_main . Otherwise, it will fail in the linking phase (ld) — undefined reference to `testing::Message::Message()'.

[build]
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
CMakeFiles/fibonacci_test.dir/objects.a(fibonacci_test.cpp.obj):
in function
`FibonacciTest_TestFibonacci1_Test::TestBody()': 
[build]
C:/Users/wenijinew/dj/gitlab/ecb/ecb-c/src/test/unit_test_generation/codeium/fibonacci_test.cpp:21:(.text+0x80):
undefined reference to
`testing::Message::Message()' 
[build]
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
C:/Users/wenijinew/dj/gitlab/ecb/ecb-c/src/test/unit_test_generation/codeium/fibonacci_test.cpp:21:(.text+0xb1):
undefined reference to
`testing::internal::AssertHelper::AssertHelper(testing::TestPartResult::Type,
char const*, int, char const*)'

Finally, the command add_test generate tests(./build/CTestTestfile.cmake) to call the executable fibonacci_test file( ./build/fibonacci_test.exe).

In the editor, open CMakeLists.txt, click the icon at the line of add_test to build and run the test.

None
Test Icon on the line of add_test
[proc] Executing command: C:\msys64\ucrt64\bin\ctest.exe -j10 -C Debug -T test --output-on-failure -R ^fibonacci_test$
[ctest]    Site: XXXXXXX
[ctest]    Build name: Win32-make
[ctest] Test project C:/Users/wenijinew/dj/gitlab/ecb/ecb-c/build
[ctest]     Start 1: fibonacci_test
[ctest] 1/1 Test #1: fibonacci_test ...................   Passed    0.14 sec
[ctest] 
[ctest] 100% tests passed, 0 tests failed out of 1
[ctest] 
[ctest] Total Test time (real) =   0.16 sec
[ctest] CTest finished with return code 0

CTest is also visible in the Testing view and the test can be run by hovering and clicking the Run Test button.

None
Hover on test case and click Run Test button to build and run CTest

It's the time to celebrate and take a rest.

None
Photo by Robson Hatsukami Morgan on Unsplash

Refer to:

Failures & Solutions

0. CMake Error: Could not create named generator MinGW Makefiles

[cmake] Not searching for unused variables given on the command line.
[cmake] CMake Error: Could not create named generator MinGW Makefiles

The command mingw32-make needs to be available. I didn't make it workable because even ming32-make is available by setting the PATH environment variable, I cannot see MinGW Makefiles in the output of cmake --help . I don't know why.

1. error:undefined reference to `testing::Test::Test()'

😇 The formal solution is to use the Cmake command to tell the compiler to compile the C file as C++ file.

set_source_files_properties(src/ecb/code_generation/codeium/c/fibonacci.c PROPERTIES LANGUAGE CXX )

😢Without CMake, then need to handle it in a special way as explained below.

Refer to

Clone googletest, build and install. Refer to Build with CMake.

Note: the below commands are executed in the MSYS2 MINGW64 shell session.

> cd googletest && mkdir build && cd build
> cmake ..
-- The C compiler identification is GNU 13.2.0
-- The CXX compiler identification is GNU 13.2.0
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19045 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19045 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /mingw64/bin/cc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19045 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /mingw64/bin/CC.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Python3: /home/wenijinew/ws/venv_v3.11.6/bin/python3.11.exe (found version "3.11.6") found components: Interpreter
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
System is unknown to cmake, create:
Platform/MINGW64_NT-10.0-19045 to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done (49.4s)
-- Generating done (0.2s)
-- Build files have been written to: /home/wenijinew/ws/github/googletest/build
> make
[ 12%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj
[ 25%] Linking CXX static library ../lib/libgtest.a
[ 25%] Built target gtest
[ 37%] Building CXX object googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.obj
[ 50%] Linking CXX static library ../lib/libgmock.a
[ 50%] Built target gmock
[ 62%] Building CXX object googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.obj
[ 75%] Linking CXX static library ../lib/libgmock_main.a
[ 75%] Built target gmock_main
[ 87%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.obj
[100%] Linking CXX static library ../lib/libgtest_main.a
[100%] Built target gtest_main
> make install
googletest/CMakeFiles/gtest.dir/compiler_depend.make:4: *** multiple target patterns.  Stop.
make[1]: *** [CMakeFiles/Makefile2:172: googletest/CMakeFiles/gtest.dir/all] Error 2
make: *** [Makefile:146: all] Error 2

Replace googletest/C:/ with /c/ will solve the failure in "make install"

googletest/CMakeFiles/gtest_main.dir/compiler_depend.make:4: *** multiple target patterns.  Stop.
make[1]: *** [CMakeFiles/Makefile2:198: googletest/CMakeFiles/gtest_main.dir/all] Error 2
make: *** [Makefile:146: all] Error 2

update all the files named as compiler_depend.make in the same way, then "make install" will succeed.

None

After installation, make changes in vs code c/c++ extension

None

Then, in the vs code editor, the compiling error disappeared

None

The test case can be built and run through the tasks defined in tasks.json as follows:

  • build source file(.c) and test case file(.cpp)
  • build executable file(.exe)
  • run the executable file(.exe)
{
  "tasks": [
    {
      "type": "cppbuild",
      "label": "1. Google Test - Build C++ File",
      "command": "C:\\msys64\\mingw64\\bin\\g++.exe",
      "args": [
        "-IC:\\msys64\\usr\\local\\include",
        "-I${workspaceFolder}\\ecb-c\\src\\include",
        "-L${workspaceFolder}\\ecb-c\\build",
        "-lfibonacci",
        "${file}",
        "-o",
        "${workspaceFolder}\\ecb-c\\build\\${fileBasenameNoExtension}.o",
        "-c"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": [
        "$gcc"
      ],
      "group": {
        "kind": "build",
        "isDefault": false
      },
      "detail": "To build both source file (.c) and test file(.cpp)."
    },
    {
      "type": "cppbuild",
      "label": "2. Google Test Build C++ Execution File",
      "command": "C:\\msys64\\mingw64\\bin\\g++.exe",
      "args": [
        "-std=c++17",
        "-fdiagnostics-color=always",
        "-g",
        "-IC:\\msys64\\usr\\local\\include",
        "-I${workspaceFolder}\\ecb-c\\src\\include",
        "${workspaceFolder}\\ecb-c\\build\\fibonacci.o",
        "${workspaceFolder}\\ecb-c\\build\\fibonacci_test.o",
        "-LC:\\msys64\\mingw64\\lib",
        "-L${workspaceFolder}\\ecb-c\\build",
        "-lgtest",
        "-lgtest_main",
        "-lpthread",
        "-o",
        "${workspaceFolder}\\ecb-c\\build\\${fileBasenameNoExtension}.exe"
      ],
      "options": {
        "cwd": "${fileDirname}"
      },
      "problemMatcher": [
        "$gcc"
      ],
      "group": {
        "kind": "build",
        "isDefault": false
      },
      "detail": "To build the executable file."
    },
    {
      "label": "3. Run Google Test by the built executable file.",
      "type": "shell",
      "command": "${workspaceFolder}\\ecb-c\\build\\${fileBasenameNoExtension}.exe",
    }
  ],
  "version": "2.0.0"
}

⚠️Do remember to add C:\\msys64\\mingw64 to PATH environment variable before starting VsCode. Otherwise, the task will fail and return -1 which is a tricky issue. The reason might be the other files under C:\\msys64\\mingw64 are needed for g++ .

If everything works well, then the tasks will run successfully.

*  Executing task: 1. Google Test - Build C++ File 

Starting build...
C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\fibonacci.c -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o -c

Build finished successfully.
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: 1. Google Test - Build C++ File 

Starting build...
C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\test\unit_test_generation\codeium\fibonacci_test.cpp -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -c

Build finished successfully.
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task: 2. Google Test Build C++ Execution File 

Starting build...
C:\msys64\mingw64\bin\g++.exe -std=c++17 -fdiagnostics-color=always -g -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -LC:\msys64\mingw64\lib -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lgtest -lgtest_main -lpthread -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe

Build finished successfully.
 *  Terminal will be reused by tasks, press any key to close it. 

 *  Executing task in folder ecb: C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe 

[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from FibonacciTest
[ RUN      ] FibonacciTest.TestFibonacci1
[       OK ] FibonacciTest.TestFibonacci1 (0 ms)
[ RUN      ] FibonacciTest.TestFibonacci2
[       OK ] FibonacciTest.TestFibonacci2 (0 ms)
[----------] 2 tests from FibonacciTest (9 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (28 ms total)
[  PASSED  ] 2 tests.
 *  Terminal will be reused by tasks, press any key to close it.

To be simple, the commands can be put in one script file and then run that script file by one task. However, the variables supported by vscode cannot be used in the script file anymore — they have to be hardcoded.

Put the commands in run_google_test.cmd

C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\fibonacci.c -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o -c

C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\test\unit_test_generation\codeium\fibonacci_test.cpp -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -c

C:\msys64\mingw64\bin\g++.exe -std=c++17 -fdiagnostics-color=always -g -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -LC:\msys64\mingw64\lib -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lgtest -lgtest_main -lpthread -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe

C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe

And configure the task to run the script file

    {
      "label": "4. Run Google Test by the script file.",
      "type": "shell",
      "command": "${workspaceFolder}\\ecb-c\\src\\resources\\run_google_test.cmd",
      "windows": {
        "command": "${workspaceFolder}\\ecb-c\\src\\resources\\run_google_test.cmd"
      },
      "group": "test",
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    }

The output:

 *  Executing task in folder ecb: C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\resources\run_google_test.cmd 


C:\Users\wenijinew\dj>C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\fibonacci.c -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o -c

C:\Users\wenijinew\dj>C:\msys64\mingw64\bin\g++.exe -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lfibonacci C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\test\unit_test_generation\codeium\fibonacci_test.cpp -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -c

C:\Users\wenijinew\dj>C:\msys64\mingw64\bin\g++.exe -std=c++17 -fdiagnostics-color=always -g -IC:\msys64\usr\local\include -IC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\include C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci.o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.o -LC:\msys64\mingw64\lib -LC:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build -lgtest -lgtest_main -lpthread -o C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe

C:\Users\wenijinew\dj>C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\build\fibonacci_test.exe
[==========] Running 2 tests from 1 test suite. 
[----------] Global test environment set-up.    
[----------] 2 tests from FibonacciTest
[ RUN      ] FibonacciTest.TestFibonacci1       
[       OK ] FibonacciTest.TestFibonacci1 (0 ms)
[ RUN      ] FibonacciTest.TestFibonacci2       
[       OK ] FibonacciTest.TestFibonacci2 (0 ms)
[----------] 2 tests from FibonacciTest (7 ms total)     

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (15 ms total)
[  PASSED  ] 2 tests.
 *  Press any key to close the terminal. 

At this moment, it's worth celebrating. Woho 😄

None
Photo by Windows on Unsplash

2. The task type "cppbuild" is not recognized in tasks.json

Error: there is no registered task type 'cppbuild'. Did you miss installing an extension that provides a corresponding task provider?
None
"cppbuild" is not accepted

The reason is that C/C++ extension(ms-vscode.cpptools) is not installed or enabled. Therefore, to fix it, check your C/C++ extension and make sure it's installed and enabled.

3. Cannot open source file "stdlib.h"

This is caused by the missed include path in C_Cpp > Default: System Include Path(C_Cpp.default.systemIncludePath) in Settings or configurations -> includePath in the c_cpp_properties.json file.

Settings

"C_Cpp.default.systemIncludePath": [
    "${workspaceFolder}/**",
    "C:/msys64/usr/local/include/**",
    "C:/msys64/ucrt64/include/**",
    "C:/msys64/ucrt64/lib/**"
],

c_cpp_properties.json file

"includePath": [
    "${workspaceFolder}/**",
    "C:/msys64/usr/local/include/**",
    "C:/msys64/ucrt64/include/**",
    "C:/msys64/ucrt64/lib/**"
 ]

📓 It seems that the "C_Cpp.default.systemIncludePath" in Settings and "includePath" in c_cpp_properties.json file are finally merged because the below configuration also works.

Settings

"C_Cpp.default.systemIncludePath": [
    "C:/msys64/ucrt64/include/**",
    "C:/msys64/ucrt64/lib/**"
],

c_cpp_properties.json file

"includePath": [
    "${workspaceFolder}/**",
    "C:/msys64/usr/local/include/**"
 ]

Normally, there is no this kind of error about system include path as long as the compiler path works well. When it occurred, the property C_Cpp.default.systemIncludePath can be used to fix the system include paths.

4. [cpptools] The build configurations generated do not contain the active build configuration. Using "" for CMAKE_BUILD_TYPE instead of "Debug" to ensure that IntelliSense configurations can be found

❓ how to make change for CMAKE_BUILD_TYPE

In settings.json file:

"cmake.configureSettings": {
    "CMAKE_BUILD_TYPE": ""
  }

5. command-line error: language modes specified are incompatible C/C++(1027)

Refer to https://github.com/microsoft/vscode-cpptools/issues/9684 which has many discussions on this topic.

None
None
  • How this error message is printed? Where is it from?

The compilation args sent to the compiler might be incorrect. The error message might be from the compiler - g++.

  • What caused this error message?

When "ms-vccode.cmake-tools", the intelliSenseMode is automatically changed to "windows-gcc-x64" and--g++ appeared in other:.Not sure if that's the root cause but one observation. (there are other different compilation args which are mentioned in my comment on github.)

Without "configurationProvider": "ms-vscode.cmake-tools"

  other: --gcc
  other: --gnu_version=130200
  stdver: c17
  intelliSenseMode: linux-gcc-x64

With "configurationProvider": "ms-vscode.cmake-tools"

  other: --g++
  other: --gnu_version=130200
  stdver: c17
  intelliSenseMode: windows-gcc-x64
  • How to fix the issue of this error message?

Solution: Create CMakeLists.txt file to build the problematic source files.

cmake_minimum_required (VERSION 3.5)

project (open_browser)
add_executable(open_browser open_browser.c)

If this CMakeLists.txt is in a subfolder (e.g. browser), then it could be called in the CMakeLists.txt which is located in the upper level.

add_subdirectory(browser)

📓Workaround: Remove the below line from c_cpp_properties.json file:

"configurationProvider": "ms-vscode.cmake-tools"
cpptools version (native): 1.18.3.0
Translation Unit Mappings:
[ C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\open_browser.c ]:
    C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\open_browser.c
Translation Unit Configurations:
[ C:\Users\wenijinew\dj\gitlab\ecb\ecb-c\src\ecb\code_generation\codeium\c\open_browser.c ]:
    Process ID: 25172
    Memory Usage: 40 MB
    Compiler Path: C:\msys64\ucrt64\bin\g++.exe
    Includes:
        C:\msys64\ucrt64\include\c++\13.2.0
        C:\msys64\ucrt64\include\c++\13.2.0\x86_64-w64-mingw32
        C:\msys64\ucrt64\include\c++\13.2.0\backward
        C:\msys64\ucrt64\lib\gcc\x86_64-w64-mingw32\13.2.0\include
        C:\msys64\ucrt64\include
        C:\msys64\ucrt64\lib\gcc\x86_64-w64-mingw32\13.2.0\include-fixed
    Standard Version: c17
    IntelliSense Mode: windows-gcc-x64
    Other Flags:
        --g++
        --gnu_version=130200

Over the past few weeks, I spent a lot of time learning CMake, CMake Tools, VsCode C/C++ extension configuration, and googletest. I learnt a lot and I know there is much more to learn.

Now, at least, I feel I am a C/C++ developer.

I think, for developers, the development environment is like shoes. If a person wears a pair of comfortable shoes, he can run fast and far.

I'm ready to embark on my C/C++ journey. And you?

References

None