Skip to content

Commit 88bbfc0

Browse files
committed
Set CC and CXX environment variables for clang toolchain
Sets the C (CC) and C++ (CXX) compiler environment variables so the choice of toolchain selected in the Build Settings tab is respected. Toolchains supported are GNU GCC and Clang. Added JUnit tests for GCCToolChain and ClangToolChain. Added test document describing manual test steps. Fixes #1140
1 parent 2c82545 commit 88bbfc0

File tree

6 files changed

+735
-4
lines changed

6 files changed

+735
-4
lines changed

build/org.eclipse.cdt.build.gcc.core.tests/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ Require-Bundle: org.eclipse.core.resources,
99
org.junit,
1010
org.eclipse.jdt.junit4.runtime,
1111
org.eclipse.core.runtime,
12-
org.eclipse.cdt.build.gcc.core
12+
org.eclipse.cdt.build.gcc.core,
13+
junit-jupiter-api
1314
Automatic-Module-Name: org.eclipse.cdt.build.gcc.core.tests
1415
Bundle-RequiredExecutionEnvironment: JavaSE-17
1516
Bundle-ActivationPolicy: lazy
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
## Overview
2+
3+
This document captures the manual tests that should be completed for Core Build toolchains.
4+
5+
Added:
6+
7+
20250617 John Moule
8+
Set CC and CXX environment variables for clang toolchain #1169
9+
https://github.com/eclipse-cdt/cdt/pull/1169
10+
11+
## Tests
12+
The manual test cases below are useful to show the expected toolchain is used for a build.
13+
14+
The following JUnits are also added:
15+
- org.eclipse.cdt.build.gcc.core.tests.TestGCCToolChain
16+
- org.eclipse.cdt.build.gcc.core.tests.TestClangToolChain
17+
18+
## Test Case Summary
19+
- A) Clang toolchain can be used to build when selected in Build Settings > Toolchain.
20+
- B) GCC toolchain can be used to build when selected in Build Settings > Toolchain.
21+
- C) Clang toolchain can be used to build when CC/CXX defined externally to gcc/g++
22+
- D) GCC toolchain can be used to build when CC/CXX defined externally to clang/clang++
23+
24+
Tests should be performed on Linux & Windows.
25+
26+
### Prerequisites
27+
Make sure cmake, make, ninja, GCC and clang toolchains are installed on the host - see [1].
28+
CC/CXX are not defined in the system environment, unless specified in the test.
29+
30+
31+
## Test case A) Clang toolchain can be used to build when selected in Build Settings > Toolchain.
32+
- Create a CMake Hello World project
33+
- From the Launch Bar, open the Launch Configuration (gear icon)
34+
- Select Build Settings tab and in the Toolchain dropdown, change to clang toolchain and click OK.
35+
- From the Launch Bar, build the project.
36+
37+
Expected: The project builds successfully and in the Console build output, it can be seen that the C and CXX compiler are identified as "Clang".
38+
39+
Actual: The following shows an example of Console build output:
40+
41+
42+
Configuring in: C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
43+
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw
44+
-- The C compiler identification is Clang 19.1.7
45+
-- The CXX compiler identification is Clang 19.1.7
46+
-- Detecting C compiler ABI info
47+
-- Detecting C compiler ABI info - done
48+
-- Check for working C compiler: C:/msys64/ucrt64/bin/clang.exe - skipped
49+
-- Detecting C compile features
50+
-- Detecting C compile features - done
51+
-- Detecting CXX compiler ABI info
52+
-- Detecting CXX compiler ABI info - done
53+
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/clang++.exe - skipped
54+
-- Detecting CXX compile features
55+
-- Detecting CXX compile features - done
56+
-- Configuring done (3.1s)
57+
-- Generating done (0.1s)
58+
-- Build files have been written to: C:/Users/a5107948/cdt-main20250110b/runtime-cdtruntime_clean/cmake_hw/build/cmake.debug.win32.x86_64.Local
59+
Building in: C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
60+
cmake --build . --target all
61+
[1/2] Building CXX object CMakeFiles/cmake_hw.dir/cmake_hw.cpp.obj
62+
[2/2] Linking CXX executable cmake_hw.exe
63+
Build complete (0 errors, 0 warnings): C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
64+
65+
66+
## Test case B) GCC toolchain can be used to build when selected in Build Settings > Toolchain.
67+
- From the Launch Bar, open the Launch Configuration (gear icon)
68+
- Select Build Settings tab and in the Toolchain dropdown, change to gcc toolchain and click OK.
69+
- Delete the project's build folder.
70+
- From the Launch Bar, build the project.
71+
72+
Expected: The project builds successfully and in the Console build output, it can be seen that the C and CXX compiler are identified as "gnu".
73+
74+
Actual: The following shows an example of Console build output:
75+
76+
Configuring in: C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
77+
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw
78+
-- The C compiler identification is GNU 14.2.0
79+
-- The CXX compiler identification is GNU 14.2.0
80+
-- Detecting C compiler ABI info
81+
-- Detecting C compiler ABI info - done
82+
-- Check for working C compiler: C:/msys64/ucrt64/bin/gcc.exe - skipped
83+
-- Detecting C compile features
84+
-- Detecting C compile features - done
85+
-- Detecting CXX compiler ABI info
86+
-- Detecting CXX compiler ABI info - done
87+
-- Check for working CXX compiler: C:/msys64/ucrt64/bin/g++.exe - skipped
88+
-- Detecting CXX compile features
89+
-- Detecting CXX compile features - done
90+
-- Configuring done (3.4s)
91+
-- Generating done (0.1s)
92+
-- Build files have been written to: C:/Users/a5107948/cdt-main20250110b/runtime-cdtruntime_clean/cmake_hw/build/cmake.debug.win32.x86_64.Local
93+
Building in: C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
94+
cmake --build . --target all
95+
[1/2] Building CXX object CMakeFiles/cmake_hw.dir/cmake_hw.cpp.obj
96+
[2/2] Linking CXX executable cmake_hw.exe
97+
Build complete (0 errors, 0 warnings): C:\Users\a5107948\cdt-main20250110b\runtime-cdtruntime_clean\cmake_hw\build\cmake.debug.win32.x86_64.Local
98+
99+
100+
101+
## Test case C) Clang toolchain can be used to build when CC/CXX defined externally to gcc/g++
102+
- Exit Eclipse and in a command shell, define the environment variables CC and CXX, for example on Windows:
103+
- - set CC=gcc
104+
- - set CXX=g++
105+
- Launch Eclipse from this command shell, so it inherits the environment.
106+
- From the Launch Bar, open the Launch Configuration (gear icon)
107+
- Select Build Settings tab and in the Toolchain dropdown, change to clang toolchain and click OK.
108+
- From the Launch Bar, build the project.
109+
110+
Expected: The project builds successfully and in the Console build output, it can be seen that the C and CXX compiler are identified as "Clang".
111+
112+
Actual: same output as Test case A).
113+
114+
## Test case D) GCC toolchain can be used to build when CC/CXX defined externally to clang/clang++
115+
- Exit Eclipse and in a command shell, define the environment variables CC and CXX, for example on Windows:
116+
- - set CC=clang
117+
- - set CXX=clang++
118+
- Launch Eclipse from this command shell, so it inherits the environment.
119+
- From the Launch Bar, open the Launch Configuration (gear icon)
120+
- Select Build Settings tab and in the Toolchain dropdown, change to gcc toolchain and click OK.
121+
- From the Launch Bar, build the project.
122+
123+
Expected: The project builds successfully and in the Console build output, it can be seen that the C and CXX compiler are identified as "gnu".
124+
125+
Actual: same output as Test case B).
126+
127+
----
128+
[1]: Before you begin
129+
C/C++ Development User Guide > Before you begin
130+
https://github.com/eclipse-cdt/cdt/blob/abe4d1b8e16b03ceafbeb25f063cb728c7487862/doc/org.eclipse.cdt.doc.user/concepts/cdt_c_before_you_begin.htm
131+
132+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Renesas Electronics Europe.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package org.eclipse.cdt.build.gcc.core.tests;
12+
13+
import static org.hamcrest.MatcherAssert.assertThat;
14+
import static org.hamcrest.Matchers.contains;
15+
import static org.hamcrest.Matchers.hasItem;
16+
import static org.hamcrest.Matchers.hasItems;
17+
import static org.hamcrest.Matchers.is;
18+
import static org.hamcrest.Matchers.not;
19+
import static org.hamcrest.Matchers.nullValue;
20+
21+
import java.nio.file.Paths;
22+
import java.util.Arrays;
23+
24+
import org.eclipse.cdt.build.gcc.core.ClangToolChain;
25+
import org.eclipse.cdt.core.build.IToolChain;
26+
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
27+
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
28+
import org.eclipse.core.runtime.Platform;
29+
import org.junit.Test;
30+
31+
/**
32+
* Tests for org.eclipse.cdt.build.gcc.core.ClangToolChain
33+
* Tests that the environment variables CC and CXX are set correctly.
34+
*/
35+
public class TestClangToolChain {
36+
37+
/**
38+
* Tests:
39+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
40+
* Where pathToToolChain=a/clang.exe
41+
* Where envVars is null.
42+
*
43+
* Expected:
44+
* IToolChain.getVariables() has items "CC=a/clang.exe", "CXX=a/clang++.exe"
45+
*/
46+
@Test
47+
public void clangExe() throws Exception {
48+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang.exe"), null, null);
49+
IEnvironmentVariable[] variables = tc.getVariables();
50+
assertThat(Arrays.asList(variables), hasItems( //
51+
new EnvironmentVariable("CC", "a/clang.exe"), //
52+
new EnvironmentVariable("CXX", "a/clang++.exe")));
53+
}
54+
55+
/**
56+
* Tests:
57+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
58+
* Where pathToToolChain=null
59+
* Where envVars is null.
60+
*
61+
* Expected:
62+
* IToolChain.getVariables() is null
63+
*/
64+
@Test
65+
public void nullPathToToolChain() throws Exception {
66+
IToolChain tc = new ClangToolChain(null, (java.nio.file.Path) null, null, null);
67+
IEnvironmentVariable[] variables = tc.getVariables();
68+
assertThat(variables, is(nullValue()));
69+
}
70+
71+
/**
72+
* Tests:
73+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
74+
* Where pathToToolChain=a/clang++.exe
75+
* Where envVars is null.
76+
*
77+
* Expected:
78+
* IToolChain.getVariables() has items "CC=a/clang.exe", "CXX=a/clang++.exe"
79+
*/
80+
@Test
81+
public void clangPlusPlusExe() throws Exception {
82+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang++.exe"), null, null);
83+
IEnvironmentVariable[] variables = tc.getVariables();
84+
assertThat(Arrays.asList(variables), hasItems( //
85+
new EnvironmentVariable("CC", "a/clang.exe"), //
86+
new EnvironmentVariable("CXX", "a/clang++.exe")));
87+
}
88+
89+
/**
90+
* Tests:
91+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
92+
* Where pathToToolChain=a/clang (no extension)
93+
* Where envVars is null.
94+
*
95+
* Expected:
96+
* IToolChain.getVariables() has items "CC=a/clang", "CXX=a/clang++"
97+
*/
98+
@Test
99+
public void clangNoExt() throws Exception {
100+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang"), null, null);
101+
IEnvironmentVariable[] variables = tc.getVariables();
102+
assertThat(Arrays.asList(variables), hasItems( //
103+
new EnvironmentVariable("CC", "a/clang"), //
104+
new EnvironmentVariable("CXX", "a/clang++")));
105+
}
106+
107+
/**
108+
* Tests:
109+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
110+
* Where pathToToolChain=a/clang++ (no extension)
111+
* Where envVars is null.
112+
*
113+
* Expected:
114+
* IToolChain.getVariables() has items "CC=a/clang", "CXX=a/clang++"
115+
*/
116+
@Test
117+
public void clangPlusPlusNoExt() throws Exception {
118+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang++"), null, null);
119+
IEnvironmentVariable[] variables = tc.getVariables();
120+
assertThat(Arrays.asList(variables), hasItems( //
121+
new EnvironmentVariable("CC", "a/clang"), //
122+
new EnvironmentVariable("CXX", "a/clang++")));
123+
}
124+
125+
/**
126+
* Tests:
127+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
128+
* Where pathToToolChain=a/c++.exe
129+
* Where envVars is null.
130+
*
131+
* Expected:
132+
* No compiler overrides added.
133+
* IToolChain.getVariables() has only the PATH item.
134+
*/
135+
@Test
136+
public void cPlusPlusExe() throws Exception {
137+
IToolChain tc = new ClangToolChain(null, Paths.get("a/c++.exe"), null, null);
138+
IEnvironmentVariable[] variables = tc.getVariables();
139+
assertThat(Arrays.asList(variables),
140+
contains(new EnvironmentVariable("PATH", "a", IEnvironmentVariable.ENVVAR_PREPEND, null)));
141+
}
142+
143+
/**
144+
* Tests:
145+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
146+
* Where pathToToolChain=a/clang.exe
147+
* Where envVars has items "CC=CCtestvalue".
148+
*
149+
* Expected:
150+
* IToolChain.getVariables() has items "CC=CCtestvalue", "CXX=a/clang++.exe"
151+
*/
152+
@Test
153+
public void clangExeCCExists() throws Exception {
154+
IEnvironmentVariable[] envVars = { new EnvironmentVariable("CC", "CCtestvalue") };
155+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang.exe"), null, envVars);
156+
IEnvironmentVariable[] variables = tc.getVariables();
157+
assertThat(Arrays.asList(variables), hasItems( //
158+
new EnvironmentVariable("CC", "CCtestvalue"), //
159+
new EnvironmentVariable("CXX", "a/clang++.exe")));
160+
}
161+
162+
/**
163+
* Tests:
164+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
165+
* Where pathToToolChain=a/clang++.exe
166+
* Where envVars has items "CC=CCtestvalue", "CXX=CXXtestvalue".
167+
*
168+
* Expected:
169+
* IToolChain.getVariables() has items "CC=CCtestvalue", "CXX=CXXtestvalue"
170+
*/
171+
@Test
172+
public void clangPPExeCCCXXExists() throws Exception {
173+
IEnvironmentVariable[] envVars = { new EnvironmentVariable("CC", "CCtestvalue"),
174+
new EnvironmentVariable("CXX", "CXXtestvalue") };
175+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang++.exe"), null, envVars);
176+
IEnvironmentVariable[] variables = tc.getVariables();
177+
assertThat(Arrays.asList(variables), hasItems( //
178+
new EnvironmentVariable("CC", "CCtestvalue"), //
179+
new EnvironmentVariable("CXX", "CXXtestvalue")));
180+
}
181+
182+
/**
183+
* Tests:
184+
* ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch, IEnvironmentVariable[] envVars)
185+
* Where pathToToolChain=a/clang
186+
* Where envVars has items "cc=cctestvalue" (lowercase cc).
187+
*
188+
* Expected:
189+
* envVars has items "CC=CCtestvalue", "CXX=a/clang++.exe"
190+
* (Windows): IToolChain.getVariables() has items "cc=cctestvalue", "CXX=clang++"
191+
* (non-Windows): IToolChain.getVariables() has items "cc=cctestvalue", "CC=clang", "CXX=clang++"
192+
*/
193+
@Test
194+
public void clangccExists() throws Exception {
195+
IEnvironmentVariable[] envVars = { new EnvironmentVariable("cc", "cctestvalue") };
196+
IToolChain tc = new ClangToolChain(null, Paths.get("a/clang"), null, envVars);
197+
IEnvironmentVariable[] variables = tc.getVariables();
198+
if (Platform.OS_WIN32.equals(Platform.getOS())) {
199+
/*
200+
* Windows: case-insensitive environment; cc is treated the same to CC; CC is not added.
201+
*/
202+
assertThat(Arrays.asList(variables), not(hasItem(new EnvironmentVariable("CC", "cctestvalue"))));
203+
assertThat(Arrays.asList(variables), hasItems( //
204+
new EnvironmentVariable("cc", "cctestvalue"), //
205+
new EnvironmentVariable("CXX", "a/clang++")));
206+
// the clang override value not applied because the envVar already existed.
207+
assertThat(Arrays.asList(variables), not(hasItem(new EnvironmentVariable("CC", "a/clang"))));
208+
} else {
209+
/*
210+
* Non-Windows: case-sensitive environment; cc is treated differently to CC; CC is added in addition to any cc.
211+
*/
212+
assertThat(Arrays.asList(variables), hasItems(//
213+
new EnvironmentVariable("cc", "cctestvalue"), //
214+
new EnvironmentVariable("CC", "a/clang"), //
215+
new EnvironmentVariable("CXX", "a/clang++")));
216+
}
217+
}
218+
}

0 commit comments

Comments
 (0)