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

com.github.xpenatan.jparser.builder.DefaultBuildTarget Maven / Gradle / Ivy

The newest version!
package com.github.xpenatan.jparser.builder;

import com.github.xpenatan.jparser.core.util.CustomFileDescriptor;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.ArrayList;

public abstract class DefaultBuildTarget extends BuildTarget {

    public String tempBuildDir;

    private final ArrayList compilerCommands = new ArrayList<>();
    protected final ArrayList linkerCommands = new ArrayList<>();

    public final ArrayList headerDirs = new ArrayList<>();
    public final ArrayList cppInclude = new ArrayList<>();
    public final ArrayList cppExclude = new ArrayList<>();

    /** Includes only files with this suffix */
    public String filterCPPSuffix = ".cpp";
    public ArrayList cppCompiler = new ArrayList<>();
    public ArrayList linkerCompiler = new ArrayList<>();
    public String compilerOutputCommand = "-o";
    public String linkerOutputCommand = "-o";
    public final ArrayList cppFlags = new ArrayList<>();
    public final ArrayList linkerFlags = new ArrayList<>();
    public String libSuffix = "";
    public String libPrefix = "";
    public String libName = "";
    public String libDirSuffix = "";
    public String linkObjSuffix = ".o";

    public boolean shouldCompile = true;
    public boolean shouldLink = true;

    public boolean isStatic = false;

    protected DefaultBuildTarget() {
        cppCompiler.add("x86_64-w64-mingw32-g++");
        linkerCompiler.add("x86_64-w64-mingw32-g++");
    }

    protected void setup(BuildConfig config) {}

    protected boolean build(BuildConfig config) {
        CustomFileDescriptor childTarget = config.buildDir.child(tempBuildDir);
        if(childTarget.exists()) {
            childTarget.deleteDirectory();
        }
        childTarget.mkdirs();

        setup(config);

        ArrayList cppFiles = new ArrayList<>(getCPPFiles(config.sourceDir, cppInclude, cppExclude, filterCPPSuffix));
        for(CustomFileDescriptor sourceDir : config.additionalSourceDirs) {
            ArrayList cppFiles1 = getCPPFiles(sourceDir, cppInclude, cppExclude, filterCPPSuffix);
            cppFiles.addAll(cppFiles1);
        }

        if(shouldCompile && shouldLink && compile(config, childTarget, cppFiles)) {
            return link(config, childTarget);
        }
        else if(shouldCompile && !shouldLink) {
            return compile(config, childTarget, cppFiles);
        }
        else if(!shouldCompile && shouldLink) {
            return link(config, childTarget);
        }
        else {
            return false;
        }
    }

    private boolean compile(BuildConfig config, CustomFileDescriptor childTarget, ArrayList cppFiles) {
        boolean retFlag = false;

        String compiledPaths = "";
        for(CustomFileDescriptor file : cppFiles) {
            String path = file.path();
            compiledPaths = compiledPaths + "\n" + path;
        }
        CustomFileDescriptor cppList = childTarget.child("cpp.txt");
        cppList.writeString(compiledPaths.trim(), false);

        compilerCommands.clear();
        compilerCommands.addAll(cppCompiler);
        compilerCommands.addAll(cppFlags);
        compilerCommands.addAll(headerDirs);
        compilerCommands.add("@" + cppList.path());
        System.err.println("##### COMPILE #####");
        boolean flag = JProcess.startProcess(config.buildDir.file(), compilerCommands);
        if(!flag) {
            return false;
        }
        retFlag = true;

        // Manually Move object files to target
        ArrayList files = new ArrayList<>();
        getObjectFiles(config.buildDir, files);
        for(CustomFileDescriptor file : files) {
            file.moveTo(childTarget);
        }
        return retFlag;
    }

    private boolean link(BuildConfig config, CustomFileDescriptor childTarget) {
        CustomFileDescriptor libDir = config.libDir.child(libDirSuffix);
        if(!libDir.exists()) {
            libDir.mkdirs();
        }
        String libName = this.libName;

        if(libName.isEmpty()) {
            libName = config.libName;
        }

        String libsDir = libDir.path();
        String fullLibName = libPrefix + libName + libSuffix;
        String libPath = libsDir + "/" + fullLibName;

        ArrayList compiledObjects = new ArrayList<>();
        getAllFiles(childTarget, compiledObjects, linkObjSuffix);

        String compiledPaths = "";
        for(CustomFileDescriptor file : compiledObjects) {
            String path = file.path();
            compiledPaths = compiledPaths + "\n" + path;
        }
        CustomFileDescriptor objList = childTarget.child("objs.txt");
        objList.writeString(compiledPaths.trim(), false);

        linkerCommands.clear();
        onLink(compiledObjects, objList.path(), libPath);

        System.err.println("##### LINK #####");
        return JProcess.startProcess(childTarget.file(), linkerCommands);
    }

    protected void onLink(ArrayList compiledObjects, String objFilePath, String libPath) {
        linkerCommands.addAll(linkerCompiler);
        linkerCommands.add("@" + objFilePath);
        linkerCommands.addAll(linkerFlags);
        linkerCommands.add(linkerOutputCommand + libPath);
    }

    public void addJNIHeaders() {
        headerDirs.add("-Ijni-headers/");
        if(isUnix()) {
            headerDirs.add("-Ijni-headers/linux");
        }
        else if(isWindows()) {
            headerDirs.add("-Ijni-headers/win32");
        }
        else if(isMac()) {
            headerDirs.add("-Ijni-headers/mac");
        }
    }

    public static ArrayList getCPPFiles(CustomFileDescriptor dir, ArrayList cppIncludes, ArrayList cppExcludes, String cppSuffix) {
        ArrayList files = new ArrayList<>();
        getAllFiles(dir, files, cppSuffix);
        for(int i = 0; i < files.size(); i++) {
            // Remove file that does not match
            CustomFileDescriptor fileDescriptor = files.get(i);
            String path = fileDescriptor.path();
            Path of = Path.of(path);
            boolean remove = true;
            for(String cppInclude : cppIncludes) {
                PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + cppInclude);
                boolean matches = pathMatcher.matches(of);
                if(matches) {
                    remove = false;
                    break;
                }
            }
            for(String cppExclude : cppExcludes) {
                PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + cppExclude);
                boolean matches = pathMatcher.matches(of);
                if(matches) {
                    remove = true;
                    break;
                }
            }
            if(remove) {
                files.remove(i);
                i--;
            }
        }
        return files;
    }

    public static void getAllFiles(CustomFileDescriptor file, ArrayList out, String suffix) {
        CustomFileDescriptor[] list = file.list();
        for(CustomFileDescriptor fileDescriptor : list) {
            if(fileDescriptor.isDirectory()) {
                getAllFiles(fileDescriptor, out, suffix);
            }
            else {
                if(!suffix.isEmpty()) {
                    if(fileDescriptor.path().endsWith(suffix)) {
                        out.add(fileDescriptor);
                    }
                }
                else {
                    out.add(fileDescriptor);
                }
            }
        }
    }

    public static void getObjectFiles(CustomFileDescriptor file, ArrayList out) {
        CustomFileDescriptor[] list = file.list();
        for(CustomFileDescriptor fileDescriptor : list) {
            if(!fileDescriptor.isDirectory()) {
                String path = fileDescriptor.path();
                if(path.endsWith(".o") || path.endsWith(".obj")) {
                    out.add(fileDescriptor);
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy