-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Get build tool from CMakeCache.txt and expose it as env var
`CMAKE_BUILD_TOOL`
- Loading branch information
Showing
6 changed files
with
518 additions
and
1 deletion.
There are no files selected for viewing
193 changes: 193 additions & 0 deletions
193
src/main/java/de/marw/cmake/cmakecache/CMakeCacheFileParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2014 Martin Weber. | ||
* All rights reserved. This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License v1.0 | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
* | ||
* Contributors: | ||
* Martin Weber - Initial implementation | ||
*******************************************************************************/ | ||
|
||
package de.marw.cmake.cmakecache; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.io.LineNumberReader; | ||
import java.text.MessageFormat; | ||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* A simple parser for CMake cache files ({@code CMakeCache.txt}). This | ||
* implementation extracts only key-value-pairs corresponding to an entry. It | ||
* does not extract any help texts nor entry types. | ||
* | ||
* @author Martin Weber | ||
*/ | ||
public class CMakeCacheFileParser { | ||
|
||
// input line is: key:type=value | ||
private static final Pattern reg = Pattern | ||
.compile("([^=:]*):([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*"); | ||
// input line is: "key":type=value | ||
private static final Pattern regQuoted = Pattern | ||
.compile("\"([^=:]*)\":([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*"); | ||
// input line is: key=value | ||
private static final Pattern regNoType = Pattern | ||
.compile("([^=]*)=(.*[^\t ]|[\t ]*)[\t ]*"); | ||
// input line is: "key"=value | ||
private static final Pattern regQuotedNoType = Pattern | ||
.compile("\"([^=]*)\"=(.*[^\t ]|[\t ]*)[\t ]*"); | ||
|
||
/** | ||
* Parses the content of the specified input stream as a CMake cache file | ||
* content. <br> | ||
* This implementation is inspired by <a href= | ||
* "https://github.com/Kitware/CMake/blob/master/Source/cmCacheManager.cxx" | ||
* >cmCacheManager.cxx</a>. | ||
* | ||
* @param is | ||
* the input stream that serves the content of the CMake cache file | ||
* @param filter | ||
* an optional filter for CMake cache file entries or {@code null} if | ||
* all entries are of interest | ||
* @param parsedEntries | ||
* receives the parsed cache file entries. Specify {@code null}, if you | ||
* want to verify the correct syntax of the cache file only. Specify an | ||
* instance of {@link List}, if you expect multiple cache entires of | ||
* the same key int the file. Normally, you would specify an instance | ||
* of {@link Set} here. | ||
* @param errorLog | ||
* receives messages concerning parse errors. Specify {@code null}, if | ||
* you are not interested in error messages. | ||
* @return {@code true} if the file could be parsed without errors, otherwise | ||
* {@code false} | ||
* @throws IOException | ||
* if an operation on the input stream failed | ||
*/ | ||
public boolean parse(final InputStream is, final EntryFilter filter, | ||
Collection<SimpleCMakeCacheEntry> parsedEntries, List<String> errorLog) | ||
throws IOException { | ||
|
||
final LineNumberReader reader = new LineNumberReader(new InputStreamReader( | ||
is)); | ||
boolean hasErrors = false; | ||
|
||
Map<String, SimpleCMakeCacheEntry> uniqueMap = null; | ||
if (parsedEntries != null && parsedEntries instanceof Set) { | ||
// avoid returning duplicate keys | ||
uniqueMap = new HashMap<String, SimpleCMakeCacheEntry>(); | ||
} | ||
|
||
for (String line; null != (line = reader.readLine());) { | ||
int idx = 0; | ||
// skip leading whitespaces... | ||
for (; idx < line.length(); idx++) { | ||
final char c = line.charAt(idx); | ||
if (!Character.isWhitespace(c)) | ||
break; | ||
} | ||
if (!(idx < line.length())) | ||
continue; // skip blank lines | ||
|
||
if (line.charAt(idx) == '#') | ||
continue; // skip cmake comment lines | ||
|
||
if (idx < line.length()) { | ||
line = line.substring(idx); | ||
|
||
if (line.startsWith("//")) | ||
continue; // ignore help string | ||
|
||
// parse cache entry... | ||
String key = null; | ||
String value = null; | ||
Matcher matcher; | ||
|
||
if ((matcher = reg.matcher(line)).matches() | ||
|| (matcher = regQuoted.matcher(line)).matches()) { | ||
// input line is: key:type=value | ||
// input line is: "key":type=value | ||
key = matcher.group(1); | ||
// we do not need the type from group(2) | ||
value = matcher.group(3); | ||
} else if ((matcher = regNoType.matcher(line)).matches() | ||
|| (matcher = regQuotedNoType.matcher(line)).matches()) { | ||
// input line is: key=value | ||
// input line is: "key"=value | ||
key = matcher.group(1); | ||
value = matcher.group(2); | ||
} else { | ||
hasErrors |= true; | ||
// add error message | ||
if (errorLog != null) { | ||
final String msg = MessageFormat.format( | ||
"Error: Line {0,number,integer}: Offending entry: {1}", | ||
reader.getLineNumber(), line); | ||
errorLog.add(msg); | ||
} | ||
} | ||
|
||
if (filter != null && parsedEntries != null) { | ||
// no need to call the filter if nothing is to be returned | ||
if (!filter.accept(key)) | ||
continue; // uninteresting entry, get next line | ||
} | ||
|
||
// if value is enclosed in single quotes ('foo') then remove them | ||
// it is used to enclose trailing space or tab | ||
if (key != null && value != null && value.length() >= 2 | ||
&& value.charAt(0) == '\'' | ||
&& value.charAt(value.length() - 1) == '\'') { | ||
|
||
value = value.substring(1, value.length()); | ||
} | ||
|
||
// store entry | ||
if (parsedEntries != null) { | ||
final SimpleCMakeCacheEntry entry = new SimpleCMakeCacheEntry(key, | ||
value); | ||
if (uniqueMap != null) | ||
uniqueMap.put(key, entry); | ||
else | ||
parsedEntries.add(entry); | ||
} | ||
} | ||
} | ||
if (parsedEntries != null && uniqueMap != null) | ||
parsedEntries.addAll(uniqueMap.values()); | ||
return hasErrors; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////// | ||
// inner classes | ||
//////////////////////////////////////////////////////////////////// | ||
/** | ||
* A filter for CMake cache file entry keys. | ||
* <p> | ||
* Instances of this interface may be passed to the | ||
* {@link CMakeCacheFileParser#CMakeCacheFileParser()} constructor of the | ||
* {@code CMakeCacheFileParser}</code> class. | ||
* | ||
* @author Martin Weber | ||
*/ | ||
public interface EntryFilter { | ||
/** | ||
* Tests whether or not the specified entry key should be included in a set | ||
* returned by {@link CMakeCacheFileParser#parse}. | ||
* | ||
* @param key | ||
* The entry key to be tested. Never {@code null} | ||
* @return <code>true</code> if and only if <code>key</code> should be | ||
* included | ||
*/ | ||
boolean accept(String key); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
src/main/java/de/marw/cmake/cmakecache/SimpleCMakeCacheEntry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2014 Martin Weber. | ||
* All rights reserved. This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License v1.0 | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
* | ||
* Contributors: | ||
* Martin Weber - Initial implementation | ||
*******************************************************************************/ | ||
package de.marw.cmake.cmakecache; | ||
|
||
/** | ||
* Represents an entry of a CMakeCache.txt file in a simple form: Holds only | ||
* key-value-pairs of an entry. It does not extract any help texts nor entry | ||
* types. | ||
* | ||
* @author Martin Weber | ||
*/ | ||
public class SimpleCMakeCacheEntry { | ||
private final String key; | ||
private final String value; | ||
|
||
/** | ||
* @throws IllegalArgumentException | ||
* if {@code key} is empty | ||
* @throws NullPointerException | ||
* if {@code key} is {@code null} or if {@code value} is {@code null} | ||
*/ | ||
public SimpleCMakeCacheEntry(String key, String value) { | ||
if (key == null) { | ||
throw new NullPointerException("key"); | ||
} | ||
if (key.length() == 0) { | ||
throw new IllegalArgumentException("key"); | ||
} | ||
if (value == null) { | ||
throw new NullPointerException("value"); | ||
} | ||
|
||
this.value = value; | ||
this.key = key; | ||
} | ||
|
||
/** | ||
* Gets the key property. | ||
* | ||
* @return the current key property. | ||
*/ | ||
public String getKey() { | ||
return this.key; | ||
} | ||
|
||
/** | ||
* Gets the value. | ||
* | ||
* @return the current value. | ||
*/ | ||
public String getValue() { | ||
return this.value; | ||
} | ||
|
||
public String toString() { | ||
return key + "=" + value; | ||
} | ||
|
||
} |
110 changes: 110 additions & 0 deletions
110
src/main/java/de/marw/cmake/cmakecache/SimpleCMakeCacheTxt.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2015 Martin Weber. | ||
* All rights reserved. This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License v1.0 | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v10.html | ||
* | ||
* Contributors: | ||
* Martin Weber - Initial implementation | ||
*******************************************************************************/ | ||
package de.marw.cmake.cmakecache; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Represents a simplistic subset of the parsed content of a CMake cache file | ||
* (CMakeCache.txt). | ||
* | ||
* @author Martin Weber | ||
*/ | ||
public class SimpleCMakeCacheTxt { | ||
|
||
private String buildTool; | ||
private List<String> tools; | ||
private List<String> commands; | ||
|
||
/** | ||
* Creates a new object by parsing the specified file. | ||
* | ||
* @param file | ||
* the file to parse. | ||
* @throws IOException | ||
* if the file could not be read | ||
*/ | ||
public SimpleCMakeCacheTxt(File file) throws IOException { | ||
ArrayList<String> tools = new ArrayList<String>(); | ||
ArrayList<String> commands = new ArrayList<String>(); | ||
|
||
// parse CMakeCache.txt... | ||
InputStream is = null; | ||
try { | ||
is = new FileInputStream(file); | ||
final Set<SimpleCMakeCacheEntry> entries = new HashSet<SimpleCMakeCacheEntry>(); | ||
new CMakeCacheFileParser().parse(is, null, entries, null); | ||
for (SimpleCMakeCacheEntry entry : entries) { | ||
final String toolKey = entry.getKey(); | ||
final String tool = entry.getValue(); | ||
if ("CMAKE_BUILD_TOOL".equals(toolKey)) { | ||
buildTool = tool; | ||
} else if ("CMAKE_COMMAND".equals(toolKey)) { | ||
commands.add(tool); | ||
} else if ("CMAKE_CPACK_COMMAND".equals(toolKey)) { | ||
commands.add(tool); | ||
} else if ("CMAKE_CTEST_COMMAND".equals(toolKey)) { | ||
commands.add(tool); | ||
} else if ("CMAKE_C_COMPILER".equals(toolKey)) { | ||
tools.add(tool); | ||
} else if ("CMAKE_CXX_COMPILER".equals(toolKey)) { | ||
tools.add(tool); | ||
} | ||
} | ||
this.tools = Collections.unmodifiableList(tools); | ||
this.commands = Collections.unmodifiableList(commands); | ||
} finally { | ||
if (is != null) { | ||
try { | ||
is.close(); | ||
} catch (IOException ignore) { | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Gets the name of the tool that processes the generated build scripts. In | ||
* most cases, this method will return the absolute file system path of the | ||
* tool, such as {@code /usr/bin/make}. | ||
* | ||
* @return the CMAKE_BUILD_TOOL entry from the CMakeCache.txt file or | ||
* {@code null} if the file could not be parsed | ||
*/ | ||
public String getBuildTool() { | ||
return buildTool; | ||
} | ||
|
||
/** | ||
* Gets the tools that process the source files to binary files (compilers, | ||
* linkers). In most cases, this method will return the absolute file system | ||
* paths of a tool, for example {@code /usr/bin/cc}. | ||
*/ | ||
public List<String> getTools() { | ||
return tools; | ||
} | ||
|
||
/** | ||
* Gets the tools provided by CMake itself (cmake, cpack, ctest). In most | ||
* cases, this method will return the absolute file system paths of a tool. | ||
*/ | ||
public List<String> getCmakeCommands() { | ||
return commands; | ||
} | ||
} |
Oops, something went wrong.