使用 Gradle 管理依赖项并在遗留 C++ 项目上启动自定义编译脚本

Use Gradle to manage dependencies and launch custom compilation script on legacy C++ project

我正在尝试逐步将一个非常混乱的遗留 C++ 项目迁移到 Gradle。

tl;博士

该项目由一个过于复杂的 shell 脚本系统编译,每个模块都包含一个额外的 .txt 文件,其中包含依赖项。那些 .txt 文件被 shell 脚本解析并按照你编写它们的顺序编译(是的,如果你以错误的顺序编写依赖项,编译将失败。

编译结果放在三个公共目录中:exe 用于可执行文件,i686 用于 *.so 文件(exe64x86_64 在 64 位情况下)和 includes 目录用于中间 .h 文件和后续编译所需的其他文件。为 Windows 而不是 Linux 编译时也会发生同样的情况,但现在我专注于 Linux.

的编译

这是存储库的样子:

root
├── dependency
│   └── shared-dependency
└── project
    ├── exe
    ├── i686
    ├── includes
    │   ├── 32
    │   └── 64
    ├── lib1
    ├── lib2
    ├── lib3
    ├── lib4
    ├── (other directories)
    └── main

shared-dependency 是第一个编译的,第二个是 main 模块(可执行文件),然后是一些 libs。对于 libs,正如我所说,依赖项在 libs 文件夹中定义。

总是编译 shared-dependencymain 模块,但不会编译库:您选择编译的库将根据其 txt file.E.g.: lib6 中的 txt 文件包含字符串 lib2 lib1 lib5,因此构建过程将按以下顺序编译:shared-dependencymainlib2lib1lib5lib6。另一个示例:lib10 中的 txt 文件包含字符串 lib2 lib5 lib28 lib8,因此构建过程将按以下顺序编译:shared-dependencymainlib2, lib5, lib28, lib8lib10.

至于现在,如果您创建一个新库,您必须手动定义它的所有依赖项并将它们写入 txt 文件(以正确的顺序!),以便您能够构建它。

问题

作为此迁移的第一步,我的目标是使用 Gradle 来:

  1. 调用构建脚本(不要使用 Gradle 的构建,我会把它留到迁移的后期,因为我必须拆开那些乱七八糟的脚本才能做到这一点) .
  2. 定义依赖项(奖励:在 lib 的子文件夹中定义每个依赖项,不要污染根 build.gradle)。

我在 project 目录中创建了一个 Gradle 项目,并以编程方式将其所有子文件夹定义为包含在 settings.gradle 文件中,并在 [=51= 中定义了构建任务] 文件:

allprojects {
    task build {
        exec {
            commandLine "sh", "build.sh"
        }
    }
}

但是我无法定义依赖项!如果我将类似的内容添加到 build.gradle 文件中:

project(':lib1') {
    dependencies {
        archives project(':main')functionalities
    }
}

无论我选择什么而不是archives这个词(比如implementation),Gradle都会抱怨

Could not find method archives() for arguments [project ':main'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

我是 Gradle 的新手,但如果我的理解是正确的,我必须应用一个插件才能使用依赖项,例如apply plugin: 'base'。但是如果我这样做,我就不能再定义构建任务了,因为我得到 Cannot add task 'build' as a task with that name already exists.。如果我尝试 task build <<< { 我会收到另一个错误:expecting '}', found 'build'.

目前我对Gradle内部逻辑的理解几乎为零,所以卡住了。

可以Gradle配置成适合我需要的方式吗?

虽然很郁闷,但最终还是如愿以偿。

settings.gradle:

rootDir.eachDir { f ->
if(!f.getName().startsWith(".") &&
       !f.getName().startsWith("include") &&
       !f.getName().startsWith("lib") &&
       !f.getName().startsWith("lib64") &&
       !f.getName().startsWith("exe") &&
       !f.getName().startsWith("i686") &&
       !f.getName().startsWith("x86_64") ) {
        include f.getName()
    }
}

这将包括所有子目录作为模块

root build.gradle:

defaultTasks 'build'

allprojects {
    task build {
        doLast {
            exec {
                commandLine 'sh', "${project.name}.sh", '32', 'all'
            }
        }
    }
}

这将为每个子模块调用自定义构建脚本。请注意,我必须向根项目添加一个空 project_name.sh,否则 Gradle 会抱怨文件丢失。不知道有没有设置告诉他不要尝试调用根目录下的构建脚本,这个我还要研究一下。

子模块示例 build.gradle:

build {
    dependsOn ":lib1:build"
    dependsOn ":lib2:build"
    dependsOn ":lib6:build"
}

这定义了作为当前模块依赖项的子模块。

就是这样!