j2objc Xcode build rules, not recognizing imports - java

I am using j2objc to compile and use a java library in iOS. I followed the processes:
http://j2objc.org/docs/Xcode-Build-Rules.html
http://j2objc.org/docs/Required-Link-Flags.html
I do not get any build errors until I start importing the header files to use them:
#import "org/library/Class.h"
The files are not found. What I am missing?
On the other hand, I tried to use the manually translated library files (using the terminal j2objc commands). If I pùt the .h and .m files into the j2objc-dist/include folder they are recognized by the editor and I can use the classes without compile errors. But, when I try to build the project it finds errors of the type _OBJ_CLASS_$_Java. I tried to include the files to the compile list in Xcode and I verified the path of libjre_emul.a but I still get the error.
My library contains packages so it has multiple folders in a tree.
My preference will be to use the first method (original Java sources)
DATA FOR JAVA SOURCES CASE:
Build rules:
Java source files
Custom script:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/j2objc -d ${DERIVED_FILES_DIR} -sourcepath ${PROJECT_DIR}/src/ ** \ --no-package-directories ${INPUT_FILE_PATH};
Output files:
${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.h
${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.m
Build phases
Link Binary with libraries:
libicucore.dylib
Security.framework
libz.dylib
Build Settings
Linking - Other Linker Flags:
-ljre_emul -L /Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib -force_load /Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib/libjre_emul.a -l jre_emul -ObjC
Search Paths - Library Seargh Paths:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib
Search Paths - User Header Search Paths:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/include
My java library files are in Project_root/src. The tree looks like this:
root/
src/
org/
orekit/
data/
time/
...
apache/
...
In my ViewController.m file I try to import with the following line without success (file not found):
#import "org/orekit/data/DataProvidersManager.h"

Xcode assumes all sources are in a top-level directory, so imports such as you describe fail. As described in the Xcode-Build-Rules page, the --no-package-directories flag is needed, as it outputs all generated files to the specified build directory without sub-directories, and generates correct #import directives.
A sample project that demonstrates including Java sources with packages is j2objc-sample-reversi. Its UI sucks (I wrote it, sigh), but the game engine is decent; if you need a tougher opponent, crank up the engine strength here.

Related

Get build.gradle file as a .class file

I have a gradle file which prints "Hello World"
task hello << {
println "Hello World"
}
This script is written in groovy. As I know we can get the output of Test.groovy into Test.class as it uses JVM. So my question is how to get the .class file of build.gradle file? Is there any specific command which I need to provide to the gradle demon?
It's true that Gradle scripts (build.gradle, init script or settings script) will be compiled into Java bytecode, during the Gradle build initialization phase. The result .class files are generated by Gradle into internal "script" cache directory structure under ${user.home}/.gradle/caches/${gradle.version}/scripts.
But this compilation process is something internal to Gradle implementation, it's not exposed through the DSL or from API (as far as I know): you can find some implementation details in the core submodule from Gradle source code : see internal package https://github.com/gradle/gradle/tree/master/subprojects/core/src/main/java/org/gradle/groovy/scripts
I don't think you can access these .class files programatically, even by hacking Gradle core implementation, but as others said in comments: why would you need that??

Running an uber jar from sbt assembly results in error: Could not find or load main class

I have a spark job packaged as an uber-jar using the sbt assembly plugin.
The build.sbt specifies a runnable main to be the target of the resulting uber-jar
mainClass in assembly := Some("com.foo.Bar")
After the assembly is correctly created, running the intended command:
java -jar assembly.jar
results in
Error: Could not find or load main class com.foo.Bar
Using the an alternative method, like java -cp assembly.jar com.foo.Bar gives the same error message.
Then, I extracted the contents of the uber-jar in a new directory. I can see my com/foo/ directory and the Bar.class file.
From the root of the extracted directory I tried:
java -cp . com.foo.Bar
and I get a correct result.
Further trying to find the reason of the error, I tried:
java -verbose -jar assembly.jar
I can see the java core classes being loaded, but I don't see any of my packaged classes being loaded.
What can possibly be wrong here?
After an extensive investigation (read: pulling hairs out), it turns out that this behavior is the result of a rogue INDEX.LIST from one of the flattened jar files landing in the META-INF directory of the resulting uber-jar.
Following the JAR file spec, the INDEX.LIST, if present, dictates what packages from the Jar file are to be loaded.
To avoid this, we updated the mergeStrategy with a rule to avoid any pollution of the resulting META-INF directory:
case PathList("META-INF", xs # _*) => MergeStrategy.discard
This fixed the issue and returned my sanity.
Update:
After some extra searching, it turns out that the default merge strategy takes proper care of INDEX.LIST. This answer applies when the customized merge strategy contains cases that handle the META-INF pathSpec

Factual API and coldfusion

I took the java implementation of the Factual API (reference http://developer.factual.com/) and made a JAR file for factual. I did this by opening a new project in eclipse with the factual java files and then exporting to a new jar file.
I put that jar file in my coldfusion installation's /WEB-INF/lib/ folder.
After restarting Coldfusion, I tried to create a new cfobject like so
<cfscript>
// Initialize the Java class.
factualClass=CreateObject("java", "src.main.java.com.factual.driver.Factual");
</cfscript>
I get an error indicating that it cannot find the Factual class.
Can anybody give me some guidance?
(Summary from comments)
It sounds like you may be exporting the source files ie *.java rather than the compiled class files, ie *.class. In the Jar Export wizard, be sure to select the "Export generated class files and resources" option. (To automatically compile the project sources before expi, enable the setting: JAR packaging > Build projects if not build automatically option). If you prefer you can also find pre-compiled jars in the MVN repository.
put that jar file in my coldfusion installation's /WEB-INF/lib/
folder.
CF10+ also supports dynamic class loading via a new application level setting THIS.javaSettings.
// Initialize the Java class.
factualClass=CreateObject("java", "src.main.java.com.factual.driver.Factual");
Just as a point of interest, src/main/java/ is not actually part of the libary class name. It is a standard directory structure used in Maven projects. It is probably included when exporting the sources, but not the compiled classes.
You can always verify the correct path and class name either by examining the API ie javadocs or by viewing one the source files. Package declarations are always at the top of the source file, such as on line 1 of src/main/java/com/factual/driver/Factual.java:
package com.factual.driver; // ie "com.factual.driver"
.. and the class declaration on line 39.
public class Factual { // ie "Factual"
Combined that gives you the exact (case-sensitive) path to use with createObject:
factualClass=CreateObject("java", "com.factual.driver.Factual");

Importing "google/protobuf/descriptor.proto" in java protocol buffers

I have a .proto file definition which needs to import "google/protobuf/descriptor.proto" because I use Custom Options.
So in my .proto file I do:
import "google/protobuf/descriptor.proto";
package ...;
...
Since my file didn't compile complaining about the dependency, I got a copy of the descriptor.proto file placing it in the same directory my proto file was.
This solved the problem but I don't believe this is the correct way. Now the descriptor.proto gets compiled together with my .proto file resulting in having 2 compiled descriptor.proto at runtime:
the one shipped with the protobuf-java-2.5.0.jar file
the one which was compiled together with my .proto file
I think the --proto-path option should be used somehow but not entirely sure what is the correct way.
Thanks for the best practise tip here!
When I have used descriptor in a .proto, I have used it like
import "google/protobuf/descriptor.proto";
message AddressBook {
required google.protobuf.FileDescriptorSet proto_files = 1;
Then to generate the java (on windows) with addressbookSD.proto in the default directory:
protoc addressbookSD.proto --java_out=./ --proto_path=./ --proto_path=<protobuf-install-directory>\src
where <protobuf-install-directory> is the protocol buffers install directory.
The key point is descriptor.proto is in
<protobuf-install-directory>\src\google\protobuf
The levels in an protobuf import stament must match directories in the File system just like they would in java.
So I use <protobuf-install-directory>\src as the import directory, The directory structure must be
<protobuf-install-directory>\src
+-- google
+-- protobuf
+-- descriptor.proto
Just for the record: I had the same problem recently, and in my case my project depends on protobuf-lite. Apparently, protobuf needed the 'full' protobuf for the custom extensions, and therefore I had to add the dependency, as shown here:
dependencies {
protobuf "io.grpc:grpc-protobuf:${grpcVersion}"
...
}
Note that I depend on gRPC in my project, but that works with com.google.protobuf, too.
Your protoc is not able to find the files in the default include folder for your system
https://github.com/golang/protobuf/issues/694
apt install protobuf-compiler does not put it in include folder
Use this if you are having errors like in linux machines
google/protobuf/descriptor.proto: File not found.
google/protobuf/duration.proto: File not found.
google/protobuf/timestamp.proto: File not found.
For Correct installation on linux systems
PROTOC_ZIP=protoc-3.7.1-linux-x86_64.zip
curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.7.1/$PROTOC_ZIP
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
rm -f $PROTOC_ZIP

JRuby, Warbler, and Java's CLASSPATH

I've been developing applications in JRuby lately and really enjoying it, but I've been running into a wall when it comes to packaging my project into a JAR file when it includes external Java libraries. If the project does not depend on any external Java library JAR files, I run into no problems.
Below is an example application. This code works perfectly fine when running the ./bin/my_proj executable. But, when I package it into a JAR file, the external Java library cannot be loaded because it is not found on the CLASSPATH.
When I unpackage my application's JAR file, I can see that it includes all of my code as well as the vendor directory containing the external Java library. So, everything's where it should be.
lib/my_proj/application.rb
java_import 'com.somecompany.somejavalibrary.SomeJavaLibraryClass'
module MyProj
class Application < SomeJavaLibraryClass
# Some code implementing SomeJavaLibraryClass
end
end
lib/my_proj.rb
require 'pathname'
module MyProj
def root
Pathname.new(__FILE__).join('..', '..').expand_path
end
def start
setup_environment
Application.new
end
def setup_environment
#setup ||= false
unless #setup
#setup = true
require 'java'
$CLASSPATH << root.join('vendor').to_s # Setup Java CLASSPATH
$LOAD_PATH << root.join('lib').to_s # Setup Ruby LOAD_PATH
require 'some_java_library' # Load the external Java library from it's JAR
require 'my_proj/application'
end
end
extend self
end
bin/my_proj
#!/usr/bin/env ruby
$:.unshift File.expand_path( File.join('..', '..', 'lib'), __FILE__ )
require 'my_proj'
MyProj.start
config/warble.rb
Warbler::Config.new do |config|
config.features = %w(gemjar compiled)
config.autodeploy_dir = 'pkg'
config.dirs = %w(assets bin config lib)
config.java_libs += FileList['vendor/*.jar']
end
vendor/some_java_library.jar
# This is the external Java library
The external jars should be in the lib folder.
You can add them in code by doing something like
$CLASSPATH << "vendor/some_java_library.jar" #or loop the directory for all jars and add them
Or you can create a META-INF/MANIFEST.MF file and specifiy the CLASSPATH jars
and adding a line like
Class-Path: vendor/some_java_library.jar jar2-name directory-name/jar3-name
http://docs.oracle.com/javase/tutorial/deployment/jar/downman.html

Categories

Resources