The SourceFile attribute only contains the file name, not a full or relative path. This is not much information to go with because javac will place the .class file in a potentially unrelated directory (relative to the -d argument), based on the package in which the class is declared. While this is required for finding and loading the class at run time, it makes the .class file location only a hint to where the .java file might be located in the source tree.
The documentation of the
com.sun.jdi.ReferenceType.sourcePaths(String) method suggests a heuristics to obtain a file system path:
In the reference implementation, for strata which do not explicitly specify source path (the Java programming language stratum never does), the returned strings are the sourceNames(String) prefixed by the package name of this ReferenceType converted to a platform dependent path.
There is no obvious way to do better than that. Of course, if the file does not exist at the expected location, one could search the source tree and check if the file name happens to be unique, and use that as the location. But beyond that, there are not many options.
Are there any other, non-obvious ways to solve this?
Related
I'm trying to read from a file in kotlin using the File class. It's just a simple txt file with a list of names with each name occupying an independent row. This is my project structure:
and here's my function for pulling out a name depending on the day of the year:
private fun getNameOfTheDay(): String {
val cal = Calendar.getInstance()
val day = cal[Calendar.DATE]
return File("data${File.separator}names.txt")
.bufferedReader()
.lineSequence()
.elementAt(day - 1)
}
I keep on getting a FileNotFound exception so I would assume that my file path is somehow wrong... What am I doing wrong here? Sorry for the dumb question, I'm still learning. By the way the function shown above is called from the MainActivity. Thanks in Advance!
Filenames can be absolute or relative. Absolute filenames start from the top level (e.g. the root directory on Unix-like filesystems, which Macs have; or a drive letter on Windows), and so specify the filename unambiguously. Relative filenames don't, and so give a file in (or in relation to) the current working directory.
In this case, data/names.txt is a relative filename. It assumes that the current directory has a subdirectory called data, and refers to a file in that.
However, the file is actually in the directory app/src/main/java/com/example/mynameis/data/ within your project — so this would only work if the current directory was /<pathToYourProject>/app/src/main/java/com/example/mynameis/, which is highly unlikely! So that probably explains the failure.
I don't know about Android projects, but in normal JVM projects the standard practice is to put data files in a src/main/resources/ directory. Gradle (or Maven) knows to copy them into the classpath when building the project. You would then load it from the classpath, e.g. with:
javaClass.getResource("data/names.txt").readText()
See e.g. this question for more details and variations.
The advantage of loading from the classpath instead of a file path is that you don't need to know exactly where the file is; it could be loose on the filesystem, or bundled into a jar or other archive (even compressed), with ways to select between different versions depending on the run profile — all completely transparent to your code.
As I said, I don't know Android, and can't find any direct answers on StackOverflow. (This question seems to suggest using a android.resource:// URI, but I don't know if that would apply here.) Maybe these external sites can give you some hints.
You should try "data\names.txt". Oftentimes slashes don't work for file paths.
I am generating a STATIC library on Linux with the name myLi using CMake, but apart from myLib.a I would like to generate one big blob of .o (OBJECT) file that contains everything in it (all the sources/object files), but I can't figure out how to do it with CMake (with makefile it's easy done). I have tried the following:
set(${SOURCE_FILES} src/file1.cpp src/file2.cpp .. )
add_library(myLib OBJECT ${SOURCE_FILES})
target_link_libraries(myLib PRIVATE ${LIBS_THAT_REQUIRED})
add_library(FinalLibrary STATIC $<TARGET_OBJECTS:myLib> ...)
I would expect to find myLib.o blob somewhere, but I can't figure out how I can generate it.
Any thoughts?
TL;DR: you can't, what you describe is not an object file, and your interest in producing such an artifact is probably misplaced.
How to generate and export one big OBJECT .o library blob from CMake instead of STATIC .a library
Object files are not among the targets that CMake provides for defining. They are of course produced incidentally in the process of building program and library targets, but they are not an end goal. You might be able to set them up as custom targets, but substantially no one does this.
And they do not do it because there is nothing anyone typically wants to do with an object file that you cannot do with a static library containing that object file, or containing multiple object files that jointly contain the same content. There are, however, one or two things that you can do with a library that you cannot do directly with an object file.
I would like to generate one big blob of .o (OBJECT) file that contains everything in it (all the sources/object files)
That's not what an object file is. An object file is the result of compiling one translation unit (roughly, one source file plus any headers / included files / whatever), and it does not contain source.
And I have no idea what you have in mind to do with such a thing. An archive of the unbuilt source is potentially interesting. One or more programs or libraries built from the source is potentially interesting. An installation package containing some or all of the above is potentially interesting. But the intermediate object files are not interesting, except as stepping stones on a path to one of the others, and none of the aggregates I just listed are object files.
I would expect to find myLib.o blob somewhere, but I can't figure out how I can generate it.
I have no idea why you would expect that unless the library were built from a single source file (which seems not to be the case for you). And if it were built from a single source file then I expect that you would have been able to find the corresponding object file. Which would not contain source, unless possibly in the form of debug information.
A static library is a container for object files. They are created by compiling some number of source files to object files, then putting those object files into the library. (From which they also can be extracted, at least with many common library formats.) There is no other intermediate involved in creating one.
To get a one big object file you need to compile a one big source file. C/C++ sources can be concatenated before the compilation and this is called a Unity build.
How do I change the path that Grammar-Kit's generated JFlex lexer Java file is generated into?
I've asked on Grammar-Kit's issue tracker, but haven't received any response.
I'm tired of of the lexer not being put into my generated files directory (where I would be able to easily delete it along with all my other generated file, and exclude it from searches, and IDE warnings and such).
I, too, got tired of of the lexer not being put into a generated files directory, so I skimmed through the plugin's source code to come up with an answer.
Grammar-Kit uses its own heuristic to decide where to stick your JFlex-generated lexer file, but that heuristic is obviously choosing wrongly in both of our cases.
If you want your generated lexer to go in the generated folder, and Grammar-Kit isn't doing that, it's because the way that GK is designed, your .flex file cannot be inside a source root. Of course, the .flex file is indeed a source file, but for GK's purposes it can't be marked that way — not if you want it to do the right thing and put its generated .java file into your designated generated folder [1].
Instead, move your .flex file out of any source folders, and into a content root that is not marked as a source directory. GK should now behave mostly properly [1]. For it's own source file, the .bnf file, it doesn't behave this odd way; only with the .flex file.
[1]: (actually, in my skimming, I think it may have looked like it's hardcoded specifically to go into a folder named 'gen', but I was only quickly skimming, so that may not be accurate. In either case, generating into a folder named 'gen' {the name most people choose for their generated folder anyway} should at least be sufficient, as your generated flex lexer will at least no longer be mixed in with your normal source files.)
This is the first time that I'm giving a chance to IntelliJ, and to be honest it's not going quite well...
I have imported my Eclipse subprojects. They use external .jar dependencies and they are specified as with a variable, ie: $EXTERNAL_LIBS/derby.jar
When I have imported my projects, IntelliJ recognize the variable and ask me to give it a value, which I misspointed to a wrong path. Now I see on the subproject properties all the module dependencies pointing to a wrong path.
I go to File - Settings and change the value of my EXTERNAL_LIBS to the right path, but all the current dependencies doesn't seem to reflect the change. They still pointing to the first and wrong path.
Am I suppose to go one by one? I do not understand how IntelliJ manages Path Variables... When I try to add a new module dependency it forces me to choose it from the hard drive, and doesn't give the change to use any of these variables.... The documentation is quite poor as well....
Path variables can be changed in File | Settings | Path Variables.
They are handled transparently by the IDE on project load and on project save.
When project loads and contains path variables, IDE will substitute them with the actual paths defined in Settings. If no path variable is defined yet, IDE will ask you to define it.
When the project files are saved on disk, IDE will transparently and silently replace all the paths matching defined variables with the variable name.
It works fully automatically and user doesn't have to define variables explicitly in any IDE settings, just use the actual paths in your libraries, they will be replaced with the corresponding variables on project save so that your project files are portable and other users can define different values for the path variables when opening this project for the first time.
I want my plugin (an automated termination analysis tool) to run on code the user selects inside Eclipse. Naturally, the user selects source code (a .java file, a method in the outline, ...). However, my program needs the compiled .class file(s) as input.
How can I get the .class files for selected source items? Related to this, how can I get a bytecode descriptor to the selected source method? In case of generics and varargs transforming a (Eclipse) source descriptor to the corresponding bytecode descriptor seems nontrivial to me.
I do not want to run javac on my own and I do not want to guess how the .class file is named (this is nasty for inner classes) and then try to find it on the disk (if it exists? maybe I can force Eclipse to compile?).
The Bytecode Outline plugin uses the following solution (see JdtUtils.getByteCodePath):
Based on the source element, find the output location, e.g. /home/user/workspace/project/build/)
Use the package information to find the right directory inside build/, e.g. /home/user/workspace/project/build/some/package/
Find the "outermost" class definition (important for inner classes), use this name as the file name of the .class file, e.g. /home/user/workspace/project/build/some/package/Foo.class
in case of an inner class, do weird magic (JdtUtils.getClassName) and modify the name of the resulting class file accordingly (maybe resulting in Foo$1.class)
So the problem of this question is solved, where the translation of inner classes to the corresponding file names could be improved. According to the author, though, the current approach (using "magic") works for "95% of the cases" and he does not know about any related bugs in the past few years.