mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Merge 680f66243b
into b4d81a130e
This commit is contained in:
commit
5ae490a1ee
2 changed files with 198 additions and 2 deletions
|
@ -0,0 +1,116 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2025 Renesas Electronics Europe.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.build.gcc.core.tests;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.build.gcc.core.ClangToolChain;
|
||||||
|
import org.eclipse.cdt.core.build.IToolChain;
|
||||||
|
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
||||||
|
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for org.eclipse.cdt.build.gcc.core.ClangToolChain
|
||||||
|
* Tests that the environment variables CC and CXX are set to clang values.
|
||||||
|
*/
|
||||||
|
public class TestClangToolChain {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ClangToolChain.ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
||||||
|
IEnvironmentVariable[] envVars).
|
||||||
|
* Where envVars is null.
|
||||||
|
* Expected:
|
||||||
|
* envVars contains "CC=clang", "CXX=clang++"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void clangContainsEnvVarsNull() throws Exception {
|
||||||
|
IToolChain tc = new ClangToolChain(null, null, null, null);
|
||||||
|
IEnvironmentVariable[] variables = tc.getVariables();
|
||||||
|
assertThat(Arrays.asList(variables), contains(//
|
||||||
|
new EnvironmentVariable("CC", "clang"), //
|
||||||
|
new EnvironmentVariable("CXX", "clang++")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ClangToolChain.ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
||||||
|
IEnvironmentVariable[] envVars).
|
||||||
|
* Where envVars is empty.
|
||||||
|
* Expected:
|
||||||
|
* envVars contains "CC=clang", "CXX=clang++"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void clangContainsEnvVarsEmpty() throws Exception {
|
||||||
|
IEnvironmentVariable[] envVars = {};
|
||||||
|
IToolChain tc = new ClangToolChain(null, null, null, envVars);
|
||||||
|
IEnvironmentVariable[] variables = tc.getVariables();
|
||||||
|
assertThat(Arrays.asList(variables), contains(//
|
||||||
|
new EnvironmentVariable("CC", "clang"), //
|
||||||
|
new EnvironmentVariable("CXX", "clang++")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ClangToolChain.ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
||||||
|
IEnvironmentVariable[] envVars).
|
||||||
|
* Where envVars contains "cc=testvalue"
|
||||||
|
* Expected:
|
||||||
|
* (Windows): envVars contains "CC=testvalue", "CXX=clang++"
|
||||||
|
* (non-Windows): envVars contains "cc=testvalue", "CC=clang", "CXX=clang++"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void clangContainscc() throws Exception {
|
||||||
|
IEnvironmentVariable[] envVars = { new EnvironmentVariable("cc", "testvalue") };
|
||||||
|
IToolChain tc = new ClangToolChain(null, null, null, envVars);
|
||||||
|
IEnvironmentVariable[] variables = tc.getVariables();
|
||||||
|
|
||||||
|
if (Platform.OS_WIN32.equals(Platform.getOS())) {
|
||||||
|
/*
|
||||||
|
* Windows: case-insensitive environment; cc is replaced with uppercase CC. value remains unchanged.
|
||||||
|
*/
|
||||||
|
assertThat(Arrays.asList(variables), not(hasItem(new EnvironmentVariable("cc", "testvalue"))));
|
||||||
|
assertThat(Arrays.asList(variables),
|
||||||
|
contains(new EnvironmentVariable("CC", "testvalue"), new EnvironmentVariable("CXX", "clang++")));
|
||||||
|
// the clang override value not applied because the envVar already existed.
|
||||||
|
assertThat(Arrays.asList(variables), not(hasItem(new EnvironmentVariable("CC", "clang"))));
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Non-Windows: case-sensitive environment; cc is not replaced with uppercase CC. CC is added in addition to any cc.
|
||||||
|
*/
|
||||||
|
assertThat(Arrays.asList(variables), contains(//
|
||||||
|
new EnvironmentVariable("cc", "testvalue"), //
|
||||||
|
new EnvironmentVariable("CC", "clang"), //
|
||||||
|
new EnvironmentVariable("CXX", "clang++")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests ClangToolChain.ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
||||||
|
IEnvironmentVariable[] envVars).
|
||||||
|
* Where envVars contains "CC=testvalue"
|
||||||
|
* Expected:
|
||||||
|
* envVars contains "CC=testvalue", "CXX=clang++"
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void clangContainsCC() throws Exception {
|
||||||
|
IEnvironmentVariable[] envVars = { new EnvironmentVariable("CC", "testvalue") };
|
||||||
|
IToolChain tc = new ClangToolChain(null, null, null, envVars);
|
||||||
|
IEnvironmentVariable[] variables = tc.getVariables();
|
||||||
|
assertThat(Arrays.asList(variables), contains(//
|
||||||
|
new EnvironmentVariable("CC", "testvalue"), //
|
||||||
|
new EnvironmentVariable("CXX", "clang++")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2017 QNX Software Systems and others.
|
* Copyright (c) 2017, 2025 QNX Software Systems and others.
|
||||||
*
|
*
|
||||||
* This program and the accompanying materials
|
* This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License 2.0
|
* are made available under the terms of the Eclipse Public License 2.0
|
||||||
|
@ -11,9 +11,15 @@
|
||||||
package org.eclipse.cdt.build.gcc.core;
|
package org.eclipse.cdt.build.gcc.core;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.build.IToolChainProvider;
|
import org.eclipse.cdt.core.build.IToolChainProvider;
|
||||||
|
import org.eclipse.cdt.core.envvar.EnvironmentVariable;
|
||||||
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Clang toolchain. There's little different from the GCC toolchain other
|
* The Clang toolchain. There's little different from the GCC toolchain other
|
||||||
|
@ -28,7 +34,81 @@ public class ClangToolChain extends GCCToolChain {
|
||||||
|
|
||||||
public ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
public ClangToolChain(IToolChainProvider provider, Path pathToToolChain, String arch,
|
||||||
IEnvironmentVariable[] envVars) {
|
IEnvironmentVariable[] envVars) {
|
||||||
super(provider, pathToToolChain, arch, envVars);
|
super(provider, pathToToolChain, arch, addClangEnvVars(envVars));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the environment variables CC and CXX, set to clang and clang++, to override the C/C++ compiler executable
|
||||||
|
* that CMake uses.
|
||||||
|
*
|
||||||
|
* Other methods of setting the compiler in CMake (eg; CMAKE_<LANG>_COMPILER in CMakeLists.txt,
|
||||||
|
* -DCMAKE_TOOLCHAIN_FILE=file) take precedence over these environment variables, so the user is not
|
||||||
|
* inhibited by this approach.
|
||||||
|
*
|
||||||
|
* @param envVars Environment variables originate from the core build toolchain (either "Discovered toolchain" or
|
||||||
|
* "User defined toolchain"); these are not the OS system envVars. When the tc is a user defined, it is possible to
|
||||||
|
* specify arbitrary environment variables, meaning the user may have already defined CC/CXX.
|
||||||
|
* If CC/CXX is already defined then nothing is added.
|
||||||
|
*
|
||||||
|
* @return the existing array of envVars, plus if they didn't already exist the envVars CC and CXX set for clang.
|
||||||
|
*/
|
||||||
|
private static IEnvironmentVariable[] addClangEnvVars(IEnvironmentVariable[] envVars) {
|
||||||
|
List<IEnvironmentVariable> envVarsNew = new ArrayList<>();
|
||||||
|
// envVars can be null if the user defined tc did not specify any env variables.
|
||||||
|
if (envVars != null) {
|
||||||
|
envVarsNew.addAll(Arrays.asList(envVars));
|
||||||
|
}
|
||||||
|
addIfAbsent("CC", "clang", envVarsNew); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
addIfAbsent("CXX", "clang++", envVarsNew); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
return envVarsNew.toArray(new EnvironmentVariable[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name The name of the environment variable.
|
||||||
|
* On case insensitive platforms (windows) the case is ignored. If an envVar with the name "cc" already exists,
|
||||||
|
* a new envVar will NOT be added.<br>
|
||||||
|
*
|
||||||
|
* However, on Windows, existing cc/cxx envVars with lower-case names will have their names changed to upper case;
|
||||||
|
* the value remains unchanged.<br>
|
||||||
|
*
|
||||||
|
* On case sensitive platforms (Non-windows) the case is respected. If an envVar with the name "cc" already exists,
|
||||||
|
* a new envVar with name "CC" will be added using the value in {@code value}.
|
||||||
|
* @param value The value of the environment variable.
|
||||||
|
* @param envVars List of environment variables to check and potentially add to.
|
||||||
|
*/
|
||||||
|
private static void addIfAbsent(String name, String value, List<IEnvironmentVariable> envVars) {
|
||||||
|
if (Platform.OS_WIN32.equals(Platform.getOS())) {
|
||||||
|
// On Windows: case-insensitive check ignores case.
|
||||||
|
Iterator<IEnvironmentVariable> iterator = envVars.iterator();
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
IEnvironmentVariable ev = iterator.next();
|
||||||
|
if (ev.getName().equalsIgnoreCase(name)) {
|
||||||
|
found = true;
|
||||||
|
// Replace if existing name is in lower-case and new name is in upper-case
|
||||||
|
if (!ev.getName().equals(name) && name.equals(name.toUpperCase())) {
|
||||||
|
// Original value is respected.
|
||||||
|
String evOldValue = ev.getValue();
|
||||||
|
iterator.remove();
|
||||||
|
envVars.add(new EnvironmentVariable(name, evOldValue));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
envVars.add(new EnvironmentVariable(name, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// On non-Windows: case-sensitive check respects case (exact match).
|
||||||
|
boolean isAbsent = envVars.stream().noneMatch(ev -> ev.getName().equals(name));
|
||||||
|
if (isAbsent) {
|
||||||
|
envVars.add(new EnvironmentVariable(name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Add table
Reference in a new issue