vector-of-bool / cmrc Goto Github PK
View Code? Open in Web Editor NEWA Resource Compiler in a Single CMake Script
License: MIT License
A Resource Compiler in a Single CMake Script
License: MIT License
When using strict compiler warnings with clang, the header cmrc.hpp
emits conversion warnings.
When building a project using cmrc, such a warning should not appear to the user, so I woud propose to specify the include directory as a system include to silence warnings:
target_include_directories(cmrc-base SYSTEM INTERFACE $<BUILD_INTERFACE:${CMRC_INCLUDE_DIR}>)
Hi!
I am currently trying to use this tool to compile shader into our shared library, but I get the following error during compile:
make[3]: *** No rule to make target '../src/shaders/debug_fragment.glsl', needed by '__cmrc_foo-shaders/intermediate/debug_fragment.glsl.cpp'. Stop.
I am using the following function to include the files:
cmrc_add_resource_library(foo-shaders ALIAS shaders::rc NAMESPACE shaders WHENCE src/shaders ...)
Hi, I hope you are doing well.
What I don't understand is how it's possible to embed arbitrary files into my executable. Would you mind explaining that to me? Of course I followed the exact method that was in the README.md file. However, the size of my executable didn't change no matter how large my resources were.
There is my project structure:
-CMakeLists.txt
-CMakeRC.cmake
-resources/
Photo.jpg
My configuration for CMake:
cmake_minimum_required(VERSION 3.10)
project(AddResource)#========== Global Configurations
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE ON)set(CMAKE_CXX_EXTENSIONS OFF)
include(CMakeRC.cmake)
cmrc_add_resource_library( app1-resources
ALIAS app1::rc NAMESPACE app1 resources/archive.zip resources/photo.jpg )
add_executable(MyExe code.cpp)
target_link_libraries(MyExe app1::rc)
My code is:
#include <stdio.h>
#include <cmrc/cmrc.hpp>
CMRC_DECLARE(app1);
int main()
{
getchar();
return 0;
}
First of all, to use Clangd's LSP feature, I set set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
in CMakeLists.txt. This makes the compile commands to be written to the compile_commands.json file, which helps the language server understand the project structure.
However, using cmrc_add_resource_library()
in CMakeLists.txt causes some header files to not recognize other header files. For example, the project structure is as follows
│ CMakeLists.txt
│ CMakeRC.cmake
├─build
├─include1
│ header1.h
├─include2
│ header2.h
├─resources
│ kitty.png
└─src
main.cpp
in this case, if header1.h imports header2.h, LSP says it could not find the file. (However, it will compile and build normally!)
I tried to use:
cmrc::resource file = cmrc::open(file); std::string data(file.begin(), file.end());
But there is no string constructor like this. How do I use CMakeRC?
你好 请问#include <cmrc/cmrc.hpp>这个文件是哪里来的,为什么找不到 呢?
Please provide one.
My current workaround is: std::string_view data(file.begin(), file.end() - file.begin());
Right now it seems that cmrc only supports adding files from the sourcetree.
I have an application where I have to add some build outputs to the resource library, but there seems to be a configure time check for the existence of the file. The actual conversion of the file is performed at build time, so I can ensure that the target generating the file is executed before and the file is present.
As a workaround I've added a file(TOUCH ...)
command before the cmrc calls. This works but looks a bit funny.
Is there a better way to do this right now? Is it a valid usecase?
Possible improvements to cmrc in this regard:
I'd be happy to contribute a PR but I wanted to make sure that this isn't already supported or going into the wrong direction.
My usecase is to compile a webasembly client in a cmake ExternalProject_add
call and then add the .wasm/.html files as resources to the server component which will serve them next to the api endpoint.
Linker error when I try to link with cmrc generated library with a SHARED
library.
/usr/bin/ld: thelibx-resources.a(lib.cpp.o): relocation R_X86_64_PC32 against symbol `_ZN4cmrc6detail9directoryD1Ev' can not be used when making a shared object; recompile with -fPIC
I want the shared library to be statically linked with the cmrc_add_resource_library
generated target thelibx-resources
.
add_library(thelibx SHARED ${THE_LIBX_SOURCES})
target_link_libraries(thelibx ${Boost_PROGRAM_OPTIONS_LIBRARY} thelibx-resources)
If I remove that SHARED
then everything works fine.
CMakeLists.txt:
include(CMakeRC.cmake)
cmrc_add_resource_library(my_files data/foo.bin)
add_executable(
MyApp
main.cpp
)
target_link_libraries(
MyApp
PRIVATE
my_files
...
)
However for some reason #include <cmrc/cmrc.hpp>
always says the include file cannot be found. When I look at the compiler command, I don't see the include path anywhere (there's no -I<...>/cmrc
anywhere).
Any idea what might be going on?
CMake version 3.23.
Hello and well done on your excellent and hard work. I find this cmake module very usefull and I want to install it system-wide on my Gentoo with an ebuild. Perphaps pimp the ebuild into the Portage tree.
But the ebuild failed in install phase with this:
OUTPUT(tests/whence elf64-x86-64)
/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/../../../../x86_64-pc-linux-gnu/bin/ld: total time in link: 0.143828
>>> Source compiled.
>>> Test phase [not enabled]: dev-cpp/cmrc-2.0.1
>>> Install dev-cpp/cmrc-2.0.1 into /mnt/Volume_3/Gentoo/temp/portage/dev-cpp/cmrc-2.0.1/image
>>> Working in BUILD_DIR: "/mnt/Volume_3/Gentoo/temp/portage/dev-cpp/cmrc-2.0.1/work/cmrc-2.0.1_build"
ninja: error: unknown target 'install'
* ERROR: dev-cpp/cmrc-2.0.1::testing failed (install phase):
* died running ninja install
*
* Call stack:
* ebuild.sh, line 125: Called src_install
* environment, line 2183: Called cmake-utils_src_install
* environment, line 974: Called die
* The specific snippet of code:
* DESTDIR="${D}" ${CMAKE_MAKEFILE_GENERATOR} install "$@" || die "died running ${CMAKE_MAKEFILE_GENERATOR} install";
*
So, could you provide an install target for the module and/or the examples?
Thank you very much.
I didn't see any license in the code or readme.
Building the current repository with Visual Studio 2017 fails:
$ mkdir build
$ cd build
$ cmake "Visual Studio 15 2017 Win64" ..
$ cmake --build .
Gives:
Microsoft (R) Build Engine version 15.7.177.53362 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 18/05/2018 9:02:30 AM.
Project "C:\work\cmrc\build\ALL_BUILD.vcxproj" on node 1 (default targets).
Project "C:\work\cmrc\build\ALL_BUILD.vcxproj" (1) is building "C:\work\cmrc\build\ZERO_CHECK.vcxproj" (2) on node 1 (d
efault targets).
PrepareForBuild:
Creating directory "x64\Debug\ZERO_CHECK\".
Creating directory "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\".
InitializeBuildStatus:
Creating "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
Checking Build System
CMake does not need to re-run because C:/work/cmrc/build/CMakeFiles/generate.stamp is up-to-date.
FinalizeBuildStatus:
Deleting file "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild".
Touching "x64\Debug\ZERO_CHECK\ZERO_CHECK.tlog\ZERO_CHECK.lastbuildstate".
Done Building Project "C:\work\cmrc\build\ZERO_CHECK.vcxproj" (default targets).
Project "C:\work\cmrc\build\ALL_BUILD.vcxproj" (1) is building "C:\work\cmrc\build\flower.vcxproj" (3) on node 1 (defau
lt targets).
Project "C:\work\cmrc\build\flower.vcxproj" (3) is building "C:\work\cmrc\build\hello.vcxproj" (4) on node 1 (default t
argets).
PrepareForBuild:
Creating directory "hello.dir\Debug\".
Creating directory "C:\work\cmrc\build\Debug\".
Creating directory "hello.dir\Debug\hello.tlog\".
InitializeBuildStatus:
Creating "hello.dir\Debug\hello.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
ComputeCustomBuildOutput:
Creating directory "C:\work\cmrc\build\hello\intermediate\".
CustomBuild:
Generating hello resource loader
Generating intermediate file for C:/work/cmrc/hello.txt
Generating intermediate file for C:/work/cmrc/flower.jpg
Building Custom Rule C:/work/cmrc/CMakeLists.txt
CMake does not need to re-run because C:/work/cmrc/build/CMakeFiles/generate.stamp is up-to-date.
ClCompile:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\HostX86\x64\CL.exe /c /IC
:\work\cmrc\build\_cmrc\include /Zi /nologo /W3 /WX- /diagnostics:classic /Od /Ob0 /D WIN32 /D _WINDOWS /D "CMAKE_INT
DIR=\"Debug\"" /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /Fo"hello.dir\D
ebug\\" /Fd"hello.dir\Debug\hello.pdb" /Gd /TP /FC /errorReport:queue C:\work\cmrc\build\hello\lib.cpp C:\work\cmrc\b
uild\hello\intermediate\hello.txt.cpp C:\work\cmrc\build\hello\intermediate\flower.jpg.cpp
lib.cpp
hello.txt.cpp
flower.jpg.cpp
c:\work\cmrc\build\hello\intermediate\flower.jpg.cpp(1): error C2026: string too big, trailing characters truncated [C:
\work\cmrc\build\hello.vcxproj]
Generating Code...
Done Building Project "C:\work\cmrc\build\hello.vcxproj" (default targets) -- FAILED.
Done Building Project "C:\work\cmrc\build\flower.vcxproj" (default targets) -- FAILED.
Done Building Project "C:\work\cmrc\build\ALL_BUILD.vcxproj" (default targets) -- FAILED.
Build FAILED.
"C:\work\cmrc\build\ALL_BUILD.vcxproj" (default target) (1) ->
"C:\work\cmrc\build\flower.vcxproj" (default target) (3) ->
"C:\work\cmrc\build\hello.vcxproj" (default target) (4) ->
(ClCompile target) ->
c:\work\cmrc\build\hello\intermediate\flower.jpg.cpp(1): error C2026: string too big, trailing characters truncated [
C:\work\cmrc\build\hello.vcxproj]
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:04.11
We can fix this by reverting back to an array of chars in the intermediate representation rather than using a string literal.
On most compilers (gcc, clang) you can actually have a nested namespace. This bit me, because MSVC doesn't let you do that by default. Maybe there's a way that a nested namespace can be detected and expanded in the generated code.
To reproduce, simply try following the instructions with
cmrc_add_resource_library(foo-resources ALIAS foo::rc NAMESPACE foo::bar ...)
And then keep going. In the generated lib.cpp
file you'll see
namespace foo::bar {
....which I think is legal C++17. I'm surprised that my gcc didn't choke (it was set to C++14), but MSVC for sure didn't like it. If this can be autoexpanded to
namespace foo { namespace bar {
(and then again on the closing braces), this will work just fine.
Would it be possible/worthwhile to have a version of this library that provides the file data in a constexpr context instead of hiding the data in a cpp file?
This library feels dangerously close to a std::embed
equivalent/workaround, and having access to some file contents from a constexpr context would be very handy.
Running this with the Ninja generator results in the following warning:
[cmake] CMake Warning (dev):
[cmake] Policy CMP0058 is not set: Ninja requires custom command byproducts to be
[cmake] explicit. Run "cmake --help-policy CMP0058" for policy details. Use the
[cmake] cmake_policy command to set the policy and suppress this warning.
[cmake]
[cmake] This project specifies custom command DEPENDS on files in the build tree
[cmake] that are not specified as the OUTPUT or BYPRODUCTS of any
[cmake] add_custom_command or add_custom_target:
[cmake]
[cmake] _cmrc/include/cmrc/cmrc.hpp
[cmake]
[cmake] For compatibility with versions of CMake that did not have the BYPRODUCTS
[cmake] option, CMake is generating phony rules for such files to convince 'ninja'
[cmake] to build.
[cmake]
[cmake] Project authors should add the missing BYPRODUCTS or OUTPUT options to the
[cmake] custom commands that produce these files.
[cmake] This warning is for project developers. Use -Wno-dev to suppress it.
It would be useful to be able to add a target to a resource.
For example a target that generates an image.
Hi,
When using CMakeRC in a project, one has to add all of the resource libraries to the export target. Like this:
cmrc_add_resource_library(foo-resources ALIAS foo::rc NAMESPACE foo data/test.txt)
target_link_libraries(sample_project PRIVATE foo::rc)
install(TARGETS sample_project foo-resources ... EXPORT sample_projectTargets ...)
foo-resources
is of course a STATIC
library, but it requires the cmrc::base
as an INTERFACE
dependency here:
target_link_libraries(${name} PUBLIC cmrc::base)
Thus, CMake complains that cmrc-base
is not in any export target. According to this, this, and this, the most simple fix would be to change that line to:
target_link_libraries(${name} PUBLIC "$<BUILD_INTERFACE:cmrc-base>")
What do you think? Is it a viable fix or it breaks something elsewhere?
Currently, directory
contains a std::deque<directory> _dirs
. This std::deque
is instantiated with the incomplete type directory
.
class directory {
std::deque<directory> _dirs;
As far as I can tell, this isn't allowed by the standard, and MSVC rejects it.
The cppreference entry on std::deque
seems to imply that it doesn't allow incomplete types, especially when juxtaposed with std::vector
. It's not just cppreference, n4659 does the same:
An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements. T shall be complete before any member of the resulting specialization of vector is referenced.
[deque] has no such mention.
I seem to have an issue with linking a library that uses cmrc. For example I have a file called foo.cpp
in my src dir which has code that calls cmrc::resource_name::filesystem()
. When I build this library I have no issues but when I link this library to its respective test file I have linkage issues where there is an error of undefined reference to cmrc::resource_name::filesystem()
.
Hi, thanks for nice work. I am having trouble with a setup like this. Use "cmrc_add_resource_library" at top level source directory and "add_subdirectory" some sub directory. Each sub directory with a "cmrc_add_resources" command for resource files in that sub directory.
CMake always complain about that it can not find source file (intermediate cpp file) at configuring (cmake) step.
CMake Error at cmake/CMakeRC.cmake:498 (add_library):
Cannot find source file:
/home/nvidia/DeepStream/release/__cmrc_vinbigdata_deepstream-resources/intermediate/rc.jpg.cpp
I'd love to here your ideas or minimal example supporting such case.
When installing a STATIC
library that includes files using cmrc_add_resource_library
, it is necessary to export and install the library generated by CMakeRC
as well. This shouldn't be necessary.
An option would be to generate an OBJECT
library instead of a STATIC
library, and to use it with target_sources
and target_include_directories
instead of linking it with target_link_libraries
I'm currently writing a C++ app for android and accessing assets from native code is far from trivial in Android.
On my search for alternatives I stumbled upon your resource compiler. It looks fantastic and would solve a lot of problems for me. However when I try to access resources it just returns null pointers as iterators.
Have a look at the following:
Inside CMakeLists.txt:
cmrc_add_resource_library(shaderFiles src/main/assets/shader/standard.fs src/main/assets/shader/standard.vs)
Inside C++:
CMRC_INIT(shaderFiles);
auto stdVertexShader = cmrc::open("src/main/assets/shader/standard.vs");
auto stdFragShader = cmrc::open("src/main/assets/shader/standard.fs");
LOGI("%d", stdVertexShader.end()-stdVertexShader.begin()); // prints "0"
LOGI("%d", (int)stdVertexShader.begin()); // prints "0"
The code compiles without errors and prints two zeros when executed. However the vertex shader file definitely contains data.
In order to get behind this I added the following line to the cmake script:
function(_cmrc_generate_intermediate_cpp libname symbol outfile infile)
message(STATUS "infile: ${infile}") # <--
add_custom_command(
This prints "infile: /home/<...>/ProjectPath/app/src/main/assets/shader/standard.vs" (and respectively "*.fs") which are the valid paths to my files I want to include. (Tested using "cat")
The table entries in "/home/<...>/ProjectPath/app/shaderFiles/lib_.cpp" are the following:
// Table entry for src/main/assets/shader/standard.fs
table.emplace("src/main/assets/shader/standard.fs", resource{res_chars::f_be11_src_main_assets_shader_standard_fs_begin, res_chars::f_be11_src_main_assets_shader_standard_fs_end});
// Table entry for src/main/assets/shader/standard.vs
table.emplace("src/main/assets/shader/standard.vs", resource{res_chars::f_6947_src_main_assets_shader_standard_vs_begin, res_chars::f_6947_src_main_assets_shader_standard_vs_end});
So I'm using the correct keys and the script uses the correct file paths. What could have gone wrong? How can I further investigate this problem? I'm not exactly a CMake expert...
I have a few resource files around 155 MB.
In the building process, the following error occurred:
(I used msvc tool set.)
~~~resourceFileName.cpp(1): fatal error C1060: compiler is out of heap space
(And overloads memory and disk. My computer almost died...)
How to solve this problem?
Issue in "CMakeRC.cmake": prefix increment operator is written as postfix and vice versa.
Should be:
iterator operator++(int) noexcept {
auto cp = *this;
++_base_iter;
return cp;
}
iterator& operator++() noexcept {
++_base_iter;
return *this;
}
I am trying to pass a cmrc resource file to a function that takes a std::istream object as input. In order to do that, I create a std::streambuf object from the cmrc data, which I can then pass to std::istream. There are two issues I've encountered:
char*
, whereas cmrc's begin() and end() return const char*
. This isn't such a big deal, as I've found a few workarounds.Is there some way to make this work? I could probably create a string from the data and then pass it to a std:istringstream, but I am trying to avoid the copy, as my data files could be very large. This is all rather new territory for me, so I wouldn't be surprised if I just overlooked something obvious.
include <cmrc/cmrc.hpp>
#include <cstddef>
#include <iostream>
#include <streambuf>
CMRC_DECLARE(simple);
struct membuf : std::streambuf {
membuf(char *begin, char *end) { this->setg(begin, begin, end); }
};
int main() {
auto fs = cmrc::simple::get_filesystem();
auto data = fs.open("hello.txt");
// Instead of const_cast, Krzysztof Tomaszewski at The Art of Code provides
// a solution to use const char* with streambuf.
// https://artofcode.wordpress.com/2010/12/12/deriving-from-stdstreambuf/
// However, I wanted to keep things simple for this example.
membuf data_buf(const_cast<char*>(data.begin()),
const_cast<char*>(data.end()));
std::istream data_stream(&data_buf);
data_stream.seekg(0, data_stream.end);
size_t data_size = data_stream.tellg();
std::cout << data_size << '\n'; // This prints 18446744073709551615 on my computer.
}
add an option to encrypt a resource using a given key
Is it possible to split the C++ source embedded in the CMake file into its own files? It would make following the project much easier.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.