All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.jnigen.AntScriptGenerator Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.jnigen;

import java.util.ArrayList;

import com.badlogic.gdx.utils.Os;
import com.badlogic.gdx.jnigen.FileDescriptor.FileType;

/** 

Generates Ant scripts for multiple native build targets based on the given {@link BuildConfig}. * * For each build target, an Ant build script is created that will compile C/C++ files to a shared library for a specific * platform. A master build script is generated that will execute the build scripts for each platform and bundles their shared * libraries into a Jar file containing all shared libraries for all desktop platform targets, and armeabi/ and armeabi-v7a/ * folders containing the shard libraries for Android. The scripts can be executed from the command line or via the * {@link BuildExecutor}. The resulting shared libraries can be loaded with the SharedLibraryLoader which will load * the correct shared library from the natives jar/arm folders based on the platform the application is running on

* * A common use case looks like this: * *
 * BuildTarget win32 = BuildTarget.newDefaultTarget(Os.Windows, Architecture.Bitness._32);
 * BuildTarget win64 = BuildTarget.newDefaultTarget(Os.Windows, Architecture.Bitness._64);
 * BuildTarget linux32 = BuildTarget.newDefaultTarget(Os.Linux, Architecture.Bitness._32);
 * BuildTarget linux64 = BuildTarget.newDefaultTarget(Os.Linux, Architecture.Bitness._64);
 * BuildTarget mac = BuildTarget.newDefaultTarget(Os.MacOsX, Architecture.Bitness._32);
 * BuildTarget android = BuildTarget.newDefaultTarget(Os.Android, Architecture.Bitness._32);
 * BuildConfig config = new BuildConfig("mysharedlibrary");
 * 
 * new AntScriptGenerator().generate(config, win32, win64, linux32, linux64, mac, android);
 * BuildExecutor.executeAnt("jni/build.xml", "clean", "all", "-v");
 * 
 * // assuming the natives jar is on the classpath of the application 
 * new SharedLibraryLoader().load("mysharedlibrary)
 * 
* *

This will create the build scripts and execute the build of the shared libraries for each platform, provided that the compilers * are available on the system. Mac OS X might have to be treated separately as there are no cross-compilers for it.

* *

The generator will also copy the necessary JNI headers to the jni/jni-headers folder for Windows, Linux and Mac OS X.

* * @author mzechner */ public class AntScriptGenerator { /** Creates a master build script and one build script for each target to generated native shared libraries. * @param config the {@link BuildConfig} * @param targets list of {@link BuildTarget} instances */ public void generate (BuildConfig config, BuildTarget... targets) { // create all the directories for outputing object files, shared libs and natives jar as well as build scripts. if (!config.libsDir.exists()) { if (!config.libsDir.mkdirs()) throw new RuntimeException("Couldn't create directory for shared library files in '" + config.libsDir + "'"); } if (!config.jniDir.exists()) { if (!config.jniDir.mkdirs()) throw new RuntimeException("Couldn't create native code directory '" + config.jniDir + "'"); } // copy jni headers copyJniHeaders(config.jniDir.path()); // copy memcpy_wrap.c, needed if your build platform uses the latest glibc, e.g. Ubuntu 12.10 if (config.jniDir.child("memcpy_wrap.c").exists() == false) { new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/memcpy_wrap.c", FileType.Classpath).copyTo(config.jniDir .child("memcpy_wrap.c")); } ArrayList buildFiles = new ArrayList(); ArrayList libsDirs = new ArrayList(); ArrayList sharedLibFiles = new ArrayList(); // generate an Ant build script for each target for (BuildTarget target : targets) { String buildFile = generateBuildTargetTemplate(config, target); FileDescriptor libsDir = new FileDescriptor(getLibsDirectory(config, target)); if (!libsDir.exists()) { if (!libsDir.mkdirs()) throw new RuntimeException("Couldn't create libs directory '" + libsDir + "'"); } String buildFileName = target.getBuildFilename(); config.jniDir.child(buildFileName).writeString(buildFile, false); System.out.println("Wrote target '" + target.os + target.architecture.toSuffix() + target.bitness.toSuffix() + "' build script '" + config.jniDir.child(buildFileName) + "'"); if (target.os == Os.IOS) { byte[] plist = new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/Info.plist.template", FileType.Classpath) .readBytes(); config.jniDir.child("Info.plist").writeBytes(plist, false); } if (!target.excludeFromMasterBuildFile) { if (target.os != Os.MacOsX && target.os != Os.IOS) { buildFiles.add(buildFileName); } String sharedLibFilename = target.getSharedLibFilename(config.sharedLibName); if (target.os != Os.Android && target.os != Os.IOS) { sharedLibFiles.add(sharedLibFilename); libsDirs.add("../" + libsDir.path().replace('\\', '/')); } } } // generate the master build script String template = new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/build.xml.template", FileType.Classpath) .readString(); StringBuilder clean = new StringBuilder(); StringBuilder compile = new StringBuilder(); StringBuilder pack = new StringBuilder(); for (int i = 0; i < buildFiles.size(); i++) { clean.append("\t\t\n"); compile.append("\t\t\n"); } for (int i = 0; i < libsDirs.size(); i++) { pack.append("\t\t\t\n"); } if (config.sharedLibs != null) { for (String sharedLib : config.sharedLibs) { pack.append("\t\t\t\n"); } } template = template.replace("%projectName%", config.sharedLibName + "-natives"); template = template.replace("", clean.toString()); template = template.replace("", compile.toString()); template = template.replace("%packFile%", "../" + config.libsDir.path().replace('\\', '/') + "/" + config.sharedLibName + "-natives.jar"); template = template.replace("", pack); config.jniDir.child("build.xml").writeString(template, false); System.out.println("Wrote master build script '" + config.jniDir.child("build.xml") + "'"); } private void copyJniHeaders (String jniDir) { final String pack = "com/badlogic/gdx/jnigen/resources/headers"; String files[] = {"classfile_constants.h", "jawt.h", "jdwpTransport.h", "jni.h", "linux/jawt_md.h", "linux/jni_md.h", "mac/jni_md.h", "win32/jawt_md.h", "win32/jni_md.h"}; for (String file : files) { new FileDescriptor(pack, FileType.Classpath).child(file).copyTo( new FileDescriptor(jniDir).child("jni-headers").child(file)); } } public static String getLibsDirectory (BuildConfig config, BuildTarget target) { return config.libsDir.child(target.getTargetFolder()).path().replace('\\', '/'); } private String generateBuildTargetTemplate (BuildConfig config, BuildTarget target) { // special case for android if (target.os == Os.Android) { new AndroidNdkScriptGenerator().generate(config, target); String template = new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/build-android.xml.template", FileType.Classpath).readString(); template = template.replace("%precompile%", target.preCompileTask == null ? "" : target.preCompileTask); template = template.replace("%postcompile%", target.postCompileTask == null ? "" : target.postCompileTask); return template; } // read template file from resources String template = null; if (target.os == Os.IOS) { template = new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/build-ios.xml.template", FileType.Classpath) .readString(); } else { template = new FileDescriptor("com/badlogic/gdx/jnigen/resources/scripts/build-target.xml.template", FileType.Classpath) .readString(); } // generate shared lib filename and jni platform headers directory name String libName = target.getSharedLibFilename(config.sharedLibName); // generate include and exclude fileset Ant description for C/C++ // append memcpy_wrap.c to list of files to be build StringBuilder cIncludes = new StringBuilder(); cIncludes.append("\t\t\n"); for (String cInclude : target.cIncludes) { cIncludes.append("\t\t\n"); } StringBuilder cppIncludes = new StringBuilder(); for (String cppInclude : target.cppIncludes) { cppIncludes.append("\t\t\n"); } StringBuilder cExcludes = new StringBuilder(); for (String cExclude : target.cExcludes) { cExcludes.append("\t\t\n"); } StringBuilder cppExcludes = new StringBuilder(); for (String cppExclude : target.cppExcludes) { cppExcludes.append("\t\t\n"); } // generate C/C++ header directories StringBuilder headerDirs = new StringBuilder(); for (String headerDir : target.headerDirs) { headerDirs.append("\t\t\t\n"); } // replace template vars with proper values template = template.replace("%projectName%", config.sharedLibName + "-" + target.os + "-" + target.architecture.toSuffix() + target.bitness.name().substring(1)); template = template.replace("%buildDir%", config.buildDir.child(target.getTargetFolder()).path().replace('\\', '/')); template = template.replace("%libsDir%", "../" + getLibsDirectory(config, target)); template = template.replace("%libName%", libName); template = template.replace("%xcframeworkName%", config.sharedLibName); template = template.replace("%xcframeworkBundleIdentifier%", target.xcframeworkBundleIdentifier == null ? ("gdx.jnigen." + config.sharedLibName) : target.xcframeworkBundleIdentifier); template = template.replace("%minIOSVersion%", target.minIOSVersion); template = template.replace("%jniPlatform%", target.os.getJniPlatform()); template = template.replace("%cCompiler%", target.cCompiler); template = template.replace("%cppCompiler%", target.cppCompiler); template = template.replace("%archiver%", target.archiver); template = template.replace("%compilerPrefix%", target.compilerPrefix); template = template.replace("%compilerSuffix%", target.compilerSuffix); template = template.replace("%cFlags%", target.cFlags); template = template.replace("%cppFlags%", target.cppFlags); template = template.replace("%linkerFlags%", target.linkerFlags); template = template.replace("%archiverFlags%", target.archiverFlags); template = template.replace("%libraries%", target.libraries); template = template.replace("%cIncludes%", cIncludes.toString().trim()); template = template.replace("%cExcludes%", cExcludes.toString().trim()); template = template.replace("%cppIncludes%", cppIncludes.toString().trim()); template = template.replace("%cppExcludes%", cppExcludes.toString().trim()); template = template.replace("%headerDirs%", headerDirs.toString().trim()); template = template.replace("%precompile%", target.preCompileTask == null ? "" : target.preCompileTask); template = template.replace("%postcompile%", target.postCompileTask == null ? "" : target.postCompileTask); return template; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy