Skip to content

Commit

Permalink
Added os touchfile and a workaround for vs2010 reloading
Browse files Browse the repository at this point in the history
vs2010 (and above) has an issue where if the vcxproj file
isn't modified but the.vcxproj.filters is modified during
premake, then VS doesn't notify the user that the project has
changed.  This can occur if the only change to a project is
with the vpaths.  Before this fix, the user would be need to
manually unload and reload the project to pick up the change.

This VS workaround checks for the case where the vcxproj.filters
file is modified but the .vcxproj file is not. At which point
premake preforms a touch on the .vcxproj file to trigger the IDE.
  • Loading branch information
bwhittle authored and Tom van Dijck committed Jun 14, 2017
1 parent 6907f67 commit 760eafc
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/actions/vstudio/vs2010.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
end

elseif p.project.isc(prj) or p.project.iscpp(prj) then
p.generate(prj, ".vcxproj", vstudio.vc2010.generate)
local projFileModified = p.generate(prj, ".vcxproj", vstudio.vc2010.generate)

-- Skip generation of empty user files
local user = p.capture(function() vstudio.vc2010.generateUser(prj) end)
Expand All @@ -69,7 +69,10 @@

-- Only generate a filters file if the source tree actually has subfolders
if tree.hasbranches(project.getsourcetree(prj)) then
p.generate(prj, ".vcxproj.filters", vstudio.vc2010.generateFilters)
if p.generate(prj, ".vcxproj.filters", vstudio.vc2010.generateFilters) == true and projFileModified == false then
-- vs workaround for issue where if only the .filters file is modified, VS doesn't automaticly trigger a reload
p.touch(prj, ".vcxproj")
end
end
end

Expand Down
39 changes: 37 additions & 2 deletions src/base/premake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@


--
-- Returns a boolean if the file was modified
-- Open a file for output, and call a function to actually do the writing.
-- Used by the actions to generate workspace and project files.
--
Expand All @@ -160,22 +161,56 @@

-- make sure output folder exists.
local dir = path.getdirectory(fn)
ok, err = os.mkdir(dir)
local ok, err = os.mkdir(dir)
if not ok then
error(err, 0)
end

local f, err = os.writefile_ifnotequal(output, fn);

if (f < 0) then
if (f == 0) then
return false -- file not modified
elseif (f < 0) then
error(err, 0)
elseif (f > 0) then
printf("Generated %s...", path.getrelative(os.getcwd(), fn))
return true -- file modified
end
end



--
-- Marks a file as modified without changing its contents
--
-- @param obj
-- A workspace or project object; will be passed to the callback function.
-- @param ext
-- An optional extension for the generated file, with the leading dot.
--

function premake.touch(obj, ext)
local fn = premake.filename(obj, ext)

-- make sure output folder exists.
local dir = path.getdirectory(fn)
local ok, err = os.mkdir(dir)
if not ok then
error(err, 0)
end

local f, err = os.touchfile(fn);

if (f == 0) then
return false -- file marked as modified
elseif (f < 0) then
error(err, 0)
elseif (f > 0) then
return true -- file created
end
end


---
-- Returns the full path a file generated from any of the project
-- objects (project, workspace, rule).
Expand Down
94 changes: 94 additions & 0 deletions src/host/os_touchfile.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* \file os_touchfile.c
* \brief markes a file as modified without changing its contents.
* \author Blizzard Entertainment (contact tvandijck@blizzard.com)
* \author Copyright (c) 2015 Jason Perkins and the Premake project
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "premake.h"

#if PLATFORM_WINDOWS
#include <io.h>
#else
#include <unistd.h>
#include <sys/types.h>
#endif

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

static int truncate_file(const char* fn)
{
FILE* file = fopen(fn, "rb");
size_t size;
file = fopen(fn, "ab");
if (file == NULL)
{
return FALSE;
}
fseek(file, 0, SEEK_END);
size = ftell(file);
// append a dummy space. There are better ways to do
// a touch, however this is a rather simple
// multiplatform method
if (fwrite(" ", 1, 1, file) != 1)
{
fclose(file);
return FALSE;
}
#if PLATFORM_WINDOWS
if (_chsize(_fileno(file), (long)size) != 0)
{
fclose(file);
return FALSE;
}
#endif
fclose(file);
#if !PLATFORM_WINDOWS
if (truncate(fn, (off_t)size) != 0)
{
return FALSE;
}
#endif
return TRUE;
}

int os_touchfile(lua_State* L)
{
FILE* file;
const char* dst = luaL_checkstring(L, 1);

// if destination exist, mark the file as modified
if (do_isfile(dst))
{
if (truncate_file(dst))
{
lua_pushinteger(L, 0);
return 1;
} else {
lua_pushinteger(L, -1);
lua_pushfstring(L, "unable to touch file '%s'", dst);
return 2;
}
}

file = fopen(dst, "wb");
if (file != NULL)
{
fclose(file);

lua_pushinteger(L, 1);
return 1;
}

lua_pushinteger(L, -1);
lua_pushfstring(L, "unable to create file to '%s'", dst);
return 2;
}
1 change: 1 addition & 0 deletions src/host/premake.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ static const luaL_Reg os_functions[] = {
{ "stat", os_stat },
{ "uuid", os_uuid },
{ "writefile_ifnotequal", os_writefile_ifnotequal },
{ "touchfile", os_touchfile },
{ "compile", os_compile },
{ NULL, NULL }
};
Expand Down
1 change: 1 addition & 0 deletions src/host/premake.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ int os_rmdir(lua_State* L);
int os_stat(lua_State* L);
int os_uuid(lua_State* L);
int os_writefile_ifnotequal(lua_State* L);
int os_touchfile(lua_State* L);
int os_compile(lua_State* L);
int string_endswith(lua_State* L);
int string_hash(lua_State* L);
Expand Down

0 comments on commit 760eafc

Please sign in to comment.