How to add C++ compiler options when using `build.gradle.kts`?

I’m currently writing a Cpp Application, but I can’t change the compiler options anyway.

I tried to configure it in the following places, but nothing worked:

  1. tasks.withType<CppCompile>{…}
  2. binaries.configureEach { compileTask.get().apply{…} }
  3. toolChains { withType<VisualCpp>{…} }

I tried to find model and components mentioned in the tutorial, but I still had no idea what they were. When I use components{ ... }, I found that the type was inconsistent and could not be initialized through the gradle project.

it’s my build.gradle.kts.

import java.io.InputStream
import java.io.OutputStream
import java.util.*
import java.util.zip.ZipInputStream

plugins {
    `cpp-application`
    java // maybe "apply false"?
}

application {
    source.from(file("src"), files("build/mergeJar", "build/mergeJar/res"))
    privateHeaders.from(file("src"), files("lib/jni", "lib/jni/win32", "lib/jni/win32/bridge", "build/mergeJar"))


    targetMachines.set(listOf(machines.windows.x86_64))

    binaries.configureEach {
        compileTask.get().apply {
            inputs.property("sourceEncoding", "UTF-8")

            if (toolChain is Gcc || toolChain is Clang) {

                compilerArgs.addAll(listOf("-finput-charset=UTF-8", "-fexec-charset=UTF-8"))
            } else if (toolChain is VisualCpp) {

                compilerArgs.addAll(listOf("/source-charset:utf-8", "/execution-charset:utf-8", "/std:c++17"))
            }
        }
    }
}

toolChains {
    withType<VisualCpp> {
        eachPlatform {
            cppCompiler.withArguments {
                listOf("/source-charset:utf-8", "/execution-charset:utf-8", "/std:c++17")
            }
        }
    }
    withType<Gcc> {
        eachPlatform {
            cppCompiler.withArguments {
                listOf("-finput-charset=UTF-8", "-fexec-charset=UTF-8")
            }
        }
    }
    withType<Clang> {
        eachPlatform {
            cppCompiler.withArguments {
                listOf("-finput-charset=UTF-8", "-fexec-charset=UTF-8")
            }
        }
    }
}

task("mergeJar") {
    dependsOn(":jar")
    dependsOn(":static:jar")
    doLast {
        val jar = rootProject.tasks.jar.get()
        val staticJar = project(":static").tasks.jar.get()
        val jarFile = jar.outputs.files.singleFile
        val staticJarFile = staticJar.outputs.files.singleFile
        val dir = projectDir.resolve("build/mergeJar")
        if (!dir.exists()) dir.mkdirs()
        val resDir = dir.resolve("res")
        resDir.deleteRecursively()
        resDir.mkdirs()

        fun mkFile(index: Long, fis: InputStream): String {
            val id = "RES" + index.toULong().toString(16).padStart(16, '0').uppercase()
            val cpp = resDir.resolve("$id.cpp")

            cpp.writer().use { w ->
                w.write(
                    """
                    #include "res.h"
                    
                    constexpr char $id[] = "
                    """.trimIndent()
                )

                val hex = HexFormat.of().withPrefix("\\x")
                val ros = object : OutputStream() {
                    override fun write(p0: Int) {
                        write(byteArrayOf(p0.toByte()), 0, 1)
                    }

                    override fun write(b: ByteArray?, off: Int, len: Int) {
                        val str = hex.formatHex(b, off, off + len)
                        w.write(str)
                    }
                }
                fis.copyTo(ros)

                w.write(
                    """
                    ";
                    
                    const char* Get${id}(){
                        return $id;
                    }
                    """.trimIndent()
                )
            }
            return id
        }

        val cpp = dir.resolve("resources_base.cpp")
        if (cpp.exists()) cpp.delete()
        val writer = cpp.writer(Charsets.UTF_8)
        writer.write(
            """
            #include <unordered_map>
            #include "resources_base.h"
            #include "res/res.h"
            """.trimIndent()
        )
        var index = 0L
        val fileMap = mutableListOf<Triple<String, String, Long>>()
        fun readJar(jar: File) {
            jar.inputStream().use { fis ->
                val jis = ZipInputStream(fis)
                while (true) {
                    val entry = jis.nextEntry ?: break
                    if (entry.isDirectory) continue

                    val id = mkFile(index, jis)

                    fileMap.add(Triple(entry.name, id, entry.size))
                    index += entry.size
                }
            }
        }
        println(jarFile)
        println(staticJarFile)
        readJar(jarFile)
        readJar(staticJarFile)

        writer.write(
            """
            
            using namespace std;
            const unordered_map<string, pair<const char* (*)(), size_t>> RESOURCES_META = {
            
            """.trimIndent()
        )

        fileMap.forEachIndexed { i, it ->
            val mark = if (i == fileMap.size - 1) "" else ","
            writer.write(
                """
                    |    {"${it.first}", {Get${it.second}, ${it.third}}}$mark
                    |
                    """.trimMargin()
            )
        }

        writer.write(
            """
            };
            
            const vector<classpath> CLASSPATH = {
            
            """.trimIndent()
        )
        val runtimeClasspath = rootProject.configurations.runtimeClasspath.get()
        val fDeps = runtimeClasspath.resolvedConfiguration.firstLevelModuleDependencies
        val fileSet = runtimeClasspath.files
        var deps = mutableListOf<ResolvedDependency>()

        fun resolve(dep: ResolvedDependency) {
            deps += dep
            dep.children.forEach(::resolve)
        }
        fDeps.forEach(::resolve)

        deps = deps.toSet().sortedWith(
            compareBy(
                { it.moduleGroup },
                { it.moduleName },
                { it.moduleVersion },
            )
        ).toMutableList()

        deps.forEachIndexed { i, it ->
            val name = it.moduleArtifacts.find { it.file in fileSet }?.file?.name ?: return@forEachIndexed
            val mark = if (i == deps.size - 1) "" else ","
            writer.write(
                """
                |    {"${it.moduleGroup}", "${it.moduleName}", "${it.moduleVersion}", "$name"}$mark
                |
                """.trimMargin()
            )
        }

        writer.write(
            """
            };
            
            std::unordered_map<std::string, std::pair<const char* (*)(), size_t>> GetResourceMeta(){
                return RESOURCES_META;
            }
            
            pair<const char*, size_t> GetResource(const string& name){
                const auto node = RESOURCES_META.find(name);
                if (node == RESOURCES_META.end()) return {nullptr, 0};
                auto [fn, length] = node->second;
                const char* bytes = fn();
                return { bytes, length };
            }
            
            vector<classpath> GetClassPath(){
                return CLASSPATH;
            }
            """.trimIndent()
        )
        writer.close()

        resDir.resolve("res.h").writer().use { w ->
            w.write("#pragma once\n\n")

            fileMap.forEach {
                w.write("const char* Get${it.second}();\n")
            }
        }
    }
}

