Here is a CMakeLists.txt that doesn’t work. I migrated a project from using the WinAPI interface directly to using SDL2. Here is the CMakeLists.txt that results. Except that, for purposes of this discussion, I'm using as source a vastly simplified test program that depends directly and only upon SDL2.
cmake_minimum_required(VERSION 3.28)
project(my-project)
set (CMAKE_CXX_STANDARD 11)
set (TEST TestCase.cpp)
#set (CMAKE_PREFIX_PATH C:\\msys64\\ucrt64)
#find_package(SDL2 REQUIRED)
#unset(CMAKE_PREFIX_PATH)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories(. Library Tools Toolkit APClass Library/jpeg ${SDL2_INCLUDE_DIRS})
# include_directories(SYSTEM C:\\msys64\\mingw64\\include)
include(Library/CMakeLists.txt)
include(Tools/CMakeLists.txt)
include(APClass/CMakeLists.txt)
add_executable(TestProgram ${TEST} ${DRAWBOX} ${TOOLS} ${APCLASS})
target_compile_features(TestProgram PUBLIC cxx_std_11)
target_compile_options(TestProgram PRIVATE )
target_link_libraries(TestProgram ${SDL2_LIBRARIES} libSDL2_gfx.a
SDL2_image SDL2_ttf
)
It won't compile. While building TestCase.cpp it gets the error:
Error C1083 Cannot open include file: 'unistd.h': No such file or directory
The problem became apparent as I experimented with CMAKE_PREFIX_PATH, but that may have no bearing. No amount of cache-clearing helps. A variety of other standard headers such as ’strings.h’ are reported likewise.
I tried adding line 13:
include_directories(SYSTEM C:\\sys64\\mingw64\\include)
but as it turns out, that brings in the headers for a different compiler, and just makes a horrible mess.
Here is a CMakeLists.txt that works, the predecessor to the one that fails. Program compiles and runs.
cmake_minimum_required(VERSION 3.28)
project(my-project)
set (CMAKE_CXX_STANDARD 11)
set (TEST Test/CheckerCheckerBoardBoard.cpp)
include_directories(. Library Tools Toolkit APClass Library/jpeg)
include(Library/CMakeLists.txt)
include(Tools/CMakeLists.txt)
include(APClass/CMakeLists.txt)
message( STATUS DRAWBOX=${DRAWBOX})
add_library(Drawbox STATIC ${DRAWBOX} ${TOOLS} ${APCLASS})
add_executable(TestProgram WIN32 ${TEST} ${DRAWBOX} ${TOOLS} ${APCLASS})
target_compile_features(Drawbox PUBLIC cxx_std_11)
target_compile_options(Drawbox PRIVATE -showIncludes)
target_compile_features(TestProgram PUBLIC cxx_std_11)
target_compile_options(TestProgram PRIVATE
)
target_link_libraries(TestProgram winmm.lib)
I’m struggling to see a difference between the two CMake scripts that could account for this issue.
Where to look for such a problem? I'd like to present a nice detailed log file, but I'm going to need some help to know how to even create it. But here’s a CMake clean-generate log:
1> CMake generation started for configuration: 'x64-Debug'.
1> Command line: "C:\Windows\system32\cmd.exe" /c "%SYSTEMROOT%\System32\chcp 65001 >NUL && "C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\2022\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G "Ninja" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="C:\Users\ken\Desktop\prog24\Drawboxish\install\x64-Debug" -DCMAKE_C_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/arm64/cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/arm64/cl.exe" -DCMAKE_MAKE_PROGRAM="C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\2022\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\Ninja\ninja.exe" "C:\Users\ken\Desktop\prog24\Drawboxish" 2>&1"
1> Working directory: C:\Users\ken\Desktop\prog24\Drawboxish\build\x64-Debug
1> [CMake] -- Configuring done (0.2s)
1> [CMake] -- Generating done (0.0s)
1> [CMake] -- Build files have been written to: C:/Users/ken/Desktop/prog24/Drawboxish/build/x64-Debug
1> Extracted CMake variables.
1> Extracted source files and headers.
1> Extracted code model.
1> Extracted toolchain configurations.
1> Extracted includes paths.
1> CMake generation finished.
Here’s TestCase.cpp.
#include <unistd.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <SDL2/SDL_ttf.h>
SDL_Window* gWindow = NULL; //The window we'll be rendering to
SDL_Renderer* gRenderer = NULL; // Renders to an offscreen "texture" (frequent)
static SDL_Texture *target;
SDL_Event event;
TTF_Font *gFont;
void DrawNow();
int points[][2] = {
{50, 50},
{200, 100},
{50, 300},
{400, 400},
{300, 70},
{70, 450}
};
void DrawText(int x, int y, const char* text, SDL_Color fg) {
int width, height;
if (strlen(text) == 0) return;
SDL_Color bgColor = { 0xff, 0xff, 0xff, 0xff};
SDL_Surface* textSurface = TTF_RenderText_Blended(gFont, text, fg);
if( textSurface == NULL )
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
else {
//Create texture from surface pixels
SDL_Texture *mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( mTexture == NULL ) {
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
} else {
//Get image dimensions
width = textSurface->w;
height = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
//Render to screen
int descent = TTF_FontDescent(gFont);
//printf("height: %d descent:%d\n", height, descent);
SDL_Rect renderQuad = { x, y-height-descent, width, height };
SDL_RenderCopy( gRenderer, mTexture, NULL, &renderQuad);
SDL_DestroyTexture(mTexture);
}
}
void TextTest() {
//Rectangle(30, 30, 140, 80, filled + blue);
SDL_Color c1 = {0xff, 0xff, 0x00, 0x00};
SDL_Color c2 = {0xff, 0x00, 0xff, 0x00};
DrawText(50, 50, "hello", c1);
DrawText(60, 55, "goodbye", c2);
DrawNow();
}
void AutoDraw() { // "User" graphics
SDL_Rect rr = {10, 10, 120, 120};
int outcome = SDL_RenderSetViewport(gRenderer, &rr);
filledCircleColor(gRenderer, 100, 100, 40, 0xff00ff00);
sleep(1);
DrawNow();
}
void DrawNow() {
while (SDL_PollEvent(&event)) {
}
SDL_SetRenderTarget(gRenderer, NULL);
SDL_RenderCopy(gRenderer, target, NULL, NULL);
SDL_RenderPresent(gRenderer);
SDL_SetRenderTarget(gRenderer, target);
}
bool drawbox_inited = false;
int main() {
if (! drawbox_inited) {
//Initialize SDL
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
return 1;
}
gWindow = SDL_CreateWindow("Drawbox", 0, 0, 1200, 900, 0);
if( gWindow == NULL ) {
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
return -1;
}
//Create renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
return -1;
}
/* Create texture for display buffering */
target = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1200, 900);
SDL_SetRenderTarget(gRenderer, target);
//SDL_RenderSetLogicalSize(gRenderer, 2000, 1400);
//Clear buffer
SDL_SetRenderDrawColor( gRenderer, 0, 0, 0, 0xff );
SDL_RenderClear( gRenderer );
// Set up for fonts and text
if (TTF_Init() < 0) {
printf("ttf could not be initialized: %s\n", SDL_GetError());
} else {
gFont = TTF_OpenFont( "Cabin-Regular.ttf", 20 );
if( gFont == NULL )
{
printf( "Failed to load default font! SDL_ttf Error: %s\n", TTF_GetError() );
}
}
// handle window creation events: A MUST!
SDL_Event event;
while (SDL_PollEvent(&event)) {
// printf("Event: %d\n", event.type);
}
}
//ClearClip();
srand(time(NULL));
AutoDraw();
sleep(6);
return 0;
}
Here is a CMakeLists.txt that doesn’t work. I migrated a project from using the WinAPI interface directly to using SDL2. Here is the CMakeLists.txt that results. Except that, for purposes of this discussion, I'm using as source a vastly simplified test program that depends directly and only upon SDL2.
cmake_minimum_required(VERSION 3.28)
project(my-project)
set (CMAKE_CXX_STANDARD 11)
set (TEST TestCase.cpp)
#set (CMAKE_PREFIX_PATH C:\\msys64\\ucrt64)
#find_package(SDL2 REQUIRED)
#unset(CMAKE_PREFIX_PATH)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories(. Library Tools Toolkit APClass Library/jpeg ${SDL2_INCLUDE_DIRS})
# include_directories(SYSTEM C:\\msys64\\mingw64\\include)
include(Library/CMakeLists.txt)
include(Tools/CMakeLists.txt)
include(APClass/CMakeLists.txt)
add_executable(TestProgram ${TEST} ${DRAWBOX} ${TOOLS} ${APCLASS})
target_compile_features(TestProgram PUBLIC cxx_std_11)
target_compile_options(TestProgram PRIVATE )
target_link_libraries(TestProgram ${SDL2_LIBRARIES} libSDL2_gfx.a
SDL2_image SDL2_ttf
)
It won't compile. While building TestCase.cpp it gets the error:
Error C1083 Cannot open include file: 'unistd.h': No such file or directory
The problem became apparent as I experimented with CMAKE_PREFIX_PATH, but that may have no bearing. No amount of cache-clearing helps. A variety of other standard headers such as ’strings.h’ are reported likewise.
I tried adding line 13:
include_directories(SYSTEM C:\\sys64\\mingw64\\include)
but as it turns out, that brings in the headers for a different compiler, and just makes a horrible mess.
Here is a CMakeLists.txt that works, the predecessor to the one that fails. Program compiles and runs.
cmake_minimum_required(VERSION 3.28)
project(my-project)
set (CMAKE_CXX_STANDARD 11)
set (TEST Test/CheckerCheckerBoardBoard.cpp)
include_directories(. Library Tools Toolkit APClass Library/jpeg)
include(Library/CMakeLists.txt)
include(Tools/CMakeLists.txt)
include(APClass/CMakeLists.txt)
message( STATUS DRAWBOX=${DRAWBOX})
add_library(Drawbox STATIC ${DRAWBOX} ${TOOLS} ${APCLASS})
add_executable(TestProgram WIN32 ${TEST} ${DRAWBOX} ${TOOLS} ${APCLASS})
target_compile_features(Drawbox PUBLIC cxx_std_11)
target_compile_options(Drawbox PRIVATE -showIncludes)
target_compile_features(TestProgram PUBLIC cxx_std_11)
target_compile_options(TestProgram PRIVATE
)
target_link_libraries(TestProgram winmm.lib)
I’m struggling to see a difference between the two CMake scripts that could account for this issue.
Where to look for such a problem? I'd like to present a nice detailed log file, but I'm going to need some help to know how to even create it. But here’s a CMake clean-generate log:
1> CMake generation started for configuration: 'x64-Debug'.
1> Command line: "C:\Windows\system32\cmd.exe" /c "%SYSTEMROOT%\System32\chcp 65001 >NUL && "C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\2022\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" -G "Ninja" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="C:\Users\ken\Desktop\prog24\Drawboxish\install\x64-Debug" -DCMAKE_C_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/arm64/cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/arm64/cl.exe" -DCMAKE_MAKE_PROGRAM="C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\2022\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\Ninja\ninja.exe" "C:\Users\ken\Desktop\prog24\Drawboxish" 2>&1"
1> Working directory: C:\Users\ken\Desktop\prog24\Drawboxish\build\x64-Debug
1> [CMake] -- Configuring done (0.2s)
1> [CMake] -- Generating done (0.0s)
1> [CMake] -- Build files have been written to: C:/Users/ken/Desktop/prog24/Drawboxish/build/x64-Debug
1> Extracted CMake variables.
1> Extracted source files and headers.
1> Extracted code model.
1> Extracted toolchain configurations.
1> Extracted includes paths.
1> CMake generation finished.
Here’s TestCase.cpp.
#include <unistd.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <SDL2/SDL_ttf.h>
SDL_Window* gWindow = NULL; //The window we'll be rendering to
SDL_Renderer* gRenderer = NULL; // Renders to an offscreen "texture" (frequent)
static SDL_Texture *target;
SDL_Event event;
TTF_Font *gFont;
void DrawNow();
int points[][2] = {
{50, 50},
{200, 100},
{50, 300},
{400, 400},
{300, 70},
{70, 450}
};
void DrawText(int x, int y, const char* text, SDL_Color fg) {
int width, height;
if (strlen(text) == 0) return;
SDL_Color bgColor = { 0xff, 0xff, 0xff, 0xff};
SDL_Surface* textSurface = TTF_RenderText_Blended(gFont, text, fg);
if( textSurface == NULL )
printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
else {
//Create texture from surface pixels
SDL_Texture *mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
if( mTexture == NULL ) {
printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
} else {
//Get image dimensions
width = textSurface->w;
height = textSurface->h;
}
//Get rid of old surface
SDL_FreeSurface( textSurface );
//Render to screen
int descent = TTF_FontDescent(gFont);
//printf("height: %d descent:%d\n", height, descent);
SDL_Rect renderQuad = { x, y-height-descent, width, height };
SDL_RenderCopy( gRenderer, mTexture, NULL, &renderQuad);
SDL_DestroyTexture(mTexture);
}
}
void TextTest() {
//Rectangle(30, 30, 140, 80, filled + blue);
SDL_Color c1 = {0xff, 0xff, 0x00, 0x00};
SDL_Color c2 = {0xff, 0x00, 0xff, 0x00};
DrawText(50, 50, "hello", c1);
DrawText(60, 55, "goodbye", c2);
DrawNow();
}
void AutoDraw() { // "User" graphics
SDL_Rect rr = {10, 10, 120, 120};
int outcome = SDL_RenderSetViewport(gRenderer, &rr);
filledCircleColor(gRenderer, 100, 100, 40, 0xff00ff00);
sleep(1);
DrawNow();
}
void DrawNow() {
while (SDL_PollEvent(&event)) {
}
SDL_SetRenderTarget(gRenderer, NULL);
SDL_RenderCopy(gRenderer, target, NULL, NULL);
SDL_RenderPresent(gRenderer);
SDL_SetRenderTarget(gRenderer, target);
}
bool drawbox_inited = false;
int main() {
if (! drawbox_inited) {
//Initialize SDL
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
return 1;
}
gWindow = SDL_CreateWindow("Drawbox", 0, 0, 1200, 900, 0);
if( gWindow == NULL ) {
printf( "Window could not be created! SDL Error: %s\n", SDL_GetError() );
return -1;
}
//Create renderer for window
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
if( gRenderer == NULL )
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
return -1;
}
/* Create texture for display buffering */
target = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1200, 900);
SDL_SetRenderTarget(gRenderer, target);
//SDL_RenderSetLogicalSize(gRenderer, 2000, 1400);
//Clear buffer
SDL_SetRenderDrawColor( gRenderer, 0, 0, 0, 0xff );
SDL_RenderClear( gRenderer );
// Set up for fonts and text
if (TTF_Init() < 0) {
printf("ttf could not be initialized: %s\n", SDL_GetError());
} else {
gFont = TTF_OpenFont( "Cabin-Regular.ttf", 20 );
if( gFont == NULL )
{
printf( "Failed to load default font! SDL_ttf Error: %s\n", TTF_GetError() );
}
}
// handle window creation events: A MUST!
SDL_Event event;
while (SDL_PollEvent(&event)) {
// printf("Event: %d\n", event.type);
}
}
//ClearClip();
srand(time(NULL));
AutoDraw();
sleep(6);
return 0;
}
Share
Improve this question
asked Jan 17 at 20:00
JoymakerJoymaker
1,4282 gold badges19 silver badges36 bronze badges
7
|
Show 2 more comments
2 Answers
Reset to default 0‘unistd.h’ is native to POSIX-compliant systems, i’ve heard of a couple equivalents out there, but i think it depends on the functions you’re trying to grab from it, but most of them usually lie in ‘windows.h’
if unistd.h is necessary with no equivalents for your code, the only case it would work is in a POSIX environment, which means anything based in UNIX (a macOS may also be able to do the trick, but keep in mind not every OS is fully compatible with POSIX)
The answer turned out quite surprising, and it took an hour with a colleague to understand it: the VC++ environment is so different from any of the MinGW/GCC environments that you have to download an entirely different version of SDL2 for it! Both libraries and headers are different. VC++ is not a POSIX compliant environment, which means in practice that things one might lightly presume to be part of C++ itself, including <unistd.h> and even <strings.h>, are not present.
I had made the mistake of taking an existing folder and installation set up for Visual Studio Code and GCC, and trying to slap a Visual Studio Solution on it.
This issue might not be evident to someone who was accustomed to using a package manager. But no! You wouldn't even use the same package manager! All becomes clearer if you download SDL2 directly from its website. This partial screenshot of their list of download options highlights the one I needed.
This also answers other questions I was struggling with, like why SDL (gcc version) was giving me libraries with the .a extension while CMake (VC++ world) was insisting on looking for libraries with the .lib extension.
unistd.h
is not a C++ standard header. I believe it is part of some POSIX standard but not C++. – john Commented Jan 17 at 20:03unistd.h
is a UNIX header - it doesn't exist on Windows and shouldn't be included in portable cross-platform code. – Jesper Juhl Commented Jan 17 at 20:03unistd.h
for? – john Commented Jan 17 at 20:06unistd.h
that's gcc/mingw only – Ahmed AEK Commented Jan 17 at 21:29