Copying file with CMake to build folder – single solution for VS Code and Visual Studio

huangapple go评论64阅读模式
英文:

Copying file with CMake to build folder - single solution for VS Code and Visual Studio

问题

I have small project (minimum example) with 3 files:

foo.cpp
script.py
CMakeLists.txt

CMakeLists.txt:

cmake_minimum_required( VERSION 3.20 )
project( PythonCppExtension )

find_package( Python  COMPONENTS Interpreter Development )

add_executable(PyRun "foo.cpp")
target_include_directories(PyRun PUBLIC ${Python_INCLUDE_DIRS})

target_link_libraries(PyRun "${Python_LIBRARY_DIRS}/python3.lib") #I am using the Stable ABI 

add_custom_command(
        TARGET PyRun POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/script.py
                ${CMAKE_CURRENT_BINARY_DIR}/script.py)

foo.cpp:

#define Py_LIMITED_API  0x03050000
#define PY_SSIZE_T_CLEAN

#ifdef _DEBUG
#undef _DEBUG
#include <python.h>
#define _DEBUG
#else
#include <python.h>
#endif

int main()
{
    const wchar_t* arg[] = { L"-i", L"script.py" };
    return Py_Main(n, const_cast<wchar_t**>(2));
}

The code may have issues and is just an example, but works for me.

I want to use cmake for building extensions that I can compile on Windows with Visual Studio or Visual Code and on Linux.

It works here, but the thing is that I still didn't figure out how to make a single solution for both Visual Studio and Visual Code. The code above works for Visual Studio, that copy the script.py to the same folder of the executable PyRun. It does so because Visual Studio passes to CMAKE the full path of the folder output at the variable CMAKE_INSTALL_PREFIX:

... -DCMAKE_INSTALL_PREFIX:PATH="C:\Users\ ... \PythonCpp\out\install\x64-Debug" ...

When I compile with Visual Code I would have to update the cmake script to:

add_custom_command(
            TARGET PyRun POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy
                    ${CMAKE_SOURCE_DIR}/script.py
                    ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/script.py)

to copy the script file to the same folder of the executable, because the executable is copied to a Debug or Release folder within CMAKE_CURRENT_BINARY_DIR.

How do I handle such an issue to make one single cmake script?

英文:

I have small project (minimum example) with 3 files:

foo.cpp
script.py
CMakeLists.txt

CMakeLists.txt:

cmake_minimum_required( VERSION 3.20 )
project( PythonCppExtension )


find_package( Python  COMPONENTS Interpreter Development )

add_executable(PyRun &quot;foo.cpp&quot;)
target_include_directories(PyRun PUBLIC ${Python_INCLUDE_DIRS})

target_link_libraries(PyRun &quot;${Python_LIBRARY_DIRS}/python3.lib&quot;) #I am using the Stable ABI 

add_custom_command(
        TARGET PyRun POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/script.py
                ${CMAKE_CURRENT_BINARY_DIR}/script.py)

foo.cpp:

#define Py_LIMITED_API  0x03050000
#define PY_SSIZE_T_CLEAN

#ifdef _DEBUG
#undef _DEBUG
	#include &lt;python.h&gt;
#define _DEBUG
#else
	#include &lt;python.h&gt;
#endif

int main()
{
	const wchar_t* arg[] = { L&quot;-i&quot;, L&quot;script.py&quot; };
	return Py_Main(n, const_cast&lt;wchar_t**&gt;(2));
}

The code may have issues and is just an example, but works for me.

I want to use cmake for building extensions that I can compile on Windows with Visual Studio or Visual Code and on Linux.

It works here, but the thing is that I still didn't figure out how to to make a single solution for both Visual Studio and Visual Code. The code above works for Visual Studio, that copy the script.py to the same folder of the executable PyRun. It does so because Visual Studio passes to CMAKE the full path of the folder output at the variable CMAKE_INSTALL_PREFIX:

 ... -DCMAKE_INSTALL_PREFIX:PATH=&quot;C:\Users\ ... \PythonCpp\out\install\x64-Debug&quot; ...