It’s build/tmp/compileDebugCpp/options.txt

/TP
/nologo
/c
/Zi
/IF:\foobar\src
/IF:\foobar\lib\jni
/IF:\foobar\lib\jni\win32
/IF:\foobar\lib\jni\win32\bridge
/IF:\foobar\build\mergeJar
"/ID:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include"
"/IC:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um"
"/IC:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared"
"/IC:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt"

At compile time, I get this error. It’s still trying to request C++17 and Unicode. 936 is GB2312 encoding, but I’m not going to use it.

classloader.cpp
F:\foobar\src\classloader.h(1): warning C4819: ���ļ����������ڵ�ǰ����ҳ(936)�б�ʾ���ַ����뽫���ļ�����Ϊ Unicode ��ʽ�Է�ֹ���ݶ�ʧ
F:\foobar\src\resources.h(1): warning C4819: ���ļ����������ڵ�ǰ����ҳ(936)�б�ʾ���ַ����뽫���ļ�����Ϊ Unicode ��ʽ�Է�ֹ���ݶ�ʧ
F:\foobar\src\resources_base.h(1): warning C4819: ���ļ����������ڵ�ǰ����ҳ(936)�б�ʾ���ַ����뽫���ļ�����Ϊ Unicode ��ʽ�Է�ֹ���ݶ�ʧ
F:\foobar\src\classloader.cpp(48): error C2429: ���Թ��� "�ṹ����" ��Ҫ��������־ "/std:c++17"

resources.cpp
F:\foobar\src\resources.h(1): warning C4819: ���ļ����������ڵ�ǰ����ҳ(936)�б�ʾ���ַ����뽫���ļ�����Ϊ Unicode ��ʽ�Է�ֹ���ݶ�ʧ
F:\foobar\src\resources_base.h(1): warning C4819: ���ļ����������ڵ�ǰ����ҳ(936)�б�ʾ���ַ����뽫���ļ�����Ϊ Unicode ��ʽ�Է�ֹ���ݶ�ʧ
F:\foobar\src\resources.cpp(28): error C2429: ���Թ��� "�ṹ����" ��Ҫ��������־ "/std:c++17"

RES00000000000151E7.cpp
F:\foobar\build\mergeJar\res\RES00000000000151E7.cpp(3): error C2026: �ַ���̫���ѽض�β���ַ�
... more ...