Leonid Pospelov (c64f6d5a) at 03 May 04:41
Help: Document append functionality of string(JSON)
I wanted to add string(JSON ... APPEND ...)
but then saw that there is undocumented functionality for appending values to JSON arrays.
I wanted to add string(JSON ... APPEND ...)
but then saw that there is undocumented functionality for appending values to JSON arrays.
I suggest touch-like behavior (in terms of empty file creation), but always overwrite file contents with "" in case of already existing file.
In one of projects I had to change touch
to copy
to always overwrite existing file:
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/dist/server/gamemode.js
)
I quick-fixed the code by using cmake -E copy
:
# create an empty file
file(WRITE "${CMAKE_BINARY_DIR}/empty_file" "")
# copy since we can't do `cmake -E write` yet
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/empty_file ${CMAKE_BINARY_DIR}/dist/server/gamemode.js
)
However I think it could be better if we could call cmake -E something to do the job, without anything else:
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E write ${CMAKE_BINARY_DIR}/dist/server/gamemode.js ""
)
Please let me know if this functionality already exists. If not, please tell me if write
is a good name in this case or not, etc
Other possible options could be:
cmake -e echo --out-file <filepath> "<text>"
cmake -E "file(WRITE foo bar)"
(new script-mode-like mode)Thank you in advance!
thanks, is it cross platform?
I suggest touch-like behavior (in terms of empty file creation), but always overwrite file contents with "" in case of already existing file.
In one of projects I had to change touch
to copy
to always overwrite existing file:
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/dist/server/gamemode.js
)
I quick-fixed the code by using cmake -E copy
:
# create an empty file
file(WRITE "${CMAKE_BINARY_DIR}/empty_file" "")
# copy since we can't do `cmake -E write` yet
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/empty_file ${CMAKE_BINARY_DIR}/dist/server/gamemode.js
)
However I think it could be better if we could call cmake -E something to do the job, without anything else:
add_custom_target(skymp5-functions-lib ALL
SOURCES ${sources}
COMMAND ${CMAKE_COMMAND} -E write ${CMAKE_BINARY_DIR}/dist/server/gamemode.js ""
)
Please let me know if this functionality already exists. If not, please tell me if write
is a good name in this case or not, etc
Other possible options could be:
cmake -e echo --out-file <filepath> "<text>"
cmake -E "file(WRITE foo bar)"
(new script-mode-like mode)Thank you in advance!
It'd be nice to have such a feature. I'll be happy if you'll be able to get back to this:)
Thanks! Yeah, I think this is a valid feature request then. However your code example works for me too.
CMake does not currently model something like add_library(foo SHARED foo.def)
, with no other sources, to produce a .lib
import library on Windows without running a linker to produce the corresponding .dll
or .exe
file.
I have a project that builds node.lib
with custom .def file (my compiler is MSVC)
project(nodelib)
add_custom_target(nodelib_def ALL
COMMAND ${NODEJS_EXECUTABLE} ${CMAKE_SOURCE_DIR}/generateNodeLibDef.js
COMMENT "Generating .def file"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
add_custom_target(nodelib ALL
COMMAND ${CMAKE_AR}
/def:${CMAKE_SOURCE_DIR}/node.def
/out:${CMAKE_BINARY_DIR}/node.lib
${CMAKE_STATIC_LINKER_FLAGS}
DEPENDS ${CMAKE_JS_NODELIB_DEF}
COMMENT "Building node.lib"
)
add_dependencies(nodelib nodelib_def)
install(FILES ${CMAKE_BINARY_DIR}/node.lib DESTINATION lib)
I'm trying to rewrite add_custom_target
with add_library
:
add_library(node STATIC)
set_target_properties(node PROPERTIES LINK_FLAGS "/def:${CMAKE_SOURCE_DIR}/node.def")
I'm getting the following error:
CMake Error at C:/projects/vcpkg/scripts/buildsystems/vcpkg.cmake:623 (_add_library):
No SOURCES given to target: node
Call Stack (most recent call first):
CMakeLists.txt:10 (add_library)
CMake Generate step failed. Build files cannot be regenerated correctly.
ninja: build stopped: subcommand failed.
Can I somehow use add_library
? Maybe there is something I'm missing
I see. Closing for now, thanks for your answer!
CMake tooling often requires binary dir to be "${CMAKE_SOURCE_DIR}/build"
I suggest adding EXPECTED_BINARY_DIR
to emit fatal error if binary dir doesn't match a specified pattern.
Currently:
https://github.com/skyrim-multiplayer/skymp/blob/main/CMakeLists.txt#L34
if(NOT "${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}/build")
set(msg "CMake binary directory must be <repo_root>/build")
set(msg "${msg}\nUse commands below after cloning the repo (replace path with your actual Skyrim SE folder):")
set(msg "${msg}\n mkdir build")
set(msg "${msg}\n cd build")
set(msg "${msg}\nFor users who have Skyrim SE installed:")
set(msg "${msg}\n cmake .. -DSKYRIM_DIR=\"C:/Program Files (x86)/Steam/steamapps/common/Skyrim Special Edition\"")
set(msg "${msg}\nFor users who don't have Skyrim SE installed:")
set(msg "${msg}\n cmake ..")
message(FATAL_ERROR "${msg}")
endif()
cmake_minimum_required(VERSION 3.18.2)
project(skymp)
With the feature implemented:
project(skymp EXPECTED_BINARY_DIR build)
Please leave a feedback for this feature request.
Sounds reasonable. Thanks! Closing for now
One of the ways of using vcpkg in project is adding it as a submodule and setting CMAKE_TOOLCHAIN_FILE
to "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
.
In that case vcpkg manages to install all dependencies specified in vcpkg.json
file.
Some users forget to checkout submodules and I use this quality-of-life fix for them:
if(NOT EXISTS "${CMAKE_TOOLCHAIN_FILE}")
set(msg "${CMAKE_TOOLCHAIN_FILE} doesn't exist. It seems that vcpkg submodule is not initialized.")
set(msg "${msg}\nUse commands below to initialize:")
set(msg "${msg}\n git submodule init")
set(msg "${msg}\n git submodule update")
message(FATAL_ERROR "${msg}")
endif()
I suggest to make this behavior standard.
Without that users would see just Could not find toolchain file
which is confusing, especially since the toolchain files are originally for cross-compiling, not for package managers, etc.
All we need to add some extra logic to CMakeDetermineSystem.cmake
P.S. It will not hardcode references to vcpkg into cmake. It will just work with any toolchain files from submodules instead.
One of the ways of using vcpkg in project is adding it as a submodule and setting CMAKE_TOOLCHAIN_FILE
to "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake"
.
In that case vcpkg manages to install all dependencies specified in vcpkg.json
file.
Some users forget to checkout submodules and I use this quality-of-life fix for them:
if(NOT EXISTS "${CMAKE_TOOLCHAIN_FILE}")
set(msg "${CMAKE_TOOLCHAIN_FILE} doesn't exist. It seems that vcpkg submodule is not initialized.")
set(msg "${msg}\nUse commands below to initialize:")
set(msg "${msg}\n git submodule init")
set(msg "${msg}\n git submodule update")
message(FATAL_ERROR "${msg}")
endif()
I suggest to make this behavior standard.
Without that users would see just Could not find toolchain file
which is confusing, especially since the toolchain files are originally for cross-compiling, not for package managers, etc.
All we need to add some extra logic to CMakeDetermineSystem.cmake
P.S. It will not hardcode references to vcpkg into cmake. It will just work with any toolchain files from submodules instead.
CMake tooling often requires binary dir to be "${CMAKE_SOURCE_DIR}/build"
I suggest adding EXPECTED_BINARY_DIR
to emit fatal error if binary dir doesn't match a specified pattern.
Currently:
https://github.com/skyrim-multiplayer/skymp/blob/main/CMakeLists.txt#L34
if(NOT "${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}/build")
set(msg "CMake binary directory must be <repo_root>/build")
set(msg "${msg}\nUse commands below after cloning the repo (replace path with your actual Skyrim SE folder):")
set(msg "${msg}\n mkdir build")
set(msg "${msg}\n cd build")
set(msg "${msg}\nFor users who have Skyrim SE installed:")
set(msg "${msg}\n cmake .. -DSKYRIM_DIR=\"C:/Program Files (x86)/Steam/steamapps/common/Skyrim Special Edition\"")
set(msg "${msg}\nFor users who don't have Skyrim SE installed:")
set(msg "${msg}\n cmake ..")
message(FATAL_ERROR "${msg}")
endif()
cmake_minimum_required(VERSION 3.18.2)
project(skymp)
With the feature implemented:
project(skymp EXPECTED_BINARY_DIR build)
Please leave a feedback for this feature request.
Hey! I'm running into an issue with CMake on my Windows machine (Visual Studio 2019 generator).
It seems this is specific to my system, but hope you have a clue on how to workaround. Non-cmake generated Visual Studio projects work fine. Before creating this issue, I was googling this error 2 days and didn't succeed. Thanks for your attention!
My CMakeLists.txt
:
cmake_minimum_required(VERSION 3.22)
project(test)
Output:
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19042.
CMake Error at CMakeLists.txt:2 (project):
Failed to run MSBuild command:
C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/MSBuild/Current/Bin/MSBuild.exe
to get the value of VCTargetsPath:
Microsoft (R) Build Engine version 16.11.2+f32259642 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 26.08.2022 13:32:38.
Project "C:\projects\test\build\CMakeFiles\3.24.1\VCTargetsPath.vcxproj" on node 1 (default targets).
InitializeBuildStatus:
Touching "x64\Debug\VCTargetsPath.tlog\unsuccessfulbuild".
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(155,5): error MSB6004: The specified task executable location "C:\WINDOWS\system32\cmd.exe" is invalid. [C:\projects\test\build\CMakeFiles\3.24.1\VCTargetsPath.vcxproj]
Done Building Project "C:\projects\test\build\CMakeFiles\3.24.1\VCTargetsPath.vcxproj" (default targets) -- FAILED.
Build FAILED.
"C:\projects\test\build\CMakeFiles\3.24.1\VCTargetsPath.vcxproj" (default target) (1) ->
(PostBuildEvent target) ->
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(155,5): error MSB6004: The specified task executable location "C:\WINDOWS\system32\cmd.exe" is invalid. [C:\projects\test\build\CMakeFiles\3.24.1\VCTargetsPath.vcxproj]
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.41
Exit code: 1
-- Configuring incomplete, errors occurred!
See also "C:/projects/test/build/CMakeFiles/CMakeOutput.log".
Thanks!