使用 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
文件(exe64
和 x86_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-dependency
和 main
模块,但不会编译库:您选择编译的库将根据其 txt
file.E.g.: lib6
中的 txt
文件包含字符串 lib2 lib1 lib5
,因此构建过程将按以下顺序编译:shared-dependency
、main
、lib2
、lib1
、lib5
、lib6
。另一个示例:lib10
中的 txt
文件包含字符串 lib2 lib5 lib28 lib8
,因此构建过程将按以下顺序编译:shared-dependency
、main
、lib2
, lib5
, lib28
,
lib8
。 lib10
.
至于现在,如果您创建一个新库,您必须手动定义它的所有依赖项并将它们写入 txt 文件(以正确的顺序!),以便您能够构建它。
问题
作为此迁移的第一步,我的目标是使用 Gradle 来:
- 调用构建脚本(不要使用 Gradle 的构建,我会把它留到迁移的后期,因为我必须拆开那些乱七八糟的脚本才能做到这一点) .
- 定义依赖项(奖励:在 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"
}
这定义了作为当前模块依赖项的子模块。
就是这样!
我正在尝试逐步将一个非常混乱的遗留 C++ 项目迁移到 Gradle。
tl;博士
该项目由一个过于复杂的 shell 脚本系统编译,每个模块都包含一个额外的 .txt
文件,其中包含依赖项。那些 .txt
文件被 shell 脚本解析并按照你编写它们的顺序编译(是的,如果你以错误的顺序编写依赖项,编译将失败。
编译结果放在三个公共目录中:exe
用于可执行文件,i686
用于 *.so
文件(exe64
和 x86_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-dependency
和 main
模块,但不会编译库:您选择编译的库将根据其 txt
file.E.g.: lib6
中的 txt
文件包含字符串 lib2 lib1 lib5
,因此构建过程将按以下顺序编译:shared-dependency
、main
、lib2
、lib1
、lib5
、lib6
。另一个示例:lib10
中的 txt
文件包含字符串 lib2 lib5 lib28 lib8
,因此构建过程将按以下顺序编译:shared-dependency
、main
、lib2
, lib5
, lib28
,
lib8
。 lib10
.
至于现在,如果您创建一个新库,您必须手动定义它的所有依赖项并将它们写入 txt 文件(以正确的顺序!),以便您能够构建它。
问题
作为此迁移的第一步,我的目标是使用 Gradle 来:
- 调用构建脚本(不要使用 Gradle 的构建,我会把它留到迁移的后期,因为我必须拆开那些乱七八糟的脚本才能做到这一点) .
- 定义依赖项(奖励:在 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"
}
这定义了作为当前模块依赖项的子模块。
就是这样!