When I compile with Visual Code I would have to update the cmake script to:

 add_custom_command(
            TARGET PyRun POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy
                    ${CMAKE_SOURCE_DIR}/script.py
                    ${CMAKE_CURRENT_BINARY_DIR}/$&lt;CONFIG&gt;/script.py)

to copy the script file to the same folder of the executable, because the executable is copied to a Debug or Release folder within CMAKE_CURRENT_BINARY_DIR.

How do I handle such a issue to make one single cmake script?

答案1

得分: 2

这是一个XY问题。您想将文件复制到与目标输出文件相同的目录。您可以使用$<TARGET_FILE_DIR:tgt>生成表达式来实现这一点。 Ex.

add_custom_command(
  TARGET PyRun POST_BUILD
  COMMAND "${CMAKE_COMMAND}" -E copy
    "${CMAKE_SOURCE_DIR}/script.py"
    "$<TARGET_FILE_DIR:PyRun>/script.py"
)

上面的代码适用于Visual Studio,它会将script.py复制到可执行文件PyRun所在的同一文件夹。这是因为Visual Studio将完整路径传递给CMAKE_INSTALL_PREFIX变量。

我相当肯定CMAKE_INSTALL_PREFIX与这个问题无关。再次说明,您之前使用${CMAKE_CURRENT_BINARY_DIR}作为复制目标位置,这可能解释了您遇到的行为。我怀疑您可能正在为VS Code项目使用单配置生成器。

您可以使用配置命令的-G参数来通常设置生成器,或者在VS Code中使用CMake Tools扩展来设置生成器,使用cmake.generator设置(如果将工作区设置文件提交到版本控制,则在工作区设置中硬编码可能不是个好主意(在这种情况下,将设置放在用户的setting.json文件中))。

从技术上讲,您可能可以通过使用"cmake.buildDirectory": "${workspaceFolder}/build/${buildType}"(文档)来解决VS Code中单配置生成器的问题,但再次强调,这只是一种解决方法,而且不是一个好的解决方法(如果将其放在工作区设置中并提交工作区settings.json文件,因为它假设单配置)。不过,在这一点上,还请参阅问题票据Feature Add option to specify cmake.buildDirectory for single- and multi-config generators, respectively #2426

英文:

This is an XY problem. You want to copy a file to the same directory as a target's output file. The way you do that is by using the $&lt;TARGET_FILE_DIR:tgt&gt; generator expression. Ex.

add_custom_command(
  TARGET PyRun POST_BUILD
  COMMAND &quot;${CMAKE_COMMAND}&quot; -E copy
    &quot;${CMAKE_SOURCE_DIR}/script.py&quot;
    &quot;$&lt;TARGET_FILE_DIR:PyRun&gt;/script.py&quot;
)

> The code above works for Visual Studio, that copy the script.py to the same folder of the executable PyRun. It does so because Visual Studio passes to CMAKE the full path of the folder output at the variable CMAKE_INSTALL_PREFIX:

I'm pretty sure CMAKE_INSTALL_PREFIX is not related to the problem here. Again, you were using ${CMAKE_CURRENT_BINARY_DIR} for the copy target location, which probably explains the behaviour you were getting. I suspect you might have been using a single-config generator for your VS Code project.

You can set the generator generally using the -G argument of the configure command, or in VS Code with the CMake Tools extension, using the cmake.generator setting (probably not a great idea to hardcode in workspace settings if you commit the workspace settings file to version control though (in that case, put the setting in your user setting.json file)).

Technically, you probably could work around a single-config generator problem in VS Code by using &quot;cmake.buildDirectory&quot;: &quot;${workspaceFolder}/build/${buildType}&quot; (docs), but again, this would just be a workaround, and a bad one at that (if you put it in workspace settings and commit the workspace settings.json file, since it assumes single-config). On this point though, see also the issue ticket [Feature] Add option to specify cmake.buildDirectory for single- and multi-config generators, respectively #2426

huangapple
  • 本文由 发表于 2023年5月13日 07:46:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76240500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定