在 nushell 编译脚本中链接时,Clang 找不到 .o 文件

Clang can't find .o files when linking in nushell compilation script

提问人:TOOL 提问时间:8/30/2023 最后编辑:UpAndAdamTOOL 更新时间:9/4/2023 访问量:36

问:

我目前正在尝试在 Nushell 中为 c++ 项目编写构建脚本。

这是一个相当简单的设置,首先构建一个库,然后构建一个 exe,并在另一个脚本中构建并链接该库。在构建库时,我的问题更加明显,所以我只展示这一点。

该库的构建脚本主要是关于定义标志和调用其他文件中定义的构建命令:

# Build script for stowy physics engine

source ../common.nu

def main [buildType: string = 'debug'] {
    let isRelease = $buildType == 'release'

    # Setup flags
    let compilerFlags = [ '-std=c++20' (if $isRelease { '-O3' } else { '-g3' })]
    const includeFlags = ['-Isrc']
    const linkerFlags = ['-shared']
    let defines = ['-DSTWEXPORT' (if $isRelease { '-DNDEBUG'} else { '-DDEBUG' })]

    build stowy_physics_engine 'src/' '../bin/' $compilerFlags $includeFlags $linkerFlags $defines $buildType library
}

这就是 common.nu 的样子:

# Builds the assembly according to the parameters
def build [
    assemblyName: string,
    sourceDirectory: path,
    binaryDirectory: path,
    compilerFlags: list<string>,
    includeFlags: list<string>,
    linkerFlags: list<string>,
    defines: list<string>,
    buildType: string = 'debug', # The optimisation level of the build. Can be 'release' or 'debug'.
    targetType: string = 'executable', # The type of target. Can be 'executable' or 'library'.
] {
    let isRelease = $buildType == 'release'

    let assemblyExtension = if $targetType == 'executable' {
        if ($env.OS | str contains 'Windows') { '.exe' } else { '' }
    } else if $targetType == 'library' {
        if ($env.OS | str contains 'Windows') { '.dll' } else { '.so' }
    } else {
        return 'Invalid targetType'
    }

    let assemblyOutputFile = $'($binaryDirectory)/($assemblyName)($assemblyExtension)'

    let cppFiles = glob **/*.cpp

    let relativeCppFiles = ($cppFiles  | path relative-to $sourceDirectory | path parse)

    # Build every .cpp to .o and get a list of every .o
    let objectFiles = $relativeCppFiles | each {|relativeCppFile| (
        # Convert from path object to string
        let inputFile = ($relativeCppFile | path join);
        let outputFile = ($relativeCppFile | upsert extension 'o' | path join);

        # Recreate the folder structure of .cpp files for the .o in the binary directory
        let inputDirectory = ($relativeCppFile | get parent);
        mkdir ($'($binaryDirectory)/($inputDirectory)');

        # concatenate the .o file with the bin directory
        let outputFileWithDir = $'($binaryDirectory)/($outputFile)'; # ex: ../bin/math/Vector2.o
        let sourceFileWithDir = $'($sourceDirectory)/($inputFile)'; # ex: src/math/Vector2.cpp

        clang++ -c -o $outputFileWithDir $sourceFileWithDir $defines $includeFlags $compilerFlags;
        $outputFileWithDir
    )}

    let startTime = date now

    clang++ -o $assemblyOutputFile $objectFiles $linkerFlags $includeFlags $defines $compilerFlags

    print $'Built and linked ($assemblyName) successfully.'
}

正如你所看到的,它通过递归搜索找到每个文件,并通过调用clang来构建每个文件(我的目标是使用ccache缓存这个构建步骤)。.cpp

然后,在循环之后,我将每个文件交给 clang 以链接(或在 linux 上,但我还没有在那里测试过)。.o.dll.so

我的问题是,当我在启动此命令之前清空 bin 目录时,似乎在编译真正完成之前调用了 link 命令,并且找不到任何 ..o

Building stowy_physics_engine in debug...
Building C:\dev\cpp\build_system_tests\bin/collision\BroadPhaseGrid.o...
...
Building C:\dev\cpp\build_system_tests\bin/math\Vector2.o...
Built objects in 266ms 309µs 700ns
Linking...
clang++: error: no such file or directory: 'C:\dev\cpp\build_system_tests\bin/collision\BroadPhaseGrid.o'
...
clang++: error: no such file or directory: 'C:\dev\cpp\build_system_tests\bin/math\Vector2.o'
clang++: error: no input files

知道是什么原因导致的吗?

C++(英语:C++) 叮叮当当++ nushell的

评论

0赞 UpAndAdam 8/31/2023
您是否需要发明自己的构建系统而不是使用 Make 或 CMake?哦,Windows...我的观点仍然是......此外,您还意识到文件中的路径斜杠方向错误,对吗?您正在混合“/”和“\”,我想系统可能不喜欢。
0赞 TOOL 8/31/2023
因为我正在做一个项目,我在其中实现了一个比较不同构建系统的过程,包括 batch、powershell、nushell 和 cmake(一旦我安装了 linux,也许是 make 和 bash)。目标是更多地了解人们如何做事,因为是的,人们仍然在某些情况下使用批处理文件。至于斜杠,确实是混淆了,但这并不是 clang 努力找到 .o 文件的原因,因为当它们已经构建时,就没有问题了。我会尝试修复它,看看
0赞 UpAndAdam 8/31/2023
powershell/batch/nushell 除了彼此之间的语法外,并没有真正改变任何东西。它们都大致相同:不是构建系统,而是您自己组装的命令行构建脚本。Make 是一个构建系统,CMake 是一个构建系统构建文件生成器。它可以为 Make、Ninja 或其他几个引擎生成。还有 WAF、介子、bazel、scons 之类的东西;我不知道其中有多少在 Windows 上。我只是想理解你为什么要自己发明一个。你给出了一个很好的理由:你是为了学习或研发目的而调查比较。

答:

1赞 TOOL 9/4/2023 #1

我能够通过调用并打印输出来解决这个问题:clangrun-external

print --no-newline (run-external --redirect-combine clang++ '-c' '-o' $outputFileWithDir $sourceFileWithDir $defines $includeFlags $compilerFlags);