我有一个Visual Studio 2010 C ++项目,其中包含需要使用生成C ++代码的内部自定义构建工具处理的文件。
我已经完成了为每个文件添加自定义构建工具的步骤。在自定义生成工具命令行中,使用“call”确保在编译C ++代码之前为所有这些文件运行自定义生成工具。
唯一的问题是自定义构建工具需要从文件所在的目录运行,而不是从Visual Studio解决方案的位置运行。
我现在看到一些可能的选项,但没有一个是理想选择:
是否有更好的选择在工作目录中的文件上运行自定义构建工具?
谢谢。
答案 0 :(得分:2)
Visual Studio项目文件是MSBuild文件。因此,您可以在VS中构建项目时手动修改项目文件并执行其他操作。
为此:
MyCustomtool.target
。此文件“替代” MSBuild目标并调用您的自定义工具。 这是示例文件:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BeforeBuild">
<Message Text="Calling custom tool for %(ClCompile.Identity)"/>
<Exec Command="customtool.exe %(ClCompile.Identity)" WorkingDirectory="$(ProjectDir)" />
</Target>
</Project>
此文件: “覆盖”目标名称“ BeforeBuild”,对于在“ ClCompile”组中定义的每个文件,将显示文本消息,并使用名称已编译的.cpp文件作为参数来执行customtool.exe。
</Project>
之前,添加文件并添加一行: <Import Project="MyCustomtool.target"/>
此Studio之后,Visual Studio将为项目中的每个文件执行您的自定义工具。
一些评论:
因为我没有安装VS 2010,所以我不确定100%可以使用哪个目标名称。我认为“ BeforeBuild”对于VS 2010应该是有效的(在VS 2017中,我正在使用“ BeforeBuildGenerateSources”)。
您可以将“工具/选项/项目和解决方案/构建和运行/ MSBuild项目构建输出详细程度”选项更改为“详细”,查看构建过程的详细输出并检查目标名称。
答案 1 :(得分:0)
您可以创建一个简单的调用程序,以更改工作目录并将构建工具作为子进程调用。您使用Visual Studio,所以我想您的平台是Windows。在这种情况下,应用程序的代码可以如下所示(基于MSDN的示例,它使用C语言编写)
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, TCHAR *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (argc < 3)
{
printf("Usage: %s working_directory !cmdline\n", argv[0]);
return 1;
}
if (!SetCurrentDirectory(argv[1]))
{
printf("SetCurrentDirectory failed (%d)\n", GetLastError());
return 1;
}
LPTSTR commandLine = GetCommandLine();
while (*commandLine && *commandLine != '!')
++commandLine;
++commandLine;
if (!CreateProcess(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
printf("CreateProcess failed (%d).\n", GetLastError());
return 1;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitCode = 0;
GetExitCodeProcess(pi.hProcess, &exitCode);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return exitCode;
}
它接收新的工作目录作为第一个参数,而不是搜索!在命令行中,并将其后的所有内容都视为子进程命令行。这非常方便,因为您无需打扰引号等。例如
cdandcall.exe C:\Windows !python -c "import os; print(os.path.abspath('.'))"
将在输出中打印C:\Windows
。 (当然,如果您将应用程序编译为cdandcall.exe
,请在python
上放置PATH
,并且文件夹C:\Windows
存在。)